From e2761cae80ec90986c642739c7b42bc387e2d580 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Aug 2026 21:59:34 +0000 Subject: [PATCH] Sync generated provider output --- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .pi/skills/impeccable/scripts/live-browser.js | 2 + .pi/skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- .../impeccable/scripts/lib/design-parser.mjs | 41 +++++++++++++++---- .../skills/impeccable/scripts/live-browser.js | 2 + .../skills/impeccable/scripts/live-server.mjs | 2 +- 45 files changed, 525 insertions(+), 150 deletions(-) diff --git a/.agents/skills/impeccable/scripts/lib/design-parser.mjs b/.agents/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.agents/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.agents/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.agents/skills/impeccable/scripts/live-browser.js b/.agents/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.agents/skills/impeccable/scripts/live-browser.js +++ b/.agents/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.agents/skills/impeccable/scripts/live-server.mjs b/.agents/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.agents/skills/impeccable/scripts/live-server.mjs +++ b/.agents/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.claude/skills/impeccable/scripts/lib/design-parser.mjs b/.claude/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.claude/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.claude/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.claude/skills/impeccable/scripts/live-browser.js b/.claude/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.claude/skills/impeccable/scripts/live-browser.js +++ b/.claude/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.claude/skills/impeccable/scripts/live-server.mjs b/.claude/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.claude/skills/impeccable/scripts/live-server.mjs +++ b/.claude/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.cursor/skills/impeccable/scripts/lib/design-parser.mjs b/.cursor/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.cursor/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.cursor/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.cursor/skills/impeccable/scripts/live-browser.js b/.cursor/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.cursor/skills/impeccable/scripts/live-browser.js +++ b/.cursor/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.cursor/skills/impeccable/scripts/live-server.mjs b/.cursor/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.cursor/skills/impeccable/scripts/live-server.mjs +++ b/.cursor/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.gemini/skills/impeccable/scripts/lib/design-parser.mjs b/.gemini/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.gemini/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.gemini/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.gemini/skills/impeccable/scripts/live-browser.js b/.gemini/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.gemini/skills/impeccable/scripts/live-browser.js +++ b/.gemini/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.gemini/skills/impeccable/scripts/live-server.mjs b/.gemini/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.gemini/skills/impeccable/scripts/live-server.mjs +++ b/.gemini/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.github/skills/impeccable/scripts/lib/design-parser.mjs b/.github/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.github/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.github/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.github/skills/impeccable/scripts/live-browser.js b/.github/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.github/skills/impeccable/scripts/live-browser.js +++ b/.github/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.github/skills/impeccable/scripts/live-server.mjs b/.github/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.github/skills/impeccable/scripts/live-server.mjs +++ b/.github/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.grok/skills/impeccable/scripts/lib/design-parser.mjs b/.grok/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.grok/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.grok/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.grok/skills/impeccable/scripts/live-browser.js b/.grok/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.grok/skills/impeccable/scripts/live-browser.js +++ b/.grok/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.grok/skills/impeccable/scripts/live-server.mjs b/.grok/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.grok/skills/impeccable/scripts/live-server.mjs +++ b/.grok/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.kiro/skills/impeccable/scripts/lib/design-parser.mjs b/.kiro/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.kiro/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.kiro/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.kiro/skills/impeccable/scripts/live-browser.js b/.kiro/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.kiro/skills/impeccable/scripts/live-browser.js +++ b/.kiro/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.kiro/skills/impeccable/scripts/live-server.mjs b/.kiro/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.kiro/skills/impeccable/scripts/live-server.mjs +++ b/.kiro/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.opencode/skills/impeccable/scripts/lib/design-parser.mjs b/.opencode/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.opencode/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.opencode/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.opencode/skills/impeccable/scripts/live-browser.js b/.opencode/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.opencode/skills/impeccable/scripts/live-browser.js +++ b/.opencode/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.opencode/skills/impeccable/scripts/live-server.mjs b/.opencode/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.opencode/skills/impeccable/scripts/live-server.mjs +++ b/.opencode/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.pi/skills/impeccable/scripts/lib/design-parser.mjs b/.pi/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.pi/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.pi/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.pi/skills/impeccable/scripts/live-browser.js b/.pi/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.pi/skills/impeccable/scripts/live-browser.js +++ b/.pi/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.pi/skills/impeccable/scripts/live-server.mjs b/.pi/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.pi/skills/impeccable/scripts/live-server.mjs +++ b/.pi/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.qoder/skills/impeccable/scripts/lib/design-parser.mjs b/.qoder/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.qoder/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.qoder/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.qoder/skills/impeccable/scripts/live-browser.js b/.qoder/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.qoder/skills/impeccable/scripts/live-browser.js +++ b/.qoder/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.qoder/skills/impeccable/scripts/live-server.mjs b/.qoder/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.qoder/skills/impeccable/scripts/live-server.mjs +++ b/.qoder/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.rovodev/skills/impeccable/scripts/lib/design-parser.mjs b/.rovodev/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.rovodev/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.rovodev/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.rovodev/skills/impeccable/scripts/live-browser.js b/.rovodev/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.rovodev/skills/impeccable/scripts/live-browser.js +++ b/.rovodev/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.rovodev/skills/impeccable/scripts/live-server.mjs b/.rovodev/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.rovodev/skills/impeccable/scripts/live-server.mjs +++ b/.rovodev/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.trae-cn/skills/impeccable/scripts/lib/design-parser.mjs b/.trae-cn/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.trae-cn/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.trae-cn/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.trae-cn/skills/impeccable/scripts/live-browser.js b/.trae-cn/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.trae-cn/skills/impeccable/scripts/live-browser.js +++ b/.trae-cn/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.trae-cn/skills/impeccable/scripts/live-server.mjs b/.trae-cn/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.trae-cn/skills/impeccable/scripts/live-server.mjs +++ b/.trae-cn/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.trae/skills/impeccable/scripts/lib/design-parser.mjs b/.trae/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.trae/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.trae/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.trae/skills/impeccable/scripts/live-browser.js b/.trae/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.trae/skills/impeccable/scripts/live-browser.js +++ b/.trae/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.trae/skills/impeccable/scripts/live-server.mjs b/.trae/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.trae/skills/impeccable/scripts/live-server.mjs +++ b/.trae/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/.vibe/skills/impeccable/scripts/lib/design-parser.mjs b/.vibe/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/.vibe/skills/impeccable/scripts/lib/design-parser.mjs +++ b/.vibe/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/.vibe/skills/impeccable/scripts/live-browser.js b/.vibe/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/.vibe/skills/impeccable/scripts/live-browser.js +++ b/.vibe/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/.vibe/skills/impeccable/scripts/live-server.mjs b/.vibe/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/.vibe/skills/impeccable/scripts/live-server.mjs +++ b/.vibe/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative. diff --git a/plugin/skills/impeccable/scripts/lib/design-parser.mjs b/plugin/skills/impeccable/scripts/lib/design-parser.mjs index f82370bb2..7b060eeca 100644 --- a/plugin/skills/impeccable/scripts/lib/design-parser.mjs +++ b/plugin/skills/impeccable/scripts/lib/design-parser.mjs @@ -2,15 +2,20 @@ // the live-mode design-system panel can render. Deterministic, dependency-free. // // Two-layer: YAML frontmatter (machine-readable tokens) + markdown body -// (prose with six canonical H2 sections). When frontmatter is present, it's +// (prose with eight canonical H2 sections). When frontmatter is present, it's // exposed on `model.frontmatter` alongside the prose-scraped sections; // consumers can prefer frontmatter values and fall back to prose. +// Array order is also match precedence: matchCanonicalSection's keyword-contained +// pass returns the first entry a heading contains, so reordering this changes +// which section an ambiguous heading resolves to. const CANONICAL_SECTIONS = [ 'Overview', 'Colors', 'Typography', + 'Layout', 'Elevation', + 'Shapes', 'Components', "Do's and Don'ts", ]; @@ -662,11 +667,19 @@ function parseTypeBullet(bullet) { }; } -function extractElevation(section) { +function extractGuidance(section) { if (!section) return null; const subs = splitSubsections(section.lines); + return { + subtitle: section.subtitle, + description: collectParagraphs(subs[0].lines).join(' ') || null, + rules: extractNamedRules(section.lines), + }; +} - const description = collectParagraphs(subs[0].lines).join(' ') || null; +function extractElevation(section) { + const guidance = extractGuidance(section); + if (!guidance) return null; const shadows = []; const seen = new Set(); @@ -691,12 +704,7 @@ function extractElevation(section) { for (const inline of extractInlineShadows(b)) dedupe(inline); } - return { - subtitle: section.subtitle, - description, - shadows, - rules: extractNamedRules(section.lines), - }; + return { ...guidance, shadows }; } function extractInlineShadows(text) { @@ -828,6 +836,15 @@ function extractDosDonts(section) { // ---------- Coverage assessment ---------- +// Sections whose model is description-plus-rules only (see extractGuidance). +const guidanceCoverage = (guidance) => + guidance + ? { + description: Boolean(guidance.description), + rules: guidance.rules.length, + } + : 'missing'; + function assessCoverage(model) { const report = {}; @@ -856,6 +873,8 @@ function assessCoverage(model) { } : 'missing'; + report.layout = guidanceCoverage(model.layout); + report.elevation = model.elevation ? { shadows: model.elevation.shadows.length, @@ -864,6 +883,8 @@ function assessCoverage(model) { } : 'missing'; + report.shapes = guidanceCoverage(model.shapes); + report.components = model.components ? { count: model.components.components.length, @@ -893,7 +914,9 @@ export function parseDesignMd(md) { overview: extractOverview(sections['Overview']), colors: extractColors(sections['Colors']), typography: extractTypography(sections['Typography']), + layout: extractGuidance(sections['Layout']), elevation: extractElevation(sections['Elevation']), + shapes: extractGuidance(sections['Shapes']), components: extractComponents(sections['Components']), dosDonts: extractDosDonts(sections["Do's and Don'ts"]), }; diff --git a/plugin/skills/impeccable/scripts/live-browser.js b/plugin/skills/impeccable/scripts/live-browser.js index 0b8debeca..aa9bd759b 100644 --- a/plugin/skills/impeccable/scripts/live-browser.js +++ b/plugin/skills/impeccable/scripts/live-browser.js @@ -11975,7 +11975,9 @@ void main() { rules: [ ...(md.colors?.rules || []).map((r) => ({ ...r, section: 'colors' })), ...(md.typography?.rules || []).map((r) => ({ ...r, section: 'typography' })), + ...(md.layout?.rules || []).map((r) => ({ ...r, section: 'layout' })), ...(md.elevation?.rules || []).map((r) => ({ ...r, section: 'elevation' })), + ...(md.shapes?.rules || []).map((r) => ({ ...r, section: 'shapes' })), ], dos: md.dosDonts?.dos || [], donts: md.dosDonts?.donts || [], diff --git a/plugin/skills/impeccable/scripts/live-server.mjs b/plugin/skills/impeccable/scripts/live-server.mjs index 29ed19bcb..86b7777be 100644 --- a/plugin/skills/impeccable/scripts/live-server.mjs +++ b/plugin/skills/impeccable/scripts/live-server.mjs @@ -873,7 +873,7 @@ function createRequestHandler({ detectScript, liveScriptParts }) { // { present, parsed, sidecar, hasMd, hasSidecar, // mdNewerThanJson, parseError?, sidecarError? } // - parsed: output of parseDesignMd (frontmatter - // + six canonical sections) when DESIGN.md exists. + // + the canonical sections) when DESIGN.md exists. // - sidecar: .impeccable/design.json contents when present. // Expected shape: schemaVersion 2, carrying // extensions + components + narrative.