@monoes/monomindcli 2.14.1 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/helpers/control-start.cjs +10 -13
- package/.claude/skills/monodesign/scripts/context.mjs +4 -4
- package/.claude/skills/monodesign/scripts/critique-storage.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detect-csp.mjs +1 -6
- package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +16 -18
- package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +3 -3
- package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +67 -47
- package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +6 -6
- package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +6 -5
- package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +6 -6
- package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +3 -3
- package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +24 -25
- package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +2 -2
- package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +2 -2
- package/.claude/skills/monodesign/scripts/hook-admin.mjs +6 -6
- package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +4 -4
- package/.claude/skills/monodesign/scripts/hook-lib.mjs +20 -11
- package/.claude/skills/monodesign/scripts/hook.mjs +1 -1
- package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +9 -42
- package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +1 -1
- package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +5 -5
- package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live/event-validation.mjs +13 -13
- package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live/session-store.mjs +5 -5
- package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +13 -13
- package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live/ui-core.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live-accept.mjs +24 -24
- package/.claude/skills/monodesign/scripts/live-browser-dom.js +8 -7
- package/.claude/skills/monodesign/scripts/live-browser-session.js +8 -7
- package/.claude/skills/monodesign/scripts/live-browser.js +405 -432
- package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +6 -6
- package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +2 -2
- package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live-inject.mjs +7 -7
- package/.claude/skills/monodesign/scripts/live-insert.mjs +11 -11
- package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live-poll.mjs +5 -5
- package/.claude/skills/monodesign/scripts/live-server.mjs +10 -10
- package/.claude/skills/monodesign/scripts/live-wrap.mjs +31 -41
- package/.claude/skills/monodesign/scripts/live.mjs +5 -5
- package/.claude/skills/monodesign/scripts/palette.mjs +3 -1
- package/.claude/skills/monodesign/scripts/pin.mjs +1 -1
- package/dist/src/commands/doc-filters.d.ts.map +1 -1
- package/dist/src/commands/doc-filters.js +6 -0
- package/dist/src/commands/doc-filters.js.map +1 -1
- package/dist/src/commands/doc-library.d.ts +2 -1
- package/dist/src/commands/doc-library.d.ts.map +1 -1
- package/dist/src/commands/doc-library.js +66 -2
- package/dist/src/commands/doc-library.js.map +1 -1
- package/dist/src/commands/doc.d.ts.map +1 -1
- package/dist/src/commands/doc.js +2 -0
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/commands/ui.d.ts.map +1 -1
- package/dist/src/commands/ui.js +60 -0
- package/dist/src/commands/ui.js.map +1 -1
- package/dist/src/knowledge/capture-envelope.d.ts +5 -0
- package/dist/src/knowledge/capture-envelope.d.ts.map +1 -1
- package/dist/src/knowledge/capture-envelope.js +2 -0
- package/dist/src/knowledge/capture-envelope.js.map +1 -1
- package/dist/src/knowledge/document-chunking.d.ts +42 -0
- package/dist/src/knowledge/document-chunking.d.ts.map +1 -0
- package/dist/src/knowledge/document-chunking.js +288 -0
- package/dist/src/knowledge/document-chunking.js.map +1 -0
- package/dist/src/knowledge/document-index.d.ts +124 -0
- package/dist/src/knowledge/document-index.d.ts.map +1 -0
- package/dist/src/knowledge/document-index.js +314 -0
- package/dist/src/knowledge/document-index.js.map +1 -0
- package/dist/src/knowledge/document-ingest.d.ts +23 -0
- package/dist/src/knowledge/document-ingest.d.ts.map +1 -0
- package/dist/src/knowledge/document-ingest.js +368 -0
- package/dist/src/knowledge/document-ingest.js.map +1 -0
- package/dist/src/knowledge/document-pipeline.d.ts +26 -208
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +25 -1104
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/knowledge/document-search.d.ts +27 -0
- package/dist/src/knowledge/document-search.d.ts.map +1 -0
- package/dist/src/knowledge/document-search.js +138 -0
- package/dist/src/knowledge/document-search.js.map +1 -0
- package/dist/src/knowledge/document-store.d.ts +28 -0
- package/dist/src/knowledge/document-store.d.ts.map +1 -0
- package/dist/src/knowledge/document-store.js +61 -0
- package/dist/src/knowledge/document-store.js.map +1 -0
- package/dist/src/knowledge/document-types.d.ts +103 -0
- package/dist/src/knowledge/document-types.d.ts.map +1 -0
- package/dist/src/knowledge/document-types.js +12 -0
- package/dist/src/knowledge/document-types.js.map +1 -0
- package/dist/src/knowledge/highlights.d.ts +168 -0
- package/dist/src/knowledge/highlights.d.ts.map +1 -0
- package/dist/src/knowledge/highlights.js +311 -0
- package/dist/src/knowledge/highlights.js.map +1 -0
- package/dist/src/knowledge/lookup.d.ts +80 -0
- package/dist/src/knowledge/lookup.d.ts.map +1 -0
- package/dist/src/knowledge/lookup.js +156 -0
- package/dist/src/knowledge/lookup.js.map +1 -0
- package/dist/src/knowledge/okf-bundle.d.ts +19 -0
- package/dist/src/knowledge/okf-bundle.d.ts.map +1 -0
- package/dist/src/knowledge/okf-bundle.js +106 -0
- package/dist/src/knowledge/okf-bundle.js.map +1 -0
- package/dist/src/knowledge/profile-store.d.ts +134 -0
- package/dist/src/knowledge/profile-store.d.ts.map +1 -0
- package/dist/src/knowledge/profile-store.js +237 -0
- package/dist/src/knowledge/profile-store.js.map +1 -0
- package/dist/src/orgrt/agent-runner.d.ts +4 -0
- package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
- package/dist/src/orgrt/agent-runner.js +22 -0
- package/dist/src/orgrt/agent-runner.js.map +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
- package/dist/src/orgrt/antigravity-runner.js +2 -1
- package/dist/src/orgrt/antigravity-runner.js.map +1 -1
- package/dist/src/orgrt/authority-mask.d.ts +32 -0
- package/dist/src/orgrt/authority-mask.d.ts.map +1 -0
- package/dist/src/orgrt/authority-mask.js +135 -0
- package/dist/src/orgrt/authority-mask.js.map +1 -0
- package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
- package/dist/src/orgrt/codex-runner.js +2 -1
- package/dist/src/orgrt/codex-runner.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
- package/dist/src/orgrt/copilot-runner.js +2 -1
- package/dist/src/orgrt/copilot-runner.js.map +1 -1
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
- package/dist/src/orgrt/crush-runner.js +6 -1
- package/dist/src/orgrt/crush-runner.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +4 -0
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +13 -2
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +9 -0
- package/dist/src/orgrt/decisions.d.ts.map +1 -1
- package/dist/src/orgrt/decisions.js +32 -5
- package/dist/src/orgrt/decisions.js.map +1 -1
- package/dist/src/orgrt/file-roots.d.ts +2 -1
- package/dist/src/orgrt/file-roots.d.ts.map +1 -1
- package/dist/src/orgrt/file-roots.js +7 -3
- package/dist/src/orgrt/file-roots.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
- package/dist/src/orgrt/grok-runner.js +2 -1
- package/dist/src/orgrt/grok-runner.js.map +1 -1
- package/dist/src/orgrt/hermes-runner.d.ts.map +1 -1
- package/dist/src/orgrt/hermes-runner.js +2 -1
- package/dist/src/orgrt/hermes-runner.js.map +1 -1
- package/dist/src/orgrt/inbox.d.ts.map +1 -1
- package/dist/src/orgrt/inbox.js +70 -4
- package/dist/src/orgrt/inbox.js.map +1 -1
- package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +2 -1
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +3 -2
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.js +3 -2
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-runner.js +2 -1
- package/dist/src/orgrt/pi-runner.js.map +1 -1
- package/dist/src/orgrt/policy.d.ts.map +1 -1
- package/dist/src/orgrt/policy.js +3 -0
- package/dist/src/orgrt/policy.js.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.js +3 -2
- package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-runner.js +2 -1
- package/dist/src/orgrt/qwen-runner.js.map +1 -1
- package/dist/src/orgrt/role-sandbox.d.ts +21 -0
- package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
- package/dist/src/orgrt/role-sandbox.js +31 -6
- package/dist/src/orgrt/role-sandbox.js.map +1 -1
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +21 -2
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/task-dag.d.ts +3 -0
- package/dist/src/orgrt/task-dag.d.ts.map +1 -1
- package/dist/src/orgrt/task-dag.js +1 -0
- package/dist/src/orgrt/task-dag.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +5 -0
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +23 -1
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/ui/dashboard.html +28 -848
- package/dist/src/ui/human-auth.mjs +103 -0
- package/dist/src/ui/org-hil.mjs +86 -37
- package/dist/src/ui/org-runtime.mjs +21 -13
- package/dist/src/ui/routes-org.mjs +49 -445
- package/dist/src/ui/server.mjs +90 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -82,7 +82,7 @@ function checkColors(opts) {
|
|
|
82
82
|
if (hasDirectText && textColor && !isEmojiOnly) {
|
|
83
83
|
// Run background-dependent checks against either a solid bg or, if the
|
|
84
84
|
// ancestor is a gradient, against every gradient stop (use the worst case).
|
|
85
|
-
const bgs = effectiveBg ? [effectiveBg] : (effectiveBgStops
|
|
85
|
+
const bgs = effectiveBg ? [effectiveBg] : (effectiveBgStops?.length ? effectiveBgStops : null);
|
|
86
86
|
if (bgs) {
|
|
87
87
|
// Gray on colored background — flag if every stop is chromatic
|
|
88
88
|
const textLum = relativeLuminance(textColor);
|
|
@@ -263,7 +263,6 @@ function isAccentColor(cssColor) {
|
|
|
263
263
|
if (!cssColor) return false;
|
|
264
264
|
const s = String(cssColor).trim();
|
|
265
265
|
// rgb / rgba — direct channel-distance check.
|
|
266
|
-
const rgbM = /rgba?\(\s*(\d+)\s*,?\s+|\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(s.replace(/rgba?\(\s*/, 'rgb(').replace(/,/g, ', '));
|
|
267
266
|
const rgbStrict = /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(s);
|
|
268
267
|
if (rgbStrict) {
|
|
269
268
|
const r = +rgbStrict[1], g = +rgbStrict[2], b = +rgbStrict[3];
|
|
@@ -308,7 +307,7 @@ function isAccentColor(cssColor) {
|
|
|
308
307
|
// uppercase eyebrow OR the modern accent-colored bold eyebrow.
|
|
309
308
|
function checkHeroEyebrow(opts) {
|
|
310
309
|
const {
|
|
311
|
-
headingTag, headingText,
|
|
310
|
+
headingTag, headingText,
|
|
312
311
|
siblingTag, siblingText, siblingTextTransform,
|
|
313
312
|
siblingFontSize, siblingLetterSpacing,
|
|
314
313
|
siblingFontWeight, siblingColor,
|
|
@@ -779,7 +778,7 @@ function parseRadiusToPx(value, widthPx) {
|
|
|
779
778
|
return num;
|
|
780
779
|
}
|
|
781
780
|
|
|
782
|
-
function resolveBorderRadiusPx(
|
|
781
|
+
function resolveBorderRadiusPx(_el, style, widthPx, _win) {
|
|
783
782
|
const fromComputed = parseRadiusToPx(style.borderRadius, widthPx);
|
|
784
783
|
if (fromComputed !== null) return fromComputed;
|
|
785
784
|
return 0;
|
|
@@ -822,7 +821,7 @@ function checkElementColorsDOM(el) {
|
|
|
822
821
|
effectiveBg,
|
|
823
822
|
effectiveBgStops: effectiveBg ? null : resolveGradientStops(el),
|
|
824
823
|
fontSize: parseFloat(style.fontSize) || 16,
|
|
825
|
-
fontWeight: parseInt(style.fontWeight) || 400,
|
|
824
|
+
fontWeight: parseInt(style.fontWeight, 10) || 400,
|
|
826
825
|
hasDirectText,
|
|
827
826
|
isEmojiOnly: isEmojiOnlyText(directText),
|
|
828
827
|
bgClip: style.webkitBackgroundClip || style.backgroundClip || '',
|
|
@@ -930,7 +929,7 @@ function buildCustomPropMap(document) {
|
|
|
930
929
|
if (!style) continue;
|
|
931
930
|
for (let i = 0; i < style.length; i++) {
|
|
932
931
|
const prop = style[i];
|
|
933
|
-
if (!prop
|
|
932
|
+
if (!prop?.startsWith('--')) continue;
|
|
934
933
|
const val = style.getPropertyValue(prop).trim();
|
|
935
934
|
if (val) map.set(prop, val);
|
|
936
935
|
}
|
|
@@ -972,7 +971,7 @@ function oklchToRgb(L, C, H) {
|
|
|
972
971
|
const bLin = -0.0041960863 * lc - 0.7034186147 * mc + 1.7076147010 * sc;
|
|
973
972
|
const enc = (x) => {
|
|
974
973
|
const c = Math.max(0, Math.min(1, x));
|
|
975
|
-
return c <= 0.0031308 ? 12.92 * c : 1.055 *
|
|
974
|
+
return c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055;
|
|
976
975
|
};
|
|
977
976
|
return {
|
|
978
977
|
r: Math.round(enc(rLin) * 255),
|
|
@@ -1274,7 +1273,7 @@ function resolveFontSizePx(el, win) {
|
|
|
1274
1273
|
const v = chain[i];
|
|
1275
1274
|
if (!v || v === 'inherit') continue;
|
|
1276
1275
|
const num = parseFloat(v);
|
|
1277
|
-
if (isNaN(num)) continue;
|
|
1276
|
+
if (Number.isNaN(num)) continue;
|
|
1278
1277
|
if (v.endsWith('px')) px = num;
|
|
1279
1278
|
else if (v.endsWith('rem')) px = num * 16;
|
|
1280
1279
|
else if (v.endsWith('em')) px = num * px;
|
|
@@ -1289,7 +1288,7 @@ function resolveFontSizePx(el, win) {
|
|
|
1289
1288
|
function resolveLengthPx(value, fontSizePx) {
|
|
1290
1289
|
if (!value || value === 'normal' || value === 'auto' || value === 'inherit') return null;
|
|
1291
1290
|
const num = parseFloat(value);
|
|
1292
|
-
if (isNaN(num)) return null;
|
|
1291
|
+
if (Number.isNaN(num)) return null;
|
|
1293
1292
|
if (value.endsWith('px')) return num;
|
|
1294
1293
|
if (value.endsWith('rem')) return num * 16;
|
|
1295
1294
|
if (value.endsWith('em')) return num * fontSizePx;
|
|
@@ -1405,7 +1404,7 @@ function checkQuality(opts) {
|
|
|
1405
1404
|
// font-size — bigger text demands proportionally more padding.
|
|
1406
1405
|
// vertical: max(4px, fontSize × 0.3)
|
|
1407
1406
|
// horizontal: max(8px, fontSize × 0.5)
|
|
1408
|
-
const isInlineCode = tag === 'code' && !
|
|
1407
|
+
const isInlineCode = tag === 'code' && !el.closest?.('pre');
|
|
1409
1408
|
if (!isInlineCode && rect && hasDirectText && textLen > 20 && rect.width > 100 && rect.height > 30) {
|
|
1410
1409
|
const borders = {
|
|
1411
1410
|
top: parseFloat(style.borderTopWidth) || 0,
|
|
@@ -1521,7 +1520,7 @@ function checkQuality(opts) {
|
|
|
1521
1520
|
const CHILD_INSULATE_THRESHOLD = 4;
|
|
1522
1521
|
const childrenInsulate = { top: false, right: false, bottom: false, left: false };
|
|
1523
1522
|
for (const child of el.children) {
|
|
1524
|
-
|
|
1523
|
+
const childStyle = getComputedStyleFor(win, child);
|
|
1525
1524
|
if (!childStyle) continue;
|
|
1526
1525
|
const childPad = {
|
|
1527
1526
|
top: resolveLengthPx(childStyle.paddingTop, fontSize) ?? 0,
|
|
@@ -1653,7 +1652,7 @@ function checkQuality(opts) {
|
|
|
1653
1652
|
// Only flag actual body content, not UI labels (buttons, tabs, badges, captions, footer text, etc.)
|
|
1654
1653
|
if (hasDirectText && textLen > 20 && fontSize < 12) {
|
|
1655
1654
|
const skipTags = ['sub', 'sup', 'code', 'kbd', 'samp', 'var', 'caption', 'figcaption'];
|
|
1656
|
-
const inUIContext = el.closest
|
|
1655
|
+
const inUIContext = el.closest?.('button, a, label, summary, pre, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], nav, footer, [aria-hidden="true"], [class*="badge" i], [class*="caption" i], [class*="chip" i], [class*="code" i], [class*="console" i], [class*="diff" i], [class*="label" i], [class*="meta" i], [class*="mock" i], [class*="pill" i], [class*="preview" i], [class*="tag" i], [class*="terminal" i], [class*="writes" i]');
|
|
1657
1656
|
const isUppercase = style.textTransform === 'uppercase';
|
|
1658
1657
|
if (!skipTags.includes(tag) && !inUIContext && !isUppercase) {
|
|
1659
1658
|
findings.push({ id: 'tiny-text', snippet: `${fontSize}px body text` });
|
|
@@ -1718,7 +1717,7 @@ function checkPageQualityFromDoc(doc) {
|
|
|
1718
1717
|
let prevLevel = 0;
|
|
1719
1718
|
let prevText = '';
|
|
1720
1719
|
for (const h of headings) {
|
|
1721
|
-
const level = parseInt(h.tagName[1]);
|
|
1720
|
+
const level = parseInt(h.tagName[1], 10);
|
|
1722
1721
|
const text = (h.textContent || '').trim().replace(/\s+/g, ' ').slice(0, 60);
|
|
1723
1722
|
if (prevLevel > 0 && level > prevLevel + 1) {
|
|
1724
1723
|
findings.push({
|
|
@@ -1766,7 +1765,7 @@ function checkElementBorders(tag, style, overrides, resolvedRadius) {
|
|
|
1766
1765
|
if (widths[s] === 0 && overrides && overrides[s]) {
|
|
1767
1766
|
widths[s] = overrides[s].width;
|
|
1768
1767
|
colors[s] = overrides[s].color;
|
|
1769
|
-
} else if (colors[s]
|
|
1768
|
+
} else if (colors[s]?.startsWith('var(') && overrides?.[s]) {
|
|
1770
1769
|
// Longhand case: jsdom kept the width but left the color as the
|
|
1771
1770
|
// literal `var(...)` string. Substitute the resolved color.
|
|
1772
1771
|
colors[s] = overrides[s].color;
|
|
@@ -1827,7 +1826,7 @@ function checkElementColors(el, style, tag, window, customPropMap, hasAnchorInhe
|
|
|
1827
1826
|
effectiveBg,
|
|
1828
1827
|
effectiveBgStops: effectiveBg ? null : resolveGradientStops(el, window),
|
|
1829
1828
|
fontSize: parseFloat(style.fontSize) || 16,
|
|
1830
|
-
fontWeight: parseInt(style.fontWeight) || 400,
|
|
1829
|
+
fontWeight: parseInt(style.fontWeight, 10) || 400,
|
|
1831
1830
|
hasDirectText,
|
|
1832
1831
|
isEmojiOnly: isEmojiOnlyText(directText),
|
|
1833
1832
|
bgClip: style.webkitBackgroundClip || style.backgroundClip || '',
|
|
@@ -1954,7 +1953,7 @@ function checkTypography() {
|
|
|
1954
1953
|
let totalTextElements = 0;
|
|
1955
1954
|
for (const el of document.querySelectorAll('p, h1, h2, h3, h4, h5, h6, li, td, th, dd, blockquote, figcaption, a, button, label, span')) {
|
|
1956
1955
|
// Skip monodesign's own elements
|
|
1957
|
-
if (el.closest
|
|
1956
|
+
if (el.closest?.('.monodesign-overlay, .monodesign-label, .monodesign-banner, .monodesign-tooltip')) continue;
|
|
1958
1957
|
// Only count elements that actually have visible direct text
|
|
1959
1958
|
const hasText = [...el.childNodes].some(n => n.nodeType === 3 && n.textContent.trim().length > 0);
|
|
1960
1959
|
if (!hasText) continue;
|
|
@@ -1995,7 +1994,7 @@ function checkTypography() {
|
|
|
1995
1994
|
const sorted = [...sizes].sort((a, b) => a - b);
|
|
1996
1995
|
const ratio = sorted[sorted.length - 1] / sorted[0];
|
|
1997
1996
|
if (ratio < 2.0) {
|
|
1998
|
-
findings.push({ type: 'flat-type-hierarchy', detail: `Sizes: ${sorted.map(s => s
|
|
1997
|
+
findings.push({ type: 'flat-type-hierarchy', detail: `Sizes: ${sorted.map(s => `${s}px`).join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
|
|
1999
1998
|
}
|
|
2000
1999
|
}
|
|
2001
2000
|
|
|
@@ -2114,7 +2113,7 @@ function checkPageTypography(doc, win) {
|
|
|
2114
2113
|
const sorted = [...sizes].sort((a, b) => a - b);
|
|
2115
2114
|
const ratio = sorted[sorted.length - 1] / sorted[0];
|
|
2116
2115
|
if (ratio < 2.0) {
|
|
2117
|
-
findings.push({ id: 'flat-type-hierarchy', snippet: `Sizes: ${sorted.map(s => s
|
|
2116
|
+
findings.push({ id: 'flat-type-hierarchy', snippet: `Sizes: ${sorted.map(s => `${s}px`).join(', ')} (ratio ${ratio.toFixed(1)}:1)` });
|
|
2118
2117
|
}
|
|
2119
2118
|
}
|
|
2120
2119
|
|
|
@@ -2246,7 +2245,7 @@ function checkCreamPalette(doc, win) {
|
|
|
2246
2245
|
// 2. Tailwind class fallback — for the static path, where utility classes
|
|
2247
2246
|
// never resolve to computed CSS.
|
|
2248
2247
|
for (const el of [body, html]) {
|
|
2249
|
-
const tok = creamFromClassList(el
|
|
2248
|
+
const tok = creamFromClassList(el?.getAttribute ? el.getAttribute('class') : '');
|
|
2250
2249
|
if (tok) {
|
|
2251
2250
|
findings.push({ id: 'cream-palette', snippet: `cream/beige page background (Tailwind ${tok})` });
|
|
2252
2251
|
break;
|
|
@@ -2282,7 +2281,7 @@ function checkOversizedH1({ tag, fontSize, headingText, rect = null, viewportWid
|
|
|
2282
2281
|
return [];
|
|
2283
2282
|
}
|
|
2284
2283
|
|
|
2285
|
-
function checkElementOversizedH1(el,
|
|
2284
|
+
function checkElementOversizedH1(el, _style, tag, window) {
|
|
2286
2285
|
if (tag !== 'h1') return [];
|
|
2287
2286
|
const fontSize = resolveFontSizePx(el, window);
|
|
2288
2287
|
const headingText = (el.textContent || '').trim().replace(/\s+/g, ' ');
|
|
@@ -2366,7 +2365,7 @@ function borderColorsFromStyle(style) {
|
|
|
2366
2365
|
];
|
|
2367
2366
|
}
|
|
2368
2367
|
|
|
2369
|
-
function checkElementGptBorderShadow(
|
|
2368
|
+
function checkElementGptBorderShadow(_el, style) {
|
|
2370
2369
|
return checkGptThinBorderWideShadow({ borderWidths: borderWidthsFromStyle(style), borderColors: borderColorsFromStyle(style), boxShadow: style.boxShadow || '' });
|
|
2371
2370
|
}
|
|
2372
2371
|
|
|
@@ -2516,7 +2515,7 @@ function checkClippedOverflow(el, style, getStyle) {
|
|
|
2516
2515
|
return [];
|
|
2517
2516
|
}
|
|
2518
2517
|
|
|
2519
|
-
function checkElementClippedOverflow(el, style,
|
|
2518
|
+
function checkElementClippedOverflow(el, style, _tag, window) {
|
|
2520
2519
|
return checkClippedOverflow(el, style, (n) => window.getComputedStyle(n));
|
|
2521
2520
|
}
|
|
2522
2521
|
|
|
@@ -2862,7 +2861,7 @@ function checkElementImageDimensions(el, style) {
|
|
|
2862
2861
|
const parts = [el.getAttribute?.('style') || el.attribs?.style || ''];
|
|
2863
2862
|
const ar = style && (style.aspectRatio || style['aspect-ratio']);
|
|
2864
2863
|
if (ar && ar !== 'auto') parts.push(`aspect-ratio:${ar}`);
|
|
2865
|
-
const h = style
|
|
2864
|
+
const h = style?.height;
|
|
2866
2865
|
if (h && h !== 'auto' && h !== '') parts.push(`height:${h}`);
|
|
2867
2866
|
return checkImageDimensions({ hasWidthAttr, hasHeightAttr, style: parts.join(';') });
|
|
2868
2867
|
}
|
|
@@ -2922,7 +2921,7 @@ function checkElementSmallTouchTarget(el, style, tag) {
|
|
|
2922
2921
|
// (button-like). jsdom returns '' for the default inline display, so key
|
|
2923
2922
|
// off "not blockish" rather than "== inline".
|
|
2924
2923
|
const isBlockish = /^(block|flex|grid|inline-block|inline-flex|table)/.test(style.display || '');
|
|
2925
|
-
const inProse = !!
|
|
2924
|
+
const inProse = !!el.closest?.(PROSE_ANCESTOR_SELECTOR);
|
|
2926
2925
|
const isInlineLinkInProse = tag === 'a' && !isBlockish && inProse;
|
|
2927
2926
|
return checkSmallTouchTarget({ tag, role, href, inputType, widthPx, heightPx, isInlineLinkInProse });
|
|
2928
2927
|
}
|
|
@@ -2936,7 +2935,7 @@ function checkElementSmallTouchTargetDOM(el) {
|
|
|
2936
2935
|
const inputType = el.getAttribute('type') || '';
|
|
2937
2936
|
const style = getComputedStyle(el);
|
|
2938
2937
|
const isBlockish = /^(block|flex|grid|inline-block|inline-flex|table)/.test(style.display || '');
|
|
2939
|
-
const inProse = !!
|
|
2938
|
+
const inProse = !!el.closest?.(PROSE_ANCESTOR_SELECTOR);
|
|
2940
2939
|
const isInlineLinkInProse = tag === 'a' && !isBlockish && inProse;
|
|
2941
2940
|
return checkSmallTouchTarget({ tag, role, href, inputType, widthPx: rect.width, heightPx: rect.height, isInlineLinkInProse });
|
|
2942
2941
|
}
|
|
@@ -72,7 +72,7 @@ function contrastRatio(c1, c2) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function parseGradientColors(bgImage) {
|
|
75
|
-
if (!bgImage
|
|
75
|
+
if (!bgImage?.includes('gradient')) return [];
|
|
76
76
|
const colors = [];
|
|
77
77
|
for (const m of bgImage.matchAll(/rgba?\([^)]+\)/g)) {
|
|
78
78
|
const c = parseRgb(m[0]);
|
|
@@ -109,7 +109,7 @@ function getHue(c) {
|
|
|
109
109
|
|
|
110
110
|
function colorToHex(c) {
|
|
111
111
|
if (!c) return '?';
|
|
112
|
-
return
|
|
112
|
+
return `#${[c.r, c.g, c.b].map(v => v.toString(16).padStart(2, '0')).join('')}`;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
export {
|
|
@@ -53,7 +53,7 @@ function isBrandFontOnOwnDomain(font) {
|
|
|
53
53
|
const allowed = BRAND_FONT_DOMAINS[font];
|
|
54
54
|
if (!allowed) return false;
|
|
55
55
|
const host = location.hostname.toLowerCase();
|
|
56
|
-
return allowed.some(suffix => host === suffix || host.endsWith(
|
|
56
|
+
return allowed.some(suffix => host === suffix || host.endsWith(`.${suffix}`));
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
const GENERIC_FONTS = new Set([
|
|
@@ -117,10 +117,10 @@ function setMatches(set, rule) {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
function isInlineIgnored(finding, directives) {
|
|
120
|
-
const rule = normalizeRule(finding
|
|
120
|
+
const rule = normalizeRule(finding?.antipattern);
|
|
121
121
|
if (!rule) return false;
|
|
122
122
|
if (setMatches(directives.file, rule)) return true;
|
|
123
|
-
const line = Number(finding
|
|
123
|
+
const line = Number(finding?.line) || 0;
|
|
124
124
|
if (line > 0) {
|
|
125
125
|
if (setMatches(directives.line.get(line), rule)) return true;
|
|
126
126
|
if (setMatches(directives.nextLine.get(line), rule)) return true;
|
|
@@ -184,7 +184,7 @@ function writeHookConfig(cwd, hookConfig, opts = {}) {
|
|
|
184
184
|
// (consent, quiet, auditLog) survive an Monodesign hooks edit.
|
|
185
185
|
const next = { ...existing, hook: { ...existingHook, ...hookConfig } };
|
|
186
186
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
187
|
-
fs.writeFileSync(filePath, JSON.stringify(next, null, 2)
|
|
187
|
+
fs.writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
188
188
|
return filePath;
|
|
189
189
|
}
|
|
190
190
|
|
|
@@ -202,14 +202,14 @@ function writeDetectorConfig(cwd, detectorConfig, opts = {}) {
|
|
|
202
202
|
if (Object.keys(nextHook).length > 0) next.hook = nextHook;
|
|
203
203
|
else delete next.hook;
|
|
204
204
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
205
|
-
fs.writeFileSync(filePath, JSON.stringify(next, null, 2)
|
|
205
|
+
fs.writeFileSync(filePath, `${JSON.stringify(next, null, 2)}\n`);
|
|
206
206
|
return filePath;
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
function mergeHookConfig(existing) {
|
|
210
210
|
const base = existing && typeof existing === 'object' ? existing : {};
|
|
211
211
|
return {
|
|
212
|
-
enabled: base.enabled
|
|
212
|
+
enabled: base.enabled !== false,
|
|
213
213
|
limits: {
|
|
214
214
|
maxFindings: Number.isFinite(base?.limits?.maxFindings) ? base.limits.maxFindings : DEFAULT_CONFIG.limits.maxFindings,
|
|
215
215
|
maxChars: Number.isFinite(base?.limits?.maxChars) ? base.limits.maxChars : DEFAULT_CONFIG.limits.maxChars,
|
|
@@ -234,7 +234,7 @@ function mergeDetectorConfig(existing, seed = null) {
|
|
|
234
234
|
if (base.designSystem && typeof base.designSystem === 'object' && !Array.isArray(base.designSystem)) {
|
|
235
235
|
out.designSystem = {
|
|
236
236
|
...(out.designSystem || {}),
|
|
237
|
-
enabled: base.designSystem.enabled
|
|
237
|
+
enabled: base.designSystem.enabled !== false,
|
|
238
238
|
};
|
|
239
239
|
}
|
|
240
240
|
if (Array.isArray(base.ignoreRules)) {
|
|
@@ -644,7 +644,7 @@ function reset(cwd) {
|
|
|
644
644
|
if (Object.keys(rest).length === 0) {
|
|
645
645
|
fs.unlinkSync(filePath);
|
|
646
646
|
} else {
|
|
647
|
-
fs.writeFileSync(filePath, JSON.stringify(rest, null, 2)
|
|
647
|
+
fs.writeFileSync(filePath, `${JSON.stringify(rest, null, 2)}\n`);
|
|
648
648
|
}
|
|
649
649
|
removed.push(path.relative(cwd, filePath).split(path.sep).join('/') || filePath);
|
|
650
650
|
} catch { /* ignore */ }
|
|
@@ -684,7 +684,7 @@ function main() {
|
|
|
684
684
|
case 'ignore-value': out = addIgnoreValue(cwd, rest); break;
|
|
685
685
|
case 'reset': out = reset(cwd); break;
|
|
686
686
|
}
|
|
687
|
-
process.stdout.write(out
|
|
687
|
+
process.stdout.write(`${out}\n`);
|
|
688
688
|
} catch (err) {
|
|
689
689
|
process.stderr.write(`Error: ${err.message || err}\n`);
|
|
690
690
|
process.exit(1);
|
|
@@ -17,11 +17,11 @@ import path from 'node:path';
|
|
|
17
17
|
import {
|
|
18
18
|
ALLOWED_EXTS,
|
|
19
19
|
EDIT_COUNT_THRESHOLD,
|
|
20
|
-
GENERATED_PATH,
|
|
21
20
|
SENSITIVE_PATH,
|
|
22
21
|
appendDesignSystemNote,
|
|
23
22
|
designSystemOptions,
|
|
24
23
|
filterFindings,
|
|
24
|
+
isGeneratedPath,
|
|
25
25
|
isNativePlatform,
|
|
26
26
|
loadDetector,
|
|
27
27
|
matchConfiguredExtension,
|
|
@@ -162,7 +162,7 @@ function replaceOnce(original, oldString, newString) {
|
|
|
162
162
|
|
|
163
163
|
function readExistingProjectFile(filePath, cwd) {
|
|
164
164
|
if (!isInsideProject(filePath, cwd)) return null;
|
|
165
|
-
if (SENSITIVE_PATH.test(filePath) ||
|
|
165
|
+
if (SENSITIVE_PATH.test(filePath) || isGeneratedPath(filePath, cwd)) return null;
|
|
166
166
|
try {
|
|
167
167
|
const stat = fs.statSync(filePath);
|
|
168
168
|
if (!stat.isFile() || stat.size > 1024 * 1024) return null;
|
|
@@ -233,7 +233,7 @@ function shellCopiedFileContent(command, cwd) {
|
|
|
233
233
|
if (!source) return '';
|
|
234
234
|
const sourcePath = path.isAbsolute(source) ? source : path.resolve(cwd, source);
|
|
235
235
|
if (!isInsideProject(sourcePath, cwd)) return '';
|
|
236
|
-
if (SENSITIVE_PATH.test(sourcePath) ||
|
|
236
|
+
if (SENSITIVE_PATH.test(sourcePath) || isGeneratedPath(sourcePath, cwd)) return '';
|
|
237
237
|
try {
|
|
238
238
|
const stat = fs.statSync(sourcePath);
|
|
239
239
|
if (!stat.isFile() || stat.size > 1024 * 1024) return '';
|
|
@@ -416,7 +416,7 @@ async function main() {
|
|
|
416
416
|
if (!filePath) return allow({ ...audit, skipped: 'no-file-path', durationMs: Date.now() - started });
|
|
417
417
|
if (!isInsideProject(filePath, cwd)) return allow({ ...audit, skipped: 'outside-project', durationMs: Date.now() - started });
|
|
418
418
|
if (SENSITIVE_PATH.test(filePath)) return allow({ ...audit, skipped: 'sensitive', durationMs: Date.now() - started });
|
|
419
|
-
if (
|
|
419
|
+
if (isGeneratedPath(filePath, cwd)) return allow({ ...audit, skipped: 'generated', durationMs: Date.now() - started });
|
|
420
420
|
|
|
421
421
|
// Config is read before the extension gate so `detector.extensions` entries
|
|
422
422
|
// (e.g. `.blade.php` template files, issue #316) can widen it.
|
|
@@ -73,6 +73,15 @@ export const SENSITIVE_PATH = new RegExp([
|
|
|
73
73
|
// Hard-skip regex for generated, lock, minified, and build-output paths.
|
|
74
74
|
export const GENERATED_PATH = /(?:\.generated\.[a-z]+$|\.d\.ts$|\.min\.[a-z]+$|[/\\]node_modules[/\\]|[/\\](?:dist|build|out|\.next|\.cache|coverage)[/\\]|[/\\]?[^/\\]+\.lock(?:\.json)?$)/i;
|
|
75
75
|
|
|
76
|
+
// GENERATED_PATH checked against the path inside the project, so a project
|
|
77
|
+
// that lives under e.g. ~/.cache/ or /srv/build/ is still scanned. Paths
|
|
78
|
+
// outside the project root fall back to the absolute path.
|
|
79
|
+
export function isGeneratedPath(filePath, projectRoot) {
|
|
80
|
+
const rel = path.relative(path.resolve(projectRoot), path.resolve(filePath));
|
|
81
|
+
const inside = rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
|
|
82
|
+
return GENERATED_PATH.test(inside ? path.sep + rel : filePath);
|
|
83
|
+
}
|
|
84
|
+
|
|
76
85
|
export const TRUTHY = /^(1|true|yes|on)$/i;
|
|
77
86
|
|
|
78
87
|
export const DEFAULT_CONFIG = Object.freeze({
|
|
@@ -184,7 +193,7 @@ export function resolveCacheCwd(primaryFile, sessionCwd) {
|
|
|
184
193
|
export function resolveProjectPlatform(cwd) {
|
|
185
194
|
try {
|
|
186
195
|
const ctx = loadContext(cwd);
|
|
187
|
-
return extractPlatform(ctx
|
|
196
|
+
return extractPlatform(ctx?.product);
|
|
188
197
|
} catch {
|
|
189
198
|
return null;
|
|
190
199
|
}
|
|
@@ -239,7 +248,7 @@ function applyDetectorConfigSource(config, raw) {
|
|
|
239
248
|
if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
|
|
240
249
|
config.designSystem = {
|
|
241
250
|
...config.designSystem,
|
|
242
|
-
enabled: raw.designSystem.enabled
|
|
251
|
+
enabled: raw.designSystem.enabled !== false,
|
|
243
252
|
};
|
|
244
253
|
}
|
|
245
254
|
if (Array.isArray(raw.ignoreRules)) {
|
|
@@ -302,10 +311,10 @@ export function matchConfiguredExtension(filePath, extensions) {
|
|
|
302
311
|
|
|
303
312
|
function applyConfigSource(config, raw) {
|
|
304
313
|
if (!raw || typeof raw !== 'object') return config;
|
|
305
|
-
if (Object.
|
|
306
|
-
config.enabled = raw.enabled
|
|
314
|
+
if (Object.hasOwn(raw, 'enabled')) {
|
|
315
|
+
config.enabled = raw.enabled !== false;
|
|
307
316
|
}
|
|
308
|
-
if (Object.
|
|
317
|
+
if (Object.hasOwn(raw, 'quiet')) {
|
|
309
318
|
config.quiet = raw.quiet === true;
|
|
310
319
|
}
|
|
311
320
|
if (typeof raw.auditLog === 'string' && raw.auditLog.trim()) {
|
|
@@ -399,7 +408,7 @@ function splitColorArgs(body) {
|
|
|
399
408
|
if (text.includes(',')) {
|
|
400
409
|
const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
|
|
401
410
|
const last = parts[parts.length - 1];
|
|
402
|
-
if (last
|
|
411
|
+
if (last?.includes('/')) {
|
|
403
412
|
const split = last.split('/').map((part) => part.trim()).filter(Boolean);
|
|
404
413
|
return [...parts.slice(0, -1), ...split];
|
|
405
414
|
}
|
|
@@ -944,7 +953,7 @@ function clampGroupedToBudget(header, lines, footer, maxChars) {
|
|
|
944
953
|
footer,
|
|
945
954
|
].join('\n');
|
|
946
955
|
|
|
947
|
-
|
|
956
|
+
const working = lines.slice();
|
|
948
957
|
let omitted = false;
|
|
949
958
|
let assembled = assemble(working, omitted);
|
|
950
959
|
while (assembled.length > maxChars && working.length > 1) {
|
|
@@ -967,7 +976,7 @@ function clampToBudget(header, lines, more, footer, maxChars) {
|
|
|
967
976
|
return blocks.join('\n');
|
|
968
977
|
};
|
|
969
978
|
|
|
970
|
-
|
|
979
|
+
const working = lines.slice();
|
|
971
980
|
let moreText = more;
|
|
972
981
|
let assembled = assemble(working, moreText);
|
|
973
982
|
while (assembled.length > maxChars && working.length > 1) {
|
|
@@ -1351,7 +1360,7 @@ export function writeAuditLog(env, entry, cwd = process.cwd()) {
|
|
|
1351
1360
|
expanded = path.resolve(baseCwd, target);
|
|
1352
1361
|
}
|
|
1353
1362
|
fs.mkdirSync(path.dirname(expanded), { recursive: true });
|
|
1354
|
-
const line = JSON.stringify({ ts: new Date().toISOString(), ...entry })
|
|
1363
|
+
const line = `${JSON.stringify({ ts: new Date().toISOString(), ...entry })}\n`;
|
|
1355
1364
|
fs.appendFileSync(expanded, line);
|
|
1356
1365
|
return true;
|
|
1357
1366
|
} catch {
|
|
@@ -1573,7 +1582,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
|
|
|
1573
1582
|
lastSkip = 'sensitive';
|
|
1574
1583
|
continue;
|
|
1575
1584
|
}
|
|
1576
|
-
if (
|
|
1585
|
+
if (isGeneratedPath(filePath, projectCwd)) {
|
|
1577
1586
|
lastSkip = 'generated';
|
|
1578
1587
|
continue;
|
|
1579
1588
|
}
|
|
@@ -1756,7 +1765,7 @@ export async function runHook({ stdinJson, env = {}, cwd = process.cwd(), now =
|
|
|
1756
1765
|
return {
|
|
1757
1766
|
exitCode: 0,
|
|
1758
1767
|
stdout: '',
|
|
1759
|
-
audit: { ...audit, error: String(err
|
|
1768
|
+
audit: { ...audit, error: String(err?.message ? err.message : err) },
|
|
1760
1769
|
};
|
|
1761
1770
|
}
|
|
1762
1771
|
}
|
|
@@ -51,7 +51,7 @@ main().catch((err) => {
|
|
|
51
51
|
writeAuditLog(process.env, {
|
|
52
52
|
ts: new Date().toISOString(),
|
|
53
53
|
event: 'PostToolUse',
|
|
54
|
-
error: String(err
|
|
54
|
+
error: String(err?.message ? err.message : err),
|
|
55
55
|
});
|
|
56
56
|
} catch { /* swallow */ }
|
|
57
57
|
if (process.env.MONODESIGN_HOOK_DEBUG) {
|
|
@@ -130,9 +130,6 @@ function parseScalar(raw) {
|
|
|
130
130
|
|
|
131
131
|
const HEX_RE = /#[0-9a-fA-F]{3,8}\b/g;
|
|
132
132
|
const OKLCH_RE = /oklch\([^)]+\)/gi;
|
|
133
|
-
const RGBA_RE = /rgba?\([^)]+\)/gi;
|
|
134
|
-
const BOX_SHADOW_RE = /(?:box-shadow:\s*)?((?:-?\d[\w\d\s\-.,/()#%]*)+)/;
|
|
135
|
-
const NAMED_RULE_RE = /\*\*(The [^*]+?Rule)\.\*\*\s*(.+)/;
|
|
136
133
|
|
|
137
134
|
// ---------- Section splitting ----------
|
|
138
135
|
|
|
@@ -246,7 +243,7 @@ function collectBullets(lines) {
|
|
|
246
243
|
}
|
|
247
244
|
// continuation of a bullet (indented line)
|
|
248
245
|
if (current && raw.match(/^\s{2,}\S/)) {
|
|
249
|
-
current +=
|
|
246
|
+
current += ` ${raw.trim()}`;
|
|
250
247
|
continue;
|
|
251
248
|
}
|
|
252
249
|
// blank line ends a bullet
|
|
@@ -415,7 +412,7 @@ function parseColorBullet(bullet) {
|
|
|
415
412
|
|
|
416
413
|
// Case 1 (Monodesign): **Name** (value-with-maybe-nested-parens): description
|
|
417
414
|
const bold = text.match(/^\*\*(.+?)\*\*\s*(.*)$/);
|
|
418
|
-
if (bold
|
|
415
|
+
if (bold?.[2].startsWith('(')) {
|
|
419
416
|
const value = extractParenGroup(bold[2]);
|
|
420
417
|
if (value !== null) {
|
|
421
418
|
const after = bold[2].slice(value.length + 2).trimStart();
|
|
@@ -485,36 +482,6 @@ function detectFormat(v) {
|
|
|
485
482
|
return 'unknown';
|
|
486
483
|
}
|
|
487
484
|
|
|
488
|
-
function scanInlineColors(lines) {
|
|
489
|
-
const out = [];
|
|
490
|
-
for (const line of lines) {
|
|
491
|
-
if (!/^\s*[-*]\s/.test(line)) continue;
|
|
492
|
-
const trimmed = line.replace(/^\s*[-*]\s+/, '');
|
|
493
|
-
const color = parseColorBullet(trimmed);
|
|
494
|
-
if (color) out.push(color);
|
|
495
|
-
}
|
|
496
|
-
return out;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
function parseStitchInlineGroups(lines) {
|
|
500
|
-
// Stitch writes: `* **Primary (`#00478d` to `#005eb8`):** Use for "..."`
|
|
501
|
-
// Each bullet IS its own role. Group them under the spoken role name.
|
|
502
|
-
const out = [];
|
|
503
|
-
for (const line of lines) {
|
|
504
|
-
if (!/^\s*[-*]\s/.test(line)) continue;
|
|
505
|
-
const trimmed = line.replace(/^\s*[-*]\s+/, '').trim();
|
|
506
|
-
const m = trimmed.match(
|
|
507
|
-
/^\*\*([A-Z][a-zA-Z]+)\s*\(([^)]+)\):\*\*\s*(.*)$/
|
|
508
|
-
);
|
|
509
|
-
if (m) {
|
|
510
|
-
const role = m[1];
|
|
511
|
-
const color = buildColor(role, m[2], m[3]);
|
|
512
|
-
out.push({ role, colors: [color] });
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return out;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
485
|
function extractTypography(section) {
|
|
519
486
|
if (!section) return null;
|
|
520
487
|
const text = section.lines.join('\n');
|
|
@@ -611,7 +578,7 @@ function extractElevation(section) {
|
|
|
611
578
|
const shadows = [];
|
|
612
579
|
const seen = new Set();
|
|
613
580
|
const dedupe = (entry) => {
|
|
614
|
-
const key =
|
|
581
|
+
const key = `${entry.name || ''}::${entry.value}`;
|
|
615
582
|
if (seen.has(key)) return;
|
|
616
583
|
seen.add(key);
|
|
617
584
|
shadows.push(entry);
|
|
@@ -660,7 +627,7 @@ function extractInlineShadows(text) {
|
|
|
660
627
|
.trim();
|
|
661
628
|
if (stripped) {
|
|
662
629
|
name =
|
|
663
|
-
stripped.charAt(0).toUpperCase() + stripped.slice(1)
|
|
630
|
+
`${stripped.charAt(0).toUpperCase() + stripped.slice(1)} shadow`;
|
|
664
631
|
}
|
|
665
632
|
}
|
|
666
633
|
out.push({
|
|
@@ -830,11 +797,11 @@ export function parseDesignMd(md) {
|
|
|
830
797
|
schemaVersion: 2,
|
|
831
798
|
title,
|
|
832
799
|
frontmatter,
|
|
833
|
-
overview: extractOverview(sections
|
|
834
|
-
colors: extractColors(sections
|
|
835
|
-
typography: extractTypography(sections
|
|
836
|
-
elevation: extractElevation(sections
|
|
837
|
-
components: extractComponents(sections
|
|
800
|
+
overview: extractOverview(sections.Overview),
|
|
801
|
+
colors: extractColors(sections.Colors),
|
|
802
|
+
typography: extractTypography(sections.Typography),
|
|
803
|
+
elevation: extractElevation(sections.Elevation),
|
|
804
|
+
components: extractComponents(sections.Components),
|
|
838
805
|
dosDonts: extractDosDonts(sections["Do's and Don'ts"]),
|
|
839
806
|
};
|
|
840
807
|
}
|
|
@@ -46,7 +46,7 @@ function isGitIgnored(absPath, cwd) {
|
|
|
46
46
|
stdio: 'ignore',
|
|
47
47
|
});
|
|
48
48
|
return true; // exit 0 = ignored
|
|
49
|
-
} catch
|
|
49
|
+
} catch {
|
|
50
50
|
// Exit code 1 = not ignored. Exit code 128 = not a git repo or other error.
|
|
51
51
|
// In both cases, treat as "not known to be ignored."
|
|
52
52
|
return false;
|
|
@@ -36,11 +36,11 @@ function safeReadJson(filePath) {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
function hookSection(raw) {
|
|
39
|
-
return raw
|
|
39
|
+
return raw?.hook && typeof raw.hook === 'object' && !Array.isArray(raw.hook) ? raw.hook : null;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function detectorSection(raw) {
|
|
43
|
-
return raw
|
|
43
|
+
return raw?.detector && typeof raw.detector === 'object' && !Array.isArray(raw.detector) ? raw.detector : null;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
const DETECTOR_CONFIG_KEYS = new Set(['ignoreRules', 'ignoreFiles', 'ignoreValues', 'designSystem']);
|
|
@@ -74,7 +74,7 @@ function applyDetectionConfigSource(config, raw) {
|
|
|
74
74
|
if (raw.designSystem && typeof raw.designSystem === 'object' && !Array.isArray(raw.designSystem)) {
|
|
75
75
|
config.designSystem = {
|
|
76
76
|
...config.designSystem,
|
|
77
|
-
enabled: raw.designSystem.enabled
|
|
77
|
+
enabled: raw.designSystem.enabled !== false,
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
80
|
if (Array.isArray(raw.ignoreRules)) {
|
|
@@ -153,7 +153,7 @@ function normalizeDetectionConfigForWrite(config) {
|
|
|
153
153
|
out.ignoreValues = normalizeIgnoreValueEntries(config?.ignoreValues || []);
|
|
154
154
|
if (config?.designSystem && typeof config.designSystem === 'object' && !Array.isArray(config.designSystem)) {
|
|
155
155
|
out.designSystem = {
|
|
156
|
-
enabled: config.designSystem.enabled
|
|
156
|
+
enabled: config.designSystem.enabled !== false,
|
|
157
157
|
};
|
|
158
158
|
}
|
|
159
159
|
return out;
|
|
@@ -242,7 +242,7 @@ function splitColorArgs(body) {
|
|
|
242
242
|
if (text.includes(',')) {
|
|
243
243
|
const parts = text.split(',').map((part) => part.trim()).filter(Boolean);
|
|
244
244
|
const last = parts[parts.length - 1];
|
|
245
|
-
if (last
|
|
245
|
+
if (last?.includes('/')) {
|
|
246
246
|
const split = last.split('/').map((part) => part.trim()).filter(Boolean);
|
|
247
247
|
return [...parts.slice(0, -1), ...split];
|
|
248
248
|
}
|
|
@@ -43,7 +43,7 @@ export function getLegacyLiveConfigPath(scriptsDir) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function resolveLiveConfigPath({ cwd = process.cwd(), scriptsDir, env = process.env, targetPath } = {}) {
|
|
46
|
-
if (env.MONODESIGN_LIVE_CONFIG
|
|
46
|
+
if (env.MONODESIGN_LIVE_CONFIG?.trim()) {
|
|
47
47
|
const configured = env.MONODESIGN_LIVE_CONFIG.trim();
|
|
48
48
|
return path.isAbsolute(configured) ? configured : path.resolve(cwd, configured);
|
|
49
49
|
}
|