test(workspace): accept only #249 decision markers and state the lint scope
The overlay lint accepted any D-number, so another issue's ruling such as "D5 (#245)" could mark a concept override. A marker now has to be a D-number with no other issue cited; the vocabulary rule that cited #245 reads "#245 decision 5". TESTING.md now states that the lint covers workspace.css only, lists the unmarked overrides still in images.css, and says PRs C and D run the lint over each page sheet they keep.
This commit is contained in:
+15
-5
@@ -319,11 +319,21 @@ other page or canvas script loads workspace CSS.
|
||||
|
||||
**Overlay decision-marker lint.** `lintOverlay` in `tools/vendor/sync-concept-css.mjs`
|
||||
fails any `workspace.css` rule whose selector is also a concept selector unless the
|
||||
rule carries a `/* D<n> */` comment, before its selector or inside its block. The lint
|
||||
test fails if `workspace.css` is missing. The match is by exact selector, so a narrower
|
||||
selector over a concept rule (for example `.ca-tools dialog.prompt-sender`) passes the
|
||||
lint. Such rules, and the page-stylesheet leftovers such as `library.css`
|
||||
`.row-actions`, name the PR that retires them, by convention.
|
||||
rule carries a `/* D<n> */` comment, before its selector or inside its block. The
|
||||
D-number must be one of this spec's (#249): a comment that cites any other issue, such
|
||||
as `D5 (#245)`, is that issue's ruling and is not a marker, so write `#245 decision 5`
|
||||
for those. The lint test fails if `workspace.css` is missing. The match is by exact
|
||||
selector, so a narrower selector over a concept rule (for example
|
||||
`.ca-tools dialog.prompt-sender`) passes the lint. Such rules, and the page-stylesheet
|
||||
leftovers such as `library.css` `.row-actions`, name the PR that retires them, by
|
||||
convention.
|
||||
|
||||
The lint covers `workspace.css` only. The page stylesheets that load before it
|
||||
(`images.css`, `library.css`, `inspector.css`) are not linted yet, and `images.css`
|
||||
still has unmarked concept-selector overrides (`.image-grid`, `.prompt-text`,
|
||||
`.prompt-actions`, `.ca-tools .prompt-actions button`). PRs C and D retire those
|
||||
sheets: each one runs `lintOverlay` over every page sheet it keeps, and adds that
|
||||
sheet to the real-file lint test.
|
||||
|
||||
**Comparison method.** Production must equal the concept except for the recorded
|
||||
deviations in the #249 design (spec §8, D-numbers). It is never compared against
|
||||
|
||||
Vendored
+11
@@ -55,6 +55,17 @@ test('overlay lint requires a decision marker on concept selectors', () => {
|
||||
assert.equal(lintOverlay(conceptCss, '/* D1 */ .card { color: blue; }\n.row { gap: 1px; }').violations.length, 1);
|
||||
});
|
||||
|
||||
test('overlay lint accepts only this spec\'s (#249) decision numbers', () => {
|
||||
const conceptCss = '.card { color: red; }\n';
|
||||
assert.deepEqual(lintOverlay(conceptCss, '/* D12 of #249 */ .card { color: blue; }').violations, []);
|
||||
assert.deepEqual(lintOverlay(conceptCss, '/* #249 D3: reason */ .card { color: blue; }').violations, []);
|
||||
// Another issue's decision numbers are not #249 rulings, so they never mark a concept override.
|
||||
assert.equal(lintOverlay(conceptCss, '/* D5 (#245) */ .card { color: blue; }').violations.length, 1);
|
||||
assert.equal(lintOverlay(conceptCss, '/* D2 of #240 and #249 */ .card { color: blue; }').violations.length, 1);
|
||||
assert.equal(lintOverlay(conceptCss, '/* #245 decision 5 */ .card { color: blue; }').violations.length, 1);
|
||||
assert.equal(lintOverlay(conceptCss, '/* AD5 */ .card { color: blue; }').violations.length, 1);
|
||||
});
|
||||
|
||||
test('overlay rules on concept selectors carry a decision marker', () => {
|
||||
const overlay = join(root, 'web/js/workspace/workspace.css');
|
||||
assert.ok(existsSync(overlay), 'web/js/workspace/workspace.css is missing');
|
||||
|
||||
Vendored
+9
-2
@@ -6,6 +6,13 @@ import { repositoryRoot } from './vendor-viewerjs.mjs';
|
||||
const CONCEPT = 'docs/concepts/workspace/style.css';
|
||||
const COPY = 'web/js/workspace/concept.css';
|
||||
const MARKER = /\/\*[^*]*\bD\d+\b[^*]*\*\//;
|
||||
const SPEC_ISSUE = '#249';
|
||||
|
||||
// A decision marker names one of this spec's (#249) D-numbers. A comment that cites any other issue is that issue's
|
||||
// ruling (for example #245's own D5), so it never marks a concept override here.
|
||||
function isDecisionMarker(comment) {
|
||||
return MARKER.test(comment) && (comment.match(/#\d+\b/g) ?? []).every(issue => issue === SPEC_ISSUE);
|
||||
}
|
||||
|
||||
// Minimal tokenizer: walks top-level rules and the bodies of @media/@supports,
|
||||
// returning each rule's normalized selectors and the comments attached to it
|
||||
@@ -84,8 +91,8 @@ export function lintOverlay(conceptCss, overlayCss) {
|
||||
const violations = [];
|
||||
for (const rule of parseRules(overlayCss)) {
|
||||
const shared = rule.selectors.filter(selector => owned.has(selector));
|
||||
if (shared.length && !rule.comments.some(comment => MARKER.test(comment))) {
|
||||
violations.push(`${shared.join(', ')}: overlay rule on a concept selector needs a /* D<n> */ decision marker`);
|
||||
if (shared.length && !rule.comments.some(isDecisionMarker)) {
|
||||
violations.push(`${shared.join(', ')}: overlay rule on a concept selector needs a /* D<n> */ (#249) decision marker`);
|
||||
}
|
||||
}
|
||||
return { violations };
|
||||
|
||||
@@ -43,7 +43,7 @@ main:focus-visible { outline: 2px solid var(--ca-focus); outline-offset: 4px; }
|
||||
/* Long tag names wrap inside the Tag cell so the Actions column keeps its intrinsic width; on two-column screens the
|
||||
minimum keeps the concept's longest sample ("architecture", about 5em) on one line. */
|
||||
.vocabulary-main td:first-child { overflow-wrap: anywhere; min-width: calc(6em + 20px); }
|
||||
/* D5 (#245): bounded lists continue with Load more; never a scroll anchor, so appended rows push the end away. */
|
||||
/* Tags & categories (#245 decision 5): bounded lists continue with Load more; never a scroll anchor, so appended rows push the end away. */
|
||||
.vocabulary-main .vocabulary-continuation { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; padding-block: 15px 0; overflow-anchor: none; }
|
||||
.vocabulary-main .vocabulary-continuation p { margin: 0; flex: 1 1 200px; font-size: 12px; color: var(--ca-muted); }
|
||||
.vocabulary-main .vocabulary-continuation .vocabulary-error { color: var(--ca-error-text); }
|
||||
|
||||
Reference in New Issue
Block a user