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.
Files changed (334) hide show
  1. package/README.md +14 -20
  2. package/bin/yida.js +6 -11
  3. package/lib/app/app-list.js +3 -7
  4. package/lib/app/canvas-compile.js +12 -22
  5. package/lib/app/check-prd-completeness.js +0 -7
  6. package/lib/app/create-app.js +1 -4
  7. package/lib/app/create-form/args.js +12 -37
  8. package/lib/app/create-form/batch.js +11 -86
  9. package/lib/app/create-form.js +86 -193
  10. package/lib/app/create-page.js +17 -84
  11. package/lib/app/custom-theme.js +0 -11
  12. package/lib/app/form-field-validator.js +41 -26
  13. package/lib/app/form-open-guard.js +10 -97
  14. package/lib/app/get-form-config.js +0 -1
  15. package/lib/app/inline-css-guard.js +31 -1
  16. package/lib/app/services/form-compiler.js +4 -2
  17. package/lib/app/theme-from-design.js +41 -144
  18. package/lib/app/theme-presets.js +1 -1
  19. package/lib/app/update-app.js +13 -63
  20. package/lib/asset/ai-image.js +9 -59
  21. package/lib/asset/asset-cmd.js +7 -18
  22. package/lib/asset/asset-plan.js +9 -102
  23. package/lib/asset/asset-resolve.js +10 -55
  24. package/lib/asset/asset-status.js +4 -5
  25. package/lib/asset/host-capabilities.js +2 -11
  26. package/lib/asset/url-verify.js +4 -19
  27. package/lib/auth/dws-sync.js +145 -0
  28. package/lib/auth/token-auth.js +73 -9
  29. package/lib/auth/token-store.js +50 -0
  30. package/lib/connector/connector-test.js +5 -19
  31. package/lib/connector/contract.js +1 -3
  32. package/lib/core/agent-capabilities.js +16 -19
  33. package/lib/core/command-manifest.js +40 -329
  34. package/lib/core/locales/en.js +17 -74
  35. package/lib/core/locales/zh.js +16 -73
  36. package/lib/core/redact.js +10 -15
  37. package/lib/core/sample.js +30 -72
  38. package/lib/core/utils.js +4 -0
  39. package/lib/design-plan/design-plan.js +4 -51
  40. package/lib/design-plan/init.js +26 -121
  41. package/lib/design-plan/materialize.js +348 -451
  42. package/lib/design-plan/normalize.js +29 -74
  43. package/lib/design-plan/parallel.js +16 -71
  44. package/lib/design-plan/patch.js +16 -63
  45. package/lib/design-plan/preview.js +8 -6
  46. package/lib/design-plan/validate.js +11 -71
  47. package/lib/process/create-process.js +50 -84
  48. package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +90 -20
  49. package/lib/samples/openyida-scaffold/canvas-nav/content.jsx +13 -93
  50. package/lib/samples/openyida-scaffold/canvas-nav/data.jsx +18 -100
  51. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +4 -6
  52. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
  53. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +2 -1
  54. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
  55. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +9 -15
  56. package/lib/samples/yida-canvas-table-form/table-form-batch-submit.canvas.jsx +83 -9
  57. package/lib/samples/yida-rechart/trend-combo.canvas.jsx +87 -14
  58. package/package.json +1 -3
  59. package/scripts/postinstall.js +3 -3
  60. package/yida-skills/SKILL.md +16 -19
  61. package/yida-skills/references/official-example-schema-patterns.md +1 -1
  62. package/yida-skills/references/yida-api.md +0 -4
  63. package/yida-skills/skills/yida-app/SKILL.md +23 -46
  64. package/yida-skills/skills/yida-app/workflow/parallel-work.md +6 -15
  65. package/yida-skills/skills/yida-app/workflow/plan/step-1-understand.md +1 -1
  66. package/yida-skills/skills/yida-app/workflow/plan/step-2-confirm.md +1 -1
  67. package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +15 -29
  68. package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -29
  69. package/yida-skills/skills/yida-app/workflow/step-1-resource-context.md +2 -4
  70. package/yida-skills/skills/yida-app/workflow/step-2-design.md +9 -23
  71. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +4 -6
  72. package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +4 -15
  73. package/yida-skills/skills/yida-app/workflow/step-6-main-page.md +4 -6
  74. package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +9 -15
  75. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +11 -25
  76. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +28 -68
  77. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +43 -42
  78. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +44 -60
  79. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +50 -72
  80. package/yida-skills/skills/yida-canvas-custom-page/references/component-library-guide.md +1 -13
  81. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +1 -140
  82. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +72 -101
  83. package/yida-skills/skills/yida-canvas-custom-page/references/page-generation-guide.md +32 -35
  84. package/yida-skills/skills/yida-canvas-custom-page/scripts/build-canvas-theme.js +3 -29
  85. package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +6 -69
  86. package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +0 -26
  87. package/yida-skills/skills/yida-create-app/SKILL.md +0 -2
  88. package/yida-skills/skills/yida-create-form-page/SKILL.md +58 -72
  89. package/yida-skills/skills/yida-create-form-page/references/advanced-form-modes.md +5 -5
  90. package/yida-skills/skills/yida-create-form-page/references/association-form-field.md +4 -4
  91. package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +5 -6
  92. package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +19 -7
  93. package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +44 -62
  94. package/yida-skills/skills/yida-create-page/SKILL.md +6 -14
  95. package/yida-skills/skills/yida-create-process/SKILL.md +2 -13
  96. package/yida-skills/skills/yida-custom-page/SKILL.md +0 -2
  97. package/yida-skills/skills/yida-custom-page/references/design-system.md +1 -1
  98. package/yida-skills/skills/yida-dashboard/SKILL.md +4 -5
  99. package/yida-skills/skills/yida-data-management/SKILL.md +2 -4
  100. package/yida-skills/skills/yida-data-management/references/data-format-guide.md +4 -4
  101. package/yida-skills/skills/yida-design/SKILL.md +14 -29
  102. package/yida-skills/skills/yida-design/references/app/blueprint.md +70 -0
  103. package/yida-skills/skills/yida-design/references/app/navigation-patterns.md +43 -0
  104. package/yida-skills/skills/yida-design/references/app/role-journey.md +30 -0
  105. package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +42 -67
  106. package/yida-skills/skills/yida-design/references/asset-workflow.md +2 -6
  107. package/yida-skills/skills/yida-design/references/design-mode.md +4 -4
  108. package/yida-skills/skills/yida-design/references/page-quality-gates.md +38 -26
  109. package/yida-skills/skills/yida-design/references/style-design-selection.md +137 -0
  110. package/yida-skills/skills/yida-design/references/style-designs/_design-md-template.md +185 -0
  111. package/yida-skills/skills/yida-design/references/style-designs/aqua-service-progress-dashboard.md +242 -0
  112. package/yida-skills/skills/yida-design/references/style-designs/blue-insight-operations-dashboard.md +243 -0
  113. package/yida-skills/skills/yida-design/references/style-designs/blue-productivity-insight-workbench.md +242 -0
  114. package/yida-skills/skills/yida-design/references/style-designs/command-filter-card-console.md +304 -0
  115. package/yida-skills/skills/yida-design/references/style-designs/contrast-command-analytics-workbench.md +261 -0
  116. package/yida-skills/skills/yida-design/references/style-designs/dark-stage-analytic-dashboard.md +369 -0
  117. package/yida-skills/skills/yida-design/references/style-designs/filterable-card-catalog.md +354 -0
  118. package/yida-skills/skills/yida-design/references/style-designs/green-timeline-progress-workbench.md +250 -0
  119. package/yida-skills/skills/yida-design/references/style-designs/registry.md +117 -0
  120. package/yida-skills/skills/yida-design/references/style-designs/soft-analytic-workbench.md +348 -0
  121. package/yida-skills/skills/yida-design/references/style-designs/soft-blue-grid-analytic-dashboard.md +658 -0
  122. package/yida-skills/skills/yida-design/references/style-designs/soft-bordered-analytic-workbench.md +385 -0
  123. package/yida-skills/skills/yida-design/references/style-designs/soft-curated-filter-gallery.md +300 -0
  124. package/yida-skills/skills/yida-design/references/style-designs/soft-modular-analytic-workbench.md +404 -0
  125. package/yida-skills/skills/yida-design/references/style-designs/soft-progress-analytics-workbench.md +382 -0
  126. package/yida-skills/skills/yida-design/references/style-designs/soft-timeline-analytics-workbench.md +367 -0
  127. package/yida-skills/skills/yida-design/references/style-designs/teal-rail-analytics-workbench.md +341 -0
  128. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +432 -350
  129. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +143 -19
  130. package/yida-skills/skills/yida-design/references/visual-scaffold-recipes.md +27 -15
  131. package/yida-skills/skills/yida-design/sub_skill/page-design/SKILL.md +0 -4
  132. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +8 -22
  133. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/README.md +10 -14
  134. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/assets/build-plan-template.html +4 -9
  135. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +27 -49
  136. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +154 -33
  137. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +127 -48
  138. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +51 -37
  139. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +48 -43
  140. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/validate_design_themes.py +190 -0
  141. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/README.md +98 -0
  142. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-media-grid.md +339 -0
  143. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-modular-clarity.md +348 -0
  144. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/airy-structured-clarity.md +344 -0
  145. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ambient-halo-layered.md +345 -0
  146. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-focus-layered.md +355 -0
  147. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/dark-luminous-modular.md +377 -0
  148. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/deep-stage-duotone.md +352 -0
  149. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/hairline-runway-clarity.md +389 -0
  150. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/high-contrast-modular.md +364 -0
  151. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/index.json +329 -0
  152. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/interlocked-vivid-modules.md +348 -0
  153. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/matrix-grid-focus.md +345 -0
  154. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/media-rail-inspector.md +379 -0
  155. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mist-layered-signal.md +347 -0
  156. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/modular-rail-signal.md +352 -0
  157. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/mono-grid-signal.md +386 -0
  158. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/ribbon-ledger-lift.md +384 -0
  159. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/segmented-meter-clarity.md +388 -0
  160. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/split-rail-precision.md +341 -0
  161. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/templates/design-themes/status-framed-media-grid.md +361 -0
  162. package/yida-skills/skills/yida-design/workflow/output-design.md +375 -117
  163. package/yida-skills/skills/yida-design/workflow/output-prd.md +185 -0
  164. package/yida-skills/skills/yida-design/workflow/step-1-read-brief.md +1 -1
  165. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +29 -33
  166. package/yida-skills/skills/yida-design/workflow/step-4-wireframe-interaction.md +1 -3
  167. package/yida-skills/skills/yida-design/workflow/step-5-visual-states.md +106 -22
  168. package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +22 -15
  169. package/yida-skills/skills/yida-form-permission/SKILL.md +0 -6
  170. package/yida-skills/skills/yida-image-assets/SKILL.md +50 -73
  171. package/yida-skills/skills/yida-image-assets/references/manifest-contract.md +52 -82
  172. package/yida-skills/skills/yida-image-assets/references/source-policy.md +15 -14
  173. package/yida-skills/skills/yida-integration/SKILL.md +0 -1
  174. package/yida-skills/skills/yida-login/SKILL.md +0 -2
  175. package/yida-skills/skills/yida-nav-group/SKILL.md +2 -4
  176. package/yida-skills/skills/yida-nav-shell/SKILL.md +12 -36
  177. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +136 -79
  178. package/yida-skills/skills/yida-page-config/SKILL.md +4 -13
  179. package/yida-skills/skills/yida-prd/SKILL.md +3 -5
  180. package/yida-skills/skills/yida-prd/references/app/blueprint.md +4 -4
  181. package/yida-skills/skills/yida-prd/references/app/navigation-patterns.md +3 -6
  182. package/yida-skills/skills/yida-prd/references/app/role-journey.md +3 -5
  183. package/yida-skills/skills/yida-prd/references/plan-content.md +0 -4
  184. package/yida-skills/skills/yida-prd/workflow/output-prd.md +11 -18
  185. package/yida-skills/skills/yida-prd/workflow/plan-business.md +4 -4
  186. package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +8 -11
  187. package/yida-skills/skills/yida-publish-page/SKILL.md +1 -9
  188. package/yida-skills/skills/yida-requirement-analysis/SKILL.md +39 -10
  189. package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +71 -40
  190. package/yida-skills/skills-index.json +16 -36
  191. package/lib/app/application-entry-urls.js +0 -31
  192. package/lib/app/application-style.js +0 -69
  193. package/lib/app/canvas-icon-exports.json +0 -6160
  194. package/lib/app/canvas-icon-guard.js +0 -87
  195. package/lib/app/canvas-navigation-guard.js +0 -84
  196. package/lib/app/canvas-path-guard.js +0 -78
  197. package/lib/app/canvas-theme-guard.js +0 -184
  198. package/lib/app/form-data-response-guard.js +0 -57
  199. package/lib/asset/asset-execution.js +0 -79
  200. package/lib/core/css-structure.js +0 -37
  201. package/lib/design/check-design.js +0 -51
  202. package/lib/design/document.js +0 -458
  203. package/lib/design/icon-contrast.js +0 -85
  204. package/lib/design/page-content.js +0 -11
  205. package/lib/design-plan/artifact-updates.js +0 -117
  206. package/lib/design-plan/confirmation.js +0 -13
  207. package/lib/design-plan/entry-navigation.js +0 -97
  208. package/lib/design-plan/navigation-policy.js +0 -38
  209. package/lib/design-plan/rebase.js +0 -60
  210. package/lib/design-plan/themes.js +0 -101
  211. package/lib/design-plan/visual-policy.js +0 -42
  212. package/lib/samples/openyida-scaffold/canvas-admin-entry.jsx +0 -62
  213. package/lib/samples/openyida-scaffold/canvas-navigation.jsx +0 -56
  214. package/lib/samples/openyida-scaffold/canvas-view-state.jsx +0 -74
  215. package/yida-skills/skills/yida-app/references/entry-navigation.md +0 -193
  216. package/yida-skills/skills/yida-canvas-custom-page/references/view-state-recovery.md +0 -52
  217. package/yida-skills/skills/yida-canvas-data-binding/references/business-action-permissions.md +0 -31
  218. package/yida-skills/skills/yida-design/references/application-style-library.md +0 -93
  219. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +0 -150
  220. package/yida-skills/skills/yida-design/references/native-form-styles.md +0 -208
  221. package/yida-skills/skills/yida-design/references/navigation-decision.md +0 -53
  222. package/yida-skills/skills/yida-design/references/page-continuity.md +0 -42
  223. package/yida-skills/skills/yida-design/references/theme/application-style-recipes.css +0 -58
  224. package/yida-skills/skills/yida-design/references/theme-selection.md +0 -67
  225. package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +0 -302
  226. package/yida-skills/skills/yida-design/templates/application-styles.json +0 -398
  227. package/yida-skills/skills/yida-design/templates/design-themes/README.md +0 -73
  228. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +0 -748
  229. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +0 -274
  230. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/form-layout.json +0 -15
  231. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +0 -748
  232. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +0 -274
  233. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/form-layout.json +0 -14
  234. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +0 -748
  235. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +0 -274
  236. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/form-layout.json +0 -13
  237. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +0 -748
  238. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +0 -274
  239. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/form-layout.json +0 -14
  240. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +0 -748
  241. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +0 -274
  242. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/form-layout.json +0 -14
  243. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +0 -748
  244. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +0 -274
  245. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/form-layout.json +0 -14
  246. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +0 -748
  247. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +0 -274
  248. package/yida-skills/skills/yida-design/templates/design-themes/app-line/form-layout.json +0 -13
  249. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +0 -748
  250. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +0 -274
  251. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/form-layout.json +0 -14
  252. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +0 -754
  253. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +0 -279
  254. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/form-layout.json +0 -13
  255. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +0 -748
  256. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +0 -274
  257. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/form-layout.json +0 -13
  258. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +0 -748
  259. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +0 -274
  260. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/form-layout.json +0 -14
  261. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +0 -748
  262. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +0 -274
  263. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/form-layout.json +0 -14
  264. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +0 -758
  265. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +0 -281
  266. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/form-layout.json +0 -14
  267. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +0 -748
  268. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +0 -274
  269. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/form-layout.json +0 -14
  270. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +0 -748
  271. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +0 -274
  272. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/form-layout.json +0 -14
  273. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +0 -754
  274. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +0 -279
  275. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/form-layout.json +0 -14
  276. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +0 -752
  277. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +0 -278
  278. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/form-layout.json +0 -13
  279. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +0 -748
  280. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +0 -274
  281. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/form-layout.json +0 -14
  282. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +0 -118
  283. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +0 -690
  284. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/design.md +0 -382
  285. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +0 -13
  286. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +0 -691
  287. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/design.md +0 -380
  288. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +0 -13
  289. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +0 -696
  290. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/design.md +0 -378
  291. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +0 -13
  292. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +0 -689
  293. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +0 -238
  294. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/form-layout.json +0 -13
  295. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +0 -692
  296. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/design.md +0 -375
  297. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +0 -13
  298. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +0 -691
  299. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/design.md +0 -362
  300. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +0 -13
  301. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +0 -691
  302. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/design.md +0 -409
  303. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +0 -13
  304. package/yida-skills/skills/yida-design/templates/design-themes/index.json +0 -464
  305. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +0 -701
  306. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/design.md +0 -379
  307. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +0 -13
  308. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +0 -691
  309. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/design.md +0 -404
  310. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +0 -13
  311. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +0 -698
  312. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/design.md +0 -389
  313. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +0 -13
  314. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +0 -691
  315. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/design.md +0 -372
  316. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +0 -13
  317. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +0 -690
  318. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/design.md +0 -455
  319. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +0 -13
  320. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +0 -698
  321. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/design.md +0 -394
  322. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +0 -13
  323. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +0 -692
  324. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/design.md +0 -391
  325. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +0 -13
  326. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +0 -711
  327. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/design.md +0 -408
  328. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +0 -13
  329. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +0 -692
  330. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/design.md +0 -383
  331. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +0 -13
  332. package/yida-skills/skills/yida-design/templates/navigation-styles.json +0 -769
  333. package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +0 -79
  334. package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +0 -68
