openyida 2026.9.21 → 2026.9.22-beta.2
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 +14 -20
- package/bin/yida.js +6 -11
- package/lib/app/app-list.js +3 -7
- package/lib/app/canvas-compile.js +12 -22
- package/lib/app/check-prd-completeness.js +0 -7
- package/lib/app/create-app.js +1 -4
- package/lib/app/create-form/args.js +12 -37
- package/lib/app/create-form/batch.js +11 -86
- package/lib/app/create-form.js +86 -193
- package/lib/app/create-page.js +17 -84
- package/lib/app/custom-theme.js +0 -11
- package/lib/app/form-field-validator.js +41 -26
- package/lib/app/form-open-guard.js +10 -97
- package/lib/app/get-form-config.js +0 -1
- package/lib/app/inline-css-guard.js +31 -1
- package/lib/app/services/form-compiler.js +4 -2
- package/lib/app/theme-from-design.js +41 -144
- package/lib/app/theme-presets.js +1 -1
- package/lib/app/update-app.js +13 -63
- package/lib/asset/ai-image.js +9 -59
- package/lib/asset/asset-cmd.js +7 -18
- package/lib/asset/asset-plan.js +9 -102
- package/lib/asset/asset-resolve.js +10 -55
- package/lib/asset/asset-status.js +4 -5
- package/lib/asset/host-capabilities.js +2 -11
- package/lib/asset/url-verify.js +4 -19
- package/lib/auth/dws-sync.js +148 -0
- package/lib/auth/token-auth.js +73 -9
- package/lib/auth/token-store.js +50 -0
- package/lib/connector/connector-test.js +5 -19
- package/lib/connector/contract.js +1 -3
- package/lib/core/agent-capabilities.js +16 -19
- package/lib/core/command-manifest.js +40 -329
- package/lib/core/locales/en.js +17 -74
- package/lib/core/locales/zh.js +16 -73
- package/lib/core/redact.js +10 -15
- package/lib/core/sample.js +30 -72
- package/lib/core/utils.js +4 -0
- package/lib/design-plan/design-plan.js +4 -51
- package/lib/design-plan/init.js +26 -121
- package/lib/design-plan/materialize.js +348 -451
- package/lib/design-plan/normalize.js +29 -74
- package/lib/design-plan/parallel.js +16 -71
- package/lib/design-plan/patch.js +16 -63
- package/lib/design-plan/preview.js +8 -6
- package/lib/design-plan/validate.js +11 -71
- package/lib/process/create-process.js +50 -84
- package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +90 -20
- package/lib/samples/openyida-scaffold/canvas-nav/content.jsx +13 -93
- package/lib/samples/openyida-scaffold/canvas-nav/data.jsx +18 -100
- package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +4 -6
- package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
- package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +2 -1
- package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
- package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +9 -15
- package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +83 -9
- package/lib/samples/yida-rechart/trend-combo.canvas.jsx +87 -14
- package/package.json +1 -3
- package/scripts/postinstall.js +3 -3
- package/yida-skills/SKILL.md +16 -19
- package/yida-skills/references/official-example-schema-patterns.md +1 -1
- package/yida-skills/references/yida-api.md +0 -4
- package/yida-skills/skills/yida-app/SKILL.md +23 -46
- package/yida-skills/skills/yida-app/workflow/parallel-work.md +6 -15
- package/yida-skills/skills/yida-app/workflow/plan/step-1-understand.md +1 -1
- package/yida-skills/skills/yida-app/workflow/plan/step-2-confirm.md +1 -1
- package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +15 -29
- package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -29
- package/yida-skills/skills/yida-app/workflow/step-1-resource-context.md +2 -4
- package/yida-skills/skills/yida-app/workflow/step-2-design.md +9 -23
- package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +4 -6
- package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +4 -15
- package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +4 -6
- package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +9 -15
- package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +11 -25
- package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +28 -68
- package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +43 -42
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +44 -60
- package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +50 -72
- package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +1 -13
- package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +1 -140
- package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +72 -101
- package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +32 -35
- package/yida-skills/skills/yida-canvas-custom-page/scripts/build-canvas-theme.js +3 -29
- package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +6 -69
- package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +0 -26
- package/yida-skills/skills/yida-create-app/SKILL.md +0 -2
- package/yida-skills/skills/yida-create-form-page/SKILL.md +58 -72
- package/yida-skills/skills/yida-create-form-page/references/advanced-form-modes.md +5 -5
- package/yida-skills/skills/yida-create-form-page/references/association-form-field.md +4 -4
- package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +5 -6
- package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +19 -7
- package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +44 -62
- package/yida-skills/skills/yida-create-page/SKILL.md +6 -14
- package/yida-skills/skills/yida-create-process/SKILL.md +2 -13
- package/yida-skills/skills/yida-custom-page/SKILL.md +0 -2
- package/yida-skills/skills/yida-custom-page/references/design-system.md +1 -1
- package/yida-skills/skills/yida-dashboard/SKILL.md +4 -5
- package/yida-skills/skills/yida-data-management/SKILL.md +2 -4
- package/yida-skills/skills/yida-data-management/references/data-format-guide.md +4 -4
- package/yida-skills/skills/yida-design/SKILL.md +14 -29
- package/yida-skills/skills/yida-design/references/app/blueprint.md +70 -0
- package/yida-skills/skills/yida-design/references/app/navigation-patterns.md +43 -0
- package/yida-skills/skills/yida-design/references/app/role-journey.md +30 -0
- package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +42 -67
- package/yida-skills/skills/yida-design/references/asset-workflow.md +2 -6
- package/yida-skills/skills/yida-design/references/design-mode.md +4 -4
- package/yida-skills/skills/yida-design/references/page-quality-gates.md +38 -26
- package/yida-skills/skills/yida-design/references/style-design-selection.md +137 -0
- package/yida-skills/skills/yida-design/references/style-designs/_design-md-template.md +185 -0
- package/yida-skills/skills/yida-design/references/style-designs/aqua-service-progress-dashboard.md +242 -0
- package/yida-skills/skills/yida-design/references/style-designs/blue-insight-operations-dashboard.md +243 -0
- package/yida-skills/skills/yida-design/references/style-designs/blue-productivity-insight-workbench.md +242 -0
- package/yida-skills/skills/yida-design/references/style-designs/command-filter-card-console.md +304 -0
- package/yida-skills/skills/yida-design/references/style-designs/contrast-command-analytics-workbench.md +261 -0
- package/yida-skills/skills/yida-design/references/style-designs/dark-stage-analytic-dashboard.md +369 -0
- package/yida-skills/skills/yida-design/references/style-designs/filterable-card-catalog.md +354 -0
- package/yida-skills/skills/yida-design/references/style-designs/green-timeline-progress-workbench.md +250 -0
- package/yida-skills/skills/yida-design/references/style-designs/registry.md +117 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-analytic-workbench.md +348 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-blue-grid-analytic-dashboard.md +658 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-bordered-analytic-workbench.md +385 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-curated-filter-gallery.md +300 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-modular-analytic-workbench.md +404 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-progress-analytics-workbench.md +382 -0
- package/yida-skills/skills/yida-design/references/style-designs/soft-timeline-analytics-workbench.md +367 -0
- package/yida-skills/skills/yida-design/references/style-designs/teal-rail-analytics-workbench.md +341 -0
- package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +432 -350
- package/yida-skills/skills/yida-design/references/visual-decision-engine.md +143 -19
- package/yida-skills/skills/yida-design/references/visual-scaffold-recipes.md +27 -15
- package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +0 -4
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +8 -22
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/README.md +10 -14
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/build-plan-template.html +4 -9
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +27 -49
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +154 -33
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +127 -48
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +51 -37
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +48 -43
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +190 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +98 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +339 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +348 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +344 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +345 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +355 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +377 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +352 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +389 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +364 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/index.json +329 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +348 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +345 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +379 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +347 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +352 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +386 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +384 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +388 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +341 -0
- package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +361 -0
- package/yida-skills/skills/yida-design/workflow/output-design.md +375 -117
- package/yida-skills/skills/yida-design/workflow/output-prd.md +185 -0
- package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +1 -1
- package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +29 -33
- package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +1 -3
- package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +106 -22
- package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +22 -15
- package/yida-skills/skills/yida-form-permission/SKILL.md +0 -6
- package/yida-skills/skills/yida-image-assets/SKILL.md +50 -73
- package/yida-skills/skills/yida-image-assets/references/manifest-contract.md +52 -82
- package/yida-skills/skills/yida-image-assets/references/source-policy.md +15 -14
- package/yida-skills/skills/yida-integration/SKILL.md +0 -1
- package/yida-skills/skills/yida-login/SKILL.md +0 -2
- package/yida-skills/skills/yida-nav-group/SKILL.md +2 -4
- package/yida-skills/skills/yida-nav-shell/SKILL.md +12 -36
- package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +136 -79
- package/yida-skills/skills/yida-page-config/SKILL.md +4 -13
- package/yida-skills/skills/yida-prd/SKILL.md +3 -5
- package/yida-skills/skills/yida-prd/references/app/blueprint.md +4 -4
- package/yida-skills/skills/yida-prd/references/app/navigation-patterns.md +3 -6
- package/yida-skills/skills/yida-prd/references/app/role-journey.md +3 -5
- package/yida-skills/skills/yida-prd/references/plan-content.md +0 -4
- package/yida-skills/skills/yida-prd/workflow/output-prd.md +11 -18
- package/yida-skills/skills/yida-prd/workflow/plan-business.md +4 -4
- package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +8 -11
- package/yida-skills/skills/yida-publish-page/SKILL.md +1 -9
- package/yida-skills/skills/yida-requirement-analysis/SKILL.md +39 -10
- package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +71 -40
- package/yida-skills/skills-index.json +16 -36
- package/lib/app/application-entry-urls.js +0 -31
- package/lib/app/application-style.js +0 -69
- package/lib/app/canvas-icon-exports.json +0 -6160
- package/lib/app/canvas-icon-guard.js +0 -87
- package/lib/app/canvas-navigation-guard.js +0 -84
- package/lib/app/canvas-path-guard.js +0 -78
- package/lib/app/canvas-theme-guard.js +0 -184
- package/lib/app/form-data-response-guard.js +0 -57
- package/lib/asset/asset-execution.js +0 -79
- package/lib/core/css-structure.js +0 -37
- package/lib/design/check-design.js +0 -51
- package/lib/design/document.js +0 -458
- package/lib/design/icon-contrast.js +0 -85
- package/lib/design/page-content.js +0 -11
- package/lib/design-plan/artifact-updates.js +0 -117
- package/lib/design-plan/confirmation.js +0 -13
- package/lib/design-plan/entry-navigation.js +0 -97
- package/lib/design-plan/navigation-policy.js +0 -38
- package/lib/design-plan/rebase.js +0 -60
- package/lib/design-plan/themes.js +0 -101
- package/lib/design-plan/visual-policy.js +0 -42
- package/lib/samples/openyida-scaffold/canvas-admin-entry.jsx +0 -62
- package/lib/samples/openyida-scaffold/canvas-navigation.jsx +0 -56
- package/lib/samples/openyida-scaffold/canvas-view-state.jsx +0 -74
- package/yida-skills/skills/yida-app/references/entry-navigation.md +0 -193
- package/yida-skills/skills/yida-canvas-custom-page/references/view-state-recovery.md +0 -52
- package/yida-skills/skills/yida-canvas-data-binding/references/business-action-permissions.md +0 -31
- package/yida-skills/skills/yida-design/references/application-style-library.md +0 -93
- package/yida-skills/skills/yida-design/references/application-theme-consistency.md +0 -150
- package/yida-skills/skills/yida-design/references/native-form-styles.md +0 -208
- package/yida-skills/skills/yida-design/references/navigation-decision.md +0 -53
- package/yida-skills/skills/yida-design/references/page-continuity.md +0 -42
- package/yida-skills/skills/yida-design/references/theme/application-style-recipes.css +0 -58
- package/yida-skills/skills/yida-design/references/theme-selection.md +0 -67
- package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +0 -302
- package/yida-skills/skills/yida-design/templates/application-styles.json +0 -398
- package/yida-skills/skills/yida-design/templates/design-themes/README.md +0 -73
- package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-amber/form-layout.json +0 -15
- package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-executive/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-finance/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-glass/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-line/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-neon/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +0 -754
- package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +0 -279
- package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-paper/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-plum/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +0 -758
- package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +0 -281
- package/yida-skills/skills/yida-design/templates/design-themes/app-pop/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-sage/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-teal/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +0 -754
- package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +0 -279
- package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +0 -752
- package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +0 -278
- package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +0 -748
- package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +0 -274
- package/yida-skills/skills/yida-design/templates/design-themes/app-wire/form-layout.json +0 -14
- package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +0 -118
- package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +0 -690
- package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/design.md +0 -382
- package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +0 -691
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +0 -380
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +0 -696
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/design.md +0 -378
- package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +0 -689
- package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +0 -238
- package/yida-skills/skills/yida-design/templates/design-themes/free-creative/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +0 -692
- package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/design.md +0 -375
- package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +0 -691
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/design.md +0 -362
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +0 -691
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/design.md +0 -409
- package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/index.json +0 -464
- package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +0 -701
- package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/design.md +0 -379
- package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +0 -691
- package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/design.md +0 -404
- package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +0 -698
- package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/design.md +0 -389
- package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +0 -691
- package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/design.md +0 -372
- package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +0 -690
- package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/design.md +0 -455
- package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +0 -698
- package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/design.md +0 -394
- package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +0 -692
- package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/design.md +0 -391
- package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +0 -711
- package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/design.md +0 -408
- package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +0 -692
- package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/design.md +0 -383
- package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +0 -13
- package/yida-skills/skills/yida-design/templates/navigation-styles.json +0 -769
- package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +0 -79
- package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +0 -68
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Babel = require('@babel/standalone');
|
|
4
|
-
const { CliError } = require('../core/cli-error');
|
|
5
|
-
const { t } = require('../core/i18n');
|
|
6
|
-
const { packages } = require('./canvas-icon-exports.json');
|
|
7
|
-
const exportSets = Object.fromEntries(Object.entries(packages).map(([name, entry]) => [name, new Set(entry.exports)]));
|
|
8
|
-
|
|
9
|
-
function packageName(source) {
|
|
10
|
-
return Object.keys(packages).find(name => source === name || source.startsWith(name + '/'));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Resolve literal namespace members and immutable aliases, respecting lexical
|
|
14
|
-
// scope. Dynamic lookups still require a validated component map / fallback.
|
|
15
|
-
function namespacePackage(p, seen = new Set()) {
|
|
16
|
-
if (!p?.isIdentifier() && !p?.isJSXIdentifier()) { return null; }
|
|
17
|
-
const binding = p.scope.getBinding(p.node.name);
|
|
18
|
-
if (!binding || seen.has(binding)) { return null; }
|
|
19
|
-
seen.add(binding);
|
|
20
|
-
if (binding.path.isImportNamespaceSpecifier()) {
|
|
21
|
-
return packageName(binding.path.parent.source.value);
|
|
22
|
-
}
|
|
23
|
-
if (binding.constant && binding.path.isVariableDeclarator()) {
|
|
24
|
-
return namespacePackage(binding.path.get('init'), seen);
|
|
25
|
-
}
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function staticKey(node, computed) {
|
|
30
|
-
if (!computed && ['Identifier', 'JSXIdentifier'].includes(node?.type)) { return node.name; }
|
|
31
|
-
if (node?.type === 'StringLiteral') { return node.value; }
|
|
32
|
-
if (node?.type === 'TemplateLiteral' && node.expressions.length === 0) { return node.quasis[0].value.cooked; }
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function assertCanvasIconExports(source, options = {}) {
|
|
37
|
-
if (!/lucide-react|@ant-design\/icons/.test(source)) { return; }
|
|
38
|
-
let ast;
|
|
39
|
-
try {
|
|
40
|
-
ast = Babel.packages.parser.parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript'] });
|
|
41
|
-
} catch { return; } // The compiler owns syntax diagnostics.
|
|
42
|
-
const check = (name, exported, node, namedImport = false) => {
|
|
43
|
-
if (!name || exported === null || exportSets[name].has(exported)) { return; }
|
|
44
|
-
if (namedImport && Object.hasOwn(packages[name].specialNamedExports || {}, exported)) { return; }
|
|
45
|
-
const suggestions = name === 'lucide-react' && exported === 'Museum' ? ['Landmark'] : [];
|
|
46
|
-
const line = node.loc?.start.line || 1;
|
|
47
|
-
throw new CliError(t('publish.canvas_icon_export_unavailable', name, exported, line, suggestions.join(', ') || '—'), {
|
|
48
|
-
code: 'OPENYIDA_CANVAS_ICON_EXPORT_UNAVAILABLE',
|
|
49
|
-
details: {
|
|
50
|
-
stage: 'canvas_compile', sourcePath: options.sourcePath || '',
|
|
51
|
-
line, column: (node.loc?.start.column || 0) + 1,
|
|
52
|
-
packageName: name, exportName: exported, suggestions,
|
|
53
|
-
runtimeAsset: packages[name].assetUrl, runtimeSha256: packages[name].sha256,
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
};
|
|
57
|
-
const member = p => check(namespacePackage(p.get('object')), staticKey(p.node.property, p.node.computed), p.node);
|
|
58
|
-
const destructure = (pattern, init) => {
|
|
59
|
-
const name = namespacePackage(init);
|
|
60
|
-
if (!name || !pattern.isObjectPattern()) { return; }
|
|
61
|
-
for (const property of pattern.node.properties) {
|
|
62
|
-
if (property.type === 'ObjectProperty') { check(name, staticKey(property.key, property.computed), property); }
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
66
|
-
traverse(ast, {
|
|
67
|
-
ImportDeclaration(p) {
|
|
68
|
-
const name = packageName(p.node.source.value);
|
|
69
|
-
if (!name || p.node.importKind === 'type') { return; }
|
|
70
|
-
for (const specifier of p.node.specifiers) {
|
|
71
|
-
if (specifier.type === 'ImportSpecifier' && specifier.importKind !== 'type') {
|
|
72
|
-
check(name, specifier.imported.name || specifier.imported.value, specifier, true);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
MemberExpression: member,
|
|
77
|
-
OptionalMemberExpression: member,
|
|
78
|
-
JSXOpeningElement(p) {
|
|
79
|
-
const name = p.get('name');
|
|
80
|
-
if (name.isJSXMemberExpression()) { member(name); }
|
|
81
|
-
},
|
|
82
|
-
VariableDeclarator(p) { destructure(p.get('id'), p.get('init')); },
|
|
83
|
-
AssignmentExpression(p) { destructure(p.get('left'), p.get('right')); },
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
module.exports = { assertCanvasIconExports };
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Babel = require('@babel/standalone');
|
|
4
|
-
const { CliError } = require('../core/cli-error');
|
|
5
|
-
const { t } = require('../core/i18n');
|
|
6
|
-
|
|
7
|
-
// Only diagnose statically known misuse of the shipped navigation contracts.
|
|
8
|
-
// Dynamic data and actual host geometry still require browser verification.
|
|
9
|
-
function assertCanvasNavigationStructure(source, options = {}) {
|
|
10
|
-
if (!/CanvasNavigationContent|loadCanvasNavigation|filterCanvasNavigation/.test(source)) { return; }
|
|
11
|
-
let ast;
|
|
12
|
-
try { ast = Babel.packages.parser.parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript'] }); }
|
|
13
|
-
catch { return; }
|
|
14
|
-
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
15
|
-
const fail = (kind, node) => {
|
|
16
|
-
const line = node.loc?.start.line || 1;
|
|
17
|
-
throw new CliError(t(`publish.canvas_navigation_${kind}`, line), {
|
|
18
|
-
code: 'OPENYIDA_CANVAS_NAVIGATION_INVALID',
|
|
19
|
-
details: { stage: 'canvas_compile', sourcePath: options.sourcePath || '', line, issueType: kind },
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
function resolve(p, seen = new Set()) {
|
|
23
|
-
if (!p?.node || seen.has(p.node)) { return null; }
|
|
24
|
-
seen.add(p.node);
|
|
25
|
-
if (!p.isIdentifier()) { return p; }
|
|
26
|
-
const binding = p.scope.getBinding(p.node.name);
|
|
27
|
-
return binding?.constant && binding.path.isVariableDeclarator() ? resolve(binding.path.get('init'), seen) : null;
|
|
28
|
-
}
|
|
29
|
-
const prop = (p, name) => {
|
|
30
|
-
const object = resolve(p);
|
|
31
|
-
return object?.isObjectExpression() ? object.get('properties').find(item => item.isObjectProperty()
|
|
32
|
-
&& !item.node.computed && (item.node.key.name || item.node.key.value) === name)?.get('value') : undefined;
|
|
33
|
-
};
|
|
34
|
-
const string = p => { const value = resolve(p); return value?.isStringLiteral() ? value.node.value : undefined; };
|
|
35
|
-
const hasUnboundLocal = (p, seen = new Set()) => {
|
|
36
|
-
const array = resolve(p);
|
|
37
|
-
if (!array?.isArrayExpression() || seen.has(array.node)) { return false; }
|
|
38
|
-
seen.add(array.node);
|
|
39
|
-
return array.get('elements').some(element => {
|
|
40
|
-
const item = resolve(element);
|
|
41
|
-
if (!item?.isObjectExpression() || item.node.properties.some(node => node.type === 'SpreadElement')) { return false; }
|
|
42
|
-
const children = resolve(prop(item, 'children'));
|
|
43
|
-
if (children?.isArrayExpression() && children.node.elements.length) { return hasUnboundLocal(children, seen); }
|
|
44
|
-
return string(prop(item, 'targetType')) === 'local'
|
|
45
|
-
|| (!prop(item, 'formUuid') && !prop(item, 'navUuid') && !!prop(item, 'key'));
|
|
46
|
-
});
|
|
47
|
-
};
|
|
48
|
-
let documentLayout = false;
|
|
49
|
-
const collapsedMains = [];
|
|
50
|
-
traverse(ast, {
|
|
51
|
-
CallExpression(p) {
|
|
52
|
-
const name = p.node.callee.name;
|
|
53
|
-
const args = p.get('arguments');
|
|
54
|
-
if (name === 'CanvasNavigationContent' && string(prop(args[0], 'layout')) === 'document') { documentLayout = true; }
|
|
55
|
-
if (!['loadCanvasNavigation', 'filterCanvasNavigation'].includes(name)) { return; }
|
|
56
|
-
const configArg = name === 'loadCanvasNavigation' ? args[0] : args[3];
|
|
57
|
-
const config = resolve(configArg);
|
|
58
|
-
if (configArg?.node && !config) { return; }
|
|
59
|
-
if (config && (!config.isObjectExpression() || config.node.properties.some(node => node.type === 'SpreadElement'))) { return; }
|
|
60
|
-
const mode = prop(config, 'mode');
|
|
61
|
-
if (mode && string(mode) !== 'platform') { return; }
|
|
62
|
-
const items = name === 'loadCanvasNavigation' ? prop(config, 'items') : args[0];
|
|
63
|
-
if (hasUnboundLocal(items)) { fail('local_platform', p.node); }
|
|
64
|
-
},
|
|
65
|
-
JSXOpeningElement(p) {
|
|
66
|
-
const attributes = p.get('attributes');
|
|
67
|
-
const attribute = name => {
|
|
68
|
-
const value = attributes.find(item => item.isJSXAttribute() && item.node.name.name === name)?.get('value');
|
|
69
|
-
return value?.isJSXExpressionContainer() ? value.get('expression') : value;
|
|
70
|
-
};
|
|
71
|
-
if (p.node.name.name === 'CanvasNavigationContent' && string(attribute('layout')) === 'document') { documentLayout = true; }
|
|
72
|
-
if (string(attribute('className')) !== 'openyida-nav-main') { return; }
|
|
73
|
-
const owner = p.getFunctionParent();
|
|
74
|
-
const ownerName = owner?.node.id?.name || (owner?.parentPath.isVariableDeclarator() ? owner.parentPath.node.id.name : '');
|
|
75
|
-
if (ownerName !== 'CanvasNavigationContent') { return; }
|
|
76
|
-
const style = resolve(attribute('style'));
|
|
77
|
-
if (style?.isObjectExpression() && string(prop(style, 'display')) === 'flex'
|
|
78
|
-
&& /^1\s+1\s+0(?:px|%)?$/.test(string(prop(style, 'flex')) || '')) { collapsedMains.push(p.node); }
|
|
79
|
-
},
|
|
80
|
-
});
|
|
81
|
-
if (documentLayout && collapsedMains.length) { fail('document_flex', collapsedMains[0]); }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
module.exports = { assertCanvasNavigationStructure };
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Babel = require('@babel/standalone');
|
|
4
|
-
const { CliError } = require('../core/cli-error');
|
|
5
|
-
const { t } = require('../core/i18n');
|
|
6
|
-
|
|
7
|
-
// Inspect navigation destinations, not every string: '/custom/' is a valid
|
|
8
|
-
// suffix in '/' + appType + '/custom/' + formUuid. Unknown values need runtime QA.
|
|
9
|
-
function assertCanvasNavigationPaths(source, options = {}) {
|
|
10
|
-
let ast;
|
|
11
|
-
try { ast = Babel.packages.parser.parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript'] }); }
|
|
12
|
-
catch { return; }
|
|
13
|
-
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
14
|
-
const name = node => node?.computed ? node.property?.value : node?.property?.name;
|
|
15
|
-
function value(p, seen = new Set()) {
|
|
16
|
-
if (!p?.node || seen.has(p.node)) { return null; }
|
|
17
|
-
seen.add(p.node);
|
|
18
|
-
if (p.isStringLiteral()) { return p.node.value; }
|
|
19
|
-
if (p.isTemplateLiteral()) { return p.node.quasis[0].value.cooked + (p.node.expressions.length ? '<dynamic>' : ''); }
|
|
20
|
-
if (p.isBinaryExpression({ operator: '+' })) {
|
|
21
|
-
const left = value(p.get('left'), new Set(seen));
|
|
22
|
-
const right = value(p.get('right'), new Set(seen));
|
|
23
|
-
return left === null ? null : left + (right === null ? '<dynamic>' : right);
|
|
24
|
-
}
|
|
25
|
-
if (p.isIdentifier()) {
|
|
26
|
-
const binding = p.scope.getBinding(p.node.name);
|
|
27
|
-
return binding?.constant && binding.path.isVariableDeclarator() ? value(binding.path.get('init'), seen) : null;
|
|
28
|
-
}
|
|
29
|
-
if (p.isNewExpression() && p.node.callee.name === 'URL') { return value(p.get('arguments.0'), seen); }
|
|
30
|
-
if (p.isMemberExpression() && ['href', 'pathname'].includes(name(p.node))) { return value(p.get('object'), seen); }
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
function check(p) {
|
|
34
|
-
if (!p?.node) { return; }
|
|
35
|
-
if (p.isConditionalExpression() || p.isLogicalExpression()) {
|
|
36
|
-
for (const key of p.isConditionalExpression() ? ['consequent', 'alternate'] : ['left', 'right']) { check(p.get(key)); }
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
const path = value(p);
|
|
40
|
-
if (!/^\s*\/(?:custom|workbench|submission|formDetail)(?:\/|[?#]|$)/.test(path || '')) { return; }
|
|
41
|
-
const line = p.node.loc?.start.line || 1;
|
|
42
|
-
throw new CliError(t('publish.canvas_path_missing_app_type', line), {
|
|
43
|
-
code: 'OPENYIDA_CANVAS_PATH_MISSING_APP_TYPE',
|
|
44
|
-
details: { stage: 'canvas_compile', sourcePath: options.sourcePath || '', line, path,
|
|
45
|
-
expectedPath: '/{appType}/{pageType}/{formUuid}', sample: 'openyida sample openyida-page-template canvas-navigation' },
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
traverse(ast, {
|
|
49
|
-
JSXAttribute(p) {
|
|
50
|
-
if (!['href', 'action', 'formAction'].includes(p.node.name.name)) { return; }
|
|
51
|
-
const val = p.get('value');
|
|
52
|
-
check(val.isJSXExpressionContainer() ? val.get('expression') : val);
|
|
53
|
-
},
|
|
54
|
-
AssignmentExpression(p) {
|
|
55
|
-
const left = p.node.left;
|
|
56
|
-
if ((left.type === 'Identifier' && left.name === 'location') || name(left) === 'location'
|
|
57
|
-
|| (['href', 'pathname'].includes(name(left)) && (left.object?.name === 'location' || name(left.object) === 'location'))) { check(p.get('right')); }
|
|
58
|
-
},
|
|
59
|
-
CallExpression(p) {
|
|
60
|
-
const callee = p.node.callee;
|
|
61
|
-
const method = name(callee);
|
|
62
|
-
const receiver = callee.object;
|
|
63
|
-
if ((method === 'open' && ['window', 'self', 'globalThis'].includes(receiver?.name))
|
|
64
|
-
|| (['assign', 'replace'].includes(method) && (receiver?.name === 'location' || name(receiver) === 'location'))
|
|
65
|
-
|| (['push', 'replace'].includes(method) && (receiver?.name === 'router' || name(receiver) === 'router'))) { check(p.get('arguments.0')); }
|
|
66
|
-
if (method === 'openPage' || callee.name === 'openPage') {
|
|
67
|
-
const arg = p.get('arguments.0');
|
|
68
|
-
if (arg?.isObjectExpression()) {
|
|
69
|
-
for (const prop of arg.get('properties')) {
|
|
70
|
-
if (prop.isObjectProperty() && (prop.node.key.name || prop.node.key.value) === 'url') { check(prop.get('value')); }
|
|
71
|
-
}
|
|
72
|
-
} else { check(arg); }
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
module.exports = { assertCanvasNavigationPaths };
|
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Babel = require('@babel/standalone');
|
|
4
|
-
const { CliError } = require('../core/cli-error');
|
|
5
|
-
const { t } = require('../core/i18n');
|
|
6
|
-
|
|
7
|
-
// Check the maintained theme contract without executing business code.
|
|
8
|
-
// Dynamic component factories and runtime branches still need browser verification.
|
|
9
|
-
function assertCanvasThemeStructure(source, options = {}) {
|
|
10
|
-
if (!/CanvasThemeProvider|useCanvasThemeContext|CanvasThemeContext|@canvas-theme-provider|antd/.test(source)) { return; }
|
|
11
|
-
let ast;
|
|
12
|
-
try {
|
|
13
|
-
ast = Babel.packages.parser.parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript'] });
|
|
14
|
-
} catch { return; } // Let the compiler report syntax errors.
|
|
15
|
-
const marker = ast.comments?.find(comment => comment.type === 'CommentBlock' && comment.value.trim() === '@canvas-theme-provider');
|
|
16
|
-
if (marker) {
|
|
17
|
-
const line = marker.loc.start.line;
|
|
18
|
-
throw new CliError(t('publish.canvas_theme_not_assembled', line), {
|
|
19
|
-
code: 'OPENYIDA_CANVAS_THEME_NOT_ASSEMBLED',
|
|
20
|
-
details: { stage: 'canvas_compile', sourcePath: options.sourcePath || '', line, issueType: 'unexpanded_marker' },
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
24
|
-
assertBrandOverrides(ast, traverse, options);
|
|
25
|
-
const functions = new Map();
|
|
26
|
-
let program;
|
|
27
|
-
let defaultExport;
|
|
28
|
-
const fail = (kind, node) => {
|
|
29
|
-
const line = node?.loc?.start.line || 1;
|
|
30
|
-
throw new CliError(t(`publish.canvas_theme_${kind}`, line), {
|
|
31
|
-
code: 'OPENYIDA_CANVAS_THEME_PROVIDER_INVALID',
|
|
32
|
-
details: { stage: 'canvas_compile', sourcePath: options.sourcePath || '', line, issueType: kind },
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
traverse(ast, {
|
|
37
|
-
Program(p) { program = p; },
|
|
38
|
-
ExportDefaultDeclaration(p) { defaultExport = p.get('declaration'); },
|
|
39
|
-
Function(p) {
|
|
40
|
-
const name = p.node.id?.name || (p.parentPath.isVariableDeclarator() ? p.parentPath.node.id.name : '');
|
|
41
|
-
functions.set(p.node, { name, calls: [], renders: [], hooks: [] });
|
|
42
|
-
},
|
|
43
|
-
VariableDeclarator(p) {
|
|
44
|
-
if (p.node.id.name === 'CanvasThemeContext' && p.getFunctionParent()) {
|
|
45
|
-
fail('context_scope', p.node);
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
function resolveFunction(p, seen = new Set()) {
|
|
51
|
-
if (!p?.node || seen.has(p.node)) { return null; }
|
|
52
|
-
seen.add(p.node);
|
|
53
|
-
if (p.isFunction()) { return p.node; }
|
|
54
|
-
if (p.isVariableDeclarator()) { return resolveFunction(p.get('init'), seen); }
|
|
55
|
-
if (p.isIdentifier() || p.isJSXIdentifier()) {
|
|
56
|
-
return resolveFunction(p.scope.getBinding(p.node.name)?.path, seen);
|
|
57
|
-
}
|
|
58
|
-
// React.memo/forwardRef retain the wrapped component's theme requirements.
|
|
59
|
-
if (p.isCallExpression()) {
|
|
60
|
-
const callee = p.node.callee;
|
|
61
|
-
const name = callee.type === 'Identifier' ? callee.name : callee.property?.name;
|
|
62
|
-
if (['memo', 'forwardRef'].includes(name)) { return resolveFunction(p.get('arguments.0'), seen); }
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
traverse(ast, {
|
|
68
|
-
CallExpression(p) {
|
|
69
|
-
const owner = functions.get(p.getFunctionParent()?.node);
|
|
70
|
-
const target = resolveFunction(p.get('callee'));
|
|
71
|
-
const targetName = functions.get(target)?.name || p.node.callee.name;
|
|
72
|
-
if (targetName === 'useCanvasThemeContext') {
|
|
73
|
-
if (!owner) { fail('root_hook', p.node); }
|
|
74
|
-
owner.hooks.push(p.node);
|
|
75
|
-
}
|
|
76
|
-
if (!owner) { return; }
|
|
77
|
-
if (target) { owner.calls.push(target); }
|
|
78
|
-
const callee = p.node.callee;
|
|
79
|
-
if (callee.type === 'MemberExpression' && callee.object.name === 'React' && callee.property.name === 'createElement') {
|
|
80
|
-
const component = resolveFunction(p.get('arguments.0'));
|
|
81
|
-
if (component) { owner.renders.push(component); }
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
JSXOpeningElement(p) {
|
|
85
|
-
const owner = functions.get(p.getFunctionParent()?.node);
|
|
86
|
-
const component = resolveFunction(p.get('name'));
|
|
87
|
-
if (owner && component) { owner.renders.push(component); }
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
const entry = resolveFunction(program.scope.getBinding('YidaComp')?.path) || resolveFunction(defaultExport);
|
|
92
|
-
if (!entry) { return; }
|
|
93
|
-
|
|
94
|
-
// Calling a hook before returning a Provider cannot read that Provider.
|
|
95
|
-
const directSeen = new Set();
|
|
96
|
-
function checkEntryCalls(node) {
|
|
97
|
-
if (directSeen.has(node)) { return; }
|
|
98
|
-
directSeen.add(node);
|
|
99
|
-
const info = functions.get(node);
|
|
100
|
-
if (info.hooks.length) { fail('root_hook', info.hooks[0]); }
|
|
101
|
-
info.calls.forEach(checkEntryCalls);
|
|
102
|
-
}
|
|
103
|
-
checkEntryCalls(entry);
|
|
104
|
-
|
|
105
|
-
const seen = new Set();
|
|
106
|
-
let providerMounted = false;
|
|
107
|
-
let firstHook;
|
|
108
|
-
function visit(node) {
|
|
109
|
-
if (seen.has(node)) { return; }
|
|
110
|
-
seen.add(node);
|
|
111
|
-
const info = functions.get(node);
|
|
112
|
-
firstHook = firstHook || info.hooks[0];
|
|
113
|
-
info.renders.forEach(child => {
|
|
114
|
-
if (functions.get(child).name === 'CanvasThemeProvider') { providerMounted = true; }
|
|
115
|
-
visit(child);
|
|
116
|
-
});
|
|
117
|
-
info.calls.forEach(visit);
|
|
118
|
-
}
|
|
119
|
-
visit(entry);
|
|
120
|
-
const hasProvider = [...functions.values()].some(info => info.name === 'CanvasThemeProvider');
|
|
121
|
-
if (!providerMounted && (hasProvider || firstHook)) {
|
|
122
|
-
fail('provider_missing', firstHook || entry);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Only reject provably fixed brand colors passed to antd's ConfigProvider.
|
|
127
|
-
// Semantic colors, layout tokens and dynamic theme resolvers remain supported.
|
|
128
|
-
function assertBrandOverrides(ast, traverse, options) {
|
|
129
|
-
const resolve = (p, seen = new Set()) => {
|
|
130
|
-
if (!p?.node || seen.has(p.node)) { return null; }
|
|
131
|
-
seen.add(p.node);
|
|
132
|
-
if (!p.isIdentifier()) { return p; }
|
|
133
|
-
const binding = p.scope.getBinding(p.node.name);
|
|
134
|
-
return binding?.constant && binding.path.isVariableDeclarator() ? resolve(binding.path.get('init'), seen) : null;
|
|
135
|
-
};
|
|
136
|
-
const properties = p => {
|
|
137
|
-
const object = resolve(p);
|
|
138
|
-
// Spreads may override earlier values; unknown shapes are not rejected.
|
|
139
|
-
return object?.isObjectExpression() && !object.node.properties.some(prop => prop.type === 'SpreadElement')
|
|
140
|
-
? object.get('properties').filter(prop => prop.isObjectProperty() && !prop.node.computed) : [];
|
|
141
|
-
};
|
|
142
|
-
const key = p => p.node.key.name || p.node.key.value;
|
|
143
|
-
const prop = (p, name) => properties(p).filter(item => key(item) === name).pop()?.get('value');
|
|
144
|
-
const check = (p, field) => {
|
|
145
|
-
const val = resolve(p);
|
|
146
|
-
if (!val?.isStringLiteral() && !(val?.isTemplateLiteral() && !val.node.expressions.length)) { return; }
|
|
147
|
-
const color = val.isStringLiteral() ? val.node.value : val.node.quasis[0].value.cooked;
|
|
148
|
-
if (!color) { return; }
|
|
149
|
-
const line = val.node.loc?.start.line || 1;
|
|
150
|
-
throw new CliError(t('publish.canvas_theme_fixed_brand', line), {
|
|
151
|
-
code: 'OPENYIDA_CANVAS_THEME_FIXED_BRAND',
|
|
152
|
-
details: { stage: 'canvas_compile', sourcePath: options.sourcePath || '', line, field, value: color,
|
|
153
|
-
sample: 'openyida sample openyida-page-template canvas-theme' },
|
|
154
|
-
});
|
|
155
|
-
};
|
|
156
|
-
const tokens = p => properties(p).forEach(item => {
|
|
157
|
-
if (/^color(?:Primary|Link)(?:Hover|Active|Bg|BgHover|Border|BorderHover|Text|TextHover|TextActive)?$/.test(key(item))) {
|
|
158
|
-
check(item.get('value'), key(item));
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
traverse(ast, {
|
|
162
|
-
JSXOpeningElement(p) {
|
|
163
|
-
const name = p.get('name');
|
|
164
|
-
const binding = p.scope.getBinding(name.isJSXIdentifier() ? name.node.name : name.node.object?.name);
|
|
165
|
-
const imported = binding?.path;
|
|
166
|
-
if (imported?.parent.source?.value !== 'antd') { return; }
|
|
167
|
-
if (!(imported.isImportSpecifier() && imported.node.imported.name === 'ConfigProvider')
|
|
168
|
-
&& !(imported.isImportNamespaceSpecifier() && name.node.property?.name === 'ConfigProvider')) { return; }
|
|
169
|
-
const attribute = p.get('attributes').find(attr => attr.isJSXAttribute() && attr.node.name.name === 'theme');
|
|
170
|
-
const theme = attribute?.get('value.expression');
|
|
171
|
-
tokens(prop(theme, 'token'));
|
|
172
|
-
const components = prop(theme, 'components');
|
|
173
|
-
for (const component of ['Button', 'Tabs', 'Segmented']) {
|
|
174
|
-
const config = prop(components, component);
|
|
175
|
-
tokens(config);
|
|
176
|
-
const fields = component === 'Tabs' ? ['inkBarColor', 'itemSelectedColor', 'itemHoverColor', 'itemActiveColor']
|
|
177
|
-
: component === 'Button' ? ['defaultHoverColor', 'defaultHoverBorderColor', 'defaultActiveColor', 'defaultActiveBorderColor'] : [];
|
|
178
|
-
fields.forEach(field => check(prop(config, field), `${component}.${field}`));
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
module.exports = { assertCanvasThemeStructure };
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const Babel = require('@babel/standalone');
|
|
4
|
-
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
5
|
-
const { CliError } = require('../core/cli-error');
|
|
6
|
-
const { t } = require('../core/i18n');
|
|
7
|
-
|
|
8
|
-
const member = (node, name) => node && ['MemberExpression', 'OptionalMemberExpression'].includes(node.type)
|
|
9
|
-
&& (node.computed ? node.property.value : node.property.name) === name;
|
|
10
|
-
|
|
11
|
-
// Only inspect a direct result from the installed Yida bridge, not arbitrary
|
|
12
|
-
// HTTP clients, adapters, similarly named methods, or a shadowed variable.
|
|
13
|
-
function bridgeMember(node) {
|
|
14
|
-
return (member(node, '__OPENYIDA_YIDA_API__') || member(node, 'openyidaYidaApi'))
|
|
15
|
-
&& node.object?.type === 'Identifier' && node.object.name === 'window';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function isYidaBridge(path) {
|
|
19
|
-
if (bridgeMember(path.node) && !path.scope.getBinding('window')) {return true;}
|
|
20
|
-
if (!path.isIdentifier()) {return false;}
|
|
21
|
-
const binding = path.scope.getBinding(path.node.name);
|
|
22
|
-
return !!(binding && binding.constant && binding.path.isVariableDeclarator()
|
|
23
|
-
&& bridgeMember(binding.path.node.init) && !binding.path.scope.getBinding('window'));
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function assertFormDataResponse(source, options = {}) {
|
|
27
|
-
let ast;
|
|
28
|
-
try { ast = Babel.packages.parser.parse(source, { sourceType: 'module', plugins: ['jsx', 'typescript'] }); }
|
|
29
|
-
catch { return; } // The compiler owns syntax diagnostics.
|
|
30
|
-
const issues = [];
|
|
31
|
-
traverse(ast, { VariableDeclarator(path) {
|
|
32
|
-
if (!path.get('id').isIdentifier() || !path.get('init').isAwaitExpression()) {return;}
|
|
33
|
-
const call = path.get('init.argument');
|
|
34
|
-
if (!call.isCallExpression() || !member(call.node.callee, 'searchFormDatas') || !isYidaBridge(call.get('callee.object'))) {return;}
|
|
35
|
-
const binding = path.scope.getBinding(path.node.id.name);
|
|
36
|
-
if (!binding || !binding.constant) {return;}
|
|
37
|
-
let unwrapsArray = false;
|
|
38
|
-
const doubleData = [];
|
|
39
|
-
for (const ref of binding.referencePaths) {
|
|
40
|
-
const first = ref.parentPath;
|
|
41
|
-
if (!member(first.node, 'data') || first.node.object !== ref.node) {continue;}
|
|
42
|
-
const next = first.parentPath;
|
|
43
|
-
if (member(next.node, 'data') && next.node.object === first.node) {doubleData.push(next);}
|
|
44
|
-
if (next.isCallExpression() && member(next.node.callee, 'isArray') && next.node.callee.object?.name === 'Array') {unwrapsArray = true;}
|
|
45
|
-
}
|
|
46
|
-
if (!unwrapsArray && doubleData.length) {
|
|
47
|
-
issues.push({ line: doubleData[0].node.loc?.start.line || 1, variable: path.node.id.name });
|
|
48
|
-
}
|
|
49
|
-
} });
|
|
50
|
-
if (issues.length) {
|
|
51
|
-
throw new CliError(t('publish.lint_searchformdata_bridge_unwrap'), {
|
|
52
|
-
code: 'OPENYIDA_FORM_DATA_RESPONSE_INVALID',
|
|
53
|
-
details: { sourcePath: options.sourcePath || '', issues, nextAction: 'normalize_form_rows' },
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
module.exports = { assertFormDataResponse };
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
function getAssetExecutionContract() {
|
|
4
|
-
return {
|
|
5
|
-
capabilitySource: 'agent-capabilities.asset_capabilities + actual_host_tool_inventory',
|
|
6
|
-
modes: ['background_agent', 'background_shell', 'synchronous'],
|
|
7
|
-
selection: 'Use a verified nonblocking agent when available; otherwise a verified background shell for scriptable steps; otherwise business-first synchronous batches.',
|
|
8
|
-
nonblockingProof: ['actual_tool_and_background_option', 'hostTaskId', 'dispatchReturnedAt_before_endedAt', 'result_and_exit_status_retrieval'],
|
|
9
|
-
shell: {
|
|
10
|
-
qwenworkHint: 'Inspect Bash.run_in_background in the current tool schema; do not infer Agent background support from Bash support or a host name.',
|
|
11
|
-
allowedWork: ['scriptable_search_with_verified_cli', 'allowed_download_or_upload', 'asset_resolve'],
|
|
12
|
-
foregroundWork: ['host_only_search_or_generation', 'visual_image_review'],
|
|
13
|
-
handoff: 'Pass task.resolve.argv with actual paths and appType when uploading; use the supported background option, save the returned job ID and log/output paths, then resume business work. Poll only at the owning page image-binding join; read exit code and manifest, and stop timed-out jobs before handing over file ownership.',
|
|
14
|
-
unsupported: 'A shell cannot call agent-only image tools. A command ending in & or a returned PID alone is not proof of durable background support.',
|
|
15
|
-
},
|
|
16
|
-
synchronousOrder: ['authorized_resource_creation_or_reuse', 'seed_if_in_scope', 'independent_page_layout_and_data_work', 'bounded_asset_batch', 'next_independent_work', 'own_page_image_binding'],
|
|
17
|
-
forbid: ['blocking_whole_collection_subagent_before_business', 'immediate_wait_after_background_dispatch', 'all_page_asset_barrier', 'claim_parallel_without_overlapping_intervals'],
|
|
18
|
-
audit: 'Copy actual taskState records and businessWork intervals into build-manifest.assetExecution for check-prd-completeness; missing evidence is not verified concurrency.',
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function selectAssetExecutionMode(backgroundAgent, backgroundShell) {
|
|
23
|
-
if (backgroundAgent.available === true) { return 'background_agent'; }
|
|
24
|
-
if (backgroundShell.available === true) { return 'background_shell'; }
|
|
25
|
-
return backgroundAgent.available === null || backgroundShell.available === null ? 'host_inventory_required' : 'synchronous';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Check recorded intervals only; this does not manufacture or verify host tool events.
|
|
29
|
-
function auditAssetExecution(record, expectedTasks = []) {
|
|
30
|
-
const issues = [];
|
|
31
|
-
const add = (code, task = {}) => issues.push({ code, taskKey: task.taskKey || '', pageId: task.pageId || '' });
|
|
32
|
-
const text = value => typeof value === 'string' && value.trim().length > 0;
|
|
33
|
-
const time = value => typeof value === 'string' && /^\d{4}-\d\d-\d\dT.*(?:Z|[+-]\d\d:\d\d)$/.test(value) ? Date.parse(value) : NaN;
|
|
34
|
-
const interval = value => {
|
|
35
|
-
const start = time(value?.startedAt), end = time(value?.endedAt);
|
|
36
|
-
return Number.isFinite(start) && Number.isFinite(end) && end >= start ? { start, end } : null;
|
|
37
|
-
};
|
|
38
|
-
if (record === undefined || record === null) {
|
|
39
|
-
if (Array.isArray(expectedTasks) && expectedTasks.length) { add('execution_record_missing'); }
|
|
40
|
-
return { status: issues.length ? 'needs_review' : 'not_checked', issues };
|
|
41
|
-
}
|
|
42
|
-
if (!Array.isArray(record.tasks) || !Array.isArray(record.businessWork)) {
|
|
43
|
-
add('execution_record_invalid');
|
|
44
|
-
return { status: 'needs_review', issues };
|
|
45
|
-
}
|
|
46
|
-
for (const task of Array.isArray(expectedTasks) ? expectedTasks : []) {
|
|
47
|
-
if (!record.tasks.some(value => value?.taskKey && value.taskKey === task?.taskKey)) { add('task_record_missing', task || {}); }
|
|
48
|
-
}
|
|
49
|
-
const work = record.businessWork.map(interval);
|
|
50
|
-
if (work.some(value => !value)) { add('business_interval_invalid'); }
|
|
51
|
-
const independent = work.filter(Boolean);
|
|
52
|
-
const noIndependentWork = record.independentWork === 'none' && text(record.noIndependentWorkReason) && !record.businessWork.length;
|
|
53
|
-
const seen = new Set();
|
|
54
|
-
for (const value of record.tasks) {
|
|
55
|
-
const task = value || {};
|
|
56
|
-
if (!text(task.taskKey) || seen.has(task.taskKey)) { add('task_identity_invalid', task); }
|
|
57
|
-
seen.add(task.taskKey);
|
|
58
|
-
if (task.executionMode === 'reused' && task.status === 'completed' && text(task.reuseEvidence)) { continue; }
|
|
59
|
-
const run = interval(task);
|
|
60
|
-
if (!run || !['completed', 'partial', 'failed'].includes(task.status)) { add('asset_interval_incomplete', task); continue; }
|
|
61
|
-
if (!['background_agent', 'background_shell', 'synchronous'].includes(task.executionMode)) { add('execution_mode_unknown', task); continue; }
|
|
62
|
-
const returned = time(task.dispatchReturnedAt);
|
|
63
|
-
const overlapStart = task.executionMode !== 'synchronous' && Number.isFinite(returned) ? Math.max(run.start, returned) : run.start;
|
|
64
|
-
const overlap = independent.some(item => Math.max(item.start, overlapStart) < Math.min(item.end, run.end));
|
|
65
|
-
if (task.executionMode !== 'synchronous') {
|
|
66
|
-
if (!text(task.hostTaskId) || !text(task.toolName) || !text(task.backgroundOption)
|
|
67
|
-
|| !Number.isFinite(returned) || returned < run.start || returned >= run.end) { add('background_dispatch_unproven', task); }
|
|
68
|
-
if (!overlap && !noIndependentWork) { add('asset_business_overlap_missing', task); }
|
|
69
|
-
} else {
|
|
70
|
-
if (!text(task.fallbackReason)) { add('synchronous_reason_missing', task); }
|
|
71
|
-
if (!noIndependentWork && !independent.some(item => item.start <= run.start)) { add('assets_before_business', task); }
|
|
72
|
-
}
|
|
73
|
-
if (task.claimedParallel === true && !overlap) { add('parallel_claim_unproven', task); }
|
|
74
|
-
}
|
|
75
|
-
if (issues.length) { return { status: 'needs_review', issues }; }
|
|
76
|
-
return { status: record.tasks.length ? 'verified' : 'not_applicable', issues, evidence: 'recorded_intervals_only' };
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports = { getAssetExecutionContract, selectAssetExecutionMode, auditAssetExecution };
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 检查静态 CSS 的括号、字符串和注释闭合;忽略转义及字面量中的括号。
|
|
5
|
-
* 供页面编译和应用主题共用,不验证属性支持或浏览器渲染效果。
|
|
6
|
-
*/
|
|
7
|
-
function findCssStructureIssue(css) {
|
|
8
|
-
const stack = [];
|
|
9
|
-
const pairs = { '(': ')', '[': ']', '{': '}' };
|
|
10
|
-
for (let index = 0; index < css.length; index++) {
|
|
11
|
-
const char = css[index];
|
|
12
|
-
if (char === '\\') { index++; continue; }
|
|
13
|
-
if (char === '/' && css[index + 1] === '*') {
|
|
14
|
-
const end = css.indexOf('*/', index + 2);
|
|
15
|
-
if (end < 0) { return { index, type: 'unclosed_comment' }; }
|
|
16
|
-
index = end + 1;
|
|
17
|
-
} else if (char === '"' || char === "'") {
|
|
18
|
-
const start = index;
|
|
19
|
-
for (index++; index < css.length; index++) {
|
|
20
|
-
if (css[index] === '\\') { index++; continue; }
|
|
21
|
-
if (css[index] === char) { break; }
|
|
22
|
-
}
|
|
23
|
-
if (index >= css.length) { return { index: start, type: 'unclosed_string' }; }
|
|
24
|
-
} else if (pairs[char]) {
|
|
25
|
-
stack.push({ char, index });
|
|
26
|
-
} else if (')]}'.includes(char)) {
|
|
27
|
-
const open = stack.pop();
|
|
28
|
-
if (!open || pairs[open.char] !== char) {
|
|
29
|
-
return { index: open ? open.index : index, type: 'mismatched_delimiter', expected: open && pairs[open.char], actual: char };
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const open = stack.pop();
|
|
34
|
-
return open ? { index: open.index, type: 'unclosed_delimiter', expected: pairs[open.char] } : null;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = { findCssStructureIssue };
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { CliError } = require('../core/cli-error');
|
|
6
|
-
const { t } = require('../core/i18n');
|
|
7
|
-
const { success } = require('../core/chalk');
|
|
8
|
-
const { validateDesignDocument } = require('./document');
|
|
9
|
-
|
|
10
|
-
function parseArgs(args = []) {
|
|
11
|
-
const options = { json: false, help: false };
|
|
12
|
-
for (let index = 0; index < args.length; index++) {
|
|
13
|
-
const arg = args[index];
|
|
14
|
-
if (arg === '--json') {options.json = true;}
|
|
15
|
-
else if (arg === '--help' || arg === '-h') {options.help = true;}
|
|
16
|
-
else if (['--prd', '--base-dir'].includes(arg) && args[index + 1] && !args[index + 1].startsWith('-')) {
|
|
17
|
-
const key = arg === '--prd' ? 'prd' : 'baseDir';
|
|
18
|
-
if (options[key]) {throw new CliError(t('design_document.usage'), { code: 'CHECK_DESIGN_USAGE' });}
|
|
19
|
-
options[key] = args[++index];
|
|
20
|
-
} else if (!arg.startsWith('-') && !options.design) {options.design = arg;}
|
|
21
|
-
else {throw new CliError(t('design_document.usage'), { code: 'CHECK_DESIGN_USAGE' });}
|
|
22
|
-
}
|
|
23
|
-
if (!options.help && !options.design) {throw new CliError(t('design_document.usage'), { code: 'CHECK_DESIGN_USAGE' });}
|
|
24
|
-
return options;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function readDocument(file) {
|
|
28
|
-
try {return fs.readFileSync(file, 'utf8');} catch (error) {
|
|
29
|
-
throw new CliError(t('design_document.read_error', file), {
|
|
30
|
-
code: 'CHECK_DESIGN_FILE_UNREADABLE', details: { file, reason: error.code },
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async function run(args = []) {
|
|
36
|
-
const options = parseArgs(args);
|
|
37
|
-
if (options.help) {console.log(t('design_document.usage')); return;}
|
|
38
|
-
const designFile = path.resolve(options.design);
|
|
39
|
-
const prdFile = options.prd ? path.resolve(options.prd) : undefined;
|
|
40
|
-
const baseDir = path.resolve(options.baseDir || process.cwd());
|
|
41
|
-
const result = validateDesignDocument(readDocument(designFile), {
|
|
42
|
-
designFile, baseDir,
|
|
43
|
-
...(prdFile ? { prdMarkdown: readDocument(prdFile) } : {}),
|
|
44
|
-
});
|
|
45
|
-
const output = { ...result, designFile, ...(prdFile ? { prdFile, baseDir } : {}) };
|
|
46
|
-
if (options.json) {console.log(JSON.stringify(output, null, 2));}
|
|
47
|
-
else {success(t('design_document.checked', result.name, result.pages.length, result.tokenCount));}
|
|
48
|
-
return output;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
module.exports = { run, parseArgs };
|