@erclx/canon 5.51.0 → 5.53.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 +20 -0
- package/README.md +1 -4
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-cli/SKILL.md +0 -3
- package/claude/skills/context-fold/REQUIREMENT.md +0 -1
- package/claude/skills/design-taste/references/kinds.md +0 -1
- package/claude/skills/draw-figure/REQUIREMENT.md +2 -3
- package/claude/skills/draw-figure/SKILL.md +4 -5
- package/claude/skills/draw-figure/references/figures.md +0 -1
- package/claude/skills/draw-figure/references/hand-drawn.md +1 -1
- package/claude/skills/git-pr/references/pr.md +1 -1
- package/claude/skills/pick-by-eye/REQUIREMENT.md +0 -1
- package/claude/skills/pick-by-eye/SKILL.md +1 -1
- package/claude/skills/review-address/SKILL.md +1 -1
- package/claude/skills/review-address/references/post-review-findings.md +1 -1
- package/claude/skills/review-pr/references/post.md +2 -2
- package/claude/skills/target-check/SKILL.md +2 -0
- package/claude/skills/target-setup/SKILL.md +1 -1
- package/claude/skills/target-update/REQUIREMENT.md +33 -0
- package/claude/skills/target-update/SKILL.md +136 -0
- package/claude/skills/teach-craft/REQUIREMENT.md +30 -0
- package/claude/skills/teach-craft/SKILL.md +39 -0
- package/claude/skills/teach-craft/references/lesson-craft.md +52 -0
- package/claude/skills/{teach-workspace → teach-craft}/references/pedagogy.md +12 -4
- package/docs/agents/audits.md +0 -1
- package/docs/agents/migrate.md +2 -1
- package/docs/target/migrations.md +12 -1
- package/docs/target/projects.md +1 -1
- package/docs/target/sync.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 +13 -14
- package/package.json +1 -4
- 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 -17
- package/src/claude/cases/setup.ts +7 -0
- package/src/claude/cases/workflow.ts +2 -38
- package/src/claude/skills-audit.ts +0 -1
- package/src/cli/help.ts +0 -7
- package/src/cli.ts +0 -6
- package/src/commands/labels.ts +9 -7
- package/src/commands/records.ts +0 -1
- package/src/commands/serve.ts +2 -2
- package/src/design/components.ts +8 -1514
- package/src/design/css.ts +5 -6
- package/src/design/fonts.ts +3 -5
- package/src/driver/drive.ts +3 -4
- package/src/driver/steps.ts +2 -5
- package/src/inventory/walk.ts +1 -1
- package/src/markdown/scope.ts +4 -31
- package/src/migrate/status.ts +5 -1
- package/src/records/validate.ts +4 -176
- package/src/sandbox/equivalence.ts +0 -5
- package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +1 -1
- 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/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/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/teach/render.ts
DELETED
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import { Code } from '@/teach/components/code'
|
|
2
|
-
import { Heading } from '@/teach/components/heading'
|
|
3
|
-
import { List } from '@/teach/components/list'
|
|
4
|
-
import { Paragraph } from '@/teach/components/paragraph'
|
|
5
|
-
import { type Reference, Refs } from '@/teach/components/refs'
|
|
6
|
-
import { render } from '@/teach/html/jsx-runtime'
|
|
7
|
-
import type { TeachRefused } from '@/teach/workspace'
|
|
8
|
-
|
|
9
|
-
export type LessonBlock =
|
|
10
|
-
| { readonly type: 'heading'; readonly level: 1 | 2; readonly text: string }
|
|
11
|
-
| {
|
|
12
|
-
readonly type: 'paragraph'
|
|
13
|
-
readonly text: string
|
|
14
|
-
readonly lede?: boolean
|
|
15
|
-
readonly cites?: readonly number[]
|
|
16
|
-
}
|
|
17
|
-
| {
|
|
18
|
-
readonly type: 'list'
|
|
19
|
-
readonly items: readonly string[]
|
|
20
|
-
readonly ordered?: boolean
|
|
21
|
-
}
|
|
22
|
-
| { readonly type: 'refs'; readonly items: readonly Reference[] }
|
|
23
|
-
| { readonly type: 'code'; readonly text: string; readonly lang?: string }
|
|
24
|
-
| { readonly type: 'raw'; readonly html: string }
|
|
25
|
-
|
|
26
|
-
export interface RenderRendered {
|
|
27
|
-
readonly ok: true
|
|
28
|
-
readonly html: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type RenderOutcome = RenderRendered | TeachRefused
|
|
32
|
-
|
|
33
|
-
const BLOCK_TYPES = [
|
|
34
|
-
'heading',
|
|
35
|
-
'paragraph',
|
|
36
|
-
'list',
|
|
37
|
-
'refs',
|
|
38
|
-
'code',
|
|
39
|
-
'raw',
|
|
40
|
-
] as const
|
|
41
|
-
|
|
42
|
-
/** Bounds a lang to what a class name can carry, so it never injects. */
|
|
43
|
-
const CODE_LANG = /^[a-z0-9+#-]+$/
|
|
44
|
-
|
|
45
|
-
const LINK_PROTOCOLS = new Set(['http:', 'https:'])
|
|
46
|
-
|
|
47
|
-
function isBlockType(value: unknown): value is LessonBlock['type'] {
|
|
48
|
-
return (BLOCK_TYPES as readonly string[]).includes(value as string)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function badBlock(index: number, message: string): TeachRefused {
|
|
52
|
-
return {
|
|
53
|
-
ok: false,
|
|
54
|
-
reason: 'bad-input',
|
|
55
|
-
message: `Block ${index}: ${message}`,
|
|
56
|
-
detail: [],
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function isString(value: unknown): value is string {
|
|
61
|
-
return typeof value === 'string'
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function isStringArray(value: unknown): value is readonly string[] {
|
|
65
|
-
return Array.isArray(value) && value.every(isString)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function isCiteArray(value: unknown): value is readonly number[] {
|
|
69
|
-
return (
|
|
70
|
-
Array.isArray(value) &&
|
|
71
|
-
value.length > 0 &&
|
|
72
|
-
value.every((cite) => Number.isInteger(cite) && cite > 0)
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function isLinkUrl(value: string): boolean {
|
|
77
|
-
if (!URL.canParse(value)) return false
|
|
78
|
-
return LINK_PROTOCOLS.has(new URL(value).protocol)
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function readReference(item: unknown, position: number): Reference | string {
|
|
82
|
-
if (typeof item !== 'object' || item === null) {
|
|
83
|
-
return `reference ${position} is not an object`
|
|
84
|
-
}
|
|
85
|
-
const { title, url, note } = item as Record<string, unknown>
|
|
86
|
-
if (!isString(title) || title === '') {
|
|
87
|
-
return `reference ${position} needs a non-empty string title`
|
|
88
|
-
}
|
|
89
|
-
if (note !== undefined && !isString(note)) {
|
|
90
|
-
return `reference ${position} note must be a string`
|
|
91
|
-
}
|
|
92
|
-
if (url !== undefined && !(isString(url) && isLinkUrl(url))) {
|
|
93
|
-
return `reference ${position} url must be an http or https URL`
|
|
94
|
-
}
|
|
95
|
-
return { title, url, note }
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
interface RenderedBlock {
|
|
99
|
-
readonly html: string
|
|
100
|
-
readonly cites?: readonly number[]
|
|
101
|
-
readonly referenceCount?: number
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function renderBlock(
|
|
105
|
-
block: unknown,
|
|
106
|
-
index: number,
|
|
107
|
-
): RenderedBlock | TeachRefused {
|
|
108
|
-
if (typeof block !== 'object' || block === null || !('type' in block)) {
|
|
109
|
-
return badBlock(index, 'not an object carrying a type')
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const type = (block as { readonly type: unknown }).type
|
|
113
|
-
|
|
114
|
-
if (!isBlockType(type)) {
|
|
115
|
-
return badBlock(index, `unrecognized type ${JSON.stringify(type)}`)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const fields = block as Record<string, unknown>
|
|
119
|
-
|
|
120
|
-
switch (type) {
|
|
121
|
-
case 'heading': {
|
|
122
|
-
if (fields.level !== 1 && fields.level !== 2) {
|
|
123
|
-
return badBlock(index, 'heading needs level 1 or 2')
|
|
124
|
-
}
|
|
125
|
-
if (!isString(fields.text)) {
|
|
126
|
-
return badBlock(index, 'heading needs a string text')
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
html: render(Heading({ level: fields.level, children: fields.text })),
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
case 'paragraph': {
|
|
133
|
-
if (!isString(fields.text)) {
|
|
134
|
-
return badBlock(index, 'paragraph needs a string text')
|
|
135
|
-
}
|
|
136
|
-
if (fields.lede !== undefined && typeof fields.lede !== 'boolean') {
|
|
137
|
-
return badBlock(index, 'paragraph lede must be a boolean')
|
|
138
|
-
}
|
|
139
|
-
if (fields.cites !== undefined && !isCiteArray(fields.cites)) {
|
|
140
|
-
return badBlock(
|
|
141
|
-
index,
|
|
142
|
-
'paragraph cites must be a non-empty array of positive integers',
|
|
143
|
-
)
|
|
144
|
-
}
|
|
145
|
-
if (fields.lede === true && fields.cites !== undefined) {
|
|
146
|
-
return badBlock(index, 'a lede paragraph cannot carry cites')
|
|
147
|
-
}
|
|
148
|
-
return {
|
|
149
|
-
html: render(
|
|
150
|
-
Paragraph({
|
|
151
|
-
lede: fields.lede,
|
|
152
|
-
cites: fields.cites,
|
|
153
|
-
children: fields.text,
|
|
154
|
-
}),
|
|
155
|
-
),
|
|
156
|
-
cites: fields.cites,
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
case 'list': {
|
|
160
|
-
if (!isStringArray(fields.items)) {
|
|
161
|
-
return badBlock(index, 'list needs an items array of strings')
|
|
162
|
-
}
|
|
163
|
-
if (fields.ordered !== undefined && typeof fields.ordered !== 'boolean') {
|
|
164
|
-
return badBlock(index, 'list ordered must be a boolean')
|
|
165
|
-
}
|
|
166
|
-
return {
|
|
167
|
-
html: render(List({ ordered: fields.ordered, items: fields.items })),
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
case 'refs': {
|
|
171
|
-
if (!Array.isArray(fields.items) || fields.items.length === 0) {
|
|
172
|
-
return badBlock(index, 'refs needs a non-empty items array')
|
|
173
|
-
}
|
|
174
|
-
const items: Reference[] = []
|
|
175
|
-
for (const [position, item] of fields.items.entries()) {
|
|
176
|
-
const reference = readReference(item, position + 1)
|
|
177
|
-
if (isString(reference)) return badBlock(index, reference)
|
|
178
|
-
items.push(reference)
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
html: render(Refs({ items })),
|
|
182
|
-
referenceCount: items.length,
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
case 'code': {
|
|
186
|
-
if (!isString(fields.text)) {
|
|
187
|
-
return badBlock(index, 'code needs a string text')
|
|
188
|
-
}
|
|
189
|
-
if (
|
|
190
|
-
fields.lang !== undefined &&
|
|
191
|
-
!(isString(fields.lang) && CODE_LANG.test(fields.lang))
|
|
192
|
-
) {
|
|
193
|
-
return badBlock(index, `code lang must match ${CODE_LANG.source}`)
|
|
194
|
-
}
|
|
195
|
-
return {
|
|
196
|
-
html: render(Code({ lang: fields.lang, text: fields.text })),
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
case 'raw': {
|
|
200
|
-
if (!isString(fields.html)) {
|
|
201
|
-
return badBlock(index, 'raw needs a string html')
|
|
202
|
-
}
|
|
203
|
-
return { html: fields.html }
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Renders a lesson body's structural blocks through the same components
|
|
210
|
-
* `lesson.test.tsx` composes as JSX, so a real lesson and the component test
|
|
211
|
-
* share one rendering mechanism. Every block past the first refusal
|
|
212
|
-
* goes unread, matching how a malformed JSON parse refuses the whole call.
|
|
213
|
-
* Citations resolve across blocks once every block has rendered, so a marker
|
|
214
|
-
* with no reference refuses rather than leaving a dead anchor.
|
|
215
|
-
*/
|
|
216
|
-
export function renderLessonBody(blocks: readonly unknown[]): RenderOutcome {
|
|
217
|
-
const rendered: RenderedBlock[] = []
|
|
218
|
-
let referenceCount = 0
|
|
219
|
-
|
|
220
|
-
for (const [index, block] of blocks.entries()) {
|
|
221
|
-
const result = renderBlock(block, index)
|
|
222
|
-
if ('ok' in result) return result
|
|
223
|
-
if (result.referenceCount !== undefined) {
|
|
224
|
-
if (referenceCount > 0) {
|
|
225
|
-
return badBlock(index, 'a lesson carries one refs block')
|
|
226
|
-
}
|
|
227
|
-
referenceCount = result.referenceCount
|
|
228
|
-
}
|
|
229
|
-
rendered.push(result)
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
for (const [index, block] of rendered.entries()) {
|
|
233
|
-
const dangling = block.cites?.find((cite) => cite > referenceCount)
|
|
234
|
-
if (dangling !== undefined) {
|
|
235
|
-
return badBlock(index, `cite ${dangling} resolves to no reference`)
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
return { ok: true, html: rendered.map((block) => block.html).join('\n') }
|
|
240
|
-
}
|