openplanr 3.2.0 → 3.3.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 +21 -0
- package/dist/cli/commands/spec.d.ts +2 -1
- package/dist/cli/commands/spec.d.ts.map +1 -1
- package/dist/cli/commands/spec.js +45 -5
- package/dist/cli/commands/spec.js.map +1 -1
- package/dist/dashboard/.vite/manifest.json +1 -1
- package/dist/dashboard/assets/index-B_96uzCl.js +572 -0
- package/dist/dashboard/assets/index-B_96uzCl.js.map +1 -0
- package/dist/dashboard/dashboard-manifest.json +10 -10
- package/dist/dashboard/index.html +1 -1
- package/dist/services/claude-plugin-service.d.ts +5 -0
- package/dist/services/claude-plugin-service.d.ts.map +1 -1
- package/dist/services/claude-plugin-service.js +18 -2
- package/dist/services/claude-plugin-service.js.map +1 -1
- package/dist/services/codex-plugin-service.d.ts.map +1 -1
- package/dist/services/codex-plugin-service.js +11 -3
- package/dist/services/codex-plugin-service.js.map +1 -1
- package/dist/services/runtime-manager/codex-discovery.d.ts +1 -3
- package/dist/services/runtime-manager/codex-discovery.d.ts.map +1 -1
- package/dist/services/runtime-manager/codex-discovery.js +3 -16
- package/dist/services/runtime-manager/codex-discovery.js.map +1 -1
- package/dist/services/runtime-manager/doctor.d.ts +25 -0
- package/dist/services/runtime-manager/doctor.d.ts.map +1 -1
- package/dist/services/runtime-manager/doctor.js +480 -0
- package/dist/services/runtime-manager/doctor.js.map +1 -1
- package/dist/services/runtime-manager/errors.d.ts +12 -0
- package/dist/services/runtime-manager/errors.d.ts.map +1 -0
- package/dist/services/runtime-manager/errors.js +14 -0
- package/dist/services/runtime-manager/errors.js.map +1 -0
- package/dist/services/runtime-manager/global-state.d.ts +7 -0
- package/dist/services/runtime-manager/global-state.d.ts.map +1 -1
- package/dist/services/runtime-manager/global-state.js +116 -0
- package/dist/services/runtime-manager/global-state.js.map +1 -1
- package/dist/services/runtime-manager/host-version-probe.d.ts +8 -0
- package/dist/services/runtime-manager/host-version-probe.d.ts.map +1 -0
- package/dist/services/runtime-manager/host-version-probe.js +14 -0
- package/dist/services/runtime-manager/host-version-probe.js.map +1 -0
- package/dist/services/runtime-manager/install-plan.d.ts +25 -0
- package/dist/services/runtime-manager/install-plan.d.ts.map +1 -1
- package/dist/services/runtime-manager/install-plan.js +305 -0
- package/dist/services/runtime-manager/install-plan.js.map +1 -1
- package/dist/services/runtime-manager/inventory.d.ts +6 -0
- package/dist/services/runtime-manager/inventory.d.ts.map +1 -1
- package/dist/services/runtime-manager/inventory.js +16 -1
- package/dist/services/runtime-manager/inventory.js.map +1 -1
- package/dist/services/runtime-manager/legacy-adapters.d.ts +9 -0
- package/dist/services/runtime-manager/legacy-adapters.d.ts.map +1 -0
- package/dist/services/runtime-manager/legacy-adapters.js +187 -0
- package/dist/services/runtime-manager/legacy-adapters.js.map +1 -0
- package/dist/services/runtime-manager/paths.d.ts +18 -0
- package/dist/services/runtime-manager/paths.d.ts.map +1 -0
- package/dist/services/runtime-manager/paths.js +83 -0
- package/dist/services/runtime-manager/paths.js.map +1 -0
- package/dist/services/runtime-manager/runtime-package.d.ts +21 -0
- package/dist/services/runtime-manager/runtime-package.d.ts.map +1 -1
- package/dist/services/runtime-manager/runtime-package.js +77 -0
- package/dist/services/runtime-manager/runtime-package.js.map +1 -1
- package/dist/services/runtime-manager/storage.d.ts +47 -0
- package/dist/services/runtime-manager/storage.d.ts.map +1 -0
- package/dist/services/runtime-manager/storage.js +604 -0
- package/dist/services/runtime-manager/storage.js.map +1 -0
- package/dist/services/runtime-manager-service.d.ts +7 -17
- package/dist/services/runtime-manager-service.d.ts.map +1 -1
- package/dist/services/runtime-manager-service.js +32 -1695
- package/dist/services/runtime-manager-service.js.map +1 -1
- package/dist/services/ship-checks/contract.d.ts +13 -1
- package/dist/services/ship-checks/contract.d.ts.map +1 -1
- package/dist/services/ship-checks/contract.js +1 -1
- package/dist/services/ship-checks/contract.js.map +1 -1
- package/dist/services/ship-checks/coverage.d.ts +4 -0
- package/dist/services/ship-checks/coverage.d.ts.map +1 -0
- package/dist/services/ship-checks/coverage.js +113 -0
- package/dist/services/ship-checks/coverage.js.map +1 -0
- package/dist/services/ship-checks/discover.d.ts.map +1 -1
- package/dist/services/ship-checks/discover.js +3 -0
- package/dist/services/ship-checks/discover.js.map +1 -1
- package/dist/services/spec-service.d.ts +18 -0
- package/dist/services/spec-service.d.ts.map +1 -1
- package/dist/services/spec-service.js +174 -9
- package/dist/services/spec-service.js.map +1 -1
- package/dist/templates/spec/spec-shaped.md.hbs +1 -1
- package/dist/templates/spec/spec.md.hbs +2 -2
- package/docs/CLI.md +49 -2
- package/lib/host-packages/adapter-registry.json +5 -5
- package/lib/host-packages/capability-map.json +3 -3
- package/lib/host-packages/claude/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/claude/openplanr/.claude-plugin/plugin.json +1 -1
- package/lib/host-packages/claude/openplanr/.openplanr-content.json +50 -46
- package/lib/host-packages/claude/openplanr/README.md +1 -1
- package/lib/host-packages/claude/openplanr/agents/planr-qa.md +5 -3
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-document.mjs +87 -2
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-handoff.mjs +1 -1
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-share.mjs +1 -1
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +102 -9
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +130 -1
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/design.mjs +271 -28
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -32
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +77 -1
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +4 -4
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/{cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.20.0 → claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0}/design-document.schema.json +131 -4
- package/lib/host-packages/claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +78 -1
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/design.mjs +30 -2
- package/lib/host-packages/claude/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/claude/openplanr/skills/design/references/design-system.md +17 -2
- package/lib/host-packages/claude/openplanr/skills/design/references/generation.md +60 -2
- package/lib/host-packages/claude/openplanr/skills/design/references/utilities.md +11 -1
- package/lib/host-packages/claude/openplanr/skills/design/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/claude/openplanr/skills/design-loop/references/design-system.md +17 -2
- package/lib/host-packages/claude/openplanr/skills/design-loop/references/generation.md +60 -2
- package/lib/host-packages/claude/openplanr/skills/design-loop/references/utilities.md +11 -1
- package/lib/host-packages/claude/openplanr/skills/design-loop/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/claude/openplanr/skills/design-review/references/design-system.md +17 -2
- package/lib/host-packages/claude/openplanr/skills/design-review/references/generation.md +60 -2
- package/lib/host-packages/claude/openplanr/skills/design-review/references/utilities.md +11 -1
- package/lib/host-packages/claude/openplanr/skills/design-review/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/claude/openplanr/skills/investigate/SKILL.md +1 -1
- package/lib/host-packages/claude/openplanr/skills/plan/SKILL.md +21 -11
- package/lib/host-packages/claude/openplanr/skills/plan/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/claude/openplanr/skills/ship/SKILL.md +31 -10
- package/lib/host-packages/claude/openplanr/skills/spec/SKILL.md +6 -0
- package/lib/host-packages/claude/openplanr/skills/spec/references/specification-contract.md +3 -1
- package/lib/host-packages/cursor/openplanr/.openplanr-content.json +48 -44
- package/lib/host-packages/cursor/openplanr/manifest.json +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/references/design-system.md +17 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design/references/generation.md +60 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design/references/utilities.md +11 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/design-system.md +17 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/generation.md +60 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/references/utilities.md +11 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-loop/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/design-system.md +17 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/generation.md +60 -2
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/references/utilities.md +11 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-design-review/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/cursor/openplanr/rules/planr-investigate.mdc +1 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-plan/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/cursor/openplanr/rules/planr-plan.mdc +21 -11
- package/lib/host-packages/cursor/openplanr/rules/planr-ship.mdc +31 -10
- package/lib/host-packages/cursor/openplanr/rules/planr-spec/references/specification-contract.md +3 -1
- package/lib/host-packages/cursor/openplanr/rules/planr-spec.mdc +6 -0
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-document.mjs +87 -2
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-handoff.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-share.mjs +1 -1
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +102 -9
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +130 -1
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/design.mjs +271 -28
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -32
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +77 -1
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +4 -4
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/{openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.20.0 → cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0}/design-document.schema.json +131 -4
- package/lib/host-packages/cursor/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +78 -1
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/design.mjs +30 -2
- package/lib/host-packages/cursor/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/openai/.claude-plugin/marketplace.json +2 -2
- package/lib/host-packages/openai/openplanr/.codex-plugin/plugin.json +1 -1
- package/lib/host-packages/openai/openplanr/.openplanr-content.json +54 -50
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-document.mjs +87 -2
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-handoff.mjs +1 -1
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-share.mjs +1 -1
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-artifact-support-dependencies-design-support-protocol-contracts-3d9b1a86.mjs +102 -9
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design-shared-protocol-contracts-b5f28f94.mjs +130 -1
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/design.mjs +271 -28
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/notices/THIRD_PARTY_NOTICES.txt +32 -32
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources/03-protocol-contracts.js +77 -1
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/artifact/templates/artifact-review-stage.js.sources.json +4 -4
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/package.json +4 -4
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/02-react.js +2 -2
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/09-react-dom-client-public-roots.js +5 -5
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/12-protocol-contracts.js +72 -2
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/13-design-review-experience.js +14 -7
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/15-canvas-engine.js +71 -34
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources/21-design-studio.js +28 -14
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/design/templates/studio/studio.js.sources.json +12 -12
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/{claude/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.20.0 → openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0}/design-document.schema.json +131 -4
- package/lib/host-packages/openai/openplanr/runtime/design/scripts/runtime/packages/protocol/schemas/v1.22.0/design-review-bundle.schema.json +822 -0
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design-protocol-contracts.mjs +78 -1
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/design.mjs +30 -2
- package/lib/host-packages/openai/openplanr/runtime/plan/scripts/runtime/packages/protocol/package.json +2 -2
- package/lib/host-packages/openai/openplanr/skills/design/references/design-system.md +17 -2
- package/lib/host-packages/openai/openplanr/skills/design/references/generation.md +60 -2
- package/lib/host-packages/openai/openplanr/skills/design/references/utilities.md +11 -1
- package/lib/host-packages/openai/openplanr/skills/design/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/openai/openplanr/skills/design-loop/references/design-system.md +17 -2
- package/lib/host-packages/openai/openplanr/skills/design-loop/references/generation.md +60 -2
- package/lib/host-packages/openai/openplanr/skills/design-loop/references/utilities.md +11 -1
- package/lib/host-packages/openai/openplanr/skills/design-loop/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/openai/openplanr/skills/design-review/references/design-system.md +17 -2
- package/lib/host-packages/openai/openplanr/skills/design-review/references/generation.md +60 -2
- package/lib/host-packages/openai/openplanr/skills/design-review/references/utilities.md +11 -1
- package/lib/host-packages/openai/openplanr/skills/design-review/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/openai/openplanr/skills/investigate/SKILL.md +1 -1
- package/lib/host-packages/openai/openplanr/skills/investigate/agents/openai.yaml +1 -1
- package/lib/host-packages/openai/openplanr/skills/investigate/openplanr.skill.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/plan/SKILL.md +21 -11
- package/lib/host-packages/openai/openplanr/skills/plan/openplanr.skill.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/plan/schemas/design-document.schema.json +131 -4
- package/lib/host-packages/openai/openplanr/skills/ship/SKILL.md +31 -10
- package/lib/host-packages/openai/openplanr/skills/ship/agents/openai.yaml +1 -1
- package/lib/host-packages/openai/openplanr/skills/ship/openplanr.skill.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/spec/SKILL.md +6 -0
- package/lib/host-packages/openai/openplanr/skills/spec/openplanr.skill.json +1 -1
- package/lib/host-packages/openai/openplanr/skills/spec/references/specification-contract.md +3 -1
- package/lib/json-schema.mjs +4 -0
- package/package.json +12 -12
- package/dist/dashboard/assets/index-L8qtwqv6.js +0 -572
- package/dist/dashboard/assets/index-L8qtwqv6.js.map +0 -1
- /package/lib/host-packages/claude/openplanr/runtime/design/scripts/{design-runtime-support-6774fd3d5d02.mjs → design-runtime-support-25485dbf1cb2.mjs} +0 -0
- /package/lib/host-packages/cursor/openplanr/runtime/design/scripts/{design-runtime-support-6774fd3d5d02.mjs → design-runtime-support-25485dbf1cb2.mjs} +0 -0
- /package/lib/host-packages/openai/openplanr/runtime/design/scripts/{design-runtime-support-6774fd3d5d02.mjs → design-runtime-support-25485dbf1cb2.mjs} +0 -0
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
currentDesign,
|
|
19
19
|
designSpecPath,
|
|
20
20
|
hash,
|
|
21
|
+
inspectLocalDocumentBody,
|
|
21
22
|
json,
|
|
22
23
|
loadReviewContext,
|
|
23
24
|
parse,
|
|
@@ -44,7 +45,8 @@ import {
|
|
|
44
45
|
import {
|
|
45
46
|
DESIGN_DOCUMENT_SCHEMA,
|
|
46
47
|
assertDesignDocument,
|
|
47
|
-
initialFrameHeight
|
|
48
|
+
initialFrameHeight,
|
|
49
|
+
validateDesignProps
|
|
48
50
|
} from "./design-shared-protocol-contracts-b5f28f94.mjs";
|
|
49
51
|
|
|
50
52
|
// packages/design/lib/design/frame-size.mjs
|
|
@@ -1620,6 +1622,15 @@ function lintDesign(html, opts = {}) {
|
|
|
1620
1622
|
const { designSystem = null } = opts;
|
|
1621
1623
|
const errors = [];
|
|
1622
1624
|
const warnings = [];
|
|
1625
|
+
if (opts.screen) {
|
|
1626
|
+
const values = Object.hasOwn(opts.variant?.props ?? {}, opts.screen.id) ? opts.variant.props[opts.screen.id] : {};
|
|
1627
|
+
errors.push(
|
|
1628
|
+
...validateDesignProps({
|
|
1629
|
+
screens: [opts.screen],
|
|
1630
|
+
variants: [{ props: { [opts.screen.id]: values } }]
|
|
1631
|
+
}).map((message) => ({ rule: "invalid-instance-prop", level: "error", message }))
|
|
1632
|
+
);
|
|
1633
|
+
}
|
|
1623
1634
|
const decls = [...styleBlockDecls(html), ...inlineStyleDecls(html)];
|
|
1624
1635
|
for (const d of decls) {
|
|
1625
1636
|
if (SPACING_PROP.test(d.prop)) {
|
|
@@ -1693,6 +1704,57 @@ function lintDesign(html, opts = {}) {
|
|
|
1693
1704
|
summary: `${errors.length} error(s), ${warnings.length} warning(s)`
|
|
1694
1705
|
};
|
|
1695
1706
|
}
|
|
1707
|
+
function withoutRootTheme(html) {
|
|
1708
|
+
if (!/theme-(?:light|dark)|data-theme/iu.test(html)) return null;
|
|
1709
|
+
const body = inspectLocalDocumentBody(html);
|
|
1710
|
+
if (!body) return null;
|
|
1711
|
+
const edits = [];
|
|
1712
|
+
for (const { name, value } of body.attrs) {
|
|
1713
|
+
const location = body.location.attrs?.[name];
|
|
1714
|
+
if (!location) continue;
|
|
1715
|
+
let replacement;
|
|
1716
|
+
if (name === "data-theme" && ["light", "dark"].includes(value)) replacement = "";
|
|
1717
|
+
if (name === "class") {
|
|
1718
|
+
const raw = html.slice(location.startOffset, location.endOffset);
|
|
1719
|
+
const quoted = /^(class\s*=\s*)(["'])([\s\S]*)\2$/iu.exec(raw);
|
|
1720
|
+
if (quoted) {
|
|
1721
|
+
const kept = quoted[3].replace(/(^|\s)theme-(?:light|dark)(?=\s|$)/gu, "$1");
|
|
1722
|
+
if (kept !== quoted[3]) replacement = `${quoted[1]}${quoted[2]}${kept}${quoted[2]}`;
|
|
1723
|
+
} else if (/^class\s*=\s*theme-(?:light|dark)$/iu.test(raw)) replacement = "";
|
|
1724
|
+
}
|
|
1725
|
+
if (replacement !== void 0) edits.push({ ...location, replacement });
|
|
1726
|
+
}
|
|
1727
|
+
if (!edits.length) return null;
|
|
1728
|
+
let normalized = html;
|
|
1729
|
+
for (const { startOffset, endOffset, replacement } of edits.sort(
|
|
1730
|
+
(a, b) => b.startOffset - a.startOffset
|
|
1731
|
+
))
|
|
1732
|
+
normalized = normalized.slice(0, startOffset) + replacement + normalized.slice(endOffset);
|
|
1733
|
+
return normalized;
|
|
1734
|
+
}
|
|
1735
|
+
function lintThemeOnlySources(sources) {
|
|
1736
|
+
const warnings = [];
|
|
1737
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1738
|
+
for (const { screenId, source, html } of sources) {
|
|
1739
|
+
const normalized = withoutRootTheme(html);
|
|
1740
|
+
if (normalized === null) continue;
|
|
1741
|
+
const key = JSON.stringify({
|
|
1742
|
+
html: normalized,
|
|
1743
|
+
styles: source.styles ?? [],
|
|
1744
|
+
scripts: source.scripts ?? []
|
|
1745
|
+
});
|
|
1746
|
+
const previous = seen.get(key);
|
|
1747
|
+
if (previous && previous.screenId !== screenId && previous.source !== source.html && previous.html !== html)
|
|
1748
|
+
warnings.push({
|
|
1749
|
+
rule: "theme-only-source",
|
|
1750
|
+
level: "warn",
|
|
1751
|
+
screenId,
|
|
1752
|
+
message: `Screens ${previous.screenId} (${previous.source}) and ${screenId} (${source.html}) differ only by a root theme marker; declare a theme prop and share one source.`
|
|
1753
|
+
});
|
|
1754
|
+
else seen.set(key, { screenId, source: source.html, html });
|
|
1755
|
+
}
|
|
1756
|
+
return warnings;
|
|
1757
|
+
}
|
|
1696
1758
|
function lintCanvasData(data, { frames } = {}) {
|
|
1697
1759
|
const errors = [];
|
|
1698
1760
|
for (const section of data?.sections || []) {
|
|
@@ -2434,8 +2496,19 @@ function prepareDesignDocument(file, { readSource, passive = false, maxBytes } =
|
|
|
2434
2496
|
])
|
|
2435
2497
|
);
|
|
2436
2498
|
for (const variant of document2.variants.filter((item) => item.status === "ready")) {
|
|
2499
|
+
const themeWarnings = lintThemeOnlySources(
|
|
2500
|
+
document2.screens.map((screen) => {
|
|
2501
|
+
const source = variant.sources?.[screen.id] ?? screen.source;
|
|
2502
|
+
return {
|
|
2503
|
+
screenId: screen.id,
|
|
2504
|
+
source,
|
|
2505
|
+
html: sourceContents.get(source.html).toString("utf8")
|
|
2506
|
+
};
|
|
2507
|
+
})
|
|
2508
|
+
);
|
|
2437
2509
|
for (const screenId of document2.screenOrder) {
|
|
2438
2510
|
const screen = document2.screens.find((item) => item.id === screenId);
|
|
2511
|
+
const values = Object.hasOwn(variant.props ?? {}, screenId) ? variant.props[screenId] : {};
|
|
2439
2512
|
const bundled = bundleLocalDocument({
|
|
2440
2513
|
root,
|
|
2441
2514
|
source: variant.sources?.[screenId] ?? screen.source,
|
|
@@ -2443,6 +2516,14 @@ function prepareDesignDocument(file, { readSource, passive = false, maxBytes } =
|
|
|
2443
2516
|
screenId,
|
|
2444
2517
|
readSource,
|
|
2445
2518
|
passive,
|
|
2519
|
+
...screen.props ? {
|
|
2520
|
+
screenProps: Object.fromEntries(
|
|
2521
|
+
Object.entries(screen.props).map(([name, declaration]) => [
|
|
2522
|
+
name,
|
|
2523
|
+
Object.hasOwn(values, name) ? values[name] : declaration.default
|
|
2524
|
+
])
|
|
2525
|
+
)
|
|
2526
|
+
} : {},
|
|
2446
2527
|
...maxBytes === void 0 ? {} : { maxBytes }
|
|
2447
2528
|
});
|
|
2448
2529
|
if (document2.frames.some(({ height }) => height === "auto"))
|
|
@@ -2465,8 +2546,12 @@ function prepareDesignDocument(file, { readSource, passive = false, maxBytes } =
|
|
|
2465
2546
|
);
|
|
2466
2547
|
}
|
|
2467
2548
|
const report = lintDesign(bundled.html, {
|
|
2468
|
-
designSystem: document2.designSystem
|
|
2549
|
+
designSystem: document2.designSystem,
|
|
2550
|
+
screen,
|
|
2551
|
+
variant
|
|
2469
2552
|
});
|
|
2553
|
+
report.warnings.push(...themeWarnings.filter((item) => item.screenId === screenId));
|
|
2554
|
+
report.summary = `${report.errors.length} error(s), ${report.warnings.length} warning(s)`;
|
|
2470
2555
|
lint.push({ variantId: variant.id, screenId, ...report });
|
|
2471
2556
|
for (const anchor of screen.anchors ?? []) {
|
|
2472
2557
|
if (!bundled.html.includes(`data-planr-id="${anchor}"`) && !bundled.html.includes(`id="${anchor}"`))
|
|
@@ -654,7 +654,7 @@ function compileDesignHandoffReadiness(input) {
|
|
|
654
654
|
if (input === null || input === void 0) return designHandoffReadinessAbsence();
|
|
655
655
|
const source = plainClone(input);
|
|
656
656
|
const document = source.document;
|
|
657
|
-
if (!document || document.kind !== "openplanr-design-document" ||
|
|
657
|
+
if (!document || document.kind !== "openplanr-design-document" || !["1.0.0", "1.1.0"].includes(document.schemaVersion) || typeof document.id !== "string" || !document.id)
|
|
658
658
|
throw new TypeError("Readiness requires one supported design document.");
|
|
659
659
|
const revision = source.sourceRevision === null || source.sourceRevision === void 0 ? null : normalizeDigest(source.sourceRevision, "design revision");
|
|
660
660
|
const direction = selectedDirection(document, source.studioState);
|
|
@@ -1807,7 +1807,7 @@ async function importDesignShareRecovery(file, { input, ...options } = {}) {
|
|
|
1807
1807
|
const pending = custody.pendingCreate ?? custody.pendingMutation.body;
|
|
1808
1808
|
const destination = join3(root, "uploads", custody.id, pending.operationId);
|
|
1809
1809
|
if (existsSync4(destination)) {
|
|
1810
|
-
const { spoolChunkReader: spoolChunkReader2 } = await import("./design-runtime-support-
|
|
1810
|
+
const { spoolChunkReader: spoolChunkReader2 } = await import("./design-runtime-support-25485dbf1cb2.mjs");
|
|
1811
1811
|
const reader = spoolChunkReader2(destination, pending);
|
|
1812
1812
|
for (const part of pending.manifest.chunks) await reader(part.index);
|
|
1813
1813
|
} else await copyUploadSpool(custody, destination);
|
|
@@ -15,7 +15,9 @@ import {
|
|
|
15
15
|
} from "./design-shared-artifact-support-protocol-contracts-ea2cd15e.mjs";
|
|
16
16
|
import {
|
|
17
17
|
DESIGN_DOCUMENT_SCHEMA,
|
|
18
|
+
DESIGN_DOCUMENT_V120_SCHEMA,
|
|
18
19
|
DESIGN_REVIEW_BUNDLE_SCHEMA,
|
|
20
|
+
validateDesignProps,
|
|
19
21
|
validateJson
|
|
20
22
|
} from "./design-shared-protocol-contracts-b5f28f94.mjs";
|
|
21
23
|
import {
|
|
@@ -323,6 +325,7 @@ var MIME = {
|
|
|
323
325
|
};
|
|
324
326
|
var children = (node) => [...node.childNodes ?? [], ...node.content?.childNodes ?? []];
|
|
325
327
|
var attr = (node, name) => node.attrs?.find((item2) => item2.name === name);
|
|
328
|
+
var isPropToken = (value) => typeof value === "string" && value.length <= 128 && /^[a-z][a-z0-9-]*(?![\s\S])/u.test(value);
|
|
326
329
|
var text = (node) => children(node).map((item2) => item2.value ?? "").join("");
|
|
327
330
|
function setText(node, value) {
|
|
328
331
|
node.childNodes = [{ nodeName: "#text", value, parentNode: node }];
|
|
@@ -332,6 +335,23 @@ function element(name, value) {
|
|
|
332
335
|
setText(node, value);
|
|
333
336
|
return node;
|
|
334
337
|
}
|
|
338
|
+
function parseBodySource(html) {
|
|
339
|
+
const roots = [];
|
|
340
|
+
const parser = new Parser({ sourceCodeLocationInfo: true });
|
|
341
|
+
const onStartTag = parser.onStartTag.bind(parser);
|
|
342
|
+
parser.onStartTag = (token) => {
|
|
343
|
+
if (token.tagName === "body") roots.push(token);
|
|
344
|
+
onStartTag(token);
|
|
345
|
+
};
|
|
346
|
+
parser.tokenizer.write(html, true);
|
|
347
|
+
const body = parser.document.childNodes.find((node) => node.tagName === "html")?.childNodes.find((node) => node.tagName === "body");
|
|
348
|
+
const root = roots.length === 1 && body?.sourceCodeLocation?.startTag?.startOffset === roots[0].location?.startOffset ? roots[0] : null;
|
|
349
|
+
return { document: parser.document, roots, root };
|
|
350
|
+
}
|
|
351
|
+
function inspectLocalDocumentBody(html) {
|
|
352
|
+
const { root } = parseBodySource(html);
|
|
353
|
+
return root ? { attrs: root.attrs, location: root.location } : null;
|
|
354
|
+
}
|
|
335
355
|
function resolveLocalDocumentFile(root, path, from = root) {
|
|
336
356
|
if (typeof path !== "string" || !path || /^(?:[a-z][a-z\d+.-]*:|\/|\\)/iu.test(path))
|
|
337
357
|
throw new Error(`Expected a local relative asset: ${path}`);
|
|
@@ -353,7 +373,8 @@ function bundleLocalDocument({
|
|
|
353
373
|
screenId,
|
|
354
374
|
maxBytes = MAX_ARTIFACT_HTML_BYTES,
|
|
355
375
|
readSource,
|
|
356
|
-
passive = false
|
|
376
|
+
passive = false,
|
|
377
|
+
screenProps
|
|
357
378
|
}) {
|
|
358
379
|
const root = realpathSync2(inputRoot);
|
|
359
380
|
const files = /* @__PURE__ */ new Map();
|
|
@@ -483,7 +504,16 @@ function bundleLocalDocument({
|
|
|
483
504
|
return value.replace(/<\/script/giu, "<\\/script");
|
|
484
505
|
}
|
|
485
506
|
const input = read(source.html);
|
|
486
|
-
const
|
|
507
|
+
const propEntries = Object.entries(screenProps ?? {});
|
|
508
|
+
let document;
|
|
509
|
+
if (propEntries.length) {
|
|
510
|
+
const parsed = parseBodySource(input.value.toString("utf8"));
|
|
511
|
+
if (!parsed.root)
|
|
512
|
+
throw new Error(
|
|
513
|
+
`Screen ${screenId} source ${source.html} requires a single authored <body> root for props; found ${parsed.roots.length}.`
|
|
514
|
+
);
|
|
515
|
+
document = parsed.document;
|
|
516
|
+
} else document = parse(input.value.toString("utf8"));
|
|
487
517
|
let head, body;
|
|
488
518
|
const deferredScripts = [];
|
|
489
519
|
const queue = [...children(document)];
|
|
@@ -575,6 +605,22 @@ function bundleLocalDocument({
|
|
|
575
605
|
body.childNodes.push(node);
|
|
576
606
|
}
|
|
577
607
|
body.attrs.push({ name: "data-planr-screen", value: screenId });
|
|
608
|
+
if (propEntries.length) {
|
|
609
|
+
const classes = (attr(body, "class")?.value ?? "").split(/\s+/u).filter(Boolean).filter((item2) => !propEntries.some(([name]) => item2.startsWith(`prop-${name}-`)));
|
|
610
|
+
for (const [name, value] of propEntries) {
|
|
611
|
+
if (!isPropToken(name) || !(typeof value === "boolean" || isPropToken(value)))
|
|
612
|
+
throw new TypeError(
|
|
613
|
+
`Screen ${screenId} source ${source.html} has invalid prop ${name}: ${JSON.stringify(value)}.`
|
|
614
|
+
);
|
|
615
|
+
const attribute = `data-prop-${name}`;
|
|
616
|
+
body.attrs = body.attrs.filter((item2) => item2.name !== attribute);
|
|
617
|
+
body.attrs.push({ name: attribute, value: String(value) });
|
|
618
|
+
const prefix = `prop-${name}-`;
|
|
619
|
+
classes.push(`${prefix}${value}`);
|
|
620
|
+
}
|
|
621
|
+
body.attrs = body.attrs.filter((item2) => item2.name !== "class");
|
|
622
|
+
body.attrs.push({ name: "class", value: classes.join(" ") });
|
|
623
|
+
}
|
|
578
624
|
const html = serialize(document);
|
|
579
625
|
if (Buffer.byteLength(html) > maxBytes)
|
|
580
626
|
throw new Error("Bundled design exceeds the output budget.");
|
|
@@ -706,14 +752,41 @@ var currentDesign2 = (
|
|
|
706
752
|
);
|
|
707
753
|
for (const key of ["frames", "layout"])
|
|
708
754
|
currentDesign2.properties[key] = /** @type {Record<string, unknown>} */
|
|
709
|
-
|
|
710
|
-
bundleCurrent.$defs = structuredClone(
|
|
755
|
+
DESIGN_DOCUMENT_V120_SCHEMA.properties[key];
|
|
756
|
+
bundleCurrent.$defs = structuredClone(DESIGN_DOCUMENT_V120_SCHEMA.$defs);
|
|
711
757
|
var currentEntries = (
|
|
712
758
|
/** @type {{ items: { properties: Record<string, unknown> } }} */
|
|
713
759
|
bundleCurrent.properties.entries
|
|
714
760
|
);
|
|
715
761
|
currentEntries.items.properties.height = { const: "auto" };
|
|
716
|
-
var
|
|
762
|
+
var bundleProps = (
|
|
763
|
+
/** @type {MutableSchema} */
|
|
764
|
+
structuredClone(bundleCurrent)
|
|
765
|
+
);
|
|
766
|
+
bundleProps.$id = "https://openplanr.dev/schemas/v1.22.0/design-review-bundle.schema.json";
|
|
767
|
+
bundleProps["x-openplanr-contract"] = { id: "design-review-bundle", version: "1.22.0" };
|
|
768
|
+
var propsDesign = (
|
|
769
|
+
/** @type {MutableSchema} */
|
|
770
|
+
bundleProps.properties.design
|
|
771
|
+
);
|
|
772
|
+
var authoredProperties = (
|
|
773
|
+
/** @type {Record<string, unknown>} */
|
|
774
|
+
DESIGN_DOCUMENT_SCHEMA.properties
|
|
775
|
+
);
|
|
776
|
+
propsDesign.properties.schemaVersion = authoredProperties.schemaVersion;
|
|
777
|
+
for (const key of ["screens", "variants"]) {
|
|
778
|
+
const projected = (
|
|
779
|
+
/** @type {{ items: { properties: Record<string, unknown> } }} */
|
|
780
|
+
propsDesign.properties[key]
|
|
781
|
+
);
|
|
782
|
+
const authored = (
|
|
783
|
+
/** @type {{ items: { properties: Record<string, unknown> } }} */
|
|
784
|
+
authoredProperties[key]
|
|
785
|
+
);
|
|
786
|
+
projected.items.properties.props = authored.items.properties.props;
|
|
787
|
+
}
|
|
788
|
+
propsDesign.allOf = structuredClone(DESIGN_DOCUMENT_SCHEMA.allOf);
|
|
789
|
+
var DESIGN_REVIEW_BUNDLE_CURRENT_SCHEMA = bundleProps;
|
|
717
790
|
var item = closed(
|
|
718
791
|
{
|
|
719
792
|
pinId: id,
|
|
@@ -830,10 +903,19 @@ function assertDesignReviewMetadata(value) {
|
|
|
830
903
|
);
|
|
831
904
|
}
|
|
832
905
|
function assertDesignReviewBundle(value) {
|
|
906
|
+
if (value?.design?.schemaVersion !== "1.1.0" && ["screens", "variants"].some(
|
|
907
|
+
(field) => Array.isArray(value?.design?.[field]) && value.design[field].some((item2) => item2 && Object.hasOwn(item2, "props"))
|
|
908
|
+
))
|
|
909
|
+
throw new TypeError('Invalid design props: props require design.schemaVersion "1.1.0"');
|
|
833
910
|
assertReviewExperience(
|
|
834
911
|
value,
|
|
835
|
-
value?.design?.
|
|
912
|
+
value?.design?.schemaVersion !== void 0 || ["screens", "variants"].some(
|
|
913
|
+
(field) => Array.isArray(value?.design?.[field]) && value.design[field].some((item2) => item2 && Object.hasOwn(item2, "props"))
|
|
914
|
+
) || value?.design?.layout !== void 0 || Array.isArray(value?.design?.frames) && value.design.frames.some(({ height }) => height === "auto") ? DESIGN_REVIEW_BUNDLE_CURRENT_SCHEMA : value?.schemaVersion === "1.2.0" ? DESIGN_REVIEW_BUNDLE_V12_SCHEMA : value?.schemaVersion === "1.1.0" ? DESIGN_REVIEW_BUNDLE_V11_SCHEMA : DESIGN_REVIEW_BUNDLE_SCHEMA
|
|
836
915
|
);
|
|
916
|
+
const propErrors = validateDesignProps(value.design);
|
|
917
|
+
if (propErrors.length) throw new TypeError(`Invalid design props:
|
|
918
|
+
${propErrors.join("\n")}`);
|
|
837
919
|
if (["1.1.0", "1.2.0"].includes(value.schemaVersion)) {
|
|
838
920
|
if (value.reviewContext.designId !== value.design.id || value.contextDigest !== sha256Hex(canonicalizeJson(value.reviewContext)))
|
|
839
921
|
throw new TypeError("Review context identity or digest does not match its published design.");
|
|
@@ -902,6 +984,7 @@ function reviewFingerprints({ document, context, screen, variant, frame, sourceD
|
|
|
902
984
|
const components = context.implementation.components.filter(
|
|
903
985
|
(component) => !component.screenIds?.length || component.screenIds.includes(screen.id)
|
|
904
986
|
);
|
|
987
|
+
const values = Object.hasOwn(variant.props ?? {}, screen.id) ? variant.props[screen.id] : {};
|
|
905
988
|
return {
|
|
906
989
|
screenId: screen.id,
|
|
907
990
|
variantId: variant.id,
|
|
@@ -909,7 +992,15 @@ function reviewFingerprints({ document, context, screen, variant, frame, sourceD
|
|
|
909
992
|
contentDigest: reviewDigest({
|
|
910
993
|
files: Object.entries(sourceDigests).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0),
|
|
911
994
|
width: frame.width,
|
|
912
|
-
height: frame.height
|
|
995
|
+
height: frame.height,
|
|
996
|
+
...screen.props === void 0 ? {} : {
|
|
997
|
+
props: Object.fromEntries(
|
|
998
|
+
Object.entries(screen.props).map(([name, declaration]) => [
|
|
999
|
+
name,
|
|
1000
|
+
Object.hasOwn(values, name) ? values[name] : declaration.default
|
|
1001
|
+
])
|
|
1002
|
+
)
|
|
1003
|
+
}
|
|
913
1004
|
}),
|
|
914
1005
|
guidanceDigest: reviewDigest({
|
|
915
1006
|
title: screen.title,
|
|
@@ -934,6 +1025,7 @@ function bundleDesignRevision(current, state = {}) {
|
|
|
934
1025
|
kind: "openplanr-design-review-bundle",
|
|
935
1026
|
schemaVersion: current.envelope.schemaVersion === "1.1.0" ? "1.2.0" : "1.1.0",
|
|
936
1027
|
design: {
|
|
1028
|
+
...document.screens.some((screen) => screen.props !== void 0) || document.variants.some((variant) => variant.props !== void 0) ? { schemaVersion: document.schemaVersion } : {},
|
|
937
1029
|
...pick(document, [
|
|
938
1030
|
"id",
|
|
939
1031
|
"title",
|
|
@@ -945,12 +1037,12 @@ function bundleDesignRevision(current, state = {}) {
|
|
|
945
1037
|
"layout"
|
|
946
1038
|
]),
|
|
947
1039
|
screens: document.screens.map(
|
|
948
|
-
(screen) => pick(screen, ["id", "title", "description", "anchors"])
|
|
1040
|
+
(screen) => pick(screen, ["id", "title", "description", "anchors", "props"])
|
|
949
1041
|
),
|
|
950
1042
|
selectedVariant: document.variants.some(
|
|
951
1043
|
(variant) => variant.id === state.selectedVariant && variant.status === "ready"
|
|
952
1044
|
) ? state.selectedVariant : document.selectedVariant,
|
|
953
|
-
variants: document.variants.filter((variant) => variant.status === "ready").map((variant) => pick(variant, ["id", "label", "status"]))
|
|
1045
|
+
variants: document.variants.filter((variant) => variant.status === "ready").map((variant) => pick(variant, ["id", "label", "status", "props"]))
|
|
954
1046
|
},
|
|
955
1047
|
envelope: structuredClone(current.envelope),
|
|
956
1048
|
entries: structuredClone(current.entries),
|
|
@@ -995,6 +1087,7 @@ export {
|
|
|
995
1087
|
serialize,
|
|
996
1088
|
parse,
|
|
997
1089
|
parseFragment,
|
|
1090
|
+
inspectLocalDocumentBody,
|
|
998
1091
|
resolveLocalDocumentFile,
|
|
999
1092
|
bundleLocalDocument,
|
|
1000
1093
|
DESIGN_HANDOFF_CONTENT_SCHEMA,
|
|
@@ -104,6 +104,7 @@ var VALIDATION_KEYWORDS = [
|
|
|
104
104
|
"maxContains",
|
|
105
105
|
"required",
|
|
106
106
|
"properties",
|
|
107
|
+
"propertyNames",
|
|
107
108
|
"additionalProperties",
|
|
108
109
|
"maxProperties",
|
|
109
110
|
"dependentRequired",
|
|
@@ -172,6 +173,7 @@ var KEYWORD_SHAPES = {
|
|
|
172
173
|
maxContains: ["a non-negative integer", isCount],
|
|
173
174
|
required: ["an array of unique strings", isUniqueStrings],
|
|
174
175
|
properties: ["an object of schemas", isSchemaMap],
|
|
176
|
+
propertyNames: ["a schema", isSchema],
|
|
175
177
|
additionalProperties: ["a schema", isSchema],
|
|
176
178
|
maxProperties: ["a non-negative integer", isCount],
|
|
177
179
|
dependentRequired: [
|
|
@@ -440,6 +442,8 @@ var validateNode = (value, schema6, path, errs, context) => {
|
|
|
440
442
|
}
|
|
441
443
|
const props = schema6.properties || {};
|
|
442
444
|
for (const [k, v] of Object.entries(value)) {
|
|
445
|
+
if (schema6.propertyNames !== void 0)
|
|
446
|
+
validateNode(k, schema6.propertyNames, `${path}.${k}`, errs, context);
|
|
443
447
|
if (Object.hasOwn(props, k)) evaluated.add(k);
|
|
444
448
|
else if (schema6.additionalProperties !== void 0) evaluated.add(k);
|
|
445
449
|
if (!Object.hasOwn(props, k)) {
|
|
@@ -4733,7 +4737,7 @@ var DESIGN_DOCUMENT_V1_SCHEMA = freeze({
|
|
|
4733
4737
|
}
|
|
4734
4738
|
}
|
|
4735
4739
|
});
|
|
4736
|
-
var
|
|
4740
|
+
var DESIGN_DOCUMENT_V120_SCHEMA = freeze({
|
|
4737
4741
|
...DESIGN_DOCUMENT_V1_SCHEMA,
|
|
4738
4742
|
$id: "https://openplanr.dev/schemas/v1.20.0/design-document.schema.json",
|
|
4739
4743
|
"x-openplanr-contract": { id: "design-document", version: "1.20.0" },
|
|
@@ -4792,11 +4796,134 @@ var DESIGN_DOCUMENT_SCHEMA = freeze({
|
|
|
4792
4796
|
coordinate: { type: "number", minimum: -1e7, maximum: 1e7 }
|
|
4793
4797
|
}
|
|
4794
4798
|
});
|
|
4799
|
+
var PROP_TOKEN_SCHEMA = {
|
|
4800
|
+
type: "string",
|
|
4801
|
+
minLength: 1,
|
|
4802
|
+
maxLength: 128,
|
|
4803
|
+
pattern: "^[a-z][a-z0-9-]*(?![\\s\\S])"
|
|
4804
|
+
};
|
|
4805
|
+
var propTokenPattern = new RegExp(PROP_TOKEN_SCHEMA.pattern, "u");
|
|
4806
|
+
var isPropToken = (value) => typeof value === "string" && value.length <= PROP_TOKEN_SCHEMA.maxLength && propTokenPattern.test(value);
|
|
4807
|
+
var currentDocument = (
|
|
4808
|
+
/** @type {{ properties: Record<string, unknown>; [key: string]: unknown }} */
|
|
4809
|
+
structuredClone(DESIGN_DOCUMENT_V120_SCHEMA)
|
|
4810
|
+
);
|
|
4811
|
+
currentDocument.$id = "https://openplanr.dev/schemas/v1.22.0/design-document.schema.json";
|
|
4812
|
+
currentDocument["x-openplanr-contract"] = { id: "design-document", version: "1.22.0" };
|
|
4813
|
+
currentDocument.properties.schemaVersion = { enum: ["1.0.0", "1.1.0"] };
|
|
4814
|
+
var screenSchema = (
|
|
4815
|
+
/** @type {{ items: { properties: Record<string, unknown> } }} */
|
|
4816
|
+
currentDocument.properties.screens
|
|
4817
|
+
);
|
|
4818
|
+
screenSchema.items.properties.props = {
|
|
4819
|
+
type: "object",
|
|
4820
|
+
propertyNames: PROP_TOKEN_SCHEMA,
|
|
4821
|
+
additionalProperties: {
|
|
4822
|
+
oneOf: [
|
|
4823
|
+
{
|
|
4824
|
+
type: "object",
|
|
4825
|
+
additionalProperties: false,
|
|
4826
|
+
required: ["type", "options", "default"],
|
|
4827
|
+
properties: {
|
|
4828
|
+
type: { const: "enum" },
|
|
4829
|
+
options: {
|
|
4830
|
+
type: "array",
|
|
4831
|
+
minItems: 1,
|
|
4832
|
+
uniqueItems: true,
|
|
4833
|
+
items: PROP_TOKEN_SCHEMA
|
|
4834
|
+
},
|
|
4835
|
+
default: PROP_TOKEN_SCHEMA
|
|
4836
|
+
}
|
|
4837
|
+
},
|
|
4838
|
+
{
|
|
4839
|
+
type: "object",
|
|
4840
|
+
additionalProperties: false,
|
|
4841
|
+
required: ["type", "default"],
|
|
4842
|
+
properties: { type: { const: "boolean" }, default: { type: "boolean" } }
|
|
4843
|
+
}
|
|
4844
|
+
]
|
|
4845
|
+
}
|
|
4846
|
+
};
|
|
4847
|
+
var variantSchema = (
|
|
4848
|
+
/** @type {{ items: { properties: Record<string, unknown> } }} */
|
|
4849
|
+
currentDocument.properties.variants
|
|
4850
|
+
);
|
|
4851
|
+
variantSchema.items.properties.props = {
|
|
4852
|
+
type: "object",
|
|
4853
|
+
propertyNames: { $ref: "#/$defs/id" },
|
|
4854
|
+
additionalProperties: {
|
|
4855
|
+
type: "object",
|
|
4856
|
+
propertyNames: PROP_TOKEN_SCHEMA,
|
|
4857
|
+
additionalProperties: { anyOf: [PROP_TOKEN_SCHEMA, { type: "boolean" }] }
|
|
4858
|
+
}
|
|
4859
|
+
};
|
|
4860
|
+
currentDocument.allOf = [
|
|
4861
|
+
{
|
|
4862
|
+
if: { properties: { schemaVersion: { const: "1.1.0" } }, required: ["schemaVersion"] },
|
|
4863
|
+
else: {
|
|
4864
|
+
properties: {
|
|
4865
|
+
screens: { items: { not: { required: ["props"] } } },
|
|
4866
|
+
variants: { items: { not: { required: ["props"] } } }
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
];
|
|
4871
|
+
var DESIGN_DOCUMENT_SCHEMA = freeze(currentDocument);
|
|
4872
|
+
function validateDesignProps(document) {
|
|
4873
|
+
const errors = [];
|
|
4874
|
+
const checkToken = (value, path) => {
|
|
4875
|
+
if (!isPropToken(value))
|
|
4876
|
+
errors.push(
|
|
4877
|
+
`${path}: ${JSON.stringify(value)} must be a lowercase token matching ${PROP_TOKEN_SCHEMA.pattern} with at most ${PROP_TOKEN_SCHEMA.maxLength} characters`
|
|
4878
|
+
);
|
|
4879
|
+
};
|
|
4880
|
+
const screens = new Map(document.screens.map((screen) => [screen.id, screen]));
|
|
4881
|
+
for (const [index2, screen] of document.screens.entries()) {
|
|
4882
|
+
for (const [name, prop] of Object.entries(screen.props ?? {})) {
|
|
4883
|
+
const path = `$.screens[${index2}].props.${name}`;
|
|
4884
|
+
checkToken(name, path);
|
|
4885
|
+
if (prop.type === "enum") {
|
|
4886
|
+
for (const [optionIndex, option] of prop.options.entries())
|
|
4887
|
+
checkToken(option, `${path}.options[${optionIndex}]`);
|
|
4888
|
+
checkToken(prop.default, `${path}.default`);
|
|
4889
|
+
if (!prop.options.includes(prop.default))
|
|
4890
|
+
errors.push(`${path}.default: '${prop.default}' is not an enum option`);
|
|
4891
|
+
}
|
|
4892
|
+
}
|
|
4893
|
+
}
|
|
4894
|
+
for (const [index2, variant] of document.variants.entries()) {
|
|
4895
|
+
for (const [screenId, values] of Object.entries(variant.props ?? {})) {
|
|
4896
|
+
const screen = screens.get(screenId);
|
|
4897
|
+
const path = `$.variants[${index2}].props.${screenId}`;
|
|
4898
|
+
if (!screen) {
|
|
4899
|
+
errors.push(`${path}: unknown screen '${screenId}'`);
|
|
4900
|
+
continue;
|
|
4901
|
+
}
|
|
4902
|
+
for (const [name, value] of Object.entries(values)) {
|
|
4903
|
+
checkToken(name, `${path}.${name}`);
|
|
4904
|
+
if (typeof value === "string") checkToken(value, `${path}.${name}`);
|
|
4905
|
+
const props = screen.props ?? {};
|
|
4906
|
+
const prop = Object.hasOwn(props, name) ? props[name] : void 0;
|
|
4907
|
+
if (!prop) errors.push(`${path}.${name}: unknown prop '${name}' on screen '${screenId}'`);
|
|
4908
|
+
else if (prop.type === "boolean" && typeof value !== "boolean")
|
|
4909
|
+
errors.push(`${path}.${name}: expected a boolean, received ${JSON.stringify(value)}`);
|
|
4910
|
+
else if (prop.type === "enum" && (typeof value !== "string" || !prop.options.includes(value)))
|
|
4911
|
+
errors.push(`${path}.${name}: ${JSON.stringify(value)} is not an enum option`);
|
|
4912
|
+
}
|
|
4913
|
+
}
|
|
4914
|
+
}
|
|
4915
|
+
return errors;
|
|
4916
|
+
}
|
|
4795
4917
|
function validateDesignDocument(value) {
|
|
4796
4918
|
const errors = validateJson(value, DESIGN_DOCUMENT_SCHEMA).map(
|
|
4797
4919
|
({ path, detail }) => `${path}: ${detail}`
|
|
4798
4920
|
);
|
|
4921
|
+
if (value?.schemaVersion === "1.0.0" && ["screens", "variants"].some(
|
|
4922
|
+
(field) => Array.isArray(value[field]) && value[field].some((item2) => item2 && Object.hasOwn(item2, "props"))
|
|
4923
|
+
))
|
|
4924
|
+
errors.push('$.schemaVersion: props require schemaVersion "1.1.0"');
|
|
4799
4925
|
if (errors.length > 0) return { ok: false, errors };
|
|
4926
|
+
errors.push(...validateDesignProps(value));
|
|
4800
4927
|
for (const field of ["frames", "screens", "flows", "variants"]) {
|
|
4801
4928
|
const seen = /* @__PURE__ */ new Set();
|
|
4802
4929
|
for (const [index2, item2] of (value[field] ?? []).entries()) {
|
|
@@ -5759,7 +5886,9 @@ function assertLargeObjectContract(value, kind) {
|
|
|
5759
5886
|
export {
|
|
5760
5887
|
validateJson,
|
|
5761
5888
|
initialFrameHeight,
|
|
5889
|
+
DESIGN_DOCUMENT_V120_SCHEMA,
|
|
5762
5890
|
DESIGN_DOCUMENT_SCHEMA,
|
|
5891
|
+
validateDesignProps,
|
|
5763
5892
|
assertDesignDocument,
|
|
5764
5893
|
DESIGN_WORKSPACE_VERSION,
|
|
5765
5894
|
DESIGN_WORKSPACE_API,
|