mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
Merge pull request #684 from pbakaus/codex/simplify-design-rule-extraction-20260831
Simplify design rule extraction
This commit is contained in:
@@ -329,47 +329,37 @@ function stripBold(s) {
|
||||
function extractNamedRules(lines) {
|
||||
const rules = [];
|
||||
const seen = new Set();
|
||||
const addRule = (name, body, { allowDuplicate = false } = {}) => {
|
||||
const key = name.toLowerCase();
|
||||
if (!allowDuplicate && seen.has(key)) return;
|
||||
seen.add(key);
|
||||
rules.push({ name, body });
|
||||
};
|
||||
|
||||
// Style A (Impeccable): "**The X Rule.** body body body" — can span lines.
|
||||
const joined = lines.join('\n');
|
||||
const inlineStart = /\*\*(The [^*]+?Rule)\.\*\*/g;
|
||||
const inlineMatches = [];
|
||||
let m;
|
||||
while ((m = inlineStart.exec(joined)) !== null) {
|
||||
inlineMatches.push({ name: m[1], start: m.index, end: inlineStart.lastIndex });
|
||||
}
|
||||
const inlineMatches = [...joined.matchAll(/\*\*(The [^*]+?Rule)\.\*\*/g)];
|
||||
for (let i = 0; i < inlineMatches.length; i++) {
|
||||
const mm = inlineMatches[i];
|
||||
const bodyEnd = i + 1 < inlineMatches.length ? inlineMatches[i + 1].start : joined.length;
|
||||
const match = inlineMatches[i];
|
||||
const bodyEnd = inlineMatches[i + 1]?.index ?? joined.length;
|
||||
const body = joined
|
||||
.slice(mm.end, bodyEnd)
|
||||
.slice(match.index + match[0].length, bodyEnd)
|
||||
.replace(/\n##[^\n]*$/s, '')
|
||||
.replace(/\n###[^\n]*$/s, '')
|
||||
.trim();
|
||||
const name = stripBold(mm.name).trim();
|
||||
seen.add(name.toLowerCase());
|
||||
rules.push({ name, body: stripBold(body) });
|
||||
// Preserve the inline format's historical behavior: repeated inline rules
|
||||
// remain visible, while the later heading and bullet formats dedupe.
|
||||
addRule(stripBold(match[1]).trim(), stripBold(body), { allowDuplicate: true });
|
||||
}
|
||||
|
||||
// Style B (Stitch): `### The "X" Rule` or `### The X Fallback`, body is the
|
||||
// bullets/paragraphs until the next heading. Accept Rule / Fallback / Principle.
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const h3 = lines[i].match(/^###\s+(.+?)\s*$/);
|
||||
if (!h3) continue;
|
||||
const headerName = stripBold(h3[1]).replace(/["“”]/g, '').trim();
|
||||
for (const subsection of splitSubsections(lines).slice(1)) {
|
||||
const headerName = stripBold(subsection.name).replace(/["“”]/g, '').trim();
|
||||
if (!/^The\b.*\b(Rule|Fallback|Principle)\b/i.test(headerName)) continue;
|
||||
if (seen.has(headerName.toLowerCase())) continue;
|
||||
|
||||
const bodyLines = [];
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
if (/^##\s|^###\s/.test(lines[j])) break;
|
||||
bodyLines.push(lines[j]);
|
||||
}
|
||||
const body = stripBold(bodyLines.join('\n').replace(/\n+/g, ' ')).trim();
|
||||
if (body) {
|
||||
seen.add(headerName.toLowerCase());
|
||||
rules.push({ name: headerName, body });
|
||||
}
|
||||
const body = stripBold(subsection.lines.join('\n').replace(/\n+/g, ' ')).trim();
|
||||
if (body) addRule(headerName, body);
|
||||
}
|
||||
|
||||
// Style C (Stitch bullet form): "* **The Layering Principle:** body"
|
||||
@@ -379,9 +369,7 @@ function extractNamedRules(lines) {
|
||||
if (!mm) continue;
|
||||
const nameRaw = mm[1].replace(/[.:]\s*$/, '').replace(/["“”]/g, '').trim();
|
||||
if (!/^The\b.+\b(Rule|Fallback|Principle)$/i.test(nameRaw)) continue;
|
||||
if (seen.has(nameRaw.toLowerCase())) continue;
|
||||
seen.add(nameRaw.toLowerCase());
|
||||
rules.push({ name: nameRaw, body: stripBold(mm[2]).trim() });
|
||||
addRule(nameRaw, stripBold(mm[2]).trim());
|
||||
}
|
||||
|
||||
return rules;
|
||||
|
||||
@@ -228,6 +228,33 @@ describe('parseDesignMd overview branch', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseDesignMd named rules', () => {
|
||||
it('preserves format precedence while deduplicating later definitions', () => {
|
||||
const md = `# Design System: Rules
|
||||
|
||||
## Layout
|
||||
|
||||
### The "Rhythm" Rule
|
||||
Ignore this duplicate heading definition.
|
||||
|
||||
### The Fallback Principle
|
||||
Use the heading definition.
|
||||
|
||||
### Named Rules
|
||||
- **The Fallback Principle:** Ignore this duplicate bullet definition.
|
||||
- **The Layering Principle:** Use the bullet definition.
|
||||
|
||||
**The Rhythm Rule.** Keep the first definition.
|
||||
`;
|
||||
|
||||
assert.deepEqual(parseDesignMd(md).layout.rules, [
|
||||
{ name: 'The Rhythm Rule', body: 'Keep the first definition.' },
|
||||
{ name: 'The Fallback Principle', body: 'Use the heading definition.' },
|
||||
{ name: 'The Layering Principle', body: 'Use the bullet definition.' },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseDesignMd canonical sections', () => {
|
||||
it('preserves content and named rules from all eight canonical sections', () => {
|
||||
const md = `# Design System: Complete
|
||||
|
||||
Reference in New Issue
Block a user