@cyber-dash-tech/revela 0.17.18 → 0.17.20

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.
@@ -81,6 +81,7 @@ const VISUAL_QUALITY_RULES = `Visual extraction and CSS quality rules:
81
81
 
82
82
  const PREVIEW_REQUIREMENTS = `Preview requirements:
83
83
  - \`preview.html\` must include a cover slide and a closing slide. Mark their \`<section class="slide">\` elements with \`data-slide-role="cover"\` and \`data-slide-role="closing"\`.
84
+ - \`preview.html\` must define an explicit CSS rule for \`.slide-canvas\` with \`width: 1920px\` and \`height: 1080px\`; every direct \`.slide-canvas\` is the fixed 1920px x 1080px export surface.
84
85
  - \`preview.html\` must showcase every \`@component:*\` defined in \`DESIGN.md\`. Mark each showcased component with \`data-preview-component="<component-name>"\`.
85
86
  - Do not save with \`revela-designs-author\` until every component has a corresponding preview marker. If a component is decorative or abstract, include a visible labeled sample state.
86
87
  - When the design supports chart styling, \`preview.html\` should include a 3x3 ECharts gallery with at least 9 chart examples. This is a preview quality requirement, not a validation blocker.`
@@ -133,6 +134,7 @@ Hard requirements:
133
134
  - \`DESIGN.md\` must include valid \`@design\`, \`@layout\`, and \`@component\` markers.
134
135
  - \`DESIGN.md\` must include at least \`@design:foundation\`, \`@design:rules\`, one layout, and one component.
135
136
  - \`preview.html\` must be self-contained and directly openable in a browser.
137
+ - \`preview.html\` must include an explicit CSS rule: \`.slide-canvas { width: 1920px; height: 1080px; }\`.
136
138
  - Every preview slide must include \`slide-qa="true"\` or \`slide-qa="false"\`.
137
139
  - \`preview.html\` must include \`data-slide-role="cover"\` and \`data-slide-role="closing"\` on slide sections.
138
140
  - \`preview.html\` must showcase every \`@component:*\` with \`data-preview-component="<component-name>"\` before saving.
@@ -172,6 +174,7 @@ Hard requirements:
172
174
  - Preserve valid frontmatter and marker structure.
173
175
  - Preserve at least \`@design:foundation\`, \`@design:rules\`, one layout, and one component.
174
176
  - \`preview.html\` must be self-contained and directly openable in a browser.
177
+ - \`preview.html\` must include an explicit CSS rule: \`.slide-canvas { width: 1920px; height: 1080px; }\`.
175
178
  - Every preview slide must include \`slide-qa="true"\` or \`slide-qa="false"\`.
176
179
  - \`preview.html\` must include \`data-slide-role="cover"\` and \`data-slide-role="closing"\` on slide sections.
177
180
  - \`preview.html\` must showcase every \`@component:*\` with \`data-preview-component="<component-name>"\` before saving.
@@ -264,6 +264,29 @@ function hasSlideRole(html: string, role: string): boolean {
264
264
  return false
265
265
  }
266
266
 
267
+ function cssRuleHasClassSelector(selectors: string, className: string): boolean {
268
+ const escaped = className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
269
+ return new RegExp(`(^|[^a-zA-Z0-9_-])\\.${escaped}(?![a-zA-Z0-9_-])`).test(selectors)
270
+ }
271
+
272
+ function cssRuleHasFixedCanvasSize(body: string): boolean {
273
+ const width = /(?:^|[;\s])width\s*:\s*1920px(?:\s*!important)?\s*(?:;|$)/i.test(body)
274
+ const height = /(?:^|[;\s])height\s*:\s*1080px(?:\s*!important)?\s*(?:;|$)/i.test(body)
275
+ return width && height
276
+ }
277
+
278
+ function hasFixedSizeCssRule(html: string, className: "slide-canvas"): boolean {
279
+ const withoutComments = html.replace(/\/\*[\s\S]*?\*\//g, "")
280
+ const ruleRe = /([^{}]+)\{([^{}]+)\}/g
281
+ let match: RegExpExecArray | null
282
+ while ((match = ruleRe.exec(withoutComments)) !== null) {
283
+ if (cssRuleHasClassSelector(match[1] ?? "", className) && cssRuleHasFixedCanvasSize(match[2] ?? "")) {
284
+ return true
285
+ }
286
+ }
287
+ return false
288
+ }
289
+
267
290
  /** Validate a local design package for the minimum Revela design contract. */
268
291
  export function validateDesignPackage(nameInput: string): ValidateDesignPackageResult {
269
292
  let name = nameInput
@@ -312,6 +335,9 @@ export function validateDesignPackage(nameInput: string): ValidateDesignPackageR
312
335
  if (!preview.includes('<section class="slide"')) errors.push("preview.html must include slide sections")
313
336
  if (!preview.includes("slide-qa=")) errors.push("preview.html slides must include slide-qa attributes")
314
337
  if (!preview.includes("slide-canvas")) errors.push("preview.html must include .slide-canvas")
338
+ if (!hasFixedSizeCssRule(preview, "slide-canvas")) {
339
+ errors.push("preview.html must define .slide-canvas CSS with width: 1920px and height: 1080px")
340
+ }
315
341
  if (!hasSlideRole(preview, "cover")) errors.push('preview.html must include a slide section with data-slide-role="cover"')
316
342
  if (!hasSlideRole(preview, "closing")) errors.push('preview.html must include a slide section with data-slide-role="closing"')
317
343
  const missingComponents = components.filter((component) => !hasDataAttribute(preview, "data-preview-component", component))
package/lib/qa/checks.ts CHANGED
@@ -209,19 +209,16 @@ function checkCanvas(metrics: SlideMetrics): LayoutIssue[] {
209
209
  }
210
210
 
211
211
  const canvasBad = Math.abs(metrics.canvasRect.width - CANVAS_W) > tol || Math.abs(metrics.canvasRect.height - CANVAS_H) > tol
212
- const slideBad = Math.abs(metrics.slideRect.width - CANVAS_W) > tol || Math.abs(metrics.slideRect.height - CANVAS_H) > tol
213
212
 
214
- if (canvasBad || slideBad) {
213
+ if (canvasBad) {
215
214
  issues.push({
216
215
  type: "canvas",
217
216
  sub: "size_mismatch",
218
217
  severity: "error",
219
- detail: `Slide and canvas must render exactly ${CANVAS_W}x${CANVAS_H}px. Measured slide ${Math.round(metrics.slideRect.width)}x${Math.round(metrics.slideRect.height)}px, canvas ${Math.round(metrics.canvasRect.width)}x${Math.round(metrics.canvasRect.height)}px.`,
218
+ detail: `.slide-canvas must render exactly ${CANVAS_W}x${CANVAS_H}px. Measured canvas ${Math.round(metrics.canvasRect.width)}x${Math.round(metrics.canvasRect.height)}px.`,
220
219
  data: {
221
220
  expectedWidth: CANVAS_W,
222
221
  expectedHeight: CANVAS_H,
223
- slideWidth: Math.round(metrics.slideRect.width),
224
- slideHeight: Math.round(metrics.slideRect.height),
225
222
  canvasWidth: Math.round(metrics.canvasRect.width),
226
223
  canvasHeight: Math.round(metrics.canvasRect.height),
227
224
  },
@@ -911,7 +908,7 @@ export function formatReport(report: QAReport): string {
911
908
  `### Action Required`,
