Files
postcss/test/location.test.ts
mizdraandGitHub ad3b622e89 Clarify documentation for node.source.end.offset (#2032)
* Clarify documentation for `node.source.end.offset`

* Add test cases for `node.source`

* Show example code for `end.offset`
2025-04-12 14:22:12 +02:00

318 lines
5.6 KiB
TypeScript

import { test } from 'uvu'
import { equal } from 'uvu/assert'
import {
AtRule,
Comment,
Declaration,
Node,
parse,
Rule
} from '../lib/postcss.js'
function checkOffset(source: string, node: Node, expected: string): void {
let start = node.source!.start!.offset
let end = node.source!.end!.offset
equal(source.slice(start, end), expected)
}
test('root', () => {
let source = '.a{}'
let css = parse(source)
checkOffset(source, css, '.a{}')
equal(css.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(css.source!.end, {
column: 5,
line: 1,
offset: 4
})
})
test('rule', () => {
let source = '.a{}'
let css = parse(source)
let rule = css.first as Rule
checkOffset(source, rule, '.a{}')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 4,
line: 1,
offset: 4
})
})
test('single decl (no semicolon)', () => {
let source = '.a{b:c}'
let css = parse(source)
let rule = css.first as Rule
let decl = rule.first as Declaration
checkOffset(source, rule, '.a{b:c}')
checkOffset(source, decl, 'b:c')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 7,
line: 1,
offset: 7
})
equal(decl.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(decl.source!.end, {
column: 6,
line: 1,
offset: 6
})
})
test('single decl (with semicolon)', () => {
let source = '.a{b:c;}'
let css = parse(source)
let rule = css.first as Rule
let decl = rule.first as Declaration
checkOffset(source, rule, '.a{b:c;}')
checkOffset(source, decl, 'b:c;')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 8,
line: 1,
offset: 8
})
equal(decl.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(decl.source!.end, {
column: 7,
line: 1,
offset: 7
})
})
test('two decls', () => {
let source = '.a{b:c;d:e}'
let css = parse(source)
let rule = css.first as Rule
let decl1 = rule.first as Declaration
let decl2 = decl1.next() as Declaration
checkOffset(source, decl1, 'b:c;')
checkOffset(source, decl2, 'd:e')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 11,
line: 1,
offset: 11
})
equal(decl1.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(decl1.source!.end, {
column: 7,
line: 1,
offset: 7
})
equal(decl2.source!.start, {
column: 8,
line: 1,
offset: 7
})
equal(decl2.source!.end, {
column: 10,
line: 1,
offset: 10
})
})
test('...rule nested in rule', () => {
let source = '.a{.b{}}'
let css = parse(source)
let rule = css.first as Rule
let rule2 = rule.first as Rule
checkOffset(source, rule, '.a{.b{}}')
checkOffset(source, rule2, '.b{}')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 8,
line: 1,
offset: 8
})
equal(rule2.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(rule2.source!.end, {
column: 7,
line: 1,
offset: 7
})
})
test('at-rule with semicolon', () => {
let source = '@a b;'
let css = parse(source)
let atrule = css.first as AtRule
checkOffset(source, atrule, '@a b;')
equal(atrule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(atrule.source!.end, {
column: 5,
line: 1,
offset: 5
})
})
test('unclosed at-rule', () => {
let source = '@a b'
let css = parse(source)
let atrule = css.first as AtRule
checkOffset(source, atrule, '@a b')
equal(atrule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(atrule.source!.end, {
column: 4,
line: 1,
offset: 4
})
})
test('unclosed at-rule in at-rule', () => {
let source = '@a{@b c}'
let css = parse(source)
let atrule = css.first as AtRule
let atrule2 = atrule.first as AtRule
checkOffset(source, atrule, '@a{@b c}')
checkOffset(source, atrule2, '@b c')
equal(atrule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(atrule.source!.end, {
column: 8,
line: 1,
offset: 8
})
equal(atrule2.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(atrule2.source!.end, {
column: 7,
line: 1,
offset: 7
})
})
test('at-rule with body', () => {
let source = '@a{}'
let css = parse(source)
let atrule = css.first as AtRule
checkOffset(source, atrule, '@a{}')
equal(atrule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(atrule.source!.end, {
column: 4,
line: 1,
offset: 4
})
})
test('at-rule nested in atrule', () => {
let source = '@a{@b{}}'
let css = parse(source)
let atrule = css.first as Rule
let atrule2 = atrule.first as Rule
checkOffset(source, atrule, '@a{@b{}}')
checkOffset(source, atrule2, '@b{}')
equal(atrule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(atrule.source!.end, {
column: 8,
line: 1,
offset: 8
})
equal(atrule2.source!.start, {
column: 4,
line: 1,
offset: 3
})
equal(atrule2.source!.end, {
column: 7,
line: 1,
offset: 7
})
})
test('comment', () => {
let source = '/*a*/'
let css = parse(source)
let rule = css.first as Comment
checkOffset(source, rule, '/*a*/')
equal(rule.source!.start, {
column: 1,
line: 1,
offset: 0
})
equal(rule.source!.end, {
column: 5,
line: 1,
offset: 5
})
})
test.run()