@cyber-dash-tech/revela 0.18.16 → 0.19.1
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 +45 -31
- package/README.zh-CN.md +45 -31
- package/assets/img/lucent-01.jpg +0 -0
- package/assets/img/lucent-02.jpg +0 -0
- package/assets/img/lucent-03.jpg +0 -0
- package/assets/img/lucent-dark-01.jpg +0 -0
- package/assets/img/lucent-dark-02.jpg +0 -0
- package/assets/img/lucent-dark-03.jpg +0 -0
- package/assets/img/monet-01.jpg +0 -0
- package/assets/img/monet-02.jpg +0 -0
- package/assets/img/monet-03.jpg +0 -0
- package/assets/img/starter-01.jpg +0 -0
- package/assets/img/starter-02.jpg +0 -0
- package/assets/img/starter-03.jpg +0 -0
- package/assets/img/summit-01.jpg +0 -0
- package/assets/img/summit-02.jpg +0 -0
- package/assets/img/summit-03.jpg +0 -0
- package/designs/lucent/DESIGN.md +76 -0
- package/designs/lucent/design.css +283 -0
- package/designs/lucent-dark/DESIGN.md +278 -0
- package/designs/lucent-dark/assets/card-lens.jpg +0 -0
- package/designs/lucent-dark/assets/closing-background.jpg +0 -0
- package/designs/lucent-dark/assets/cover-background.jpg +0 -0
- package/designs/lucent-dark/assets/report-visual.jpg +0 -0
- package/designs/lucent-dark/assets/soft-texture.jpg +0 -0
- package/designs/lucent-dark/assets/toc-orb.png +0 -0
- package/designs/lucent-dark/design.css +417 -0
- package/designs/monet/DESIGN.md +14 -0
- package/designs/monet/assets/card-lens.jpg +0 -0
- package/designs/monet/assets/closing-background.jpg +0 -0
- package/designs/monet/assets/cover-background.jpg +0 -0
- package/designs/monet/assets/report-visual.jpg +0 -0
- package/designs/monet/assets/soft-texture.jpg +0 -0
- package/designs/monet/assets/toc-orb.png +0 -0
- package/designs/monet/design.css +340 -0
- package/designs/starter/DESIGN.md +14 -0
- package/designs/starter/assets/card-lens.jpg +0 -0
- package/designs/starter/assets/closing-background.jpg +0 -0
- package/designs/starter/assets/cover-background.jpg +0 -0
- package/designs/starter/assets/report-visual.jpg +0 -0
- package/designs/starter/assets/soft-texture.jpg +0 -0
- package/designs/starter/assets/toc-orb.png +0 -0
- package/designs/starter/design.css +322 -0
- package/designs/summit/DESIGN.md +18 -0
- package/designs/summit/assets/card-lens.jpg +0 -0
- package/designs/summit/assets/closing-background.jpg +0 -0
- package/designs/summit/assets/cover-background.jpg +0 -0
- package/designs/summit/assets/report-visual.jpg +0 -0
- package/designs/summit/assets/soft-texture.jpg +0 -0
- package/designs/summit/assets/toc-orb.png +0 -0
- package/designs/summit/design.css +334 -0
- package/lib/commands/designs-new.ts +13 -25
- package/lib/commands/designs-preview.ts +3 -8
- package/lib/deck-html/foundation.ts +8 -8
- package/lib/design/designs.ts +317 -14
- package/lib/narrative-state/deck-plan-artifact.ts +40 -3
- package/lib/page-templates/built-in-preview.html +373 -0
- package/lib/page-templates/contracts.ts +2 -0
- package/lib/page-templates/css.ts +2 -0
- package/lib/page-templates/foundation.ts +41 -0
- package/lib/page-templates/index.ts +6 -0
- package/lib/page-templates/registry.ts +3 -0
- package/lib/page-templates/render.ts +1202 -0
- package/lib/page-templates/templates/agenda.ts +4 -0
- package/lib/page-templates/templates/chart-takeaways.ts +4 -0
- package/lib/page-templates/templates/claim-supporting-visual.ts +4 -0
- package/lib/page-templates/templates/closing.ts +4 -0
- package/lib/page-templates/templates/cover.ts +4 -0
- package/lib/page-templates/templates/executive-summary.ts +4 -0
- package/lib/page-templates/templates/index.ts +19 -0
- package/lib/page-templates/templates/key-message-evidence.ts +4 -0
- package/lib/page-templates/templates/metric-highlight.ts +4 -0
- package/lib/page-templates/templates/problem-context.ts +4 -0
- package/lib/page-templates/templates/process-steps.ts +4 -0
- package/lib/page-templates/templates/recommendation-decision.ts +4 -0
- package/lib/page-templates/templates/risks-tradeoffs.ts +4 -0
- package/lib/page-templates/templates/section-divider.ts +4 -0
- package/lib/page-templates/templates/shared.ts +11 -0
- package/lib/page-templates/templates/table-comparison.ts +4 -0
- package/lib/page-templates/templates/timeline-roadmap.ts +4 -0
- package/lib/page-templates/vocabulary.ts +158 -0
- package/lib/prompt-builder.ts +5 -5
- package/lib/qa/artifact.ts +66 -1
- package/lib/qa/compliance.ts +5 -1
- package/lib/runtime/index.ts +99 -3
- package/package.json +7 -15
- package/plugins/revela/.codex-plugin/plugin.json +1 -1
- package/plugins/revela/hooks/revela_guard.ts +35 -0
- package/plugins/revela/hooks/revela_post_write_notice.ts +4 -4
- package/plugins/revela/mcp/revela-server.ts +104 -6
- package/plugins/revela/skills/revela/SKILL.md +1 -1
- package/plugins/revela/skills/revela-design/SKILL.md +22 -16
- package/plugins/revela/skills/revela-helper/SKILL.md +1 -1
- package/plugins/revela/skills/revela-make-deck/SKILL.md +25 -16
- package/designs/lucent/preview.html +0 -529
- package/designs/monet/preview.html +0 -190
- package/designs/starter/preview.html +0 -335
- package/designs/summit/preview.html +0 -186
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { listPageTemplateVocabulary } from "../vocabulary"
|
|
2
|
+
|
|
3
|
+
export const BUILTIN_PAGE_TEMPLATE_IDS = listPageTemplateVocabulary().map((template) => template.templateId)
|
|
4
|
+
|
|
5
|
+
export * from "./agenda"
|
|
6
|
+
export * from "./chart-takeaways"
|
|
7
|
+
export * from "./claim-supporting-visual"
|
|
8
|
+
export * from "./closing"
|
|
9
|
+
export * from "./cover"
|
|
10
|
+
export * from "./executive-summary"
|
|
11
|
+
export * from "./key-message-evidence"
|
|
12
|
+
export * from "./metric-highlight"
|
|
13
|
+
export * from "./problem-context"
|
|
14
|
+
export * from "./process-steps"
|
|
15
|
+
export * from "./recommendation-decision"
|
|
16
|
+
export * from "./risks-tradeoffs"
|
|
17
|
+
export * from "./section-divider"
|
|
18
|
+
export * from "./table-comparison"
|
|
19
|
+
export * from "./timeline-roadmap"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { getPageTemplateFoundation } from "../foundation"
|
|
2
|
+
import { getPageTemplateVocabulary } from "../vocabulary"
|
|
3
|
+
|
|
4
|
+
export function templateModule(templateId: string) {
|
|
5
|
+
return {
|
|
6
|
+
templateId,
|
|
7
|
+
foundation: () => getPageTemplateFoundation(templateId),
|
|
8
|
+
vocabulary: () => getPageTemplateVocabulary(templateId),
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
export interface PageTemplateSlotVocabulary {
|
|
2
|
+
name: string
|
|
3
|
+
required: boolean
|
|
4
|
+
editable: boolean
|
|
5
|
+
replaceable: boolean
|
|
6
|
+
description: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface PageTemplateVocabulary {
|
|
10
|
+
templateId: string
|
|
11
|
+
rootClasses: string[]
|
|
12
|
+
requiredClasses: string[]
|
|
13
|
+
optionalClasses: string[]
|
|
14
|
+
slots: PageTemplateSlotVocabulary[]
|
|
15
|
+
editableSlots: string[]
|
|
16
|
+
replaceableSlots: string[]
|
|
17
|
+
contractNotes: string[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const sharedClasses = [
|
|
21
|
+
"template-slide",
|
|
22
|
+
"template-frame",
|
|
23
|
+
"template-eyebrow",
|
|
24
|
+
"template-title",
|
|
25
|
+
"template-body",
|
|
26
|
+
"template-grid",
|
|
27
|
+
"template-chart-layout",
|
|
28
|
+
"cols-2",
|
|
29
|
+
"cols-3",
|
|
30
|
+
"cols-4",
|
|
31
|
+
"template-card",
|
|
32
|
+
"template-list",
|
|
33
|
+
"template-hero",
|
|
34
|
+
"template-hero-title",
|
|
35
|
+
"template-hero--cover",
|
|
36
|
+
"template-hero--section-divider",
|
|
37
|
+
"template-hero--closing",
|
|
38
|
+
"template-frame--catalog",
|
|
39
|
+
"template-page-number",
|
|
40
|
+
"template-image-card",
|
|
41
|
+
"template-image-frame",
|
|
42
|
+
"template-image-caption",
|
|
43
|
+
"template-visual-placeholder",
|
|
44
|
+
"template-visual-placeholder-frame",
|
|
45
|
+
"template-visual-placeholder-label",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
export const PAGE_TEMPLATE_VOCABULARY: PageTemplateVocabulary[] = [
|
|
49
|
+
vocab("cover", ["template-hero"], ["hero"], ["hero"], ["Cover, divider, and closing templates use the hero frame; keep title hierarchy visible."]),
|
|
50
|
+
vocab("section-divider", ["template-hero"], ["hero"], ["hero"], ["Section divider uses the same hero-safe structure as cover."]),
|
|
51
|
+
vocab("closing", ["template-hero"], ["hero"], ["hero"], ["Closing uses the same hero-safe structure as cover."]),
|
|
52
|
+
vocab("agenda", ["template-agenda-panel"], ["agenda", "agenda-list"], ["agenda", "agenda-list"], ["Agenda numbers must remain in DOM order."]),
|
|
53
|
+
vocab("executive-summary", ["template-card"], ["summary-cards"], ["summary-cards"], ["Cards are editable; visual placeholders are optional and may become image/chart slots."]),
|
|
54
|
+
vocab("problem-context", ["template-card"], ["context", "supporting-points"], ["context", "supporting-points"], ["Context should stay separate from supporting bullets."]),
|
|
55
|
+
vocab("key-message-evidence", ["template-key-message-panel", "template-evidence-grid"], ["key-message", "evidence"], ["key-message", "evidence"], ["Key message and evidence regions must remain distinct."]),
|
|
56
|
+
vocab("claim-supporting-visual", ["template-claim-text-panel", "template-visual-slot-panel"], ["claim", "visual"], ["claim", "visual"], ["Visual slot may be replaced by image, chart, table, or diagram container."]),
|
|
57
|
+
vocab("metric-highlight", ["template-stat-grid"], ["metrics"], ["metrics", "insight"], ["Metric values should remain visible outside prose."]),
|
|
58
|
+
vocab("chart-takeaways", ["template-chart-panel", "template-chart-takeaway-panel"], ["visual", "takeaways"], ["visual", "takeaways"], ["Chart/image slot and takeaway text panel must both remain present."]),
|
|
59
|
+
vocab("table-comparison", ["template-table-wrap", "template-table"], ["table"], ["table", "insight"], ["Table headers and body should remain structured, not prose-only."]),
|
|
60
|
+
vocab("timeline-roadmap", ["template-timeline", "template-timeline-item", "template-timeline-dot", "template-timeline-copy", "template-insight-icon"], ["timeline"], ["timeline", "insight"], ["Each timeline item must keep dot and copy as sibling anchors inside one item.", "Horizontal timeline cards reuse .template-card; highlight uses the item modifier."]),
|
|
61
|
+
vocab("process-steps", ["template-steps", "template-step-number"], ["steps"], ["steps"], ["Steps should remain ordered in DOM order."]),
|
|
62
|
+
vocab("recommendation-decision", ["template-card"], ["recommendation", "rationale", "next-steps"], ["recommendation", "rationale", "next-steps"], ["Keep recommendation, rationale, and next steps separate."]),
|
|
63
|
+
vocab("risks-tradeoffs", ["template-card"], ["risks"], ["risks"], ["Risk/tradeoff cards should name uncertainty explicitly."]),
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
const additionalClasses = [
|
|
67
|
+
"template-key-message-panel",
|
|
68
|
+
"template-key-message-kicker",
|
|
69
|
+
"template-evidence-grid",
|
|
70
|
+
"template-evidence-card",
|
|
71
|
+
"template-claim-text-panel",
|
|
72
|
+
"template-claim-text-title",
|
|
73
|
+
"template-claim-text-body",
|
|
74
|
+
"template-agenda-panel",
|
|
75
|
+
"template-agenda-inner",
|
|
76
|
+
"template-agenda-header",
|
|
77
|
+
"template-agenda-footer",
|
|
78
|
+
"template-agenda-list",
|
|
79
|
+
"template-agenda-item",
|
|
80
|
+
"template-stat-grid",
|
|
81
|
+
"template-stat-value",
|
|
82
|
+
"template-metric-layout",
|
|
83
|
+
"template-metric-layout--insight-top",
|
|
84
|
+
"template-metric-layout--insight-bottom",
|
|
85
|
+
"template-chart-panel",
|
|
86
|
+
"template-chart-placeholder",
|
|
87
|
+
"template-visual-slot-panel",
|
|
88
|
+
"template-visual-slot-label",
|
|
89
|
+
"template-chart-takeaway-panel",
|
|
90
|
+
"template-chart-takeaway-list",
|
|
91
|
+
"template-chart-takeaway-item",
|
|
92
|
+
"template-bar",
|
|
93
|
+
"template-table",
|
|
94
|
+
"template-table-wrap",
|
|
95
|
+
"template-side-panel",
|
|
96
|
+
"template-side-panel-title",
|
|
97
|
+
"template-side-panel-body",
|
|
98
|
+
"template-side-panel--left",
|
|
99
|
+
"template-side-panel--right",
|
|
100
|
+
"template-text-panel",
|
|
101
|
+
"template-text-panel-title",
|
|
102
|
+
"template-text-panel-body",
|
|
103
|
+
"template-insight-panel",
|
|
104
|
+
"template-insight-title",
|
|
105
|
+
"template-insight-icon",
|
|
106
|
+
"template-insight-body",
|
|
107
|
+
"template-timeline",
|
|
108
|
+
"template-timeline-layout",
|
|
109
|
+
"template-timeline-layout--left",
|
|
110
|
+
"template-timeline-layout--right",
|
|
111
|
+
"template-timeline--horizontal",
|
|
112
|
+
"template-timeline--vertical",
|
|
113
|
+
"template-timeline-item",
|
|
114
|
+
"template-timeline-item--highlight",
|
|
115
|
+
"template-timeline-dot",
|
|
116
|
+
"template-timeline-copy",
|
|
117
|
+
"template-timeline-date",
|
|
118
|
+
"template-steps",
|
|
119
|
+
"template-step-number",
|
|
120
|
+
"template-catalog-panel",
|
|
121
|
+
"template-catalog-kicker",
|
|
122
|
+
"template-catalog-title",
|
|
123
|
+
"template-catalog-grid",
|
|
124
|
+
"template-catalog-section",
|
|
125
|
+
"template-catalog-list",
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
export const PAGE_TEMPLATE_CLASSES = [...new Set([...sharedClasses, ...additionalClasses])]
|
|
129
|
+
|
|
130
|
+
export function listPageTemplateVocabulary(): PageTemplateVocabulary[] {
|
|
131
|
+
return PAGE_TEMPLATE_VOCABULARY
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function getPageTemplateVocabulary(templateId: string): PageTemplateVocabulary {
|
|
135
|
+
const vocabulary = PAGE_TEMPLATE_VOCABULARY.find((item) => item.templateId === templateId)
|
|
136
|
+
if (!vocabulary) throw new Error(`Unknown page template vocabulary: ${templateId}`)
|
|
137
|
+
return vocabulary
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function vocab(templateId: string, requiredClasses: string[], slotNames: string[], replaceableSlots: string[], contractNotes: string[]): PageTemplateVocabulary {
|
|
141
|
+
const slots = slotNames.map((name) => ({
|
|
142
|
+
name,
|
|
143
|
+
required: true,
|
|
144
|
+
editable: true,
|
|
145
|
+
replaceable: replaceableSlots.includes(name),
|
|
146
|
+
description: `${templateId} ${name} slot.`,
|
|
147
|
+
}))
|
|
148
|
+
return {
|
|
149
|
+
templateId,
|
|
150
|
+
rootClasses: ["template-slide", "template-frame", ...requiredClasses.slice(0, 1)],
|
|
151
|
+
requiredClasses,
|
|
152
|
+
optionalClasses: [],
|
|
153
|
+
slots,
|
|
154
|
+
editableSlots: slotNames,
|
|
155
|
+
replaceableSlots,
|
|
156
|
+
contractNotes,
|
|
157
|
+
}
|
|
158
|
+
}
|
package/lib/prompt-builder.ts
CHANGED
|
@@ -82,12 +82,12 @@ export function buildPrompt(optionsOrDesignName?: BuildPromptOptions | string, l
|
|
|
82
82
|
// Layer 1 — core skill for the selected prompt mode.
|
|
83
83
|
const coreSkill = readFileSync(mode === "deck-render" ? SKILL_MD_PATH : NARRATIVE_SKILL_MD_PATH, "utf-8")
|
|
84
84
|
|
|
85
|
-
// Check for
|
|
85
|
+
// Check for CSS-native design styling.
|
|
86
86
|
const designDir = join(DESIGNS_DIR, design)
|
|
87
|
-
const
|
|
88
|
-
const previewLine =
|
|
89
|
-
? "<!-- -
|
|
90
|
-
: "<!-- - (no
|
|
87
|
+
const hasDesignCss = existsSync(join(designDir, "design.css"))
|
|
88
|
+
const previewLine = hasDesignCss
|
|
89
|
+
? "<!-- - design.css — executable design styling; generated previews use the built-in page template fixture -->"
|
|
90
|
+
: "<!-- - (no design.css for this design; compatibility CSS may be generated from DESIGN.md) -->"
|
|
91
91
|
|
|
92
92
|
// Layer 2 — DOMAIN.md skill text (narrative mode only). Deck-render mode
|
|
93
93
|
// renders the approved canonical narrative and must not re-interpret domain
|
package/lib/qa/artifact.ts
CHANGED
|
@@ -4,8 +4,10 @@ import type { DesignClassVocabulary, DesignComponentContract } from "../design/d
|
|
|
4
4
|
import { formatReport, runQA } from "./index"
|
|
5
5
|
import { runComplianceQA } from "./compliance"
|
|
6
6
|
import { runComponentContractQA } from "./component-contracts"
|
|
7
|
+
import { formatPageTemplateContractReport, validatePageTemplateContracts } from "../page-templates"
|
|
7
8
|
import type { QAReport } from "./checks"
|
|
8
|
-
import {
|
|
9
|
+
import { existsSync, readFileSync } from "fs"
|
|
10
|
+
import { basename, dirname, resolve } from "path"
|
|
9
11
|
|
|
10
12
|
export interface ArtifactQAReport {
|
|
11
13
|
file: string
|
|
@@ -43,6 +45,16 @@ export async function runArtifactQA(input: {
|
|
|
43
45
|
sections.push("**[deck HTML contract]**\n\n" + formatDeckHtmlContractReport(contract))
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
const designCss = validateLinkedDesignCss(input.filePath)
|
|
49
|
+
if (designCss.errors.length > 0 || designCss.warnings.length > 0) {
|
|
50
|
+
hardErrorCount += designCss.errors.length
|
|
51
|
+
warningCount += designCss.warnings.length
|
|
52
|
+
sections.push("**[design CSS snapshot]**\n\n" + [
|
|
53
|
+
...designCss.errors.map((message) => `- ERROR: ${message}`),
|
|
54
|
+
...designCss.warnings.map((message) => `- WARNING: ${message}`),
|
|
55
|
+
].join("\n"))
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
if (shouldRunArtifactCompliance(input.filePath)) {
|
|
47
59
|
const compliance = runComplianceQA(input.filePath, input.vocabulary)
|
|
48
60
|
const complianceErrors = hardErrors(compliance)
|
|
@@ -64,6 +76,13 @@ export async function runArtifactQA(input: {
|
|
|
64
76
|
}
|
|
65
77
|
}
|
|
66
78
|
|
|
79
|
+
const templateContracts = validatePageTemplateContracts(input.filePath)
|
|
80
|
+
if (templateContracts.issues.length > 0) {
|
|
81
|
+
hardErrorCount += templateContracts.issues.filter((issue) => issue.severity === "error").length
|
|
82
|
+
warningCount += templateContracts.issues.filter((issue) => issue.severity === "warning").length
|
|
83
|
+
sections.push("**[page template contracts]**\n\n" + formatPageTemplateContractReport(templateContracts))
|
|
84
|
+
}
|
|
85
|
+
|
|
67
86
|
try {
|
|
68
87
|
const browser = await runQA(input.filePath)
|
|
69
88
|
const browserErrors = hardErrors(browser)
|
|
@@ -86,6 +105,52 @@ export async function runArtifactQA(input: {
|
|
|
86
105
|
}
|
|
87
106
|
}
|
|
88
107
|
|
|
108
|
+
function validateLinkedDesignCss(filePath: string): { errors: string[]; warnings: string[] } {
|
|
109
|
+
if (isDesignPreviewFile(filePath)) return { errors: [], warnings: [] }
|
|
110
|
+
const errors: string[] = []
|
|
111
|
+
const warnings: string[] = []
|
|
112
|
+
let html = ""
|
|
113
|
+
try {
|
|
114
|
+
html = readFileSync(filePath, "utf-8")
|
|
115
|
+
} catch {
|
|
116
|
+
return { errors, warnings }
|
|
117
|
+
}
|
|
118
|
+
const hrefs = [...html.matchAll(/<link\b[^>]*rel=["']stylesheet["'][^>]*href=["']([^"']*design\.css)["'][^>]*>/gi)].map((match) => match[1])
|
|
119
|
+
if (hrefs.length === 0) {
|
|
120
|
+
warnings.push("Deck does not reference a design.css snapshot.")
|
|
121
|
+
return { errors, warnings }
|
|
122
|
+
}
|
|
123
|
+
for (const href of hrefs) {
|
|
124
|
+
if (/^[a-z][a-z0-9+.-]*:/i.test(href)) continue
|
|
125
|
+
const cssPath = resolve(dirname(filePath), href)
|
|
126
|
+
if (!existsSync(cssPath)) {
|
|
127
|
+
errors.push(`Linked design CSS is missing: ${href}`)
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
const css = readFileSync(cssPath, "utf-8")
|
|
131
|
+
for (const asset of cssAssetUrls(css)) {
|
|
132
|
+
const assetPath = resolve(dirname(cssPath), asset)
|
|
133
|
+
if (!existsSync(assetPath)) errors.push(`Linked design CSS references missing asset: ${href} -> ${asset}`)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { errors, warnings }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function cssAssetUrls(css: string): string[] {
|
|
140
|
+
const urls: string[] = []
|
|
141
|
+
const seen = new Set<string>()
|
|
142
|
+
const urlRe = /url\(\s*["']?([^"')]+)["']?\s*\)/gi
|
|
143
|
+
let match: RegExpExecArray | null
|
|
144
|
+
while ((match = urlRe.exec(css)) !== null) {
|
|
145
|
+
const raw = match[1].trim()
|
|
146
|
+
if (!raw || raw.startsWith("data:") || /^[a-z][a-z0-9+.-]*:/i.test(raw) || raw.startsWith("#")) continue
|
|
147
|
+
if (seen.has(raw)) continue
|
|
148
|
+
seen.add(raw)
|
|
149
|
+
urls.push(raw)
|
|
150
|
+
}
|
|
151
|
+
return urls
|
|
152
|
+
}
|
|
153
|
+
|
|
89
154
|
function componentContractsForArtifact(filePath: string): DesignComponentContract[] {
|
|
90
155
|
const designName = designNameFromPreviewPath(filePath)
|
|
91
156
|
try {
|
package/lib/qa/compliance.ts
CHANGED
|
@@ -103,9 +103,13 @@ function extractCssDefinedClasses(html: string): ClassUse[] {
|
|
|
103
103
|
while ((styleMatch = styleRe.exec(html)) !== null) {
|
|
104
104
|
const styleBody = styleMatch[1]
|
|
105
105
|
const bodyOffset = styleMatch.index + styleMatch[0].indexOf(styleBody)
|
|
106
|
+
const scanBody = styleBody
|
|
107
|
+
.replace(/url\([^)]*\)/gi, "url()")
|
|
108
|
+
.replace(/"[^"]*"/g, '""')
|
|
109
|
+
.replace(/'[^']*'/g, "''")
|
|
106
110
|
classRe.lastIndex = 0
|
|
107
111
|
let classMatch: RegExpExecArray | null
|
|
108
|
-
while ((classMatch = classRe.exec(
|
|
112
|
+
while ((classMatch = classRe.exec(scanBody)) !== null) {
|
|
109
113
|
const cls = classMatch[1]
|
|
110
114
|
if (classes.has(cls)) continue
|
|
111
115
|
|
package/lib/runtime/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
installDesignDraftPackage,
|
|
16
16
|
listDesignAssets,
|
|
17
17
|
listDesigns,
|
|
18
|
+
materializeDesignPreview,
|
|
18
19
|
packDesignPackage,
|
|
19
20
|
seedBuiltinDesigns,
|
|
20
21
|
validateDesignDraftPackage,
|
|
@@ -30,6 +31,7 @@ import { runNarrativeMarkdownQa, type MarkdownQaOptions } from "../narrative-vau
|
|
|
30
31
|
import { formatArtifactQaUserNotice, formatMarkdownQaUserNotice } from "../hook-notifications"
|
|
31
32
|
import { deckPlanDesignDiagnostics, readDeckPlanArtifact, upsertDeckPlanSlideArtifact, type DeckPlanSlideUpsertInput } from "../narrative-state/deck-plan-artifact"
|
|
32
33
|
import { extractDesignClasses } from "../design/designs"
|
|
34
|
+
import { addTemplateScaffold as addPageTemplateScaffold, addTemplateSlide as addPageTemplateSlide, getPageTemplateFoundation, getPageTemplateVocabulary, listPageTemplates as listBuiltinPageTemplates, renderTemplateScaffold as renderPageTemplateScaffold, renderTemplateSlide as renderPageTemplateSlide } from "../page-templates"
|
|
33
35
|
import { recordRenderedArtifact, workspaceRelative } from "../workspace-state/rendered-artifacts"
|
|
34
36
|
import { existingWorkspaceMetaPath, workspaceMetaPath } from "../workspace-meta"
|
|
35
37
|
import { checkMaterialIntake, extractMaterial, materialIntakeNoticeForCommand, prepareLocalMaterials, recordMaterialReview } from "../material-intake"
|
|
@@ -84,17 +86,49 @@ export interface RuntimeDeckPlanSlideUpsertInput extends RuntimeWorkspaceInput,
|
|
|
84
86
|
designName?: string
|
|
85
87
|
}
|
|
86
88
|
|
|
89
|
+
export interface RuntimeTemplateSlideInput extends RuntimeWorkspaceInput {
|
|
90
|
+
templateId: string
|
|
91
|
+
slideIndex: number
|
|
92
|
+
content: Record<string, any>
|
|
93
|
+
designName?: string
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export interface RuntimeTemplateSlideAddInput extends RuntimeTemplateSlideInput {
|
|
97
|
+
outputPath: string
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface RuntimeTemplateScaffoldInput extends RuntimeWorkspaceInput {
|
|
101
|
+
templateId: string
|
|
102
|
+
slideIndex: number
|
|
103
|
+
seed?: Record<string, any>
|
|
104
|
+
designName?: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface RuntimeTemplateScaffoldAddInput extends RuntimeTemplateScaffoldInput {
|
|
108
|
+
outputPath: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface RuntimePageTemplateReadInput {
|
|
112
|
+
templateId: string
|
|
113
|
+
}
|
|
114
|
+
|
|
87
115
|
export interface RuntimeDesignCreateInput {
|
|
88
116
|
name: string
|
|
89
117
|
base?: string
|
|
90
118
|
designMd: string
|
|
91
|
-
|
|
119
|
+
designCss?: string
|
|
120
|
+
previewHtml?: string
|
|
92
121
|
assets?: DesignPackageAssetInput[]
|
|
93
122
|
overwrite?: boolean
|
|
94
123
|
}
|
|
95
124
|
|
|
96
125
|
export interface RuntimeDesignDraftCreateInput extends RuntimeDesignCreateInput, RuntimeWorkspaceInput {}
|
|
97
126
|
|
|
127
|
+
export interface RuntimeDesignPreviewInput extends RuntimeWorkspaceInput {
|
|
128
|
+
name: string
|
|
129
|
+
source?: "draft" | "installed" | "builtin"
|
|
130
|
+
}
|
|
131
|
+
|
|
98
132
|
export interface RuntimeDomainCreateInput {
|
|
99
133
|
name: string
|
|
100
134
|
domainMd: string
|
|
@@ -218,6 +252,58 @@ export function createDeckFoundation(input: RuntimeDeckFoundationInput) {
|
|
|
218
252
|
})
|
|
219
253
|
}
|
|
220
254
|
|
|
255
|
+
export function listPageTemplates() {
|
|
256
|
+
return listBuiltinPageTemplates()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export function renderTemplateSlide(input: RuntimeTemplateSlideInput) {
|
|
260
|
+
return renderPageTemplateSlide({
|
|
261
|
+
templateId: requiredString(input?.templateId, "templateId"),
|
|
262
|
+
slideIndex: input.slideIndex,
|
|
263
|
+
content: input.content ?? {},
|
|
264
|
+
designName: input.designName || activeDesign(),
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export function renderTemplateScaffold(input: RuntimeTemplateScaffoldInput) {
|
|
269
|
+
return renderPageTemplateScaffold({
|
|
270
|
+
templateId: requiredString(input?.templateId, "templateId"),
|
|
271
|
+
slideIndex: input.slideIndex,
|
|
272
|
+
seed: input.seed ?? {},
|
|
273
|
+
designName: input.designName || activeDesign(),
|
|
274
|
+
})
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function addTemplateSlide(input: RuntimeTemplateSlideAddInput) {
|
|
278
|
+
return addPageTemplateSlide({
|
|
279
|
+
workspaceRoot: root(input.workspaceRoot),
|
|
280
|
+
outputPath: requiredString(input?.outputPath, "outputPath"),
|
|
281
|
+
templateId: requiredString(input?.templateId, "templateId"),
|
|
282
|
+
slideIndex: input.slideIndex,
|
|
283
|
+
content: input.content ?? {},
|
|
284
|
+
designName: input.designName || activeDesign(),
|
|
285
|
+
})
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export function addTemplateScaffold(input: RuntimeTemplateScaffoldAddInput) {
|
|
289
|
+
return addPageTemplateScaffold({
|
|
290
|
+
workspaceRoot: root(input.workspaceRoot),
|
|
291
|
+
outputPath: requiredString(input?.outputPath, "outputPath"),
|
|
292
|
+
templateId: requiredString(input?.templateId, "templateId"),
|
|
293
|
+
slideIndex: input.slideIndex,
|
|
294
|
+
seed: input.seed ?? {},
|
|
295
|
+
designName: input.designName || activeDesign(),
|
|
296
|
+
})
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function pageTemplateFoundation(input: RuntimePageTemplateReadInput) {
|
|
300
|
+
return { ok: true, foundation: getPageTemplateFoundation(requiredString(input?.templateId, "templateId")) }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function pageTemplateVocabulary(input: RuntimePageTemplateReadInput) {
|
|
304
|
+
return { ok: true, vocabulary: getPageTemplateVocabulary(requiredString(input?.templateId, "templateId")) }
|
|
305
|
+
}
|
|
306
|
+
|
|
221
307
|
export async function runDeckQa(input: RuntimeFileInput) {
|
|
222
308
|
const { formatArtifactQAReport, runArtifactQA } = await import("../qa/artifact")
|
|
223
309
|
const workspaceRoot = root(input.workspaceRoot)
|
|
@@ -362,7 +448,8 @@ export function designCreate(input: RuntimeDesignCreateInput) {
|
|
|
362
448
|
name: requiredString(input?.name, "design name"),
|
|
363
449
|
base: input.base,
|
|
364
450
|
designMd: requiredString(input?.designMd, "designMd"),
|
|
365
|
-
|
|
451
|
+
designCss: input.designCss,
|
|
452
|
+
previewHtml: input.previewHtml,
|
|
366
453
|
assets: input.assets,
|
|
367
454
|
overwrite: input.overwrite ?? false,
|
|
368
455
|
})
|
|
@@ -378,7 +465,8 @@ export function designDraftCreate(input: RuntimeDesignDraftCreateInput) {
|
|
|
378
465
|
name: requiredString(input?.name, "design name"),
|
|
379
466
|
base: input.base,
|
|
380
467
|
designMd: requiredString(input?.designMd, "designMd"),
|
|
381
|
-
|
|
468
|
+
designCss: input.designCss,
|
|
469
|
+
previewHtml: input.previewHtml,
|
|
382
470
|
assets: input.assets,
|
|
383
471
|
overwrite: input.overwrite ?? false,
|
|
384
472
|
})
|
|
@@ -388,6 +476,14 @@ export function designDraftValidate(input: RuntimeWorkspaceInput & RuntimeNameIn
|
|
|
388
476
|
return validateDesignDraftPackage(root(input.workspaceRoot), requiredName(input, "design draft"))
|
|
389
477
|
}
|
|
390
478
|
|
|
479
|
+
export function designPreview(input: RuntimeDesignPreviewInput) {
|
|
480
|
+
return materializeDesignPreview({
|
|
481
|
+
workspaceRoot: root(input.workspaceRoot),
|
|
482
|
+
name: requiredName(input, "design"),
|
|
483
|
+
source: input.source,
|
|
484
|
+
})
|
|
485
|
+
}
|
|
486
|
+
|
|
391
487
|
export function designDraftInstall(input: RuntimeDraftInstallInput) {
|
|
392
488
|
seedBuiltinDesigns()
|
|
393
489
|
return installDesignDraftPackage({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyber-dash-tech/revela",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Codex-first CLI/MCP workspace for trusted narrative artifacts from local sources, research, and evidence",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -11,11 +11,7 @@
|
|
|
11
11
|
".": "./index.ts"
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
|
-
"assets/img/
|
|
15
|
-
"assets/img/logo-64.png",
|
|
16
|
-
"assets/img/logo-256.png",
|
|
17
|
-
"assets/img/logo-wordmark.png",
|
|
18
|
-
"assets/img/review-ui.png",
|
|
14
|
+
"assets/img/",
|
|
19
15
|
"bin/",
|
|
20
16
|
"plugin.ts",
|
|
21
17
|
"lib/",
|
|
@@ -23,15 +19,11 @@
|
|
|
23
19
|
"tools/",
|
|
24
20
|
"skill/",
|
|
25
21
|
"designs/aurora/DESIGN.md",
|
|
26
|
-
"designs/starter/
|
|
27
|
-
"designs/
|
|
28
|
-
"designs/
|
|
29
|
-
"designs/
|
|
30
|
-
"designs/
|
|
31
|
-
"designs/monet/preview.html",
|
|
32
|
-
"designs/lucent/DESIGN.md",
|
|
33
|
-
"designs/lucent/preview.html",
|
|
34
|
-
"designs/lucent/assets/",
|
|
22
|
+
"designs/starter/",
|
|
23
|
+
"designs/summit/",
|
|
24
|
+
"designs/monet/",
|
|
25
|
+
"designs/lucent/",
|
|
26
|
+
"designs/lucent-dark/",
|
|
35
27
|
"domains/general/INDUSTRY.md",
|
|
36
28
|
"domains/deeptech-investment/INDUSTRY.md",
|
|
37
29
|
"domains/consulting/INDUSTRY.md",
|