@cyber-dash-tech/revela 0.17.22 → 0.17.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.
- package/lib/design/designs.ts +123 -39
- package/lib/runtime/index.ts +44 -4
- package/package.json +1 -1
- package/plugins/revela/.mcp.json +1 -1
- package/plugins/revela/mcp/revela-server.ts +39 -0
- package/plugins/revela/skills/revela-design/SKILL.md +7 -5
- package/plugins/revela/skills/revela-make-deck/SKILL.md +10 -9
package/lib/design/designs.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DesignManager — manage revela visual design templates.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* User designs are stored in ~/.config/revela/designs/<name>/.
|
|
5
|
+
* Built-in designs are shipped read-only with this package under designs/<name>/.
|
|
5
6
|
* Each design directory contains DESIGN.md (required) and optionally preview.html.
|
|
6
|
-
*
|
|
7
|
-
* Built-in designs are shipped with the npm package under designs/ and seeded
|
|
8
|
-
* to the config directory on first run.
|
|
9
7
|
*/
|
|
10
8
|
|
|
11
9
|
import {
|
|
@@ -152,21 +150,46 @@ export function parseDesignFile(filePath: string): DesignInfo | null {
|
|
|
152
150
|
// Public API
|
|
153
151
|
// ---------------------------------------------------------------------------
|
|
154
152
|
|
|
155
|
-
|
|
153
|
+
function designDirHasPackage(dir: string): boolean {
|
|
154
|
+
return existsSync(dir) && statSync(dir).isDirectory() && existsSync(join(dir, "DESIGN.md"))
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function resolveDesignDir(nameInput?: string): string | null {
|
|
158
|
+
const name = normalizeDesignName(nameInput || activeDesign())
|
|
159
|
+
const userDir = join(DESIGNS_DIR, name)
|
|
160
|
+
if (designDirHasPackage(userDir)) return userDir
|
|
161
|
+
|
|
162
|
+
const bundledDir = join(SEED_DIR, name)
|
|
163
|
+
if (designDirHasPackage(bundledDir)) return bundledDir
|
|
164
|
+
|
|
165
|
+
return null
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function readDesignsFromDir(root: string): Map<string, DesignInfo> {
|
|
169
|
+
const designs = new Map<string, DesignInfo>()
|
|
170
|
+
if (!existsSync(root)) return designs
|
|
171
|
+
|
|
172
|
+
for (const entry of readdirSync(root).sort()) {
|
|
173
|
+
const dir = join(root, entry)
|
|
174
|
+
if (!designDirHasPackage(dir)) continue
|
|
175
|
+
const info = parseDesignFile(join(dir, "DESIGN.md"))
|
|
176
|
+
if (info) designs.set(entry, info)
|
|
177
|
+
}
|
|
178
|
+
return designs
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** List available designs, sorted by name. User designs override bundled designs with the same name. Internal designs are hidden by default. */
|
|
156
182
|
export function listDesigns(options: ListDesignsOptions = {}): DesignInfo[] {
|
|
157
|
-
if (!existsSync(DESIGNS_DIR)) return []
|
|
158
|
-
const results: DesignInfo[] = []
|
|
159
183
|
const includeInternal = options.includeInternal ?? false
|
|
184
|
+
const available = readDesignsFromDir(SEED_DIR)
|
|
160
185
|
|
|
161
|
-
for (const entry of
|
|
162
|
-
|
|
163
|
-
if (!statSync(dir).isDirectory()) continue
|
|
164
|
-
const mdPath = join(dir, "DESIGN.md")
|
|
165
|
-
if (!existsSync(mdPath)) continue
|
|
166
|
-
const info = parseDesignFile(mdPath)
|
|
167
|
-
if (info && (includeInternal || !info.internal)) results.push(info)
|
|
186
|
+
for (const [entry, info] of readDesignsFromDir(DESIGNS_DIR)) {
|
|
187
|
+
available.set(entry, info)
|
|
168
188
|
}
|
|
169
|
-
|
|
189
|
+
|
|
190
|
+
return [...available.values()]
|
|
191
|
+
.filter((info) => includeInternal || !info.internal)
|
|
192
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
170
193
|
}
|
|
171
194
|
|
|
172
195
|
/** Get the name of the currently active design. */
|
|
@@ -187,11 +210,12 @@ export function activateDesign(name: string): void {
|
|
|
187
210
|
|
|
188
211
|
/** Get the skill text body from a design's DESIGN.md. */
|
|
189
212
|
export function getDesignSkillMd(name?: string): string {
|
|
190
|
-
const designName = name || activeDesign()
|
|
191
|
-
const
|
|
192
|
-
if (!
|
|
213
|
+
const designName = normalizeDesignName(name || activeDesign())
|
|
214
|
+
const designDir = resolveDesignDir(designName)
|
|
215
|
+
if (!designDir) {
|
|
193
216
|
throw new Error(`Design '${designName}' is not installed`)
|
|
194
217
|
}
|
|
218
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
195
219
|
const info = parseDesignFile(mdPath)
|
|
196
220
|
if (!info) {
|
|
197
221
|
throw new Error(`Failed to parse DESIGN.md for '${designName}'`)
|
|
@@ -202,9 +226,8 @@ export function getDesignSkillMd(name?: string): string {
|
|
|
202
226
|
/** Resolve a design's preview.html path. Throws if the design is not installed. */
|
|
203
227
|
export function resolveDesignPreview(name?: string): DesignPreviewInfo {
|
|
204
228
|
const designName = normalizeDesignName(name || activeDesign())
|
|
205
|
-
const designDir =
|
|
206
|
-
|
|
207
|
-
if (!existsSync(designDir) || !existsSync(mdPath)) {
|
|
229
|
+
const designDir = resolveDesignDir(designName)
|
|
230
|
+
if (!designDir) {
|
|
208
231
|
throw new Error(`Design '${designName}' is not installed`)
|
|
209
232
|
}
|
|
210
233
|
|
|
@@ -388,12 +411,15 @@ function hasFixedSizeCssRule(html: string, className: "slide-canvas"): boolean {
|
|
|
388
411
|
/** Validate a local design package for the minimum Revela design contract. */
|
|
389
412
|
export function validateDesignPackage(nameInput: string): ValidateDesignPackageResult {
|
|
390
413
|
let name = nameInput
|
|
414
|
+
let hasValidName = true
|
|
391
415
|
try {
|
|
392
416
|
name = normalizeDesignName(nameInput)
|
|
393
417
|
} catch {
|
|
418
|
+
hasValidName = false
|
|
394
419
|
// validateDesignPackageAt records the invalid-name error.
|
|
395
420
|
}
|
|
396
|
-
|
|
421
|
+
const dir = hasValidName ? resolveDesignDir(name) || join(DESIGNS_DIR, name) : join(DESIGNS_DIR, name)
|
|
422
|
+
return validateDesignPackageAt(nameInput, dir)
|
|
397
423
|
}
|
|
398
424
|
|
|
399
425
|
function validateDesignPackageAt(nameInput: string, dir: string): ValidateDesignPackageResult {
|
|
@@ -493,6 +519,25 @@ export interface DesignSections {
|
|
|
493
519
|
hasMarkers: boolean
|
|
494
520
|
}
|
|
495
521
|
|
|
522
|
+
export interface DesignInventoryLayout {
|
|
523
|
+
name: string
|
|
524
|
+
qa: boolean
|
|
525
|
+
description: string
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export interface DesignInventoryComponent {
|
|
529
|
+
name: string
|
|
530
|
+
description: string
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export interface DesignInventory {
|
|
534
|
+
name: string
|
|
535
|
+
sections: string[]
|
|
536
|
+
layouts: DesignInventoryLayout[]
|
|
537
|
+
components: DesignInventoryComponent[]
|
|
538
|
+
hasMarkers: boolean
|
|
539
|
+
}
|
|
540
|
+
|
|
496
541
|
/**
|
|
497
542
|
* Parse a DESIGN.md body (no frontmatter) into sections, layouts, and components
|
|
498
543
|
* using the three-layer HTML comment marker convention:
|
|
@@ -566,7 +611,7 @@ export function generateComponentIndex(components: Record<string, string>): stri
|
|
|
566
611
|
"|---|---|",
|
|
567
612
|
...rows,
|
|
568
613
|
"",
|
|
569
|
-
"_Use `
|
|
614
|
+
"_Use `revela_design_read_component` with `component: \"<name>\"` to get full CSS/HTML for any component._",
|
|
570
615
|
].join("\n")
|
|
571
616
|
}
|
|
572
617
|
|
|
@@ -598,10 +643,47 @@ export function generateLayoutIndex(layouts: Record<string, LayoutInfo>): string
|
|
|
598
643
|
"|---|---|---|",
|
|
599
644
|
...rows,
|
|
600
645
|
"",
|
|
601
|
-
"_Use `
|
|
646
|
+
"_Use `revela_design_read_layout` with `layout: \"<name>\"` to get full HTML/CSS for any layout._",
|
|
602
647
|
].join("\n")
|
|
603
648
|
}
|
|
604
649
|
|
|
650
|
+
export function getDesignInventory(designName?: string): DesignInventory {
|
|
651
|
+
const name = normalizeDesignName(designName || activeDesign())
|
|
652
|
+
const designDir = resolveDesignDir(name)
|
|
653
|
+
if (!designDir) {
|
|
654
|
+
throw new Error(`Design '${name}' is not installed`)
|
|
655
|
+
}
|
|
656
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
657
|
+
const text = readFileSync(mdPath, "utf-8")
|
|
658
|
+
const { body } = parseFrontmatter(text)
|
|
659
|
+
const { sections, layouts, components, hasMarkers } = parseDesignSections(body)
|
|
660
|
+
|
|
661
|
+
return {
|
|
662
|
+
name,
|
|
663
|
+
sections: Object.keys(sections),
|
|
664
|
+
layouts: Object.entries(layouts).map(([layoutName, layout]) => ({
|
|
665
|
+
name: layoutName,
|
|
666
|
+
qa: layout.qa,
|
|
667
|
+
description: designBlockDescription(layout.content),
|
|
668
|
+
})),
|
|
669
|
+
components: Object.entries(components).map(([componentName, content]) => ({
|
|
670
|
+
name: componentName,
|
|
671
|
+
description: designBlockDescription(content),
|
|
672
|
+
})),
|
|
673
|
+
hasMarkers,
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function designBlockDescription(body: string): string {
|
|
678
|
+
const firstLine = body
|
|
679
|
+
.split("\n")
|
|
680
|
+
.map((line) => line.trim())
|
|
681
|
+
.find((line) => line && !line.startsWith("<!--") && !line.startsWith("```"))
|
|
682
|
+
return firstLine
|
|
683
|
+
? firstLine.replace(/^#+\s*/, "").replace(/\(.*?\)/, "").trim()
|
|
684
|
+
: ""
|
|
685
|
+
}
|
|
686
|
+
|
|
605
687
|
/**
|
|
606
688
|
* Get the raw text of one or more named layouts from a DESIGN.md.
|
|
607
689
|
* @param layoutNames - Comma-separated layout names or an array.
|
|
@@ -611,11 +693,12 @@ export function getDesignLayout(
|
|
|
611
693
|
layoutNames: string | string[],
|
|
612
694
|
designName?: string,
|
|
613
695
|
): string {
|
|
614
|
-
const name = designName || activeDesign()
|
|
615
|
-
const
|
|
616
|
-
if (!
|
|
696
|
+
const name = normalizeDesignName(designName || activeDesign())
|
|
697
|
+
const designDir = resolveDesignDir(name)
|
|
698
|
+
if (!designDir) {
|
|
617
699
|
throw new Error(`Design '${name}' is not installed`)
|
|
618
700
|
}
|
|
701
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
619
702
|
const text = readFileSync(mdPath, "utf-8")
|
|
620
703
|
const { body } = parseFrontmatter(text)
|
|
621
704
|
const { layouts, hasMarkers } = parseDesignSections(body)
|
|
@@ -644,11 +727,12 @@ export function getDesignLayout(
|
|
|
644
727
|
* Throws if the design is not installed or the section doesn't exist.
|
|
645
728
|
*/
|
|
646
729
|
export function getDesignSection(sectionName: string, designName?: string): string {
|
|
647
|
-
const name = designName || activeDesign()
|
|
648
|
-
const
|
|
649
|
-
if (!
|
|
730
|
+
const name = normalizeDesignName(designName || activeDesign())
|
|
731
|
+
const designDir = resolveDesignDir(name)
|
|
732
|
+
if (!designDir) {
|
|
650
733
|
throw new Error(`Design '${name}' is not installed`)
|
|
651
734
|
}
|
|
735
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
652
736
|
const text = readFileSync(mdPath, "utf-8")
|
|
653
737
|
const { body } = parseFrontmatter(text)
|
|
654
738
|
const { sections, hasMarkers } = parseDesignSections(body)
|
|
@@ -671,11 +755,12 @@ export function getDesignComponent(
|
|
|
671
755
|
componentNames: string | string[],
|
|
672
756
|
designName?: string,
|
|
673
757
|
): string {
|
|
674
|
-
const name = designName || activeDesign()
|
|
675
|
-
const
|
|
676
|
-
if (!
|
|
758
|
+
const name = normalizeDesignName(designName || activeDesign())
|
|
759
|
+
const designDir = resolveDesignDir(name)
|
|
760
|
+
if (!designDir) {
|
|
677
761
|
throw new Error(`Design '${name}' is not installed`)
|
|
678
762
|
}
|
|
763
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
679
764
|
const text = readFileSync(mdPath, "utf-8")
|
|
680
765
|
const { body } = parseFrontmatter(text)
|
|
681
766
|
const { components, hasMarkers } = parseDesignSections(body)
|
|
@@ -742,8 +827,7 @@ export async function installDesign(
|
|
|
742
827
|
// ---------------------------------------------------------------------------
|
|
743
828
|
|
|
744
829
|
function designExists(name: string): boolean {
|
|
745
|
-
|
|
746
|
-
return existsSync(dir) && existsSync(join(dir, "DESIGN.md"))
|
|
830
|
+
return resolveDesignDir(name) !== null
|
|
747
831
|
}
|
|
748
832
|
|
|
749
833
|
function installFromPath(srcPath: string, name?: string): string {
|
|
@@ -814,13 +898,13 @@ export interface DesignClassVocabulary {
|
|
|
814
898
|
* Falls back to UNIVERSAL_CLASSES-only when the design has no markers.
|
|
815
899
|
*/
|
|
816
900
|
export function extractDesignClasses(designName?: string): DesignClassVocabulary {
|
|
817
|
-
const name = designName || activeDesign()
|
|
818
|
-
const
|
|
819
|
-
|
|
820
|
-
if (!existsSync(mdPath)) {
|
|
901
|
+
const name = normalizeDesignName(designName || activeDesign())
|
|
902
|
+
const designDir = resolveDesignDir(name)
|
|
903
|
+
if (!designDir) {
|
|
821
904
|
return { classes: new Set(UNIVERSAL_CLASSES), prefixExemptions: DEFAULT_PREFIX_EXEMPTIONS }
|
|
822
905
|
}
|
|
823
906
|
|
|
907
|
+
const mdPath = join(designDir, "DESIGN.md")
|
|
824
908
|
const raw = readFileSync(mdPath, "utf-8")
|
|
825
909
|
const { body } = parseFrontmatter(raw)
|
|
826
910
|
const { sections, layouts, components, hasMarkers } = parseDesignSections(body)
|
package/lib/runtime/index.ts
CHANGED
|
@@ -6,6 +6,9 @@ import {
|
|
|
6
6
|
activateDesign,
|
|
7
7
|
createDesignDraftPackage,
|
|
8
8
|
createDesignPackage,
|
|
9
|
+
getDesignComponent,
|
|
10
|
+
getDesignInventory,
|
|
11
|
+
getDesignLayout,
|
|
9
12
|
getDesignSection,
|
|
10
13
|
getDesignSkillMd,
|
|
11
14
|
installDesignDraftPackage,
|
|
@@ -59,6 +62,20 @@ export interface RuntimeDesignReadInput {
|
|
|
59
62
|
section?: string
|
|
60
63
|
}
|
|
61
64
|
|
|
65
|
+
export interface RuntimeDesignInventoryInput {
|
|
66
|
+
name?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface RuntimeDesignLayoutReadInput {
|
|
70
|
+
name?: string
|
|
71
|
+
layout: string | string[]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface RuntimeDesignComponentReadInput {
|
|
75
|
+
name?: string
|
|
76
|
+
component: string | string[]
|
|
77
|
+
}
|
|
78
|
+
|
|
62
79
|
export interface RuntimeDesignCreateInput {
|
|
63
80
|
name: string
|
|
64
81
|
base?: string
|
|
@@ -212,7 +229,6 @@ export async function reviewDeckOpen(input: ReviewDeckOpenInput) {
|
|
|
212
229
|
}
|
|
213
230
|
|
|
214
231
|
export function designList() {
|
|
215
|
-
seedBuiltinDesigns()
|
|
216
232
|
return {
|
|
217
233
|
ok: true,
|
|
218
234
|
activeDesign: activeDesign(),
|
|
@@ -226,7 +242,6 @@ export function designList() {
|
|
|
226
242
|
}
|
|
227
243
|
|
|
228
244
|
export function designRead(input: RuntimeDesignReadInput = {}) {
|
|
229
|
-
seedBuiltinDesigns()
|
|
230
245
|
const name = input.name || activeDesign()
|
|
231
246
|
if (input.section) {
|
|
232
247
|
const markdown = getDesignSection(input.section, name)
|
|
@@ -246,6 +261,33 @@ export function designRead(input: RuntimeDesignReadInput = {}) {
|
|
|
246
261
|
}
|
|
247
262
|
}
|
|
248
263
|
|
|
264
|
+
export function designInventory(input: RuntimeDesignInventoryInput = {}) {
|
|
265
|
+
return {
|
|
266
|
+
ok: true,
|
|
267
|
+
...getDesignInventory(input.name || activeDesign()),
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function designReadLayout(input: RuntimeDesignLayoutReadInput) {
|
|
272
|
+
const name = input.name || activeDesign()
|
|
273
|
+
return {
|
|
274
|
+
ok: true,
|
|
275
|
+
name,
|
|
276
|
+
layout: input.layout,
|
|
277
|
+
markdown: getDesignLayout(input.layout, name),
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export function designReadComponent(input: RuntimeDesignComponentReadInput) {
|
|
282
|
+
const name = input.name || activeDesign()
|
|
283
|
+
return {
|
|
284
|
+
ok: true,
|
|
285
|
+
name,
|
|
286
|
+
component: input.component,
|
|
287
|
+
markdown: getDesignComponent(input.component, name),
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
249
291
|
export function designCreate(input: RuntimeDesignCreateInput) {
|
|
250
292
|
seedBuiltinDesigns()
|
|
251
293
|
return createDesignPackage({
|
|
@@ -258,7 +300,6 @@ export function designCreate(input: RuntimeDesignCreateInput) {
|
|
|
258
300
|
}
|
|
259
301
|
|
|
260
302
|
export function designValidate(input: RuntimeNameInput) {
|
|
261
|
-
seedBuiltinDesigns()
|
|
262
303
|
return validateDesignPackage(requiredName(input, "design"))
|
|
263
304
|
}
|
|
264
305
|
|
|
@@ -296,7 +337,6 @@ export interface DesignRulesReadinessResult {
|
|
|
296
337
|
const DESIGN_RULES_MARKER_TTL_MS = 8 * 60 * 60 * 1000
|
|
297
338
|
|
|
298
339
|
export function checkDesignRulesReadiness(input: RuntimeWorkspaceInput = {}): DesignRulesReadinessResult {
|
|
299
|
-
seedBuiltinDesigns()
|
|
300
340
|
const workspaceRoot = root(input.workspaceRoot)
|
|
301
341
|
const design = activeDesign()
|
|
302
342
|
const rules = getDesignSection("rules", design)
|
package/package.json
CHANGED
package/plugins/revela/.mcp.json
CHANGED
|
@@ -19,6 +19,9 @@ type RuntimeModule = {
|
|
|
19
19
|
exportPptx(input: any): Promise<any>
|
|
20
20
|
designList(): any
|
|
21
21
|
designRead(input?: any): any
|
|
22
|
+
designInventory(input?: any): any
|
|
23
|
+
designReadLayout(input: any): any
|
|
24
|
+
designReadComponent(input: any): any
|
|
22
25
|
designActivate(input: any): any
|
|
23
26
|
designCreate(input: any): any
|
|
24
27
|
designValidate(input: any): any
|
|
@@ -125,6 +128,29 @@ const tools = [
|
|
|
125
128
|
section: stringProp("Optional design section, such as rules, foundation, or chart-rules."),
|
|
126
129
|
}),
|
|
127
130
|
},
|
|
131
|
+
{
|
|
132
|
+
name: "revela_design_inventory",
|
|
133
|
+
description: "List the active or requested Revela design sections, layouts, and components.",
|
|
134
|
+
inputSchema: objectSchema({
|
|
135
|
+
name: stringProp("Optional design name."),
|
|
136
|
+
}),
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: "revela_design_read_layout",
|
|
140
|
+
description: "Read one or more layout blocks from the active or requested Revela design.",
|
|
141
|
+
inputSchema: objectSchema({
|
|
142
|
+
name: stringProp("Optional design name."),
|
|
143
|
+
layout: stringOrArrayProp("Layout name, comma-separated names, or an array of layout names."),
|
|
144
|
+
}, ["layout"]),
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: "revela_design_read_component",
|
|
148
|
+
description: "Read one or more component blocks from the active or requested Revela design.",
|
|
149
|
+
inputSchema: objectSchema({
|
|
150
|
+
name: stringProp("Optional design name."),
|
|
151
|
+
component: stringOrArrayProp("Component name, comma-separated names, or an array of component names."),
|
|
152
|
+
}, ["component"]),
|
|
153
|
+
},
|
|
128
154
|
{
|
|
129
155
|
name: "revela_design_activate",
|
|
130
156
|
description: "Activate a Revela design for future deck planning and artifact generation.",
|
|
@@ -394,6 +420,9 @@ async function callTool(name: string, args: any): Promise<any> {
|
|
|
394
420
|
if (name === "revela_export_pptx") return r.exportPptx(args)
|
|
395
421
|
if (name === "revela_design_list") return r.designList()
|
|
396
422
|
if (name === "revela_design_read") return r.designRead(args)
|
|
423
|
+
if (name === "revela_design_inventory") return r.designInventory(args)
|
|
424
|
+
if (name === "revela_design_read_layout") return r.designReadLayout(args)
|
|
425
|
+
if (name === "revela_design_read_component") return r.designReadComponent(args)
|
|
397
426
|
if (name === "revela_design_activate") return r.designActivate(args)
|
|
398
427
|
if (name === "revela_design_create") return r.designCreate(args)
|
|
399
428
|
if (name === "revela_design_validate") return r.designValidate(args)
|
|
@@ -458,6 +487,16 @@ function arrayProp(description: string) {
|
|
|
458
487
|
return { type: "array", items: { type: "string" }, description }
|
|
459
488
|
}
|
|
460
489
|
|
|
490
|
+
function stringOrArrayProp(description: string) {
|
|
491
|
+
return {
|
|
492
|
+
anyOf: [
|
|
493
|
+
{ type: "string" },
|
|
494
|
+
{ type: "array", items: { type: "string" } },
|
|
495
|
+
],
|
|
496
|
+
description,
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
461
500
|
function arrayObjectProp(description: string) {
|
|
462
501
|
return {
|
|
463
502
|
type: "array",
|
|
@@ -11,11 +11,13 @@ Use this skill when the user asks about Revela designs or when generating deck H
|
|
|
11
11
|
|
|
12
12
|
1. Call `revela_design_list` to inspect installed designs.
|
|
13
13
|
2. Call `revela_design_read` with `section: "rules"` before writing or patching `decks/*.html`; this records the Codex hook context required for deck writes.
|
|
14
|
-
3.
|
|
15
|
-
4.
|
|
16
|
-
5.
|
|
17
|
-
6.
|
|
18
|
-
7.
|
|
14
|
+
3. Call `revela_design_inventory` before authoring or repairing `deck-plan/` so planned layout/component names come from the active design.
|
|
15
|
+
4. Read required details with `revela_design_read_layout` and `revela_design_read_component` before writing slide HTML that uses those layouts/components.
|
|
16
|
+
5. When the user asks to switch designs for future work, call `revela_design_activate` with the requested design name, then read the active design again.
|
|
17
|
+
6. For one-off deck generation with a requested design, read that design by name, call `revela_design_inventory` with that name, and pass `designName` to `revela_create_deck_foundation` without changing active design unless the user asked to switch.
|
|
18
|
+
7. Use the current simplified built-in design grammar: `box`, `text-panel`, `media`, `echart-panel`, `data-table`, `steps`, `roadmap-horizontal`, `roadmap-vertical`, `hero`, `stat-card`, `quote`, `toc`, `page-number`, and `brand-watermark`.
|
|
19
|
+
8. Fetch chart/design guidance before creating ECharts or complex layouts.
|
|
20
|
+
9. Do not invent unsupported component names.
|
|
19
21
|
|
|
20
22
|
Deck HTML must keep exactly one direct `.slide-canvas` child inside every `<section class="slide" ...>`; place `.page` or layout containers inside `.slide-canvas`, not directly under `.slide`.
|
|
21
23
|
|
|
@@ -18,15 +18,16 @@ Use this skill when the user asks to make, generate, or update a Revela deck.
|
|
|
18
18
|
|
|
19
19
|
1. Call `revela_compile_narrative` and `revela_markdown_qa`.
|
|
20
20
|
2. Report narrative and Markdown diagnostics, but treat only malformed/unsafe files and technical artifact validity as hard blockers.
|
|
21
|
-
3. Call `
|
|
22
|
-
4.
|
|
23
|
-
5.
|
|
24
|
-
6.
|
|
25
|
-
7.
|
|
26
|
-
8.
|
|
27
|
-
9.
|
|
28
|
-
10.
|
|
29
|
-
11.
|
|
21
|
+
3. Call `revela_design_list`, `revela_design_read` using `section: "rules"`, and `revela_design_inventory` before authoring or repairing `deck-plan/`; deck-plan layout/component names must come from the selected design inventory.
|
|
22
|
+
4. Call `revela_read_deck_plan` as the required deck-plan preflight before any HTML generation.
|
|
23
|
+
5. If `deck-plan/` is missing or incomplete, author or repair `deck-plan/index.md` and `deck-plan/slides/*.md` before calling `revela_create_deck_foundation`; use only inventory-listed layouts/components in slide frontmatter and visual intent.
|
|
24
|
+
6. Report deck-plan diagnostics before artifact generation, including stale narrative hashes, missing slide projections, missing evidence trace, caveats, malformed plan files, or layout/component names outside the active design inventory.
|
|
25
|
+
7. Do not start HTML generation from narrative alone unless the user explicitly asks for a throwaway diagnostic smoke deck.
|
|
26
|
+
8. For new HTML files, call `revela_create_deck_foundation`.
|
|
27
|
+
9. Before patching slide HTML, read the specific layouts/components used by the deck plan with `revela_design_read_layout` and `revela_design_read_component`; fetch `section: "chart-rules"` and the `echart-panel` component before creating or changing ECharts. If the user asks to switch designs persistently, call `revela_design_activate`; if they ask for a one-off design, read that design by name, call `revela_design_inventory` with that name, and pass `designName` to `revela_create_deck_foundation`.
|
|
28
|
+
10. Patch slides into the foundation between Revela slide markers. Preserve positive 1-based `data-slide-index` values. Every slide must use `<section class="slide" ...>` with exactly one direct `.slide-canvas` child.
|
|
29
|
+
11. Generate chapter by chapter. Keep the HTML valid after each write.
|
|
30
|
+
12. After every HTML write, call `revela_run_deck_qa` and repair hard errors before review or export.
|
|
30
31
|
|
|
31
32
|
## Generated Visual Assets
|
|
32
33
|
|