@erclx/canon 5.52.0 → 5.54.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/CHANGELOG.md +17 -0
- package/README.md +11 -13
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-cli/SKILL.md +5 -8
- package/claude/skills/context-fold/REQUIREMENT.md +0 -1
- package/claude/skills/design-identity/REQUIREMENT.md +2 -2
- package/claude/skills/design-identity/SKILL.md +6 -6
- package/claude/skills/design-record/REQUIREMENT.md +2 -2
- package/claude/skills/design-record/SKILL.md +4 -4
- package/claude/skills/design-record/references/folder.md +1 -1
- package/claude/skills/design-taste/REQUIREMENT.md +1 -1
- package/claude/skills/design-taste/references/kinds.md +0 -1
- package/claude/skills/draw-figure/REQUIREMENT.md +3 -4
- package/claude/skills/draw-figure/SKILL.md +5 -6
- package/claude/skills/draw-figure/references/figures.md +0 -1
- package/claude/skills/draw-figure/references/hand-drawn.md +1 -1
- package/claude/skills/pick-by-eye/REQUIREMENT.md +4 -5
- package/claude/skills/pick-by-eye/SKILL.md +34 -41
- package/claude/skills/pick-by-eye/references/board.md +42 -0
- package/claude/skills/pick-by-eye/references/live-arms.md +3 -3
- package/claude/skills/plan-groundwork/SKILL.md +1 -1
- package/claude/skills/teach-craft/REQUIREMENT.md +30 -0
- package/claude/skills/teach-craft/SKILL.md +70 -0
- package/claude/skills/teach-craft/references/adopted.md +113 -0
- package/claude/skills/teach-craft/references/lesson-craft.md +60 -0
- package/claude/skills/{teach-workspace → teach-craft}/references/pedagogy.md +41 -6
- package/docs/agents/audits.md +0 -1
- package/docs/agents/install-and-sync.md +0 -8
- package/docs/target/migrations.md +16 -2
- package/docs/target/projects.md +1 -1
- package/docs/workflow/parallel-features.md +1 -1
- package/docs/workflow/skill-map-on-request.md +10 -22
- package/docs/workflow/skill-map.md +11 -14
- package/docs/workflow/visual-design-workflow.md +1 -4
- package/governance/detect.toml +1 -6
- package/governance/renames.toml +0 -1
- package/package.json +2 -8
- package/scripts/core/regen-web-previews.ts +2 -67
- package/src/audits/catalog.ts +0 -1
- package/src/browser/engine.ts +3 -6
- package/src/capture/render.ts +1 -1
- package/src/claude/cases/authoring.ts +0 -12
- package/src/claude/cases/misc.ts +0 -22
- package/src/claude/cases/workflow.ts +2 -38
- package/src/claude/skills-audit.ts +1 -1
- package/src/cli/help.ts +0 -10
- package/src/cli.ts +0 -8
- package/src/commands/design.ts +16 -315
- package/src/commands/records.ts +0 -1
- package/src/commands/serve.ts +2 -2
- package/src/commands/sync.ts +4 -5
- package/src/design/components.ts +8 -1514
- package/src/design/css.ts +5 -6
- package/src/design/fonts.ts +3 -5
- package/src/design/regen.ts +5 -32
- package/src/design/render.ts +1 -1
- package/src/design/tokens.ts +3 -2
- package/src/driver/drive.ts +3 -4
- package/src/driver/steps.ts +2 -5
- package/src/gate/stages.ts +4 -10
- package/src/gov/audit.ts +1 -6
- package/src/inventory/walk.ts +1 -1
- package/src/markdown/scope.ts +6 -35
- package/src/records/validate.ts +4 -176
- package/src/sandbox/equivalence.ts +0 -5
- package/src/shipped/references.ts +1 -2
- package/src/sync/check.ts +4 -29
- package/src/sync/stamp.ts +6 -6
- package/src/sync/target.ts +1 -4
- package/tooling/claude/reference.md +1 -1
- package/tooling/claude/seeds/canon/DESIGN.md +1 -1
- package/claude/skills/canvas-board/REQUIREMENT.md +0 -35
- package/claude/skills/canvas-board/SKILL.md +0 -143
- package/claude/skills/canvas-board/references/canvas.md +0 -170
- package/claude/skills/draft-and-pick/REQUIREMENT.md +0 -26
- package/claude/skills/draft-and-pick/SKILL.md +0 -11
- package/claude/skills/draft-doc/REQUIREMENT.md +0 -26
- package/claude/skills/draft-doc/SKILL.md +0 -11
- package/claude/skills/draft-figure/REQUIREMENT.md +0 -26
- package/claude/skills/draft-figure/SKILL.md +0 -11
- package/claude/skills/draft-identity/REQUIREMENT.md +0 -26
- package/claude/skills/draft-identity/SKILL.md +0 -11
- package/claude/skills/draft-ready/REQUIREMENT.md +0 -26
- package/claude/skills/draft-ready/SKILL.md +0 -11
- package/claude/skills/draft-screencast/REQUIREMENT.md +0 -26
- package/claude/skills/draft-screencast/SKILL.md +0 -11
- package/claude/skills/draft-slides/REQUIREMENT.md +0 -26
- package/claude/skills/draft-slides/SKILL.md +0 -11
- package/claude/skills/make-deck/REQUIREMENT.md +0 -36
- package/claude/skills/make-deck/SKILL.md +0 -80
- package/claude/skills/make-deck/references/deck.md +0 -183
- package/claude/skills/read-frames/REQUIREMENT.md +0 -30
- package/claude/skills/read-frames/SKILL.md +0 -55
- package/claude/skills/record-screencast/REQUIREMENT.md +0 -35
- package/claude/skills/record-screencast/SKILL.md +0 -99
- package/claude/skills/script-screencast/REQUIREMENT.md +0 -34
- package/claude/skills/script-screencast/SKILL.md +0 -70
- package/claude/skills/script-screencast/references/beats-template.md +0 -119
- package/claude/skills/teach-workspace/REQUIREMENT.md +0 -34
- package/claude/skills/teach-workspace/SKILL.md +0 -196
- package/claude/skills/teach-workspace/references/glossary.md +0 -90
- package/claude/skills/teach-workspace/references/lesson-build.md +0 -106
- package/claude/skills/teach-workspace/references/lesson-craft.md +0 -135
- package/claude/skills/teach-workspace/references/promotion-fold.md +0 -35
- package/claude/skills/teach-workspace/references/promotion.md +0 -116
- package/claude/skills/teach-workspace/references/revisit.md +0 -28
- package/claude/skills/teach-workspace/references/teach.md +0 -211
- package/claude/skills/video-craft/REQUIREMENT.md +0 -35
- package/claude/skills/video-craft/SKILL.md +0 -96
- package/claude/skills/video-craft/references/adopted.md +0 -110
- package/governance/rules/ui/canvas.md +0 -13
- package/src/canvas/address.ts +0 -227
- package/src/canvas/arrange.ts +0 -66
- package/src/canvas/capture.ts +0 -391
- package/src/canvas/client/app.tsx +0 -188
- package/src/canvas/client/inspector/align-grid.tsx +0 -162
- package/src/canvas/client/inspector/color-field.tsx +0 -398
- package/src/canvas/client/inspector/color-inputs.tsx +0 -139
- package/src/canvas/client/inspector/color-picker.tsx +0 -668
- package/src/canvas/client/inspector/color-space.ts +0 -240
- package/src/canvas/client/inspector/field.tsx +0 -263
- package/src/canvas/client/inspector/fields.css +0 -763
- package/src/canvas/client/inspector/section.tsx +0 -27
- package/src/canvas/client/inspector/size-field.tsx +0 -69
- package/src/canvas/client/inspector/token-select.tsx +0 -109
- package/src/canvas/client/inspector/values.ts +0 -297
- package/src/canvas/client/inspector.tsx +0 -692
- package/src/canvas/client/keys.ts +0 -71
- package/src/canvas/client/layers.tsx +0 -118
- package/src/canvas/client/main.tsx +0 -71
- package/src/canvas/client/pages-panel.tsx +0 -212
- package/src/canvas/client/panel-handle.tsx +0 -90
- package/src/canvas/client/selection.tsx +0 -199
- package/src/canvas/client/shell.css +0 -762
- package/src/canvas/client/state.ts +0 -792
- package/src/canvas/client/surface.tsx +0 -803
- package/src/canvas/client/theme-panel.tsx +0 -55
- package/src/canvas/client/tools.tsx +0 -153
- package/src/canvas/content.ts +0 -781
- package/src/canvas/edit.ts +0 -575
- package/src/canvas/editing.ts +0 -203
- package/src/canvas/fit.ts +0 -238
- package/src/canvas/global.d.ts +0 -15
- package/src/canvas/history.ts +0 -116
- package/src/canvas/index.html +0 -20
- package/src/canvas/server.ts +0 -766
- package/src/canvas/tokens.ts +0 -221
- package/src/commands/canvas.ts +0 -1097
- package/src/commands/demo.ts +0 -542
- package/src/commands/slides.ts +0 -184
- package/src/commands/teach.ts +0 -1401
- package/src/demo/beats.ts +0 -135
- package/src/demo/compile.ts +0 -350
- package/src/demo/container.ts +0 -219
- package/src/demo/cursors.ts +0 -55
- package/src/demo/drive.ts +0 -442
- package/src/demo/pointer.ts +0 -178
- package/src/demo/theme.ts +0 -112
- package/src/demo/timeline.ts +0 -64
- package/src/design/adapter.ts +0 -59
- package/src/design/base.css +0 -203
- package/src/design/brand-favicon.ts +0 -18
- package/src/design/neutral.ts +0 -127
- package/src/design/project-fonts.ts +0 -392
- package/src/slides/convert/chart.ts +0 -165
- package/src/slides/convert/deck.ts +0 -244
- package/src/slides/convert/export.ts +0 -567
- package/src/slides/convert/master.ts +0 -198
- package/src/slides/convert/shapes.ts +0 -804
- package/src/slides/convert/svg.ts +0 -38
- package/src/slides/convert/walk.ts +0 -671
- package/src/slides/decks.ts +0 -110
- package/src/slides/open.ts +0 -18
- package/src/slides/package/fonts.ts +0 -301
- package/src/slides/package/motion.ts +0 -316
- package/src/slides/package/test-face.ts +0 -113
- package/src/teach/browser/compile.ts +0 -44
- package/src/teach/browser/dismiss.ts +0 -76
- package/src/teach/browser/focus-line.ts +0 -19
- package/src/teach/browser/glossary-filter.ts +0 -44
- package/src/teach/browser/head.ts +0 -30
- package/src/teach/browser/quiz.ts +0 -19
- package/src/teach/browser/reload.ts +0 -9
- package/src/teach/browser/sidebar.ts +0 -233
- package/src/teach/browser/theme.ts +0 -18
- package/src/teach/components/code.tsx +0 -24
- package/src/teach/components/heading.tsx +0 -11
- package/src/teach/components/list.tsx +0 -17
- package/src/teach/components/paragraph.tsx +0 -29
- package/src/teach/components/refs.tsx +0 -28
- package/src/teach/cross-references.ts +0 -78
- package/src/teach/fonts.ts +0 -16
- package/src/teach/highlight.ts +0 -71
- package/src/teach/html/jsx-dev-runtime.ts +0 -13
- package/src/teach/html/jsx-runtime.ts +0 -113
- package/src/teach/html/raw.ts +0 -28
- package/src/teach/lesson.ts +0 -178
- package/src/teach/nav.ts +0 -1337
- package/src/teach/render.ts +0 -240
- package/src/teach/workspace.ts +0 -1164
- package/src/teach/write-if-changed.ts +0 -17
package/src/commands/design.ts
CHANGED
|
@@ -1,53 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { join, relative } from 'node:path'
|
|
3
3
|
import type { Command } from 'commander'
|
|
4
|
-
import {
|
|
5
|
-
createDesignAdapter,
|
|
6
|
-
DESIGN_INSTALL_DIR,
|
|
7
|
-
DESIGN_PROJECT_SUBDIR,
|
|
8
|
-
} from '@/design/adapter'
|
|
9
4
|
import { buildDesignCss } from '@/design/css'
|
|
10
5
|
import { HAND_DRAWN_FONT_FACES } from '@/design/fonts'
|
|
11
|
-
import {
|
|
12
|
-
import { renderDesignDoc } from '@/design/render'
|
|
13
|
-
import { DESIGN_BASE_CSS, DESIGN_DOCUMENT, regenDesign } from '@/design/regen'
|
|
6
|
+
import { DESIGN_DOCUMENT, regenDesign } from '@/design/regen'
|
|
14
7
|
import { checkoutMismatchWarning, PROJECT_ROOT } from '@/roots/project'
|
|
15
|
-
import {
|
|
16
|
-
import { surfaceDir } from '@/roots/surface'
|
|
17
|
-
import { recordStamp, runDomainSync } from '@/sync/engine'
|
|
18
|
-
import { isDirectory, resolveTarget } from '@/targets/validate'
|
|
19
|
-
import {
|
|
20
|
-
intro,
|
|
21
|
-
logAdd,
|
|
22
|
-
logError,
|
|
23
|
-
logInfo,
|
|
24
|
-
logWarn,
|
|
25
|
-
outro,
|
|
26
|
-
palette,
|
|
27
|
-
} from '@/cli/ui'
|
|
8
|
+
import { logWarn, palette } from '@/cli/ui'
|
|
28
9
|
|
|
29
10
|
export function register(program: Command): void {
|
|
30
11
|
const design = program
|
|
31
12
|
.command('design')
|
|
32
13
|
.helpOption('-h, --help', 'Show this help message')
|
|
33
|
-
.description(
|
|
34
|
-
'Design system commands (regen, css, render, install, sync, fonts)',
|
|
35
|
-
)
|
|
14
|
+
.description('Design system commands (regen, css)')
|
|
36
15
|
|
|
37
16
|
design
|
|
38
17
|
.command('regen')
|
|
39
18
|
.helpOption('-h, --help', 'Show this help message')
|
|
40
|
-
.description(
|
|
41
|
-
'Rewrite canon/DESIGN.md and the base stylesheet from src/design/tokens.ts',
|
|
42
|
-
)
|
|
19
|
+
.description('Rewrite canon/DESIGN.md from src/design/tokens.ts')
|
|
43
20
|
.addHelpText(
|
|
44
21
|
'after',
|
|
45
22
|
[
|
|
46
23
|
'',
|
|
47
|
-
'
|
|
48
|
-
'
|
|
49
|
-
'
|
|
50
|
-
'
|
|
24
|
+
'This runs against the toolkit checkout rather than a target. It',
|
|
25
|
+
'rewrites the record from the token module and refuses where the record',
|
|
26
|
+
'is absent, which is what the CLI installed into a project as a',
|
|
27
|
+
'dependency looks like.',
|
|
51
28
|
'',
|
|
52
29
|
].join('\n'),
|
|
53
30
|
)
|
|
@@ -60,10 +37,10 @@ export function register(program: Command): void {
|
|
|
60
37
|
// so each emits it after its own opener rather than ahead of the branch.
|
|
61
38
|
const mismatch = checkoutMismatchWarning(process.cwd())
|
|
62
39
|
|
|
63
|
-
//
|
|
40
|
+
// The output resolves from `PROJECT_ROOT`, which is the installed
|
|
64
41
|
// package directory when the CLI runs out of a target's `node_modules`.
|
|
65
|
-
// The record is
|
|
66
|
-
//
|
|
42
|
+
// The record is already committed here and ships with no package, so
|
|
43
|
+
// its absence is what separates the two.
|
|
67
44
|
if (!existsSync(join(PROJECT_ROOT, DESIGN_DOCUMENT))) {
|
|
68
45
|
process.stderr.write(`${GREY}┌${NC}\n`)
|
|
69
46
|
if (mismatch !== undefined) logWarn(mismatch)
|
|
@@ -79,11 +56,9 @@ export function register(program: Command): void {
|
|
|
79
56
|
)
|
|
80
57
|
if (mismatch !== undefined) logWarn(mismatch)
|
|
81
58
|
const result = regenDesign(PROJECT_ROOT)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
}
|
|
59
|
+
process.stderr.write(
|
|
60
|
+
`${GREY}│${NC} ${GREEN}✓${NC} ${relative(PROJECT_ROOT, result.documentPath)}\n`,
|
|
61
|
+
)
|
|
87
62
|
process.stderr.write(`${GREY}└${NC}\n`)
|
|
88
63
|
})
|
|
89
64
|
|
|
@@ -107,278 +82,4 @@ export function register(program: Command): void {
|
|
|
107
82
|
}),
|
|
108
83
|
)
|
|
109
84
|
})
|
|
110
|
-
|
|
111
|
-
design
|
|
112
|
-
.command('render')
|
|
113
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
114
|
-
.description('Render DESIGN.md tokens to HTML and CSS preview')
|
|
115
|
-
.option(
|
|
116
|
-
'-s, --source <path>',
|
|
117
|
-
'Source DESIGN.md path',
|
|
118
|
-
relative(process.cwd(), surfaceDir(process.cwd(), 'DESIGN.md')),
|
|
119
|
-
)
|
|
120
|
-
.option(
|
|
121
|
-
'-o, --out <path>',
|
|
122
|
-
'Output directory',
|
|
123
|
-
creationRel(process.cwd(), SCRATCH, 'render', 'design'),
|
|
124
|
-
)
|
|
125
|
-
.option(
|
|
126
|
-
'--embed-fonts',
|
|
127
|
-
'Declare each vendored face the typography table names, and set the page body in the body stack',
|
|
128
|
-
)
|
|
129
|
-
.action((opts: { source: string; out: string; embedFonts?: boolean }) => {
|
|
130
|
-
const sourcePath = resolve(process.cwd(), opts.source)
|
|
131
|
-
const outDir = resolve(process.cwd(), opts.out)
|
|
132
|
-
const { GREEN, GREY, NC, RED, WHITE } = palette(process.stderr)
|
|
133
|
-
if (!existsSync(sourcePath)) {
|
|
134
|
-
process.stderr.write(
|
|
135
|
-
`${GREY}┌${NC}\n${GREY}│${NC} ${RED}✗${NC} ${opts.source} not found\n${GREY}└${NC}\n`,
|
|
136
|
-
)
|
|
137
|
-
process.exitCode = 1
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
process.stderr.write(
|
|
141
|
-
`${GREY}┌${NC}\n${GREY}│${NC} ${WHITE}Render design tokens${NC}\n`,
|
|
142
|
-
)
|
|
143
|
-
const result = renderDesignDoc(sourcePath, outDir, {
|
|
144
|
-
embedFonts: opts.embedFonts,
|
|
145
|
-
})
|
|
146
|
-
process.stderr.write(
|
|
147
|
-
`${GREY}│${NC} ${GREEN}✓${NC} ${result.htmlPath}\n${GREY}│${NC} ${GREEN}✓${NC} ${result.cssPath}\n${GREY}└${NC}\n`,
|
|
148
|
-
)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
design
|
|
152
|
-
.command('install')
|
|
153
|
-
.description('Install the base stylesheet into a project')
|
|
154
|
-
.argument('[target]', 'Target directory', '.')
|
|
155
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
156
|
-
.addHelpText(
|
|
157
|
-
'after',
|
|
158
|
-
[
|
|
159
|
-
'',
|
|
160
|
-
'Installs one toolkit-owned file and creates no override. A project',
|
|
161
|
-
`overrides a value by writing ${join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR)}/`,
|
|
162
|
-
'itself, which sync never touches. Nothing arrives on a project that',
|
|
163
|
-
'has not run this, so a design value reaches a target on an install',
|
|
164
|
-
'rather than on the next sync. A base stylesheet already installed is',
|
|
165
|
-
'replaced.',
|
|
166
|
-
'',
|
|
167
|
-
'Exit codes:',
|
|
168
|
-
' 0 the stylesheet was installed',
|
|
169
|
-
' 1 the target is missing or is the toolkit root, or the toolkit',
|
|
170
|
-
' source is absent',
|
|
171
|
-
'',
|
|
172
|
-
].join('\n'),
|
|
173
|
-
)
|
|
174
|
-
.action(async (target: string) => {
|
|
175
|
-
process.exitCode = await runInstall(target)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
design
|
|
179
|
-
.command('sync')
|
|
180
|
-
.description(
|
|
181
|
-
'Update the base stylesheet already installed under .claude/design/',
|
|
182
|
-
)
|
|
183
|
-
.argument('[target]', 'Target directory', '.')
|
|
184
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
185
|
-
.addHelpText(
|
|
186
|
-
'after',
|
|
187
|
-
[
|
|
188
|
-
'',
|
|
189
|
-
'Replaces the shipped design files under .claude/design/ with the',
|
|
190
|
-
'toolkit copy, edited or not, and leaves',
|
|
191
|
-
`${join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR)}/ alone. It deletes nothing it finds no`,
|
|
192
|
-
'source for.',
|
|
193
|
-
'',
|
|
194
|
-
'Exit codes:',
|
|
195
|
-
' 0 synced, already up to date, or the prompt was cancelled',
|
|
196
|
-
' 1 the target is missing or is the toolkit root',
|
|
197
|
-
'',
|
|
198
|
-
].join('\n'),
|
|
199
|
-
)
|
|
200
|
-
.action(async (target: string) => {
|
|
201
|
-
process.exitCode = await runDomainSync(
|
|
202
|
-
createDesignAdapter(PROJECT_ROOT),
|
|
203
|
-
target,
|
|
204
|
-
{ protectedRoot: PROJECT_ROOT },
|
|
205
|
-
)
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
registerFonts(design)
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const FONTS_DIR = join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR, 'fonts')
|
|
212
|
-
|
|
213
|
-
interface FontsRefused {
|
|
214
|
-
readonly ok: false
|
|
215
|
-
readonly reason: string
|
|
216
|
-
readonly detail: string
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function writeJson(record: unknown): void {
|
|
220
|
-
process.stdout.write(`${JSON.stringify(record)}\n`)
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function refuseFonts(
|
|
224
|
-
title: string,
|
|
225
|
-
refusal: FontsRefused,
|
|
226
|
-
emitJson: boolean,
|
|
227
|
-
): number {
|
|
228
|
-
if (emitJson) writeJson(refusal)
|
|
229
|
-
intro(title)
|
|
230
|
-
logError(refusal.detail)
|
|
231
|
-
outro()
|
|
232
|
-
return 1
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
/** A target that is a directory, or the refusal naming the path given. */
|
|
236
|
-
function fontsTarget(target: string): string | FontsRefused {
|
|
237
|
-
const resolved = resolve(target)
|
|
238
|
-
if (!isDirectory(resolved)) {
|
|
239
|
-
return {
|
|
240
|
-
ok: false,
|
|
241
|
-
reason: 'no-target',
|
|
242
|
-
detail: `Target directory not found: ${target}`,
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
return resolved
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function registerFonts(design: Command): void {
|
|
249
|
-
const fonts = design
|
|
250
|
-
.command('fonts')
|
|
251
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
252
|
-
.description(`Read and add the project's own faces under ${FONTS_DIR}/`)
|
|
253
|
-
.addHelpText(
|
|
254
|
-
'after',
|
|
255
|
-
[
|
|
256
|
-
'',
|
|
257
|
-
`Faces are declared as @font-face rules in ${join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR)}/fonts.css,`,
|
|
258
|
-
'which the canvas embeds into every frame. Sync never writes the folder.',
|
|
259
|
-
'',
|
|
260
|
-
].join('\n'),
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
fonts
|
|
264
|
-
.command('list')
|
|
265
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
266
|
-
.description('List each face the project override sheets declare')
|
|
267
|
-
.argument('[target]', 'Target directory', '.')
|
|
268
|
-
.option('--json', 'Emit the record on stdout')
|
|
269
|
-
.action((target: string, opts: { json?: boolean }) => {
|
|
270
|
-
const title = 'canon design fonts list'
|
|
271
|
-
const resolved = fontsTarget(target)
|
|
272
|
-
if (typeof resolved !== 'string') {
|
|
273
|
-
process.exitCode = refuseFonts(title, resolved, Boolean(opts.json))
|
|
274
|
-
return
|
|
275
|
-
}
|
|
276
|
-
const faces = listProjectFaces(resolved)
|
|
277
|
-
if (opts.json) writeJson({ ok: true, faces })
|
|
278
|
-
intro(title)
|
|
279
|
-
if (faces.length === 0) logInfo(`No faces declared under ${FONTS_DIR}/`)
|
|
280
|
-
for (const face of faces) {
|
|
281
|
-
const line = `${face.family} ${face.weight} ${face.style}: ${face.file} in ${face.sheet}`
|
|
282
|
-
if (face.present) logInfo(line)
|
|
283
|
-
else logWarn(`${line} (${face.problem ?? 'missing'})`)
|
|
284
|
-
}
|
|
285
|
-
outro()
|
|
286
|
-
})
|
|
287
|
-
|
|
288
|
-
fonts
|
|
289
|
-
.command('add')
|
|
290
|
-
.helpOption('-h, --help', 'Show this help message')
|
|
291
|
-
.description(
|
|
292
|
-
`Copy a woff2, woff, ttf, or otf face into ${FONTS_DIR}/ and declare it`,
|
|
293
|
-
)
|
|
294
|
-
.argument('<file>', 'Font file to copy')
|
|
295
|
-
.argument('[target]', 'Target directory', '.')
|
|
296
|
-
.requiredOption('--family <name>', 'Family name the face declares')
|
|
297
|
-
.option('--weight <n>', "Weight, or a range such as '100 900'", '400')
|
|
298
|
-
.option('--style <style>', 'normal or italic', 'normal')
|
|
299
|
-
.option('--json', 'Emit the record on stdout')
|
|
300
|
-
.action(
|
|
301
|
-
(
|
|
302
|
-
file: string,
|
|
303
|
-
target: string,
|
|
304
|
-
opts: { family: string; weight: string; style: string; json?: boolean },
|
|
305
|
-
) => {
|
|
306
|
-
const title = 'canon design fonts add'
|
|
307
|
-
const emitJson = Boolean(opts.json)
|
|
308
|
-
const resolved = fontsTarget(target)
|
|
309
|
-
if (typeof resolved !== 'string') {
|
|
310
|
-
process.exitCode = refuseFonts(title, resolved, emitJson)
|
|
311
|
-
return
|
|
312
|
-
}
|
|
313
|
-
if (resolved === PROJECT_ROOT) {
|
|
314
|
-
process.exitCode = refuseFonts(
|
|
315
|
-
title,
|
|
316
|
-
{
|
|
317
|
-
ok: false,
|
|
318
|
-
reason: 'toolkit-root',
|
|
319
|
-
detail:
|
|
320
|
-
'Cannot run against toolkit root. Files here are the source of truth.',
|
|
321
|
-
},
|
|
322
|
-
emitJson,
|
|
323
|
-
)
|
|
324
|
-
return
|
|
325
|
-
}
|
|
326
|
-
const outcome = addProjectFace(resolved, resolve(file), {
|
|
327
|
-
family: opts.family,
|
|
328
|
-
weight: opts.weight,
|
|
329
|
-
style: opts.style,
|
|
330
|
-
})
|
|
331
|
-
if (!outcome.ok) {
|
|
332
|
-
process.exitCode = refuseFonts(title, outcome, emitJson)
|
|
333
|
-
return
|
|
334
|
-
}
|
|
335
|
-
if (emitJson) writeJson(outcome)
|
|
336
|
-
intro(title)
|
|
337
|
-
logAdd(join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR, outcome.file))
|
|
338
|
-
logInfo(
|
|
339
|
-
`Declared ${outcome.family} ${outcome.weight} ${outcome.style} in ${outcome.sheet}`,
|
|
340
|
-
)
|
|
341
|
-
outro()
|
|
342
|
-
},
|
|
343
|
-
)
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Copies the base and stops. The override folder is deliberately not created:
|
|
348
|
-
* an empty override is a file the project did not ask for and did not write,
|
|
349
|
-
* the three-way merge already handles a missing side, and an empty file invites
|
|
350
|
-
* a target to fill it before it has an opinion.
|
|
351
|
-
*/
|
|
352
|
-
async function runInstall(target: string): Promise<number> {
|
|
353
|
-
intro('canon design install')
|
|
354
|
-
|
|
355
|
-
const resolved = resolveTarget(target, PROJECT_ROOT)
|
|
356
|
-
if (typeof resolved === 'number') {
|
|
357
|
-
outro()
|
|
358
|
-
return resolved
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const source = join(PROJECT_ROOT, DESIGN_BASE_CSS)
|
|
362
|
-
if (!existsSync(source)) {
|
|
363
|
-
logError(
|
|
364
|
-
`No base stylesheet at ${DESIGN_BASE_CSS}. Run canon design regen.`,
|
|
365
|
-
)
|
|
366
|
-
outro()
|
|
367
|
-
return 1
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const dir = join(resolved, DESIGN_INSTALL_DIR)
|
|
371
|
-
mkdirSync(dir, { recursive: true })
|
|
372
|
-
|
|
373
|
-
const dest = join(dir, basename(source))
|
|
374
|
-
copyFileSync(source, dest)
|
|
375
|
-
logAdd(relative(resolved, dest))
|
|
376
|
-
|
|
377
|
-
await recordStamp(createDesignAdapter(PROJECT_ROOT), resolved, new Date())
|
|
378
|
-
|
|
379
|
-
logInfo(
|
|
380
|
-
`Override a value in ${join(DESIGN_INSTALL_DIR, DESIGN_PROJECT_SUBDIR)}/, which sync leaves alone.`,
|
|
381
|
-
)
|
|
382
|
-
outro()
|
|
383
|
-
return 0
|
|
384
85
|
}
|
package/src/commands/records.ts
CHANGED
|
@@ -127,7 +127,6 @@ export function register(program: Command): void {
|
|
|
127
127
|
'Examples:',
|
|
128
128
|
' canon records validate plans',
|
|
129
129
|
' canon records validate plans feature-records-by-heading',
|
|
130
|
-
' canon records validate teach',
|
|
131
130
|
' canon records validate intake --json',
|
|
132
131
|
'',
|
|
133
132
|
].join('\n'),
|
package/src/commands/serve.ts
CHANGED
|
@@ -40,8 +40,8 @@ export function register(program: Command): void {
|
|
|
40
40
|
'starts it in the background and reads the record off stdout.',
|
|
41
41
|
'',
|
|
42
42
|
'Examples:',
|
|
43
|
-
' canon serve
|
|
44
|
-
' canon serve
|
|
43
|
+
' canon serve site',
|
|
44
|
+
' canon serve site --entry guide/index.html',
|
|
45
45
|
' canon serve dist --port 4000 --json',
|
|
46
46
|
' canon serve .canon/groundwork --index',
|
|
47
47
|
'',
|
package/src/commands/sync.ts
CHANGED
|
@@ -35,7 +35,6 @@ import { describeSkew } from '@/version/skew'
|
|
|
35
35
|
|
|
36
36
|
const SYNC_ARGS: Record<SyncDomain, readonly string[]> = {
|
|
37
37
|
governance: ['gov', 'sync'],
|
|
38
|
-
design: ['design', 'sync'],
|
|
39
38
|
claude: ['claude', 'sync'],
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -58,10 +57,10 @@ export function register(program: Command): void {
|
|
|
58
57
|
'after',
|
|
59
58
|
[
|
|
60
59
|
'',
|
|
61
|
-
'Runs `canon gov sync
|
|
62
|
-
'
|
|
63
|
-
'
|
|
64
|
-
'
|
|
60
|
+
'Runs `canon gov sync` and `canon claude sync` on each domain',
|
|
61
|
+
'installed, so each carries its own replace behavior: governance',
|
|
62
|
+
'replaces an edited rule and deletes a retired one, and claude writes',
|
|
63
|
+
'.gitignore alone.',
|
|
65
64
|
'Tooling is not synced. Refuses a dirty working tree.',
|
|
66
65
|
'',
|
|
67
66
|
'Exit codes:',
|