@morya-ui/setup 0.2.6 → 0.2.7

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/README.md CHANGED
@@ -4,10 +4,12 @@ One-shot setup for consumer Vue projects using [`morya-ui`](https://www.npmjs.co
4
4
 
5
5
  Docs (zh/en):
6
6
 
7
- - [AI setup](https://morya-space.github.io/morya-ui/docs/ai-setup) — one-shot CLI
7
+ - [One-shot setup](https://morya-space.github.io/morya-ui/docs/setup) — CLI commands and options
8
+ - [AI setup](https://morya-space.github.io/morya-ui/docs/ai-setup) — Agent workflow
8
9
  - [Agent Skill](https://morya-space.github.io/morya-ui/docs/agent-skill) — `morya-ui-pages` behavior
10
+ - [Quick start](https://morya-space.github.io/morya-ui/docs/quick-start) — install and first component
9
11
 
10
- Installs the UI library, copies Agent skill / Cursor rules / design docs from `ai-design-config`, merges Cursor MCP for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp), injects `import 'morya-ui/styles.css'`, and writes `src/styles/morya-app-shell.css` with its entry import.
12
+ Installs the UI library, copies Agent skill / Cursor rules / design docs from `design-kit`, merges Cursor MCP for [`@morya-ui/mcp`](https://www.npmjs.com/package/@morya-ui/mcp), injects `import 'morya-ui/styles.css'`, and writes `src/styles/morya-app-shell.css` with its entry import.
11
13
 
12
14
  ## Usage
13
15
 
@@ -17,6 +19,16 @@ In your app project root:
17
19
  npx @morya-ui/setup
18
20
  ```
19
21
 
22
+ Other common commands:
23
+
24
+ ```bash
25
+ # AI config + MCP only (library already installed)
26
+ npx @morya-ui/setup ai
27
+
28
+ # Library + styles only
29
+ npx @morya-ui/setup app
30
+ ```
31
+
20
32
  ### Options
21
33
 
22
34
  | Flag | Meaning |
@@ -32,6 +44,12 @@ npx @morya-ui/setup
32
44
  | `--skip-scripts` | Do not add `check:colors` to `package.json` |
33
45
  | `-h`, `--help` | Show help |
34
46
 
47
+ Example: MCP only:
48
+
49
+ ```bash
50
+ npx @morya-ui/setup ai --skip-template --skip-scripts
51
+ ```
52
+
35
53
  ### Conflict policy
36
54
 
37
55
  - Template files and `.cursor/rules/*`: **skip** if the destination exists (unless `--force`).
@@ -41,7 +59,7 @@ npx @morya-ui/setup
41
59
 
42
60
  ### What gets copied
43
61
 
44
- From the package `template/` (synced from repo `ai-design-config/`):
62
+ From the package `template/` (synced from repo `design-kit/`):
45
63
 
46
64
  - `DESIGN.md`
47
65
  - `.agents/skills/morya-ui-pages/`
@@ -50,7 +68,8 @@ From the package `template/` (synced from repo `ai-design-config/`):
50
68
  - `design-tokens/`
51
69
  - `scripts/check-raw-colors.mjs`
52
70
  - `src/examples/`
53
- - `src/styles/morya-app-shell.css`
71
+
72
+ `morya-app-shell.css` is written by the CLI (not copied from the template tree).
54
73
 
55
74
  ### MCP (Cursor)
56
75
 
@@ -85,7 +104,7 @@ The CLI does **not** call `app.use(MoryaUI)` or edit `App.vue`.
85
104
  ## Local development (this monorepo)
86
105
 
87
106
  ```bash
88
- pnpm setup:sync-template # refresh packages/setup/template from ai-design-config
107
+ pnpm setup:sync-template # refresh packages/setup/template from design-kit
89
108
  pnpm setup:build
90
109
  node packages/setup/bin/morya-ui-setup.js --cwd /path/to/app --dry-run
91
110
  ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@morya-ui/setup",
3
3
  "type": "module",
4
- "version": "0.2.6",
4
+ "version": "0.2.7",
5
5
  "description": "One-shot setup for morya-ui: install the library, Cursor MCP, Agent skills, and design config.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/morya-space/morya-ui/tree/main/packages/setup#readme",
package/src/cli.mjs CHANGED
@@ -1,6 +1,8 @@
1
+ import { existsSync } from 'node:fs'
1
2
  import { dirname, join, resolve } from 'node:path'
2
3
  import { fileURLToPath } from 'node:url'
3
4
  import { copyTemplate } from './copy-template.mjs'
5
+ import { readJson } from './fs-utils.mjs'
4
6
  import { installMoryaUi } from './install.mjs'
5
7
  import { mergeMcpConfig } from './mcp.mjs'
6
8
  import { ensureCheckColorsScript } from './package-json.mjs'
@@ -10,6 +12,26 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
10
12
  const PKG_ROOT = resolve(__dirname, '..')
11
13
  const TEMPLATE_ROOT = join(PKG_ROOT, 'template')
12
14
 
15
+ const MODES = new Set(['app', 'ai', 'full'])
16
+
17
+ /** AI pack paths under template/ (excludes runtime src/styles — owned by app mode). */
18
+ const AI_TEMPLATE_INCLUDE = [
19
+ 'DESIGN.md',
20
+ '.agents/skills/morya-ui-pages',
21
+ '.cursor/rules',
22
+ 'docs',
23
+ 'design-tokens',
24
+ 'scripts/check-raw-colors.mjs',
25
+ 'src/examples',
26
+ ]
27
+
28
+ /** Mode → default skips (user --skip-* can only add more skips). */
29
+ const MODE_DEFAULTS = {
30
+ full: {},
31
+ app: { skipTemplate: true, skipMcp: true, skipScripts: true },
32
+ ai: { skipInstall: true, skipStyles: true },
33
+ }
34
+
13
35
  const SKIP_FLAGS = {
14
36
  '--skip-install': 'skipInstall',
15
37
  '--skip-template': 'skipTemplate',
@@ -19,14 +41,20 @@ const SKIP_FLAGS = {
19
41
  }
20
42
 
21
43
  export function printHelp() {
22
- console.log(`Usage: morya-ui-setup [options]
44
+ console.log(`Usage: morya-ui-setup [command] [options]
45
+
46
+ Commands:
47
+ (default) / full Install morya-ui, AI template, MCP, styles, check:colors
48
+ app Install morya-ui and inject styles / app-shell CSS
49
+ ai Copy Agent skill / rules / DESIGN / docs / tokens / examples,
50
+ merge Cursor MCP, add check:colors
23
51
 
24
- One-shot setup for morya-ui in a consumer Vue project:
52
+ Default command:
25
53
  - install morya-ui
26
54
  - copy DESIGN.md, Agent skill, Cursor rules, docs, tokens, examples
27
55
  - merge .cursor/mcp.json for @morya-ui/mcp
28
56
  - inject import 'morya-ui/styles.css' into the app entry when found
29
- - write src/styles/morya-app-shell.css (html/body/#app height chain) and inject its import
57
+ - write src/styles/morya-app-shell.css and inject its import
30
58
  - add check:colors script when missing
31
59
 
32
60
  Options:
@@ -48,6 +76,7 @@ Options:
48
76
  */
49
77
  export function parseArgs(argv) {
50
78
  const options = {
79
+ mode: 'full',
51
80
  cwd: process.cwd(),
52
81
  pm: undefined,
53
82
  force: false,
@@ -66,6 +95,10 @@ export function parseArgs(argv) {
66
95
  options.help = true
67
96
  continue
68
97
  }
98
+ if (MODES.has(arg)) {
99
+ options.mode = arg
100
+ continue
101
+ }
69
102
  if (arg === '--force') {
70
103
  options.force = true
71
104
  continue
@@ -101,6 +134,11 @@ export function parseArgs(argv) {
101
134
  throw new Error(`Unknown argument: ${arg}`)
102
135
  }
103
136
 
137
+ const defaults = MODE_DEFAULTS[options.mode] || {}
138
+ for (const [key, value] of Object.entries(defaults)) {
139
+ if (value) options[key] = true
140
+ }
141
+
104
142
  return options
105
143
  }
106
144
 
@@ -109,11 +147,30 @@ function rel(cwd, path) {
109
147
  return path.startsWith(cwd) ? path.slice(cwd.length).replace(/^[\\/]/, '') || path : path
110
148
  }
111
149
 
150
+ /**
151
+ * @param {string} cwd
152
+ */
153
+ function hasMoryaUiDependency(cwd) {
154
+ const path = join(cwd, 'package.json')
155
+ if (!existsSync(path)) return false
156
+ try {
157
+ const pkg = readJson(path)
158
+ return Boolean(
159
+ pkg.dependencies?.['morya-ui']
160
+ || pkg.devDependencies?.['morya-ui']
161
+ || pkg.peerDependencies?.['morya-ui'],
162
+ )
163
+ } catch {
164
+ return false
165
+ }
166
+ }
167
+
112
168
  /**
113
169
  * @param {ReturnType<typeof parseArgs>} options
114
170
  */
115
171
  export async function runSetup(options) {
116
172
  const {
173
+ mode,
117
174
  cwd,
118
175
  force,
119
176
  dryRun,
@@ -125,14 +182,25 @@ export async function runSetup(options) {
125
182
  pm,
126
183
  } = options
127
184
 
128
- console.log(`@morya-ui/setup → ${cwd}${dryRun ? ' (dry-run)' : ''}`)
185
+ console.log(`@morya-ui/setup [${mode}] → ${cwd}${dryRun ? ' (dry-run)' : ''}`)
129
186
  console.log('')
130
187
 
188
+ if (mode === 'ai' && !hasMoryaUiDependency(cwd)) {
189
+ console.log(
190
+ 'Warning: morya-ui is not listed in package.json. Run `npx @morya-ui/setup app` first (or pnpm add morya-ui).',
191
+ )
192
+ console.log('')
193
+ }
194
+
131
195
  const install = installMoryaUi(cwd, { pm, dryRun, skipInstall })
132
196
 
133
197
  const template = skipTemplate
134
198
  ? { copied: [], skipped: [], forced: [], skippedStep: true }
135
- : copyTemplate(TEMPLATE_ROOT, cwd, { force, dryRun })
199
+ : copyTemplate(TEMPLATE_ROOT, cwd, {
200
+ force,
201
+ dryRun,
202
+ include: mode === 'ai' || mode === 'full' ? AI_TEMPLATE_INCLUDE : undefined,
203
+ })
136
204
 
137
205
  const mcp = skipMcp
138
206
  ? { path: join(cwd, '.cursor', 'mcp.json'), action: 'skipped-flag' }
@@ -158,7 +226,7 @@ export async function runSetup(options) {
158
226
  }
159
227
 
160
228
  if (template.skippedStep) {
161
- console.log('Template: skipped (--skip-template)')
229
+ console.log('Template: skipped (--skip-template or app mode)')
162
230
  } else {
163
231
  console.log(
164
232
  `Template: ${template.copied.length} copied, ${template.forced.length} overwritten, ${template.skipped.length} skipped`,
@@ -172,13 +240,13 @@ export async function runSetup(options) {
172
240
  }
173
241
 
174
242
  if (mcp.action === 'skipped-flag') {
175
- console.log('MCP: skipped (--skip-mcp)')
243
+ console.log('MCP: skipped (--skip-mcp or app mode)')
176
244
  } else {
177
245
  console.log(`MCP: ${mcp.action} (${rel(cwd, mcp.path) || '.cursor/mcp.json'})`)
178
246
  }
179
247
 
180
248
  if (styles.reason === 'skip-styles') {
181
- console.log('Styles: skipped (--skip-styles)')
249
+ console.log('Styles: skipped (--skip-styles or ai mode)')
182
250
  } else if (styles.action === 'injected') {
183
251
  console.log(`Styles: injected into ${rel(cwd, styles.path)}`)
184
252
  } else if (styles.action === 'skipped') {
@@ -189,7 +257,7 @@ export async function runSetup(options) {
189
257
  }
190
258
 
191
259
  if (shell.reason === 'skip-styles') {
192
- console.log('Shell CSS: skipped (--skip-styles)')
260
+ console.log('Shell CSS: skipped (--skip-styles or ai mode)')
193
261
  } else {
194
262
  console.log(
195
263
  `Shell CSS: file ${shell.fileAction}`
@@ -200,17 +268,26 @@ export async function runSetup(options) {
200
268
  }
201
269
 
202
270
  if (scripts.action === 'skipped-flag') {
203
- console.log('Scripts: skipped (--skip-scripts)')
271
+ console.log('Scripts: skipped (--skip-scripts or app mode)')
204
272
  } else {
205
273
  console.log(`Scripts: check:colors ${scripts.action}`)
206
274
  }
207
275
 
208
276
  console.log('')
209
277
  console.log('Next:')
210
- console.log(' 1. Ensure styles.css + morya-app-shell.css imports are in your app entry.')
211
- console.log(' 2. Restart Cursor (or reload MCP) so morya-ui MCP tools appear.')
212
- console.log(' 3. Have the agent read DESIGN.md before generating pages.')
213
- console.log(' 4. Optional: pnpm check:colors')
278
+ if (mode === 'app') {
279
+ console.log(' 1. Ensure styles.css + morya-app-shell.css imports are in your app entry.')
280
+ console.log(' 2. Optional AI pack: npx @morya-ui/setup ai')
281
+ } else if (mode === 'ai') {
282
+ console.log(' 1. Restart Cursor (or reload MCP) so morya-ui MCP tools appear.')
283
+ console.log(' 2. Have the agent read DESIGN.md before generating pages.')
284
+ console.log(' 3. Optional: pnpm check:colors')
285
+ } else {
286
+ console.log(' 1. Ensure styles.css + morya-app-shell.css imports are in your app entry.')
287
+ console.log(' 2. Restart Cursor (or reload MCP) so morya-ui MCP tools appear.')
288
+ console.log(' 3. Have the agent read DESIGN.md before generating pages.')
289
+ console.log(' 4. Optional: pnpm check:colors')
290
+ }
214
291
 
215
- return { install, template, mcp, styles, shell, scripts }
292
+ return { mode, install, template, mcp, styles, shell, scripts }
216
293
  }
@@ -20,11 +20,27 @@ function listFiles(dir) {
20
20
  return out
21
21
  }
22
22
 
23
+ /**
24
+ * @param {string} rel
25
+ * @param {string[] | undefined} include
26
+ */
27
+ function matchesInclude(rel, include) {
28
+ if (!include || include.length === 0) return true
29
+ const norm = rel.replace(/\\/g, '/')
30
+ return include.some((prefix) => {
31
+ const p = prefix.replace(/\\/g, '/')
32
+ return norm === p || norm.startsWith(`${p}/`)
33
+ })
34
+ }
35
+
23
36
  /**
24
37
  * Copy template tree into target cwd.
38
+ * @param {string} templateRoot
39
+ * @param {string} cwd
40
+ * @param {{ force?: boolean, dryRun?: boolean, include?: string[] }} [options]
25
41
  * @returns {{ copied: string[], skipped: string[], forced: string[] }}
26
42
  */
27
- export function copyTemplate(templateRoot, cwd, { force = false, dryRun = false } = {}) {
43
+ export function copyTemplate(templateRoot, cwd, { force = false, dryRun = false, include } = {}) {
28
44
  const copied = []
29
45
  const skipped = []
30
46
  const forced = []
@@ -35,7 +51,7 @@ export function copyTemplate(templateRoot, cwd, { force = false, dryRun = false
35
51
  )
36
52
  }
37
53
 
38
- const files = listFiles(templateRoot)
54
+ const files = listFiles(templateRoot).filter((rel) => matchesInclude(rel, include))
39
55
  for (const rel of files) {
40
56
  const from = join(templateRoot, rel)
41
57
  const to = join(cwd, rel)
package/src/fs-utils.mjs CHANGED
@@ -2,7 +2,8 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
2
  import { dirname } from 'node:path'
3
3
 
4
4
  export function readJson(path) {
5
- return JSON.parse(readFileSync(path, 'utf8'))
5
+ const text = readFileSync(path, 'utf8').replace(/^\uFEFF/, '')
6
+ return JSON.parse(text)
6
7
  }
7
8
 
8
9
  export function writeJson(path, value, { dryRun = false } = {}) {
@@ -1,6 +1,6 @@
1
1
  # Morya UI 设计系统(AI 第一信源)
2
2
 
3
- > 基于 `morya-ui` v0.1.x。生成或审查业务页面时,**必须先遵守本文**,再查阅 `docs/components.md` 与 `docs/golden-pages/`。
3
+ > 基于 `morya-ui` v0.2.6。生成或审查业务页面时,**必须先遵守本文**,再查阅 `docs/components.md` 与 `docs/golden-pages/`。
4
4
 
5
5
  ## 1. 设计原则
6
6
 
@@ -108,7 +108,7 @@ import 'morya-ui/styles.css'
108
108
 
109
109
  ## 8. 禁止项
110
110
 
111
- - 禁止引入第二套 UI 库(Element Plus、Naive UI 等)混用同一页面。
111
+ - 禁止引入第二套 UI 库混用同一页面。
112
112
  - 禁止在业务 CSS 中写死主题色;暗色模式必须能随 `[data-theme="dark"]` 生效。
113
113
  - 禁止用 `<div onclick>` 代替 `<button>` / `MButton`。
114
114
  - 禁止 Select 与 Dropdown 混用:选项选择用 `MSelect` / `MTreeSelect`;动作菜单用 `MDropdown`。
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://design-tokens.github.io/community-group/format/",
3
3
  "meta": {
4
4
  "name": "morya-ui",
5
- "version": "0.1.1",
5
+ "version": "0.2.6",
6
6
  "source": "morya-ui/src/theme/styles.css",
7
7
  "prefix": "m"
8
8
  },
@@ -88,13 +88,13 @@ message.error('操作失败')
88
88
  | 删除确认用 Message/Toast | `MConfirmDialog` |
89
89
  | 所有反馈都用 Toast | 默认改 Message,仅 detail 场景保留 Toast |
90
90
 
91
- ## 与 Naive / Element Plus 的对应
91
+ ## 概念对照
92
92
 
93
- | Morya UI | 近似概念 |
93
+ | API | 用途 |
94
94
  | --- | --- |
95
- | `message` | Naive `message` / Element `ElMessage` |
96
- | `toast` | Naive `notification` / Element `ElNotification` |
97
- | `<MMessage>` | 页面内 `el-alert` / 表单顶部错误条 |
95
+ | `message` | 轻量、短暂的操作反馈(默认首选) |
96
+ | `toast` | 带摘要 + 详情、或需停留更久的通知 |
97
+ | `<MMessage>` | 页面内常驻提示条(如表单顶部错误) |
98
98
 
99
99
  ## 相关文档
100
100