@@ -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
- const styleInputs = ['dividerType', 'dividerStyle', 'styleType', 'typeStyle']
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 + '.' + key,
253
- DIVIDER_TYPES.join(' | '),
254
- typeof value === 'string' ? value : describeActual(value),
255
- t('create_form.divider_type_invalid', String(value), DIVIDER_TYPES.join(', ')),
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 (['IfStatement', 'ConditionalExpression'].includes(parent.node?.type)) {
137
- const direction = mobileCondition(parent.node.test);
138
- if ((direction === 1 && nodeContains(parent.node.consequent, pathRef.node))
139
- || (direction === -1 && nodeContains(parent.node.alternate, pathRef.node))) {return true;}
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?.type === 'LogicalExpression' && nodeContains(parent.node.right, pathRef.node)) {
142
- const direction = mobileCondition(parent.node.left);
143
- if ((parent.node.operator === '&&' && direction === 1)
144
- || (parent.node.operator === '||' && direction === -1)) {return true;}
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.type === 'Identifier' && callee.name === 'useYidaFormOpen') {
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 t('publish.lint_form_open_container');
216
+ return '自定义页内打开表单提交/详情只能使用 FormOpenContainer:PC 端用 50vw 抽屉 iframe,移动端才整页或新页打开。按钮事件请调用 openForm({ type: "submission" | "detail", ... })。';
304
217
  }
