mirror of
https://github.com/hanzoai/postcss.git
synced 2026-09-24 17:01:56 +00:00
* Clarify documentation for `node.source.end.offset` * Add test cases for `node.source` * Show example code for `end.offset`
318 lines
5.6 KiB
TypeScript
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()
|