openyida 2026.9.21 → 2026.9.22-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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 +145 -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
package/lib/app/custom-theme.js
CHANGED
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { getAccessToken } = require('../auth/token-auth');
|
|
6
|
-
const { CliError } = require('../core/cli-error');
|
|
7
|
-
const { t } = require('../core/i18n');
|
|
8
|
-
const { findCssStructureIssue } = require('../core/css-structure');
|
|
9
6
|
|
|
10
7
|
const MAX_THEME_FILE_BYTES = 20 * 1024 * 1024;
|
|
11
8
|
const REQUIRED_BRAND_SCALE_TOKENS = Object.freeze([
|
|
@@ -150,14 +147,6 @@ function extractThemeColor(cssText) {
|
|
|
150
147
|
|
|
151
148
|
function validateThemeCssContent(cssText) {
|
|
152
149
|
const source = String(cssText || '');
|
|
153
|
-
// Check the original text before stripping comments or rewriting token scopes.
|
|
154
|
-
const issue = findCssStructureIssue(source);
|
|
155
|
-
if (issue) {
|
|
156
|
-
const line = source.slice(0, issue.index).split('\n').length;
|
|
157
|
-
throw new CliError(t('design_document.theme_css_invalid', line), {
|
|
158
|
-
code: 'THEME_CSS_STRUCTURE_INVALID', details: { line, ...issue },
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
150
|
const sourceWithoutComments = source.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
162
151
|
for (const rule of UNSAFE_THEME_PATTERNS) {
|
|
163
152
|
if (rule.pattern.test(sourceWithoutComments)) {
|
|
@@ -1,19 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { t } = require('../core/i18n');
|
|
4
|
-
|
|
5
|
-
// vc-deep-yida: components/vs-divider-style + components/yida-divider.
|
|
6
|
-
// 这里只定义平台能力,不按业务场景排序;样式由页面设计选择。
|
|
7
|
-
const DIVIDER_TYPES = Object.freeze([
|
|
8
|
-
'solid', 'dashed', 'thick', 'dotted', 'bold-with-thin',
|
|
9
|
-
'solid-center', 'solid-left', 'left-dot-title', 'light-left-bar',
|
|
10
|
-
'light-bar', 'dark-bar', 'light-left-title', 'light-center-title',
|
|
11
|
-
'light-house-title', 'light-hexagon-title', 'hexagon-title', 'badge-line',
|
|
12
|
-
'multi-parallelograms-end', 'center-title-with-bar', 'double-color-trapezoid',
|
|
13
|
-
'arrow-right-title', 'square-blocks-title', 'inner-ellipse-title',
|
|
14
|
-
]);
|
|
15
|
-
const DEFAULT_DIVIDER_TYPE = 'bold-with-thin';
|
|
16
|
-
|
|
17
3
|
const FIELD_TYPE_ALIAS = Object.freeze({
|
|
18
4
|
TextAreaField: 'TextareaField',
|
|
19
5
|
Textareafield: 'TextareaField',
|
|
@@ -58,6 +44,10 @@ const PRESENTATION_TYPE_ALIAS = Object.freeze({
|
|
|
58
44
|
columnContainer: 'ColumnContainer',
|
|
59
45
|
Column: 'Column',
|
|
60
46
|
column: 'Column',
|
|
47
|
+
GroupContainer: 'GroupContainer',
|
|
48
|
+
groupContainer: 'GroupContainer',
|
|
49
|
+
PageSection: 'PageSection',
|
|
50
|
+
pageSection: 'PageSection',
|
|
61
51
|
});
|
|
62
52
|
|
|
63
53
|
const BUSINESS_FIELD_TYPES = Object.freeze([
|
|
@@ -86,6 +76,8 @@ const PRESENTATION_FIELD_TYPES = Object.freeze([
|
|
|
86
76
|
'Divider',
|
|
87
77
|
'ColumnContainer',
|
|
88
78
|
'Column',
|
|
79
|
+
'GroupContainer',
|
|
80
|
+
'PageSection',
|
|
89
81
|
]);
|
|
90
82
|
|
|
91
83
|
const OPTION_FIELD_TYPES = Object.freeze([
|
|
@@ -240,19 +232,14 @@ function validateDivider(field, path, diagnostics) {
|
|
|
240
232
|
'Use a plain string title or omit title.'
|
|
241
233
|
);
|
|
242
234
|
}
|
|
243
|
-
|
|
244
|
-
.map(key => [key, field[key]]);
|
|
245
|
-
styleInputs.push(['props.type', field.props?.type]);
|
|
246
|
-
for (const [key, value] of styleInputs) {
|
|
247
|
-
if (value === undefined || value === null || value === '') {continue;}
|
|
248
|
-
if (typeof value === 'string' && DIVIDER_TYPES.includes(value.trim())) {continue;}
|
|
235
|
+
if (field.dividerType !== undefined && typeof field.dividerType !== 'string') {
|
|
249
236
|
pushDiagnostic(
|
|
250
237
|
diagnostics,
|
|
251
238
|
'INVALID_DIVIDER_TYPE',
|
|
252
|
-
path + '.'
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
239
|
+
path + '.dividerType',
|
|
240
|
+
'string',
|
|
241
|
+
describeActual(field.dividerType),
|
|
242
|
+
'Divider.dividerType must be a string when provided.',
|
|
256
243
|
'Use a supported divider style string or omit dividerType.'
|
|
257
244
|
);
|
|
258
245
|
}
|
|
@@ -366,6 +353,11 @@ function validateFieldDefinition(field, path, diagnostics, options) {
|
|
|
366
353
|
return;
|
|
367
354
|
}
|
|
368
355
|
|
|
356
|
+
if (type === 'GroupContainer' || type === 'PageSection') {
|
|
357
|
+
validateOneDimensionalChildren(field, path, diagnostics, type);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
369
361
|
if (type === 'TableField') {
|
|
370
362
|
validateTableField(field, path, diagnostics);
|
|
371
363
|
}
|
|
@@ -485,6 +477,31 @@ function validateColumnContainer(field, path, diagnostics) {
|
|
|
485
477
|
});
|
|
486
478
|
}
|
|
487
479
|
|
|
480
|
+
function validateOneDimensionalChildren(field, path, diagnostics, type) {
|
|
481
|
+
if (!validateChildrenPropertyShape(field, path, diagnostics, 'FieldDefinition[]')) {
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
if (field.children === undefined || field.children === null) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
field.children.forEach(function (child, childIndex) {
|
|
488
|
+
const childPath = path + '.children[' + childIndex + ']';
|
|
489
|
+
if (Array.isArray(child)) {
|
|
490
|
+
pushDiagnostic(
|
|
491
|
+
diagnostics,
|
|
492
|
+
'INVALID_' + type.toUpperCase() + '_CHILDREN_DEPTH',
|
|
493
|
+
childPath,
|
|
494
|
+
'FieldDefinition object',
|
|
495
|
+
'array',
|
|
496
|
+
type + '.children must be a one-dimensional field array.',
|
|
497
|
+
'Remove extra array nesting from ' + type + '.children.'
|
|
498
|
+
);
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
validateFieldDefinition(child, childPath, diagnostics);
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
|
|
488
505
|
function validateTableField(field, path, diagnostics) {
|
|
489
506
|
if (!validateChildrenPropertyShape(field, path, diagnostics, 'FieldDefinition[]')) {
|
|
490
507
|
return;
|
|
@@ -540,6 +557,4 @@ module.exports = {
|
|
|
540
557
|
normalizeDefinitionType,
|
|
541
558
|
BUSINESS_FIELD_TYPES,
|
|
542
559
|
PRESENTATION_FIELD_TYPES,
|
|
543
|
-
DIVIDER_TYPES,
|
|
544
|
-
DEFAULT_DIVIDER_TYPE,
|
|
545
560
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const Babel = require('@babel/standalone');
|
|
4
|
-
const { t } = require('../core/i18n');
|
|
5
4
|
|
|
6
5
|
const parser = Babel.packages.parser;
|
|
7
6
|
const traverse = Babel.packages.traverse.default || Babel.packages.traverse;
|
|
@@ -78,13 +77,6 @@ function isWindowOpenCall(callee) {
|
|
|
78
77
|
);
|
|
79
78
|
}
|
|
80
79
|
|
|
81
|
-
function isLocationCall(callee) {
|
|
82
|
-
return callee?.type === 'MemberExpression'
|
|
83
|
-
&& ['assign', 'replace'].includes(callee.property?.name)
|
|
84
|
-
&& (callee.object?.name === 'location'
|
|
85
|
-
|| (callee.object?.object?.name === 'window' && callee.object?.property?.name === 'location'));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
80
|
function isOpenPageCall(callee) {
|
|
89
81
|
return !!(
|
|
90
82
|
callee &&
|
|
@@ -122,26 +114,18 @@ function isLocationHrefAssignment(node) {
|
|
|
122
114
|
}
|
|
123
115
|
|
|
124
116
|
function isMobileGuarded(pathRef, sourceCode) {
|
|
125
|
-
const mobileCondition = node => {
|
|
126
|
-
if (node?.type === 'UnaryExpression' && node.operator === '!') {return -mobileCondition(node.argument);}
|
|
127
|
-
const text = getNodeText(sourceCode, node);
|
|
128
|
-
if (node?.type === 'Identifier' || node?.type === 'MemberExpression' || node?.type === 'CallExpression') {
|
|
129
|
-
return MOBILE_GUARD_PATTERN.test(text) && !/min-width/.test(text) ? 1 : 0;
|
|
130
|
-
}
|
|
131
|
-
return 0;
|
|
132
|
-
};
|
|
133
117
|
let cursor = pathRef;
|
|
134
118
|
while (cursor && cursor.parentPath) {
|
|
135
119
|
const parent = cursor.parentPath;
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
120
|
+
if (parent.node && parent.node.type === 'IfStatement' && nodeContains(parent.node.consequent, pathRef.node)) {
|
|
121
|
+
if (MOBILE_GUARD_PATTERN.test(getNodeText(sourceCode, parent.node.test))) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
140
124
|
}
|
|
141
|
-
if (parent.node
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
125
|
+
if (parent.node && parent.node.type === 'ConditionalExpression') {
|
|
126
|
+
if (MOBILE_GUARD_PATTERN.test(getNodeText(sourceCode, parent.node.test))) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
145
129
|
}
|
|
146
130
|
cursor = parent;
|
|
147
131
|
}
|
|
@@ -177,17 +161,9 @@ function findDirectFormOpenIssues(sourceCode, options = {}) {
|
|
|
177
161
|
}
|
|
178
162
|
|
|
179
163
|
const knownFormUrlNames = new Set();
|
|
180
|
-
const containerNames = new Set(['formOpenContainer']);
|
|
181
164
|
traverse(ast, {
|
|
182
165
|
VariableDeclarator(pathRef) {
|
|
183
166
|
const id = pathRef.node.id;
|
|
184
|
-
if (id?.type === 'ObjectPattern' && pathRef.node.init?.callee?.name === 'useYidaFormOpen') {
|
|
185
|
-
for (const property of id.properties) {
|
|
186
|
-
if (property.key?.name === 'formOpenContainer' && property.value?.type === 'Identifier') {
|
|
187
|
-
containerNames.add(property.value.name);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
167
|
if (!id || id.type !== 'Identifier') {
|
|
192
168
|
return;
|
|
193
169
|
}
|
|
@@ -198,30 +174,10 @@ function findDirectFormOpenIssues(sourceCode, options = {}) {
|
|
|
198
174
|
});
|
|
199
175
|
|
|
200
176
|
const issues = [];
|
|
201
|
-
const templateParts = new Map();
|
|
202
|
-
const templateUses = [];
|
|
203
|
-
let containerRendered = false;
|
|
204
|
-
const functionName = pathRef => {
|
|
205
|
-
const owner = pathRef.getFunctionParent();
|
|
206
|
-
return owner?.node.id?.name || owner?.parentPath?.node.id?.name;
|
|
207
|
-
};
|
|
208
|
-
const addTemplatePart = (owner, part) => {
|
|
209
|
-
if (!templateParts.has(owner)) {templateParts.set(owner, new Set());}
|
|
210
|
-
templateParts.get(owner).add(part);
|
|
211
|
-
};
|
|
212
177
|
traverse(ast, {
|
|
213
178
|
CallExpression(pathRef) {
|
|
214
179
|
const callee = pathRef.node.callee;
|
|
215
|
-
if (callee
|
|
216
|
-
templateUses.push(pathRef.node);
|
|
217
|
-
}
|
|
218
|
-
if (callee.type === 'Identifier' && ['openForm', 'setFormRequest'].includes(callee.name)
|
|
219
|
-
&& pathRef.node.arguments[0]?.type === 'ObjectExpression'
|
|
220
|
-
&& pathRef.node.arguments[0].properties.some(property => (property.key?.name || property.key?.value) === 'type'
|
|
221
|
-
&& ['submission', 'detail'].includes(property.value?.value))) {
|
|
222
|
-
templateUses.push(pathRef.node);
|
|
223
|
-
}
|
|
224
|
-
if (!isWindowOpenCall(callee) && !isOpenPageCall(callee) && !isLocationCall(callee)) {
|
|
180
|
+
if (!isWindowOpenCall(callee) && !isOpenPageCall(callee)) {
|
|
225
181
|
return;
|
|
226
182
|
}
|
|
227
183
|
const firstArg = pathRef.node.arguments && pathRef.node.arguments[0];
|
|
@@ -251,56 +207,13 @@ function findDirectFormOpenIssues(sourceCode, options = {}) {
|
|
|
251
207
|
callee: getNodeText(sourceCode, pathRef.node.left),
|
|
252
208
|
});
|
|
253
209
|
},
|
|
254
|
-
JSXExpressionContainer(pathRef) {
|
|
255
|
-
if ((pathRef.parentPath.isJSXElement() || pathRef.parentPath.isJSXFragment())
|
|
256
|
-
&& containerNames.has(pathRef.node.expression?.name)) {
|
|
257
|
-
containerRendered = true;
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
JSXOpeningElement(pathRef) {
|
|
261
|
-
const name = pathRef.node.name?.name;
|
|
262
|
-
const owner = functionName(pathRef);
|
|
263
|
-
addTemplatePart(owner, name);
|
|
264
|
-
if (name === 'FormOpenContainer' && owner !== 'useYidaFormOpen') {
|
|
265
|
-
templateUses.push(pathRef.node);
|
|
266
|
-
containerRendered = true;
|
|
267
|
-
}
|
|
268
|
-
const attribute = key => pathRef.node.attributes.find(item => item.type === 'JSXAttribute' && item.name?.name === key)?.value;
|
|
269
|
-
const value = node => node?.type === 'JSXExpressionContainer' ? node.expression : node;
|
|
270
|
-
if (owner === 'CanvasDrawer' && attribute('className')?.value === 'oy-drawer-resize'
|
|
271
|
-
&& attribute('onPointerDown') && attribute('onPointerMove') && attribute('onPointerUp') && attribute('onKeyDown')) {
|
|
272
|
-
addTemplatePart(owner, 'resize-handle');
|
|
273
|
-
}
|
|
274
|
-
if (name === 'a' && expressionLooksLikeFormUrl(value(attribute('href')), sourceCode, knownFormUrlNames)) {
|
|
275
|
-
issues.push({ line: getNodeLine(pathRef.node), callee: 'a[href]' });
|
|
276
|
-
}
|
|
277
|
-
if (!['iframe', 'YidaCanvasIframe'].includes(name) || owner === 'FormOpenContainer') {return;}
|
|
278
|
-
if (!expressionLooksLikeFormUrl(value(attribute('src')), sourceCode, knownFormUrlNames)) {return;}
|
|
279
|
-
// 导航主内容可以嵌原生页;弹层内的表单必须使用提供的容器。
|
|
280
|
-
const overlay = pathRef.findParent(parent => parent.isJSXElement() && (
|
|
281
|
-
['Drawer', 'Modal', 'CanvasDrawer'].includes(parent.node.openingElement.name?.name)
|
|
282
|
-
|| parent.node.openingElement.attributes.some(item => item.type === 'JSXAttribute'
|
|
283
|
-
&& ((item.name?.name === 'role' && item.value?.value === 'dialog')
|
|
284
|
-
|| (item.name?.name === 'style' && /position\s*:\s*['"]fixed['"]/.test(getNodeText(sourceCode, item.value)))))));
|
|
285
|
-
if (overlay) {issues.push({ line: getNodeLine(pathRef.node), callee: `${name} outside FormOpenContainer` });}
|
|
286
|
-
},
|
|
287
210
|
});
|
|
288
211
|
|
|
289
|
-
if (templateUses.length) {
|
|
290
|
-
const hasParts = (owner, parts) => parts.every(part => templateParts.get(owner)?.has(part));
|
|
291
|
-
const complete = hasParts('FormOpenContainer', ['CanvasDrawer', 'iframe'])
|
|
292
|
-
&& hasParts('CanvasDrawer', ['Drawer', 'ExternalLink', 'Maximize2', 'Minimize2', 'X', 'resize-handle'])
|
|
293
|
-
&& hasParts('useYidaFormOpen', ['FormOpenContainer']) && containerRendered;
|
|
294
|
-
if (!complete) {
|
|
295
|
-
issues.push({ line: getNodeLine(templateUses[0]), callee: 'incomplete FormOpenContainer template' });
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
212
|
return issues;
|
|
300
213
|
}
|
|
301
214
|
|
|
302
215
|
function formatDirectFormOpenMessage() {
|
|
303
|
-
return
|
|
216
|
+
return '自定义页内打开表单提交/详情只能使用 FormOpenContainer:PC 端用 50vw 抽屉 iframe,移动端才整页或新页打开。按钮事件请调用 openForm({ type: "submission" | "detail", ... })。';
|
|
304
217
|
}
|
|
305
218
|
|
|
306
219
|
module.exports = {
|
|
@@ -4,7 +4,37 @@ const Babel = require('@babel/standalone');
|
|
|
4
4
|
const { CliError } = require('../core/cli-error');
|
|
5
5
|
const { t } = require('../core/i18n');
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
// 检查 CSS 的结构闭合,避免一个未闭合 var() 吞掉后续规则。
|
|
8
|
+
// 不执行页面代码,也不把动态插值当成完整 CSS 进行猜测性校验。
|
|
9
|
+
function findCssStructureIssue(css) {
|
|
10
|
+
const stack = [];
|
|
11
|
+
const pairs = { '(': ')', '[': ']', '{': '}' };
|
|
12
|
+
for (let index = 0; index < css.length; index++) {
|
|
13
|
+
const char = css[index];
|
|
14
|
+
if (char === '\\') { index++; continue; }
|
|
15
|
+
if (char === '/' && css[index + 1] === '*') {
|
|
16
|
+
const end = css.indexOf('*/', index + 2);
|
|
17
|
+
if (end < 0) { return { index, type: 'unclosed_comment' }; }
|
|
18
|
+
index = end + 1;
|
|
19
|
+
} else if (char === '"' || char === "'") {
|
|
20
|
+
const start = index;
|
|
21
|
+
for (index++; index < css.length; index++) {
|
|
22
|
+
if (css[index] === '\\') { index++; continue; }
|
|
23
|
+
if (css[index] === char) { break; }
|
|
24
|
+
}
|
|
25
|
+
if (index >= css.length) { return { index: start, type: 'unclosed_string' }; }
|
|
26
|
+
} else if (pairs[char]) {
|
|
27
|
+
stack.push({ char, index });
|
|
28
|
+
} else if (')]}'.includes(char)) {
|
|
29
|
+
const open = stack.pop();
|
|
30
|
+
if (!open || pairs[open.char] !== char) {
|
|
31
|
+
return { index: open ? open.index : index, type: 'mismatched_delimiter', expected: open && pairs[open.char], actual: char };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const open = stack.pop();
|
|
36
|
+
return open ? { index: open.index, type: 'unclosed_delimiter', expected: pairs[open.char] } : null;
|
|
37
|
+
}
|
|
8
38
|
|
|
9
39
|
function resolveStaticCss(pathRef, seen = new Set()) {
|
|
10
40
|
if (pathRef.isStringLiteral()) { return { text: pathRef.node.value, node: pathRef.node }; }
|
|
@@ -1615,7 +1615,7 @@ function buildFormSchema(formTitle, fields, formUuid, corpId, appType, layout, t
|
|
|
1615
1615
|
id: nextNodeId(),
|
|
1616
1616
|
props: {
|
|
1617
1617
|
contentBgColor: 'white',
|
|
1618
|
-
pageStyle: { backgroundColor: '
|
|
1618
|
+
pageStyle: { backgroundColor: '#f2f3f5' },
|
|
1619
1619
|
contentMargin: '20',
|
|
1620
1620
|
contentPadding: '20',
|
|
1621
1621
|
showTitle: false,
|
|
@@ -1638,6 +1638,7 @@ function buildFormSchema(formTitle, fields, formUuid, corpId, appType, layout, t
|
|
|
1638
1638
|
labelWeightMobile: 'normal',
|
|
1639
1639
|
},
|
|
1640
1640
|
condition: true,
|
|
1641
|
+
css: 'body{background-color:#f2f3f5}',
|
|
1641
1642
|
methods: {
|
|
1642
1643
|
__initMethods__: {
|
|
1643
1644
|
type: 'js',
|
|
@@ -1832,7 +1833,7 @@ function buildEmptyFormSchema() {
|
|
|
1832
1833
|
id: nextNodeId(),
|
|
1833
1834
|
props: {
|
|
1834
1835
|
contentBgColor: 'white',
|
|
1835
|
-
pageStyle: { backgroundColor: '
|
|
1836
|
+
pageStyle: { backgroundColor: '#f2f3f5' },
|
|
1836
1837
|
contentMargin: '20',
|
|
1837
1838
|
contentPadding: '20',
|
|
1838
1839
|
showTitle: false,
|
|
@@ -1843,6 +1844,7 @@ function buildEmptyFormSchema() {
|
|
|
1843
1844
|
contentBgColorMobile: 'white',
|
|
1844
1845
|
},
|
|
1845
1846
|
condition: true,
|
|
1847
|
+
css: 'body{background-color:#f2f3f5}',
|
|
1846
1848
|
methods: {
|
|
1847
1849
|
__initMethods__: {
|
|
1848
1850
|
type: 'js',
|
|
@@ -1,33 +1,42 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
3
|
const { CliError } = require('../core/cli-error');
|
|
6
4
|
const { REQUIRED_BRAND_SCALE_TOKENS, validateThemeCssContent, extractThemeColor } = require('./custom-theme');
|
|
7
|
-
const { parseDesignDocument, extractDesignTokens } = require('../design/document');
|
|
8
|
-
const NAVIGATION_COLOR_TOKENS = [
|
|
9
|
-
'--pod-shell-theme-bg-color', '--pod-nav-item-text-color', '--pod-nav-item-text-hover-color',
|
|
10
|
-
'--pod-nav-item-text-selected-color', '--pod-nav-menu-bg-hover-color', '--pod-nav-menu-bg-selected-color',
|
|
11
|
-
];
|
|
12
|
-
const DECLARATIONS = /^[ \t]*(--[\w-]+)\s*:\s*([^;]+);/gm;
|
|
13
5
|
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
// Both flat Fast tokens and grouped Plan tokens use one scalar declaration per line.
|
|
7
|
+
function readDesignTokens(markdown) {
|
|
8
|
+
const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(markdown);
|
|
16
9
|
if (!frontmatter) {
|
|
17
10
|
throw new CliError('design.md 缺少包含 token 的 frontmatter', { code: 'DESIGN_THEME_TOKENS_REQUIRED' });
|
|
18
11
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
const tokens = {};
|
|
13
|
+
for (const line of frontmatter[1].split(/\r?\n/)) {
|
|
14
|
+
const match = /^\s*["']?(--[\w-]+)["']?\s*:\s*(.+?)\s*$/.exec(line);
|
|
15
|
+
if (!match) {continue;}
|
|
16
|
+
const name = match[1];
|
|
17
|
+
// YAML comments may follow a quoted value; # inside a color or string is data.
|
|
18
|
+
const scalar = /^("(?:[^"\\]|\\.)*"|'(?:[^']|'')*'|.*?)\s*(?:\s+#.*)?$/.exec(match[2]);
|
|
19
|
+
const raw = scalar[1].trim();
|
|
20
|
+
let value = raw;
|
|
21
|
+
if (raw.startsWith('"')) {
|
|
22
|
+
try { value = JSON.parse(raw); } catch {
|
|
23
|
+
throw new CliError(`token ${name} 必须是单行字符串`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
24
|
+
}
|
|
25
|
+
} else if (raw.startsWith("'")) {
|
|
26
|
+
if (!raw.endsWith("'")) {throw new CliError(`token ${name} 引号不完整`, { code: 'DESIGN_THEME_TOKEN_INVALID' });}
|
|
27
|
+
value = raw.slice(1, -1).replace(/''/g, "'");
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== 'string' || !value.trim() || /[;{}\r\n<>]|\/\*|\*\//.test(value) || /^[|>]/.test(value)) {
|
|
30
|
+
throw new CliError(`token ${name} 必须是已确定的单行 CSS 值`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
31
|
+
}
|
|
32
|
+
if (name in tokens && tokens[name] !== value) {
|
|
33
|
+
throw new CliError(`token ${name} 存在冲突值`, { code: 'DESIGN_THEME_TOKEN_CONFLICT' });
|
|
34
|
+
}
|
|
35
|
+
if (/^--color-brand1-(4|7|8)$/.test(name)) {
|
|
36
|
+
throw new CliError(`平台不支持 ${name}`, { code: 'DESIGN_THEME_TOKEN_INVALID' });
|
|
37
|
+
}
|
|
38
|
+
tokens[name] = value;
|
|
39
|
+
}
|
|
31
40
|
const missing = REQUIRED_BRAND_SCALE_TOKENS.filter(name => !tokens[name]);
|
|
32
41
|
if (missing.length) {
|
|
33
42
|
throw new CliError(`design.md 缺少品牌 token:${missing.join(', ')}`, { code: 'DESIGN_THEME_TOKENS_REQUIRED' });
|
|
@@ -35,8 +44,8 @@ function tokensFromMetadata(metadata) {
|
|
|
35
44
|
return tokens;
|
|
36
45
|
}
|
|
37
46
|
|
|
38
|
-
function resolveDesignTokens(
|
|
39
|
-
const tokens =
|
|
47
|
+
function resolveDesignTokens(markdown) {
|
|
48
|
+
const tokens = readDesignTokens(markdown);
|
|
40
49
|
for (const [alias, source] of Object.entries({
|
|
41
50
|
'--color-brand-1': '--color-brand1-10', '--color-brand-2': '--color-brand1-1',
|
|
42
51
|
'--color-brand-3': '--color-brand1-6', '--color-brand-4': '--color-brand1-9',
|
|
@@ -47,118 +56,14 @@ function resolveDesignTokens(metadata) {
|
|
|
47
56
|
return tokens;
|
|
48
57
|
}
|
|
49
58
|
|
|
50
|
-
function navigationTone(metadata, tokens) {
|
|
51
|
-
if (!NAVIGATION_COLOR_TOKENS.every(name => tokens[name])) {return null;}
|
|
52
|
-
const tone = metadata.themeProfile?.navTheme;
|
|
53
|
-
if (['light', 'dark'].includes(tone)) {return tone;}
|
|
54
|
-
if (tone !== undefined) {throw new CliError('themeProfile.navTheme 必须是 light 或 dark', { code: 'DESIGN_THEME_NAVIGATION_INVALID' });}
|
|
55
|
-
const seen = new Set();
|
|
56
|
-
let value = tokens['--pod-shell-theme-bg-color'];
|
|
57
|
-
while (/^var\(/.test(value || '')) {
|
|
58
|
-
const alias = /^var\((--[\w-]+)(?:,\s*([^)]+))?\)$/.exec(value);
|
|
59
|
-
if (!alias || seen.has(alias[1])) {return null;}
|
|
60
|
-
seen.add(alias[1]);
|
|
61
|
-
value = tokens[alias[1]] || alias[2];
|
|
62
|
-
}
|
|
63
|
-
let rgb;
|
|
64
|
-
if (/^#[\da-f]{3}$/i.test(value || '')) {value = `#${[...value.slice(1)].map(char => char + char).join('')}`;}
|
|
65
|
-
if (/^#[\da-f]{6}$/i.test(value || '')) {rgb = [1, 3, 5].map(index => parseInt(value.slice(index, index + 2), 16));}
|
|
66
|
-
const functional = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/.exec(value || '');
|
|
67
|
-
if (functional) {rgb = functional.slice(1, 4).map(Number);}
|
|
68
|
-
return rgb ? (rgb[0] * 0.2126 + rgb[1] * 0.7152 + rgb[2] * 0.0722 < 128 ? 'dark' : 'light') : null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function declarationValues(body) {
|
|
72
|
-
return Object.fromEntries([...body.matchAll(DECLARATIONS)].map(match => [match[1], match[2].trim()]));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function replaceDeclarations(body, values, addMissing = false) {
|
|
76
|
-
const existing = new Set();
|
|
77
|
-
let result = body.replace(DECLARATIONS, (line, name, value) => {
|
|
78
|
-
existing.add(name);
|
|
79
|
-
return name in values ? line.replace(value, () => values[name]) : line;
|
|
80
|
-
});
|
|
81
|
-
if (addMissing) {
|
|
82
|
-
result += Object.entries(values).filter(([name]) => !existing.has(name))
|
|
83
|
-
.map(([name, value]) => ` ${name}: ${value};\n`).join('');
|
|
84
|
-
}
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function applyNavigationTokens(css, tokens, changed, tone, previousTone) {
|
|
89
|
-
// The public stylesheet has a second :root and explicit mode overrides. Read
|
|
90
|
-
// their defaults so applying a dark project cannot leak white text into light modes.
|
|
91
|
-
const source = fs.readFileSync(path.resolve(__dirname,
|
|
92
|
-
'../../yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css'), 'utf8');
|
|
93
|
-
const defaults = Object.assign({}, ...[...source.matchAll(/^:root\s*\{([^}]+)\}/gm)].map(match => declarationValues(match[1])));
|
|
94
|
-
const isNavigation = name => /^(--pod-nav-|--pod-shell-|--pod-page-header-)/.test(name);
|
|
95
|
-
const navigationNames = Object.keys(tokens).filter(isNavigation);
|
|
96
|
-
const navigationChanged = Object.fromEntries(navigationNames.filter(name => name in changed).map(name => [name, tokens[name]]));
|
|
97
|
-
let output = css.replace(/(^:root\s*\{)([^}]+)(\})/gm,
|
|
98
|
-
(block, start, body, close) => start + replaceDeclarations(body, navigationChanged) + close);
|
|
99
|
-
for (const mode of ['light', 'dark']) {
|
|
100
|
-
const modeDefaults = { ...defaults };
|
|
101
|
-
for (const selector of [`nav-${mode}`, `is-${mode}`]) {
|
|
102
|
-
Object.assign(modeDefaults, declarationValues(source.match(new RegExp(`\\.pod-premium\\.${selector}\\s*\\{([^}]+)\\}`))?.[1] || ''));
|
|
103
|
-
}
|
|
104
|
-
// A first application or a mode change establishes both palettes. Delta
|
|
105
|
-
// updates otherwise leave unrelated, manually customized declarations alone.
|
|
106
|
-
const resetMode = !previousTone || previousTone !== tone;
|
|
107
|
-
// The selected marker is a mode-independent shape, not a navigation palette.
|
|
108
|
-
const names = (resetMode ? navigationNames : (mode === tone ? Object.keys(navigationChanged) : []))
|
|
109
|
-
.filter(name => name !== '--pod-nav-menu-item-selected-shadow');
|
|
110
|
-
const values = Object.fromEntries(names.map(name => [name, mode === tone ? tokens[name] : modeDefaults[name]])
|
|
111
|
-
.filter(([, value]) => value !== undefined));
|
|
112
|
-
if (!Object.keys(values).length) {continue;}
|
|
113
|
-
const isForeground = name => name.startsWith('--pod-nav-') || name === '--pod-page-header-text-color';
|
|
114
|
-
const background = Object.fromEntries(Object.entries(values).filter(([name]) => !isForeground(name)));
|
|
115
|
-
const shell = values['--pod-shell-theme-bg-color'];
|
|
116
|
-
if (shell && !tokens['--pod-page-header-bg-color']) {
|
|
117
|
-
background['--pod-page-header-bg-color'] = mode === tone ? shell : modeDefaults['--pod-page-header-bg-color'];
|
|
118
|
-
}
|
|
119
|
-
if (Object.keys(background).length) {
|
|
120
|
-
output = output.replace(new RegExp(`(\\.pod-premium\\.nav-${mode}\\s*\\{)([^}]*)(\\})`, 'g'),
|
|
121
|
-
(block, start, body, close) => start + replaceDeclarations(body, background, true) + close);
|
|
122
|
-
}
|
|
123
|
-
const foregrounds = Object.fromEntries(Object.entries(values).filter(([name]) => isForeground(name)));
|
|
124
|
-
output = output.replace(new RegExp(`(\\.pod-premium\\.is-${mode}\\s*\\{)([^}]*)(\\})`, 'g'),
|
|
125
|
-
(block, start, body, close) => start + replaceDeclarations(body, foregrounds, true) + close);
|
|
126
|
-
}
|
|
127
|
-
return output;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
59
|
function applyDesignTokens(template, markdown, previousMarkdown) {
|
|
131
|
-
const
|
|
132
|
-
const
|
|
133
|
-
const tokens = resolveDesignTokens(metadata);
|
|
134
|
-
// Bundled CSS is an authoring template. Fill only unresolved declarations from
|
|
135
|
-
// the completed design before validating and rewriting CSS scopes.
|
|
136
|
-
template = template.replace(/^([ \t]*)(--[\w-]+)(\s*:\s*)([^;\n]+);/gm,
|
|
137
|
-
(line, indent, name, separator, value) => {
|
|
138
|
-
if (!/\{\{PRIMARY_COLOR\}\}|<生成实际色值:/.test(value)) {return line;}
|
|
139
|
-
if (!tokens[name] || /\{\{|<生成实际色值:/.test(tokens[name])) {
|
|
140
|
-
throw new CliError(`design.md 缺少品牌 token:${name}`, { code: 'DESIGN_THEME_TOKENS_REQUIRED' });
|
|
141
|
-
}
|
|
142
|
-
return `${indent}${name}${separator}${tokens[name]};`;
|
|
143
|
-
});
|
|
144
|
-
// Reject damaged templates or existing stylesheets before the scope rewrite.
|
|
145
|
-
validateThemeCssContent(template);
|
|
146
|
-
// Older generated files have the selected-shadow rule only. Bring in the
|
|
147
|
-
// shared consumer once when a design opts into menu borders, retaining all
|
|
148
|
-
// existing project rules and declarations during incremental updates.
|
|
149
|
-
if (tokens['--pod-nav-menu-item-border'] && !template.includes('border: var(--pod-nav-menu-item-border,')) {
|
|
150
|
-
const source = fs.readFileSync(path.resolve(__dirname,
|
|
151
|
-
'../../yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css'), 'utf8');
|
|
152
|
-
const shapeRules = source.match(/\/\* openyida-navigation-shape:start \*\/[\s\S]*?\/\* openyida-navigation-shape:end \*\//)[0];
|
|
153
|
-
template += `\n${shapeRules}\n`;
|
|
154
|
-
}
|
|
155
|
-
const previous = previousMetadata === metadata ? tokens : (previousMetadata ? resolveDesignTokens(previousMetadata) : null);
|
|
156
|
-
const tone = navigationTone(metadata, tokens);
|
|
157
|
-
const previousTone = previous ? navigationTone(previousMetadata, previous) : null;
|
|
60
|
+
const tokens = resolveDesignTokens(markdown);
|
|
61
|
+
const previous = previousMarkdown ? resolveDesignTokens(previousMarkdown) : null;
|
|
158
62
|
const changed = Object.fromEntries(Object.entries(tokens).filter(([name, value]) => !previous || previous[name] !== value));
|
|
159
|
-
if (!Object.keys(changed).length
|
|
63
|
+
if (!Object.keys(changed).length) {
|
|
64
|
+
validateThemeCssContent(template);
|
|
160
65
|
extractThemeColor(template);
|
|
161
|
-
return
|
|
66
|
+
return template;
|
|
162
67
|
}
|
|
163
68
|
const root = /^:root\s*\{([\s\S]*?)^\}/m.exec(template);
|
|
164
69
|
if (!root) {throw new Error('应用主题模板缺少 :root');}
|
|
@@ -171,18 +76,10 @@ function applyDesignTokens(template, markdown, previousMarkdown) {
|
|
|
171
76
|
let body = root[1].replace(declarations, (line, name, value) => line.replace(value, () => changed[name] || replaceBrand(value)));
|
|
172
77
|
const extra = Object.entries(changed).filter(([name]) => !(name in original));
|
|
173
78
|
body += extra.map(([name, value]) => ` ${name}: ${value};\n`).join('');
|
|
174
|
-
|
|
79
|
+
// Keep scoped nav/light/dark selectors and their variable relationships intact.
|
|
80
|
+
const tail = template.slice(root.index + root[0].length).replace(declarations,
|
|
175
81
|
(line, name, value) => line.replace(value, () => replaceBrand(value)));
|
|
176
|
-
|
|
177
|
-
if (!tone && changed['--pod-shell-theme-bg-color']) {
|
|
178
|
-
tail = tail.replace(/(\.pod-premium\.nav-(light|dark)\s*\{)([^}]*)(\})/g,
|
|
179
|
-
(block, selector, tone, body, close) => selector + body.replace(declarations,
|
|
180
|
-
(line, name, value) => ['--pod-shell-theme-bg-color', '--pod-page-header-bg-color'].includes(name)
|
|
181
|
-
? line.replace(value, `var(--color-brand1-${tone === 'dark' ? 5 : 3})`) : line) + close);
|
|
182
|
-
}
|
|
183
|
-
let css = `${template.slice(0, root.index)}:root {${body}}${tail}`;
|
|
184
|
-
if (tone) {css = applyNavigationTokens(css, tokens, changed, tone, previousTone);}
|
|
185
|
-
css = require('./application-style').applyApplicationStyle(css, metadata, tokens);
|
|
82
|
+
const css = `${template.slice(0, root.index)}:root {${body}}${tail}`;
|
|
186
83
|
validateThemeCssContent(css);
|
|
187
84
|
extractThemeColor(css);
|
|
188
85
|
return css;
|
package/lib/app/theme-presets.js
CHANGED
|
@@ -122,7 +122,7 @@ function assertPresetThemeKey(themeKey) {
|
|
|
122
122
|
throw new Error(
|
|
123
123
|
`Unsupported theme: ${themeKey}. Use one of: ${formatPresetThemeKeys()}. ` +
|
|
124
124
|
'For custom colors or application theme token profiles that are not platform --theme keys, ' +
|
|
125
|
-
'upload an application theme CSS file with update-app --theme-file.'
|
|
125
|
+
'upload an application theme CSS file with update-app --theme-file and pass --theme-color instead.'
|
|
126
126
|
);
|
|
127
127
|
}
|
|
128
128
|
|