305
218
 
306
219
  module.exports = {
@@ -24,7 +24,6 @@ const { throwCommandError } = require('../core/command-errors');
24
24
 
25
25
  // 常用配置字段白名单(人读摘要),--json 会输出完整对象
26
26
  const SUMMARY_FIELDS = [
27
- 'renderNav',
28
27
  'isRenderNav',
29
28
  'submissionRule',
30
29
  'defaultOrder',
@@ -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
- const { findCssStructureIssue } = require('../core/css-structure');
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: 'transparent' },
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: 'transparent' },
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
- function designMetadata(markdown) {
15
- const frontmatter = /^\uFEFF?---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(markdown);
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
- // Historical Fast files permitted bare HEX values. Versioned documents use
20
- // valid YAML; all consumers share the same narrow legacy compatibility path.
21
- return parseDesignDocument(markdown, { legacyTokenValues: true }).metadata;
22
- }
23
-
24
- // New Fast and Plan files share grouped tokens. Legacy flat files remain readable.
25
- function readDesignTokens(markdown) {
26
- return tokensFromMetadata(designMetadata(markdown));
27
- }
28
-
29
- function tokensFromMetadata(metadata) {
30
- const tokens = extractDesignTokens(metadata, { strict: false });
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(metadata) {
39
- const tokens = tokensFromMetadata(metadata);
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 metadata = designMetadata(markdown);
132
- const previousMetadata = previousMarkdown === markdown ? metadata : (previousMarkdown ? designMetadata(previousMarkdown) : null);
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 && tone === previousTone) {
63
+ if (!Object.keys(changed).length) {
64
+ validateThemeCssContent(template);
160
65
  extractThemeColor(template);
161
- return require('./application-style').applyApplicationStyle(template, metadata, tokens);
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
- let tail = template.slice(root.index + root[0].length).replace(declarations,
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
- // Platform navigation modes bind independently; the root shell remains the custom-page default.
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;
@@ -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