@morya-ui/setup 0.3.4 → 0.3.6

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 (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -103
  3. package/bin/morya-ui-setup.js +14 -14
  4. package/catalog/skills.json +46 -46
  5. package/package.json +4 -5
  6. package/src/__tests__/mcp.test.mjs +141 -0
  7. package/src/cli.mjs +330 -335
  8. package/src/copy-template.mjs +78 -78
  9. package/src/fs-utils.mjs +24 -24
  10. package/src/install.mjs +134 -63
  11. package/src/mcp.mjs +220 -50
  12. package/src/package-json.mjs +30 -30
  13. package/src/skills.mjs +224 -223
  14. package/src/styles.mjs +119 -119
  15. package/template/.agents/skills/morya-ui-pages/SKILL.md +191 -184
  16. package/template/.agents/skills/morya-ui-pages/evals/evals.json +89 -89
  17. package/template/.agents/skills/morya-ui-pages/references/component-index.md +99 -99
  18. package/template/.agents/skills/morya-ui-pages/references/decision-recipes.md +72 -5
  19. package/template/.agents/skills/morya-ui-pages/references/design-system.md +101 -101
  20. package/template/.agents/skills/morya-ui-pages/references/feedback.md +68 -68
  21. package/template/.agents/skills/morya-ui-pages/references/optional-companions.md +62 -107
  22. package/template/.agents/skills/morya-ui-pages/references/page-layouts.md +133 -141
  23. package/template/.agents/skills/morya-ui-pages/references/review-checklist.md +76 -64
  24. package/template/.agents/skills/morya-ui-pages/references/style-presets.md +68 -73
  25. package/template/.agents/skills/morya-ui-pages/references/surfaces.md +91 -91
  26. package/template/.agents/skills/morya-ui-pages/references/visual-craft.md +131 -221
  27. package/template/.cursor/rules/coding-style.mdc +41 -41
  28. package/template/.cursor/rules/component-usage.mdc +41 -41
  29. package/template/.cursor/rules/design-system.mdc +18 -17
  30. package/template/.cursor/rules/page-layout.mdc +97 -97
  31. package/template/AGENTS.md +33 -0
  32. package/template/DESIGN.md +81 -59
  33. package/template/scripts/check-raw-colors.mjs +74 -74
package/src/styles.mjs CHANGED
@@ -1,119 +1,119 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs'
2
- import { join, resolve } from 'node:path'
3
-
4
- const STYLE_IMPORT = "import 'morya-ui/styles.css'"
5
- const STYLE_MARKER = 'morya-ui/styles.css'
6
-
7
- const CANDIDATES = [
8
- 'src/main.ts',
9
- 'src/main.js',
10
- 'src/main.tsx',
11
- 'src/main.jsx',
12
- 'main.ts',
13
- 'main.js',
14
- 'src/app.ts',
15
- 'src/app.js',
16
- ]
17
-
18
- /**
19
- * @param {string} cwd
20
- * @returns {string | null} absolute path
21
- */
22
- export function findEntryFile(cwd) {
23
- for (const rel of CANDIDATES) {
24
- const full = join(cwd, rel)
25
- if (existsSync(full)) return full
26
- }
27
-
28
- const indexHtml = join(cwd, 'index.html')
29
- if (existsSync(indexHtml)) {
30
- const html = readFileSync(indexHtml, 'utf8')
31
- const match = html.match(/<script[^>]*type=["']module["'][^>]*src=["']([^"']+)["']/i)
32
- || html.match(/<script[^>]*src=["']([^"']+)["'][^>]*type=["']module["']/i)
33
- if (match?.[1]) {
34
- const src = match[1].replace(/^\//, '')
35
- const full = resolve(cwd, src)
36
- if (existsSync(full)) return full
37
- }
38
- }
39
-
40
- return null
41
- }
42
-
43
- /**
44
- * Insert an import after the last leading import, or at top.
45
- * @param {string} source
46
- * @param {string} importLine
47
- * @param {string} marker substring that means "already present"
48
- */
49
- export function injectImportLine(source, importLine, marker) {
50
- if (source.includes(marker)) {
51
- return { source, changed: false, reason: 'already-present' }
52
- }
53
-
54
- const lines = source.split(/\r?\n/)
55
- let lastImportIndex = -1
56
- for (let i = 0; i < lines.length; i++) {
57
- const line = lines[i].trim()
58
- if (!line) {
59
- if (lastImportIndex >= 0) continue
60
- continue
61
- }
62
- if (line.startsWith('//') || line.startsWith('/*') || line.startsWith('*')) {
63
- if (lastImportIndex < 0) continue
64
- break
65
- }
66
- if (/^import\s/.test(line) || /^import["']/.test(line)) {
67
- lastImportIndex = i
68
- continue
69
- }
70
- break
71
- }
72
-
73
- if (lastImportIndex >= 0) {
74
- lines.splice(lastImportIndex + 1, 0, importLine)
75
- }
76
- else {
77
- let insertAt = 0
78
- if (lines[0]?.startsWith('#!')) insertAt = 1
79
- lines.splice(insertAt, 0, importLine, '')
80
- }
81
-
82
- return { source: lines.join('\n'), changed: true }
83
- }
84
-
85
- /**
86
- * @param {string} source
87
- * @deprecated use injectImportLine
88
- */
89
- export function injectStyleImport(source) {
90
- return injectImportLine(source, STYLE_IMPORT, STYLE_MARKER)
91
- }
92
-
93
- /**
94
- * @returns {{
95
- * action: 'injected' | 'skipped' | 'missing-entry',
96
- * path?: string,
97
- * reason?: string,
98
- * dryRun?: boolean
99
- * }}
100
- */
101
- export function ensureStylesImport(cwd, { dryRun = false } = {}) {
102
- const entry = findEntryFile(cwd)
103
- if (!entry) {
104
- return { action: 'missing-entry', reason: 'no-entry-found' }
105
- }
106
-
107
- const original = readFileSync(entry, 'utf8')
108
- const { source, changed, reason } = injectImportLine(original, STYLE_IMPORT, STYLE_MARKER)
109
-
110
- if (!changed) {
111
- return { action: 'skipped', path: entry, reason: reason || 'already-present' }
112
- }
113
-
114
- if (!dryRun) {
115
- writeFileSync(entry, source, 'utf8')
116
- }
117
-
118
- return { action: 'injected', path: entry, dryRun }
119
- }
1
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
2
+ import { join, resolve } from 'node:path'
3
+
4
+ const STYLE_IMPORT = "import 'morya-ui/styles.css'"
5
+ const STYLE_MARKER = 'morya-ui/styles.css'
6
+
7
+ const CANDIDATES = [
8
+ 'src/main.ts',
9
+ 'src/main.js',
10
+ 'src/main.tsx',
11
+ 'src/main.jsx',
12
+ 'main.ts',
13
+ 'main.js',
14
+ 'src/app.ts',
15
+ 'src/app.js',
16
+ ]
17
+
18
+ /**
19
+ * @param {string} cwd
20
+ * @returns {string | null} absolute path
21
+ */
22
+ export function findEntryFile(cwd) {
23
+ for (const rel of CANDIDATES) {
24
+ const full = join(cwd, rel)
25
+ if (existsSync(full)) return full
26
+ }
27
+
28
+ const indexHtml = join(cwd, 'index.html')
29
+ if (existsSync(indexHtml)) {
30
+ const html = readFileSync(indexHtml, 'utf8')
31
+ const match = html.match(/<script[^>]*type=["']module["'][^>]*src=["']([^"']+)["']/i)
32
+ || html.match(/<script[^>]*src=["']([^"']+)["'][^>]*type=["']module["']/i)
33
+ if (match?.[1]) {
34
+ const src = match[1].replace(/^\//, '')
35
+ const full = resolve(cwd, src)
36
+ if (existsSync(full)) return full
37
+ }
38
+ }
39
+
40
+ return null
41
+ }
42
+
43
+ /**
44
+ * Insert an import after the last leading import, or at top.
45
+ * @param {string} source
46
+ * @param {string} importLine
47
+ * @param {string} marker substring that means "already present"
48
+ */
49
+ export function injectImportLine(source, importLine, marker) {
50
+ if (source.includes(marker)) {
51
+ return { source, changed: false, reason: 'already-present' }
52
+ }
53
+
54
+ const lines = source.split(/\r?\n/)
55
+ let lastImportIndex = -1
56
+ for (let i = 0; i < lines.length; i++) {
57
+ const line = lines[i].trim()
58
+ if (!line) {
59
+ if (lastImportIndex >= 0) continue
60
+ continue
61
+ }
62
+ if (line.startsWith('//') || line.startsWith('/*') || line.startsWith('*')) {
63
+ if (lastImportIndex < 0) continue
64
+ break
65
+ }
66
+ if (/^import\s/.test(line) || /^import["']/.test(line)) {
67
+ lastImportIndex = i
68
+ continue
69
+ }
70
+ break
71
+ }
72
+
73
+ if (lastImportIndex >= 0) {
74
+ lines.splice(lastImportIndex + 1, 0, importLine)
75
+ }
76
+ else {
77
+ let insertAt = 0
78
+ if (lines[0]?.startsWith('#!')) insertAt = 1
79
+ lines.splice(insertAt, 0, importLine, '')
80
+ }
81
+
82
+ return { source: lines.join('\n'), changed: true }
83
+ }
84
+
85
+ /**
86
+ * @param {string} source
87
+ * @deprecated use injectImportLine
88
+ */
89
+ export function injectStyleImport(source) {
90
+ return injectImportLine(source, STYLE_IMPORT, STYLE_MARKER)
91
+ }
92
+
93
+ /**
94
+ * @returns {{
95
+ * action: 'injected' | 'skipped' | 'missing-entry',
96
+ * path?: string,
97
+ * reason?: string,
98
+ * dryRun?: boolean
99
+ * }}
100
+ */
101
+ export function ensureStylesImport(cwd, { dryRun = false } = {}) {
102
+ const entry = findEntryFile(cwd)
103
+ if (!entry) {
104
+ return { action: 'missing-entry', reason: 'no-entry-found' }
105
+ }
106
+
107
+ const original = readFileSync(entry, 'utf8')
108
+ const { source, changed, reason } = injectImportLine(original, STYLE_IMPORT, STYLE_MARKER)
109
+
110
+ if (!changed) {
111
+ return { action: 'skipped', path: entry, reason: reason || 'already-present' }
112
+ }
113
+
114
+ if (!dryRun) {
115
+ writeFileSync(entry, source, 'utf8')
116
+ }
117
+
118
+ return { action: 'injected', path: entry, dryRun }
119
+ }