@monoes/monodesign 1.2.20 → 1.2.23

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.
Files changed (95) hide show
  1. package/README.md +2 -2
  2. package/cli/engine/cli/main.mjs +21 -1
  3. package/cli/engine/design-system-checks.mjs +381 -0
  4. package/cli/engine/design-system-parse.mjs +433 -0
  5. package/cli/engine/design-system.mjs +20 -736
  6. package/cli/engine/detect-antipatterns-browser.js +28 -5
  7. package/cli/engine/detect-antipatterns.mjs +1 -0
  8. package/cli/engine/engines/regex/detect-text-matchers.mjs +371 -0
  9. package/cli/engine/engines/regex/detect-text-run.mjs +186 -0
  10. package/cli/engine/engines/regex/detect-text.mjs +11 -523
  11. package/cli/engine/engines/static-html/css-cascade-color.mjs +219 -0
  12. package/cli/engine/engines/static-html/css-cascade-static-data.mjs +138 -0
  13. package/cli/engine/engines/static-html/css-cascade-static-dom.mjs +132 -0
  14. package/cli/engine/engines/static-html/css-cascade-static-parse.mjs +393 -0
  15. package/cli/engine/engines/static-html/css-cascade.mjs +24 -837
  16. package/cli/engine/engines/static-html/detect-html.mjs +6 -1
  17. package/cli/engine/findings-group.mjs +94 -0
  18. package/cli/engine/fix/index.mjs +1 -26
  19. package/cli/engine/fix/unified-diff.mjs +107 -0
  20. package/cli/engine/rules/checks-background.mjs +17 -3
  21. package/cli/engine/rules/checks-element.mjs +2 -0
  22. package/cli/engine/rules/checks-pure.mjs +9 -2
  23. package/cli/lib/monodesign-config-consent.mjs +93 -0
  24. package/cli/lib/monodesign-config-core.mjs +37 -0
  25. package/cli/lib/monodesign-config-detection.mjs +133 -0
  26. package/cli/lib/monodesign-config-filter.mjs +198 -0
  27. package/cli/lib/monodesign-config-ignore-value.mjs +212 -0
  28. package/cli/lib/monodesign-config.mjs +21 -623
  29. package/package.json +2 -2
  30. package/skill/scripts/context-fields.mjs +65 -0
  31. package/skill/scripts/context-resolve.mjs +425 -0
  32. package/skill/scripts/context-update.mjs +151 -0
  33. package/skill/scripts/context-utils.mjs +68 -0
  34. package/skill/scripts/context-workspace.mjs +245 -0
  35. package/skill/scripts/context.mjs +17 -891
  36. package/skill/scripts/hook-admin-config.mjs +152 -0
  37. package/skill/scripts/hook-admin-ignore.mjs +131 -0
  38. package/skill/scripts/hook-admin-manifest.mjs +292 -0
  39. package/skill/scripts/hook-admin.mjs +8 -541
  40. package/skill/scripts/hook-lib-cache.mjs +145 -0
  41. package/skill/scripts/hook-lib-config.mjs +292 -0
  42. package/skill/scripts/hook-lib-detector.mjs +72 -0
  43. package/skill/scripts/hook-lib-events.mjs +182 -0
  44. package/skill/scripts/hook-lib-findings.mjs +201 -0
  45. package/skill/scripts/hook-lib-ignore.mjs +205 -0
  46. package/skill/scripts/hook-lib-render.mjs +273 -0
  47. package/skill/scripts/hook-lib-run.mjs +281 -0
  48. package/skill/scripts/hook-lib-scan-targets.mjs +128 -0
  49. package/skill/scripts/hook-lib.mjs +71 -1747
  50. package/skill/scripts/lib/design-parser-colors.mjs +182 -0
  51. package/skill/scripts/lib/design-parser-extract.mjs +333 -0
  52. package/skill/scripts/lib/design-parser-sections.mjs +214 -0
  53. package/skill/scripts/lib/design-parser-yaml.mjs +135 -0
  54. package/skill/scripts/lib/design-parser.mjs +10 -783
  55. package/skill/scripts/live/manual-apply-chunk.mjs +151 -0
  56. package/skill/scripts/live/manual-apply-compact.mjs +122 -0
  57. package/skill/scripts/live/manual-apply-evidence.mjs +115 -0
  58. package/skill/scripts/live/manual-apply-log.mjs +179 -0
  59. package/skill/scripts/live/manual-apply-transaction.mjs +122 -0
  60. package/skill/scripts/live/manual-apply.mjs +65 -640
  61. package/skill/scripts/live/svelte-component-accept.mjs +248 -0
  62. package/skill/scripts/live/svelte-component-css.mjs +230 -0
  63. package/skill/scripts/live/svelte-component-markup.mjs +104 -0
  64. package/skill/scripts/live/svelte-component-scaffold.mjs +118 -0
  65. package/skill/scripts/live/svelte-component-session.mjs +158 -0
  66. package/skill/scripts/live/svelte-component.mjs +32 -792
  67. package/skill/scripts/live-accept-mutate.mjs +152 -0
  68. package/skill/scripts/live-accept-parse.mjs +370 -0
  69. package/skill/scripts/live-accept-scrub.mjs +59 -0
  70. package/skill/scripts/live-accept-search.mjs +58 -0
  71. package/skill/scripts/live-accept.mjs +15 -631
  72. package/skill/scripts/live-commit-manual-edits-paths.mjs +27 -0
  73. package/skill/scripts/live-commit-manual-edits-repair.mjs +166 -0
  74. package/skill/scripts/live-commit-manual-edits-rollback.mjs +231 -0
  75. package/skill/scripts/live-commit-manual-edits-utils.mjs +167 -0
  76. package/skill/scripts/live-commit-manual-edits-verify.mjs +356 -0
  77. package/skill/scripts/live-commit-manual-edits.mjs +24 -881
  78. package/skill/scripts/live-copy-edit-agent.mjs +16 -551
  79. package/skill/scripts/live-copy-edit-compact.mjs +137 -0
  80. package/skill/scripts/live-copy-edit-post-apply.mjs +175 -0
  81. package/skill/scripts/live-copy-edit-runners.mjs +297 -0
  82. package/skill/scripts/live-inject-csp.mjs +132 -0
  83. package/skill/scripts/live-inject-files.mjs +229 -0
  84. package/skill/scripts/live-inject-tag.mjs +114 -0
  85. package/skill/scripts/live-inject.mjs +13 -440
  86. package/skill/scripts/live-server-poll.mjs +232 -0
  87. package/skill/scripts/live-server-routes.mjs +449 -0
  88. package/skill/scripts/live-server-state.mjs +361 -0
  89. package/skill/scripts/live-server.mjs +10 -946
  90. package/skill/scripts/live-wrap-css.mjs +132 -0
  91. package/skill/scripts/live-wrap-manual-edit.mjs +153 -0
  92. package/skill/scripts/live-wrap-search.mjs +247 -0
  93. package/skill/scripts/live-wrap.mjs +21 -484
  94. package/skill/scripts/palette-seeds.mjs +401 -0
  95. package/skill/scripts/palette.mjs +1 -395
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Small generic helpers and shared constants for context.mjs's project/context
3
+ * resolution: canonical file name lists, monorepo marker/ignore sets, and
4
+ * path/JSON primitives used across the context-*.mjs sibling modules.
5
+ *
6
+ * Split out of context.mjs. See that file for context.
7
+ */
8
+ import fs from 'node:fs';
9
+ import path from 'node:path';
10
+
11
+ export const PRODUCT_NAMES = ['PRODUCT.md', 'Product.md', 'product.md'];
12
+ export const DESIGN_NAMES = ['DESIGN.md', 'Design.md', 'design.md'];
13
+ export const FALLBACK_DIRS = ['.agents/context', 'docs'];
14
+ export const MONOREPO_MARKER_FILES = ['pnpm-workspace.yaml', 'turbo.json', 'nx.json', 'lerna.json'];
15
+ export const MONOREPO_FALLBACK_PROJECT_DIRS = ['apps', 'packages'];
16
+ export const WORKSPACE_DISCOVERY_IGNORED_DIRS = new Set([
17
+ 'node_modules',
18
+ '.git',
19
+ 'dist',
20
+ 'build',
21
+ '.next',
22
+ '.nuxt',
23
+ '.svelte-kit',
24
+ '.turbo',
25
+ '.cache',
26
+ 'coverage',
27
+ ]);
28
+
29
+ export function isPathInside(candidate, root) {
30
+ const rel = path.relative(root, candidate).split(path.sep).join('/');
31
+ return !!rel && !rel.startsWith('..') && !path.isAbsolute(rel);
32
+ }
33
+
34
+ export function isPathInsideOrEqual(candidate, root) {
35
+ return path.resolve(candidate) === path.resolve(root) || isPathInside(candidate, root);
36
+ }
37
+
38
+ export function readJson(filePath) {
39
+ try {
40
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
41
+ } catch {
42
+ return null;
43
+ }
44
+ }
45
+
46
+ export function firstExisting(dir, names) {
47
+ for (const name of names) {
48
+ const abs = path.join(dir, name);
49
+ if (fs.existsSync(abs)) return abs;
50
+ }
51
+ return null;
52
+ }
53
+
54
+ export function safeRead(p) {
55
+ try {
56
+ return fs.readFileSync(p, 'utf-8');
57
+ } catch {
58
+ return null;
59
+ }
60
+ }
61
+
62
+ export function escapeRegExp(value) {
63
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
64
+ }
65
+
66
+ export function hasTargetOption(options) {
67
+ return !!(options && typeof options.targetPath === 'string' && options.targetPath.trim());
68
+ }
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Monorepo workspace pattern discovery for context.mjs: reading workspace
3
+ * globs from package.json/pnpm-workspace.yaml/lerna.json, matching a target
4
+ * path against them, and resolving the nearest project-like root when no
5
+ * pattern matches.
6
+ *
7
+ * Split out of context.mjs. See that file for context.
8
+ */
9
+ import fs from 'node:fs';
10
+ import path from 'node:path';
11
+ import {
12
+ DESIGN_NAMES,
13
+ MONOREPO_FALLBACK_PROJECT_DIRS,
14
+ PRODUCT_NAMES,
15
+ escapeRegExp,
16
+ firstExisting,
17
+ isPathInsideOrEqual,
18
+ readJson,
19
+ } from './context-utils.mjs';
20
+
21
+ export function resolveWorkspaceProjectRoot(repoRoot, targetDir) {
22
+ const rel = path.relative(repoRoot, targetDir).split(path.sep).join('/');
23
+ if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return repoRoot;
24
+ // rel is POSIX-normalised above, so split on '/' — splitting on path.sep here
25
+ // returned the whole string as a single segment on Windows, no workspace
26
+ // pattern ever matched, and every child project silently resolved to the
27
+ // repo root instead.
28
+ const relSegments = rel.split('/').filter(Boolean);
29
+ const patterns = readWorkspacePatterns(repoRoot);
30
+ const excluded = isExcludedByWorkspacePattern(relSegments, patterns);
31
+ if (!excluded) {
32
+ for (const pattern of patterns) {
33
+ const projectRoot = projectRootFromWorkspacePattern(repoRoot, relSegments, pattern);
34
+ if (projectRoot) return projectRoot;
35
+ }
36
+ }
37
+ if (excluded) return repoRoot;
38
+ if (
39
+ relSegments.length >= 2
40
+ && MONOREPO_FALLBACK_PROJECT_DIRS.includes(relSegments[0])
41
+ ) {
42
+ return path.join(repoRoot, relSegments[0], relSegments[1]);
43
+ }
44
+ const nearest = nearestProjectLikeRoot(repoRoot, targetDir);
45
+ if (nearest) return nearest;
46
+ return repoRoot;
47
+ }
48
+
49
+ export function isExcludedByWorkspacePattern(relSegments, patterns) {
50
+ return patterns.some((rawPattern) => {
51
+ const pattern = normalizeWorkspacePattern(rawPattern);
52
+ if (!pattern.startsWith('!')) return false;
53
+ return workspacePatternMatchesRel(pattern.slice(1), relSegments);
54
+ });
55
+ }
56
+
57
+ function nearestProjectLikeRoot(repoRoot, targetDir) {
58
+ let dir = path.resolve(targetDir);
59
+ const stop = path.resolve(repoRoot);
60
+ while (dir && dir !== stop) {
61
+ if (
62
+ firstExisting(dir, [...PRODUCT_NAMES, ...DESIGN_NAMES])
63
+ || fs.existsSync(path.join(dir, 'package.json'))
64
+ ) {
65
+ return dir;
66
+ }
67
+ const parent = path.dirname(dir);
68
+ if (parent === dir) break;
69
+ dir = parent;
70
+ }
71
+ return null;
72
+ }
73
+
74
+ function nearestPackageRootBetween(repoRoot, targetDir, stopDir) {
75
+ let dir = path.resolve(targetDir);
76
+ const stop = path.resolve(stopDir || repoRoot);
77
+ const root = path.resolve(repoRoot);
78
+ while (dir && dir !== stop && isPathInsideOrEqual(dir, root)) {
79
+ if (fs.existsSync(path.join(dir, 'package.json'))) return dir;
80
+ const parent = path.dirname(dir);
81
+ if (parent === dir) break;
82
+ dir = parent;
83
+ }
84
+ return null;
85
+ }
86
+
87
+ function workspacePatternMatchesRel(pattern, relSegments) {
88
+ const patternSegments = normalizeWorkspacePattern(pattern).split('/').filter(Boolean);
89
+ if (!patternSegments.length) return false;
90
+ if (patternSegments.includes('**')) {
91
+ const firstGlobIndex = patternSegments.findIndex((segment) => segment.includes('*'));
92
+ const literalPrefix = firstGlobIndex === -1
93
+ ? patternSegments
94
+ : patternSegments.slice(0, firstGlobIndex);
95
+ if (relSegments.length < literalPrefix.length + 1) return false;
96
+ for (let i = 0; i < literalPrefix.length; i++) {
97
+ if (!segmentMatches(literalPrefix[i], relSegments[i])) return false;
98
+ }
99
+ return true;
100
+ }
101
+ if (relSegments.length < patternSegments.length) return false;
102
+ for (let i = 0; i < patternSegments.length; i++) {
103
+ if (!segmentMatches(patternSegments[i], relSegments[i])) return false;
104
+ }
105
+ return true;
106
+ }
107
+
108
+ export function readWorkspacePatterns(repoRoot) {
109
+ return [
110
+ ...readPackageWorkspaces(repoRoot),
111
+ ...readPnpmWorkspaces(repoRoot),
112
+ ...readLernaWorkspaces(repoRoot),
113
+ ].filter(Boolean);
114
+ }
115
+
116
+ function readPackageWorkspaces(repoRoot) {
117
+ const pkg = readJson(path.join(repoRoot, 'package.json'));
118
+ const workspaces = pkg?.workspaces;
119
+ if (Array.isArray(workspaces)) return workspaces;
120
+ if (Array.isArray(workspaces?.packages)) return workspaces.packages;
121
+ return [];
122
+ }
123
+
124
+ function readLernaWorkspaces(repoRoot) {
125
+ const lerna = readJson(path.join(repoRoot, 'lerna.json'));
126
+ return Array.isArray(lerna?.packages) ? lerna.packages : [];
127
+ }
128
+
129
+ function readPnpmWorkspaces(repoRoot) {
130
+ try {
131
+ const body = fs.readFileSync(path.join(repoRoot, 'pnpm-workspace.yaml'), 'utf-8');
132
+ const patterns = [];
133
+ let inPackages = false;
134
+ for (const line of body.split(/\r?\n/)) {
135
+ const trimmed = stripYamlInlineComment(line).trim();
136
+ if (!trimmed || trimmed.startsWith('#')) continue;
137
+ const flowMatch = trimmed.match(/^packages:\s*\[(.*)\]\s*$/);
138
+ if (flowMatch) {
139
+ patterns.push(...parseYamlFlowList(flowMatch[1]));
140
+ inPackages = false;
141
+ continue;
142
+ }
143
+ if (/^packages:\s*$/.test(trimmed)) {
144
+ inPackages = true;
145
+ continue;
146
+ }
147
+ if (inPackages && /^[A-Za-z0-9_-]+:\s*/.test(trimmed)) break;
148
+ if (inPackages) {
149
+ const match = trimmed.match(/^-\s*(.+)$/);
150
+ if (match) patterns.push(unquoteYamlValue(match[1]));
151
+ }
152
+ }
153
+ return patterns;
154
+ } catch {
155
+ return [];
156
+ }
157
+ }
158
+
159
+ function stripYamlInlineComment(line) {
160
+ let quote = null;
161
+ for (let i = 0; i < line.length; i++) {
162
+ const ch = line[i];
163
+ if ((ch === '"' || ch === "'") && line[i - 1] !== '\\') {
164
+ quote = quote === ch ? null : quote || ch;
165
+ continue;
166
+ }
167
+ if (ch === '#' && !quote) return line.slice(0, i);
168
+ }
169
+ return line;
170
+ }
171
+
172
+ function parseYamlFlowList(body) {
173
+ const items = [];
174
+ let quote = null;
175
+ let current = '';
176
+ for (let i = 0; i < body.length; i++) {
177
+ const ch = body[i];
178
+ if ((ch === '"' || ch === "'") && body[i - 1] !== '\\') {
179
+ quote = quote === ch ? null : quote || ch;
180
+ current += ch;
181
+ continue;
182
+ }
183
+ if (ch === ',' && !quote) {
184
+ const value = unquoteYamlValue(current);
185
+ if (value) items.push(value);
186
+ current = '';
187
+ continue;
188
+ }
189
+ current += ch;
190
+ }
191
+ const value = unquoteYamlValue(current);
192
+ if (value) items.push(value);
193
+ return items;
194
+ }
195
+
196
+ function unquoteYamlValue(value) {
197
+ return String(value || '')
198
+ .trim()
199
+ .replace(/^['"]|['"]$/g, '');
200
+ }
201
+ function projectRootFromWorkspacePattern(repoRoot, relSegments, rawPattern) {
202
+ const pattern = normalizeWorkspacePattern(rawPattern);
203
+ if (!pattern || pattern.startsWith('!')) return null;
204
+ const patternSegments = pattern.split('/').filter(Boolean);
205
+ if (!patternSegments.length) return null;
206
+ if (patternSegments.includes('**')) {
207
+ return projectRootFromDoubleStarPattern(repoRoot, relSegments, patternSegments);
208
+ }
209
+ if (relSegments.length < patternSegments.length) return null;
210
+ for (let i = 0; i < patternSegments.length; i++) {
211
+ if (!segmentMatches(patternSegments[i], relSegments[i])) return null;
212
+ }
213
+ return path.join(repoRoot, ...relSegments.slice(0, patternSegments.length));
214
+ }
215
+
216
+ function projectRootFromDoubleStarPattern(repoRoot, relSegments, patternSegments) {
217
+ const firstGlobIndex = patternSegments.findIndex((segment) => segment.includes('*'));
218
+ const literalPrefix = firstGlobIndex === -1
219
+ ? patternSegments
220
+ : patternSegments.slice(0, firstGlobIndex);
221
+ if (relSegments.length < literalPrefix.length + 1) return null;
222
+ for (let i = 0; i < literalPrefix.length; i++) {
223
+ if (!segmentMatches(literalPrefix[i], relSegments[i])) return null;
224
+ }
225
+ const prefixDir = path.join(repoRoot, ...literalPrefix);
226
+ const targetDir = path.join(repoRoot, ...relSegments);
227
+ const packageRoot = nearestPackageRootBetween(repoRoot, targetDir, prefixDir);
228
+ if (packageRoot) return packageRoot;
229
+ return path.join(repoRoot, ...relSegments.slice(0, literalPrefix.length + 1));
230
+ }
231
+
232
+ export function normalizeWorkspacePattern(pattern) {
233
+ return String(pattern || '')
234
+ .trim()
235
+ .replace(/^['"]|['"]$/g, '')
236
+ .replace(/^\.\//, '')
237
+ .replace(/\/+$/, '');
238
+ }
239
+
240
+ export function segmentMatches(patternSegment, relSegment) {
241
+ if (patternSegment === '*') return true;
242
+ if (!patternSegment.includes('*')) return patternSegment === relSegment;
243
+ const re = new RegExp(`^${escapeRegExp(patternSegment).replace(/\\\*/g, '[^/]*')}$`);
244
+ return re.test(relSegment);
245
+ }