File size: 3,751 Bytes
2d39154 794b22f 2d39154 794b22f 2d39154 794b22f 2d39154 794b22f 2d39154 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #!/usr/bin/env node
/* test-v071.mjs - v0.7.1 regression: comment line numbers.
* The extension's test suite caught it: every `//` comment doubled a newline
* in the stripped source, so every line number after the first comment
* drifted +1 and diagnostics pointed one line late. Block comments were
* fine; line comments were lying. These tests pin the fix. */
import { parse } from '../public/dssl/parser.js';
import { resolve } from '../public/dssl/resolver.js';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
const here = path.dirname(fileURLToPath(import.meta.url));
let passed = 0, failed = 0;
const ok = (cond, name) => {
if (cond) { passed++; console.log(` ok ${name}`); }
else { failed++; console.log(`FAIL ${name}`); }
};
console.log('1 - comment placements keep true line numbers');
{
const cases = [
['leading', '// c\n.a {\n x: 1\n}', 3],
['inner', '.a {\n // c\n x: 1\n}', 3],
['trailing', '.a {\n x: 1 // c\n}', 2],
['block leading', '/* c */\n.a {\n x: 1\n}', 3],
['block inner', '.a {\n /* c */\n x: 1\n}', 3],
['many comments', '// one\n// two\n.a {\n // three\n x: 1 // four\n}', 5],
['comment at eof no newline', '.a {\n x: 1\n}\n// tail', null],
['crlf', '// c\r\n.a {\r\n x: 1\r\n}', 3],
];
for (const [name, src, want] of cases) {
const { ast, errors } = parse(src, 't.dssl');
const rule = ast.children.find((n) => n.kind === 'selector');
const got = rule ? rule.children[0].line : null;
const bad = errors.filter((e) => !/missing|not a valid|expected/.test(e.message));
ok((want === null || got === want) && bad.length === 0, `${name}: decl line ${got}${want === null ? '' : ' (want ' + want + ')'}`);
}
}
console.log('2 - errors and warnings carry honest lines after comments');
{
const src = '// header comment\n.nav-links {\n display: none\n column: gap 2\n}\n.bad {\n background: colr.accent\n}\n';
// lines 1-based: display=3, column=4, colr=7
const { ast } = parse(src, 't.dssl');
const doc = resolve(ast, 't.dssl', {});
const warn = doc.warnings.find((w) => w.message.includes('column'));
ok(warn && warn.line === 4, `ordering warning fires on the column: line (got ${warn && warn.line}, want 4)`);
const err = doc.errors.find((e) => e.message.includes('colr'));
ok(err && err.line === 7, `misspelled token error on its own line (got ${err && err.line}, want 7)`);
}
console.log('3 - the real site stylesheets: spot-check line honesty');
{
// parse a real stylesheet that opens with a comment block and verify a
// known rule lands where it lives on disk
import('node:fs').then(({ readFileSync }) => {
try {
const p = path.join(here, '..', 'public', 'styles', 'tokens.dssl');
const src = readFileSync(p, 'utf8');
const lines = src.split('\n');
// find a real declaration line with a known shape
const idx = lines.findIndex((l) => /--dssl-color-ink/.test(l));
if (idx >= 0) {
const { ast } = parse(src, 'tokens.dssl');
let found = null;
const walk = (n) => {
if (found) return;
for (const c of n.children || []) {
if (c.kind === 'decl' && /ink/.test(c.prop || '')) { found = c; return; }
walk(c);
}
};
walk(ast);
ok(found && found.line === idx + 1, `tokens.dssl decl on disk line ${idx + 1}, parser says ${found && found.line}`);
} else {
ok(true, 'tokens.dssl shape changed; spot-check skipped');
}
} catch (e) {
ok(false, 'site stylesheet spot-check threw: ' + e.message);
}
finish();
});
}
function finish() {
console.log(`\n${passed} passed, ${failed} failed`);
process.exit(failed ? 1 : 0);
}
|