912
909
  ``,
913
910
  `Please fix the above hard-error issues in the HTML file. For each issue type:`,
914
- `- **canvas**: ensure each slide and .slide-canvas render exactly 1920x1080px, not merely any 16:9 size.`,
911
+ `- **canvas**: ensure each canonical .slide has exactly one direct .slide-canvas and that .slide-canvas renders exactly 1920x1080px, not merely any 16:9 size.`,
915
912
  `- **scrollbar**: remove horizontal document/body scrolling and slide-internal scrolling. Multi-slide decks may use normal vertical document scroll for navigation.`,
916
913
  `- **navigation**: keep every .slide in normal document flow; do not stack slides with fixed/absolute positioning or rely on aria-hidden/visibility toggles for pagination. Use scrollIntoView-based navigation.`,
917
914
  `- **overflow**: reduce font size, padding, or content amount for the affected element.`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyber-dash-tech/revela",
3
- "version": "0.17.18",
3
+ "version": "0.17.20",
4
4
  "description": "OpenCode plugin for trusted narrative artifacts from local sources, research, and evidence",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "revela": {
4
4
  "command": "npx",
5
- "args": ["-y", "@cyber-dash-tech/revela@0.17.18", "mcp"]
5
+ "args": ["-y", "@cyber-dash-tech/revela@0.17.20", "mcp"]
6
6
  }
7
7
  }
8
8
  }
@@ -29,6 +29,6 @@ After confirmation, read the base design with `revela_design_read`. Generate com
29
29
 
30
30
  `DESIGN.md` must include frontmatter with `name`, `description`, `author`, and `version`, plus valid marker blocks for `@design:foundation`, `@design:rules`, at least one `@layout`, and at least one `@component`.
31
31
 
32
- `preview.html` must be self-contained and directly openable in a browser. Every `<section class="slide">` must include `slide-qa` and exactly one direct `.slide-canvas` child. Include a cover slide with `data-slide-role="cover"`, a closing slide with `data-slide-role="closing"`, and a visible sample for every `@component:*` using `data-preview-component="<component-name>"`.
32
+ `preview.html` must be self-contained and directly openable in a browser. Every `<section class="slide">` must include `slide-qa` and exactly one direct `.slide-canvas` child. Every direct `.slide-canvas` is the fixed 1920px x 1080px export surface and must use explicit CSS with `width: 1920px` and `height: 1080px`; `.slide` may remain a viewport/navigation wrapper. Include a cover slide with `data-slide-role="cover"`, a closing slide with `data-slide-role="closing"`, and a visible sample for every `@component:*` using `data-preview-component="<component-name>"`.
33
33
 
34
34
  Do not automatically activate a newly created design. Report the saved path and tell the user they can activate it with `revela_design_activate`.