@ng-prism/core 22.5.0 → 22.7.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/README.md +13 -9
  2. package/dist/app/canvas/canvas-bg.styles.d.ts +1 -1
  3. package/dist/app/canvas/canvas-bg.styles.d.ts.map +1 -1
  4. package/dist/app/canvas/canvas-bg.styles.js +1 -1
  5. package/dist/app/canvas/canvas-overlay-tokens.d.ts +12 -0
  6. package/dist/app/canvas/canvas-overlay-tokens.d.ts.map +1 -0
  7. package/dist/app/canvas/canvas-overlay-tokens.js +52 -0
  8. package/dist/app/canvas/prism-canvas-bg-pill.component.js +2 -2
  9. package/dist/app/canvas/prism-canvas-pin-row.component.js +2 -2
  10. package/dist/app/canvas/prism-canvas-rulers.component.d.ts +2 -0
  11. package/dist/app/canvas/prism-canvas-rulers.component.d.ts.map +1 -1
  12. package/dist/app/canvas/prism-canvas-rulers.component.js +17 -12
  13. package/dist/app/canvas/prism-canvas-toolbar.component.d.ts +25 -3
  14. package/dist/app/canvas/prism-canvas-toolbar.component.d.ts.map +1 -1
  15. package/dist/app/canvas/prism-canvas-toolbar.component.js +154 -89
  16. package/dist/app/canvas/prism-template-popover.component.d.ts.map +1 -1
  17. package/dist/app/canvas/prism-template-popover.component.js +16 -7
  18. package/dist/app/canvas/state-chips.d.ts +50 -0
  19. package/dist/app/canvas/state-chips.d.ts.map +1 -0
  20. package/dist/app/canvas/state-chips.js +40 -0
  21. package/dist/app/component-head/head-metrics.d.ts +35 -19
  22. package/dist/app/component-head/head-metrics.d.ts.map +1 -1
  23. package/dist/app/component-head/head-metrics.js +57 -27
  24. package/dist/app/component-head/pipe-facts.d.ts +9 -0
  25. package/dist/app/component-head/pipe-facts.d.ts.map +1 -0
  26. package/dist/app/component-head/pipe-facts.js +15 -0
  27. package/dist/app/component-head/prism-component-head.component.d.ts +20 -22
  28. package/dist/app/component-head/prism-component-head.component.d.ts.map +1 -1
  29. package/dist/app/component-head/prism-component-head.component.js +85 -96
  30. package/dist/app/component-head/prism-head-gauge.component.d.ts +8 -12
  31. package/dist/app/component-head/prism-head-gauge.component.d.ts.map +1 -1
  32. package/dist/app/component-head/prism-head-gauge.component.js +51 -67
  33. package/dist/app/component-head/prism-head-info.component.d.ts +14 -2
  34. package/dist/app/component-head/prism-head-info.component.d.ts.map +1 -1
  35. package/dist/app/component-head/prism-head-info.component.js +84 -20
  36. package/dist/app/component-head/prism-stat.component.d.ts +4 -5
  37. package/dist/app/component-head/prism-stat.component.d.ts.map +1 -1
  38. package/dist/app/component-head/prism-stat.component.js +16 -12
  39. package/dist/app/component-head/service-facts.d.ts +8 -0
  40. package/dist/app/component-head/service-facts.d.ts.map +1 -0
  41. package/dist/app/component-head/service-facts.js +11 -0
  42. package/dist/app/controls/boolean-control.component.js +2 -2
  43. package/dist/app/controls/json-control.component.js +2 -2
  44. package/dist/app/controls/union-control.component.js +4 -3
  45. package/dist/app/directives/resize-value.d.ts +1 -1
  46. package/dist/app/directives/resize-value.js +1 -1
  47. package/dist/app/discovery-manifest.d.ts +2 -2
  48. package/dist/app/discovery-manifest.d.ts.map +1 -1
  49. package/dist/app/discovery-manifest.js +15 -3
  50. package/dist/app/header/header-brand.d.ts +25 -0
  51. package/dist/app/header/header-brand.d.ts.map +1 -0
  52. package/dist/app/header/header-brand.js +10 -0
  53. package/dist/app/header/prism-header.component.d.ts +2 -2
  54. package/dist/app/header/prism-header.component.d.ts.map +1 -1
  55. package/dist/app/header/prism-header.component.js +73 -57
  56. package/dist/app/icons/icon-registry.d.ts.map +1 -1
  57. package/dist/app/icons/icon-registry.js +4 -1
  58. package/dist/app/index.d.ts +12 -0
  59. package/dist/app/index.d.ts.map +1 -1
  60. package/dist/app/index.js +12 -1
  61. package/dist/app/layout-menu/prism-layout-menu.component.d.ts +3 -0
  62. package/dist/app/layout-menu/prism-layout-menu.component.d.ts.map +1 -1
  63. package/dist/app/layout-menu/prism-layout-menu.component.js +72 -58
  64. package/dist/app/overview/open-in-playground.d.ts +19 -0
  65. package/dist/app/overview/open-in-playground.d.ts.map +1 -0
  66. package/dist/app/overview/open-in-playground.js +25 -0
  67. package/dist/app/overview/overview-matrix.d.ts +85 -0
  68. package/dist/app/overview/overview-matrix.d.ts.map +1 -0
  69. package/dist/app/overview/overview-matrix.js +98 -0
  70. package/dist/app/overview/overview-visibility.d.ts +10 -2
  71. package/dist/app/overview/overview-visibility.d.ts.map +1 -1
  72. package/dist/app/overview/overview-visibility.js +14 -3
  73. package/dist/app/overview/prism-overview-cell.component.d.ts +27 -2
  74. package/dist/app/overview/prism-overview-cell.component.d.ts.map +1 -1
  75. package/dist/app/overview/prism-overview-cell.component.js +145 -28
  76. package/dist/app/overview/prism-overview-matrix.component.d.ts +29 -0
  77. package/dist/app/overview/prism-overview-matrix.component.d.ts.map +1 -0
  78. package/dist/app/overview/prism-overview-matrix.component.js +155 -0
  79. package/dist/app/overview/prism-overview.component.d.ts +4 -0
  80. package/dist/app/overview/prism-overview.component.d.ts.map +1 -1
  81. package/dist/app/overview/prism-overview.component.js +37 -14
  82. package/dist/app/page-renderer/prism-page-renderer.component.js +2 -2
  83. package/dist/app/panels/a11y/a11y-core.plugin.d.ts.map +1 -1
  84. package/dist/app/panels/a11y/a11y-core.plugin.js +0 -1
  85. package/dist/app/panels/a11y/a11y-header-badge.component.d.ts +1 -4
  86. package/dist/app/panels/a11y/a11y-header-badge.component.d.ts.map +1 -1
  87. package/dist/app/panels/a11y/a11y-header-badge.component.js +8 -19
  88. package/dist/app/panels/a11y/a11y-keyboard-overlay.component.js +2 -2
  89. package/dist/app/panels/a11y/a11y-overlay-host.component.d.ts +1 -0
  90. package/dist/app/panels/a11y/a11y-overlay-host.component.d.ts.map +1 -1
  91. package/dist/app/panels/a11y/a11y-overlay-host.component.js +4 -3
  92. package/dist/app/panels/a11y/a11y-panel.component.d.ts +4 -1
  93. package/dist/app/panels/a11y/a11y-panel.component.d.ts.map +1 -1
  94. package/dist/app/panels/a11y/a11y-panel.component.js +32 -54
  95. package/dist/app/panels/a11y/a11y-score.component.d.ts +8 -3
  96. package/dist/app/panels/a11y/a11y-score.component.d.ts.map +1 -1
  97. package/dist/app/panels/a11y/a11y-score.component.js +19 -35
  98. package/dist/app/panels/a11y/a11y-sr-overlay.component.js +2 -2
  99. package/dist/app/panels/a11y/a11y-sr.component.js +2 -2
  100. package/dist/app/panels/a11y/a11y-summary.d.ts.map +1 -1
  101. package/dist/app/panels/a11y/a11y-summary.js +8 -1
  102. package/dist/app/panels/a11y/a11y-tree.component.js +2 -2
  103. package/dist/app/panels/a11y/a11y-violations.component.d.ts +23 -2
  104. package/dist/app/panels/a11y/a11y-violations.component.d.ts.map +1 -1
  105. package/dist/app/panels/a11y/a11y-violations.component.js +104 -89
  106. package/dist/app/panels/a11y/severity.d.ts +9 -0
  107. package/dist/app/panels/a11y/severity.d.ts.map +1 -0
  108. package/dist/app/panels/a11y/severity.js +12 -0
  109. package/dist/app/panels/controls/controls-plugin.d.ts.map +1 -1
  110. package/dist/app/panels/controls/controls-plugin.js +1 -2
  111. package/dist/app/panels/controls/non-editable-input-types.d.ts +9 -1
  112. package/dist/app/panels/controls/non-editable-input-types.d.ts.map +1 -1
  113. package/dist/app/panels/controls/non-editable-input-types.js +18 -0
  114. package/dist/app/panels/controls/prism-controls-panel.component.d.ts +2 -1
  115. package/dist/app/panels/controls/prism-controls-panel.component.d.ts.map +1 -1
  116. package/dist/app/panels/controls/prism-controls-panel.component.js +77 -59
  117. package/dist/app/panels/events/events-plugin.d.ts.map +1 -1
  118. package/dist/app/panels/events/events-plugin.js +1 -2
  119. package/dist/app/panels/events/prism-events-panel.component.d.ts +2 -0
  120. package/dist/app/panels/events/prism-events-panel.component.d.ts.map +1 -1
  121. package/dist/app/panels/events/prism-events-panel.component.js +20 -7
  122. package/dist/app/panels/events/prism-json-node.utils.d.ts +6 -0
  123. package/dist/app/panels/events/prism-json-node.utils.d.ts.map +1 -1
  124. package/dist/app/panels/events/prism-json-node.utils.js +8 -0
  125. package/dist/app/panels/panel-host/addon-panels.d.ts +11 -0
  126. package/dist/app/panels/panel-host/addon-panels.d.ts.map +1 -0
  127. package/dist/app/panels/panel-host/addon-panels.js +12 -0
  128. package/dist/app/panels/panel-host/panel-badge.d.ts +22 -0
  129. package/dist/app/panels/panel-host/panel-badge.d.ts.map +1 -1
  130. package/dist/app/panels/panel-host/panel-badge.js +56 -11
  131. package/dist/app/panels/panel-host/prism-panel-host.component.d.ts +4 -1
  132. package/dist/app/panels/panel-host/prism-panel-host.component.d.ts.map +1 -1
  133. package/dist/app/panels/panel-host/prism-panel-host.component.js +36 -70
  134. package/dist/app/pseudo/pseudo-state-marker.d.ts +32 -10
  135. package/dist/app/pseudo/pseudo-state-marker.d.ts.map +1 -1
  136. package/dist/app/pseudo/pseudo-state-marker.js +83 -67
  137. package/dist/app/pseudo/pseudo-targets.d.ts +11 -0
  138. package/dist/app/pseudo/pseudo-targets.d.ts.map +1 -0
  139. package/dist/app/pseudo/pseudo-targets.js +46 -0
  140. package/dist/app/pseudo/state-fit.d.ts +28 -0
  141. package/dist/app/pseudo/state-fit.d.ts.map +1 -0
  142. package/dist/app/pseudo/state-fit.js +97 -0
  143. package/dist/app/renderer/composition.d.ts +20 -0
  144. package/dist/app/renderer/composition.d.ts.map +1 -0
  145. package/dist/app/renderer/composition.js +26 -0
  146. package/dist/app/renderer/input-bindings.d.ts +28 -0
  147. package/dist/app/renderer/input-bindings.d.ts.map +1 -0
  148. package/dist/app/renderer/input-bindings.js +42 -0
  149. package/dist/app/renderer/known-inputs.d.ts +8 -1
  150. package/dist/app/renderer/known-inputs.d.ts.map +1 -1
  151. package/dist/app/renderer/known-inputs.js +13 -5
  152. package/dist/app/renderer/prism-renderer.component.d.ts +18 -4
  153. package/dist/app/renderer/prism-renderer.component.d.ts.map +1 -1
  154. package/dist/app/renderer/prism-renderer.component.js +78 -44
  155. package/dist/app/renderer/projectable-content.d.ts +8 -1
  156. package/dist/app/renderer/projectable-content.d.ts.map +1 -1
  157. package/dist/app/renderer/projectable-content.js +40 -29
  158. package/dist/app/renderer/rendered-key.d.ts +20 -6
  159. package/dist/app/renderer/rendered-key.d.ts.map +1 -1
  160. package/dist/app/renderer/rendered-key.js +25 -8
  161. package/dist/app/renderer/snippet-generator.d.ts +14 -2
  162. package/dist/app/renderer/snippet-generator.d.ts.map +1 -1
  163. package/dist/app/renderer/snippet-generator.js +138 -81
  164. package/dist/app/services/navigation-item.d.ts +10 -0
  165. package/dist/app/services/navigation-item.d.ts.map +1 -0
  166. package/dist/app/services/navigation-item.js +20 -0
  167. package/dist/app/services/navigation-item.types.d.ts +8 -0
  168. package/dist/app/services/navigation-item.types.d.ts.map +1 -1
  169. package/dist/app/services/prism-layout.service.d.ts +12 -0
  170. package/dist/app/services/prism-layout.service.d.ts.map +1 -1
  171. package/dist/app/services/prism-layout.service.js +17 -7
  172. package/dist/app/services/prism-manifest.service.d.ts +4 -0
  173. package/dist/app/services/prism-manifest.service.d.ts.map +1 -1
  174. package/dist/app/services/prism-manifest.service.js +4 -0
  175. package/dist/app/services/prism-navigation.service.d.ts +12 -0
  176. package/dist/app/services/prism-navigation.service.d.ts.map +1 -1
  177. package/dist/app/services/prism-navigation.service.js +85 -19
  178. package/dist/app/services/prism-panel.service.d.ts +7 -3
  179. package/dist/app/services/prism-panel.service.d.ts.map +1 -1
  180. package/dist/app/services/prism-panel.service.js +13 -4
  181. package/dist/app/services/prism-pseudo-state.service.d.ts +59 -14
  182. package/dist/app/services/prism-pseudo-state.service.d.ts.map +1 -1
  183. package/dist/app/services/prism-pseudo-state.service.js +86 -29
  184. package/dist/app/services/prism-renderer.service.d.ts +23 -0
  185. package/dist/app/services/prism-renderer.service.d.ts.map +1 -1
  186. package/dist/app/services/prism-renderer.service.js +77 -8
  187. package/dist/app/services/prism-search.service.d.ts +4 -0
  188. package/dist/app/services/prism-search.service.d.ts.map +1 -1
  189. package/dist/app/services/prism-search.service.js +29 -6
  190. package/dist/app/services/prism-theme.service.d.ts +11 -3
  191. package/dist/app/services/prism-theme.service.d.ts.map +1 -1
  192. package/dist/app/services/prism-theme.service.js +27 -19
  193. package/dist/app/services/prism-url-state.service.d.ts.map +1 -1
  194. package/dist/app/services/prism-url-state.service.js +81 -12
  195. package/dist/app/shared/badge.types.d.ts +7 -0
  196. package/dist/app/shared/badge.types.d.ts.map +1 -0
  197. package/dist/app/shared/badge.types.js +9 -0
  198. package/dist/app/shared/brand-mark.d.ts +35 -0
  199. package/dist/app/shared/brand-mark.d.ts.map +1 -0
  200. package/dist/app/shared/brand-mark.js +52 -0
  201. package/dist/app/shared/metric-bar.d.ts +6 -0
  202. package/dist/app/shared/metric-bar.d.ts.map +1 -0
  203. package/dist/app/shared/metric-bar.js +7 -0
  204. package/dist/app/shared/prism-badge.component.d.ts +21 -0
  205. package/dist/app/shared/prism-badge.component.d.ts.map +1 -0
  206. package/dist/app/shared/prism-badge.component.js +68 -0
  207. package/dist/app/shared/prism-button.component.d.ts +12 -0
  208. package/dist/app/shared/prism-button.component.d.ts.map +1 -0
  209. package/dist/app/shared/prism-button.component.js +28 -0
  210. package/dist/app/shared/prism-icon-button.component.d.ts +17 -0
  211. package/dist/app/shared/prism-icon-button.component.d.ts.map +1 -0
  212. package/dist/app/shared/prism-icon-button.component.js +37 -0
  213. package/dist/app/shared/prism-list-row.component.d.ts +17 -0
  214. package/dist/app/shared/prism-list-row.component.d.ts.map +1 -0
  215. package/dist/app/shared/prism-list-row.component.js +57 -0
  216. package/dist/app/shared/prism-logo.component.d.ts +24 -0
  217. package/dist/app/shared/prism-logo.component.d.ts.map +1 -0
  218. package/dist/app/shared/prism-logo.component.js +77 -0
  219. package/dist/app/shared/prism-metric-badge.component.d.ts +9 -4
  220. package/dist/app/shared/prism-metric-badge.component.d.ts.map +1 -1
  221. package/dist/app/shared/prism-metric-badge.component.js +33 -12
  222. package/dist/app/shared/prism-metric-card.component.d.ts +30 -0
  223. package/dist/app/shared/prism-metric-card.component.d.ts.map +1 -0
  224. package/dist/app/shared/prism-metric-card.component.js +111 -0
  225. package/dist/app/shared/prism-panel-toolbar.component.d.ts +13 -0
  226. package/dist/app/shared/prism-panel-toolbar.component.d.ts.map +1 -0
  227. package/dist/app/shared/prism-panel-toolbar.component.js +28 -0
  228. package/dist/app/shared/prism-segmented.component.d.ts +25 -0
  229. package/dist/app/shared/prism-segmented.component.d.ts.map +1 -0
  230. package/dist/app/shared/prism-segmented.component.js +77 -0
  231. package/dist/app/shared/prism-tabs.component.d.ts +44 -0
  232. package/dist/app/shared/prism-tabs.component.d.ts.map +1 -0
  233. package/dist/app/shared/prism-tabs.component.js +134 -0
  234. package/dist/app/shared/roving-focus.d.ts +13 -0
  235. package/dist/app/shared/roving-focus.d.ts.map +1 -0
  236. package/dist/app/shared/roving-focus.js +34 -0
  237. package/dist/app/shell/prism-shell.component.d.ts +13 -0
  238. package/dist/app/shell/prism-shell.component.d.ts.map +1 -1
  239. package/dist/app/shell/prism-shell.component.js +57 -28
  240. package/dist/app/shell/should-select-first.d.ts +17 -0
  241. package/dist/app/shell/should-select-first.d.ts.map +1 -0
  242. package/dist/app/shell/should-select-first.js +13 -0
  243. package/dist/app/sidebar/navigation-decorations.d.ts +23 -1
  244. package/dist/app/sidebar/navigation-decorations.d.ts.map +1 -1
  245. package/dist/app/sidebar/navigation-decorations.js +33 -2
  246. package/dist/app/sidebar/prism-sidebar.component.d.ts +5 -15
  247. package/dist/app/sidebar/prism-sidebar.component.d.ts.map +1 -1
  248. package/dist/app/sidebar/prism-sidebar.component.js +89 -77
  249. package/dist/app/theme/deprecated-tokens.d.ts +15 -0
  250. package/dist/app/theme/deprecated-tokens.d.ts.map +1 -0
  251. package/dist/app/theme/deprecated-tokens.js +22 -0
  252. package/dist/app/theme/favicon.d.ts +3 -0
  253. package/dist/app/theme/favicon.d.ts.map +1 -0
  254. package/dist/app/theme/favicon.js +3 -0
  255. package/dist/app/theme/prism-default-theme.d.ts.map +1 -1
  256. package/dist/app/theme/prism-default-theme.js +122 -66
  257. package/dist/app/theme/resolve-theme-tokens.d.ts +29 -0
  258. package/dist/app/theme/resolve-theme-tokens.d.ts.map +1 -0
  259. package/dist/app/theme/resolve-theme-tokens.js +43 -0
  260. package/dist/app/variant-ribbon/prism-variant-ribbon.component.d.ts +4 -7
  261. package/dist/app/variant-ribbon/prism-variant-ribbon.component.d.ts.map +1 -1
  262. package/dist/app/variant-ribbon/prism-variant-ribbon.component.js +31 -69
  263. package/dist/app/view-tab-bar/next-view-id.d.ts +7 -1
  264. package/dist/app/view-tab-bar/next-view-id.d.ts.map +1 -1
  265. package/dist/app/view-tab-bar/next-view-id.js +9 -1
  266. package/dist/app/view-tab-bar/panel-inputs.d.ts +28 -0
  267. package/dist/app/view-tab-bar/panel-inputs.d.ts.map +1 -0
  268. package/dist/app/view-tab-bar/panel-inputs.js +41 -0
  269. package/dist/app/view-tab-bar/prism-view-panel-host.component.d.ts +2 -3
  270. package/dist/app/view-tab-bar/prism-view-panel-host.component.d.ts.map +1 -1
  271. package/dist/app/view-tab-bar/prism-view-panel-host.component.js +9 -9
  272. package/dist/app/view-tab-bar/prism-view-tab-bar.component.d.ts +6 -0
  273. package/dist/app/view-tab-bar/prism-view-tab-bar.component.d.ts.map +1 -1
  274. package/dist/app/view-tab-bar/prism-view-tab-bar.component.js +22 -29
  275. package/dist/builder/config-loader/deprecated-options.d.ts +9 -0
  276. package/dist/builder/config-loader/deprecated-options.d.ts.map +1 -0
  277. package/dist/builder/config-loader/deprecated-options.js +34 -0
  278. package/dist/builder/manifest/composition-wrapper.generator.d.ts +14 -0
  279. package/dist/builder/manifest/composition-wrapper.generator.d.ts.map +1 -0
  280. package/dist/builder/manifest/composition-wrapper.generator.js +66 -0
  281. package/dist/builder/manifest/host-parser.d.ts +2 -0
  282. package/dist/builder/manifest/host-parser.d.ts.map +1 -1
  283. package/dist/builder/manifest/host-parser.js +9 -4
  284. package/dist/builder/manifest/manifest-imports.d.ts +34 -0
  285. package/dist/builder/manifest/manifest-imports.d.ts.map +1 -0
  286. package/dist/builder/manifest/manifest-imports.js +91 -0
  287. package/dist/builder/manifest/runtime-manifest.generator.d.ts +13 -0
  288. package/dist/builder/manifest/runtime-manifest.generator.d.ts.map +1 -1
  289. package/dist/builder/manifest/runtime-manifest.generator.js +137 -65
  290. package/dist/builder/manifest/selector-element.d.ts +16 -0
  291. package/dist/builder/manifest/selector-element.d.ts.map +1 -0
  292. package/dist/builder/manifest/selector-element.js +46 -0
  293. package/dist/builder/manifest/template-literal.d.ts +3 -0
  294. package/dist/builder/manifest/template-literal.d.ts.map +1 -0
  295. package/dist/builder/manifest/template-literal.js +4 -0
  296. package/dist/builder/plugin-runner/plugin-runner.d.ts.map +1 -1
  297. package/dist/builder/plugin-runner/plugin-runner.js +29 -26
  298. package/dist/builder/scanner/api/angular-decorators.d.ts +84 -0
  299. package/dist/builder/scanner/api/angular-decorators.d.ts.map +1 -0
  300. package/dist/builder/scanner/api/angular-decorators.js +157 -0
  301. package/dist/builder/scanner/api/component-api.extractor.d.ts +13 -0
  302. package/dist/builder/scanner/api/component-api.extractor.d.ts.map +1 -0
  303. package/dist/builder/scanner/api/component-api.extractor.js +104 -0
  304. package/dist/builder/scanner/api/doc-tags.d.ts +13 -0
  305. package/dist/builder/scanner/api/doc-tags.d.ts.map +1 -0
  306. package/dist/builder/scanner/api/doc-tags.js +101 -0
  307. package/dist/builder/scanner/api/export-index.d.ts +18 -0
  308. package/dist/builder/scanner/api/export-index.d.ts.map +1 -0
  309. package/dist/builder/scanner/api/export-index.js +22 -0
  310. package/dist/builder/scanner/api/member.extractor.d.ts +90 -0
  311. package/dist/builder/scanner/api/member.extractor.d.ts.map +1 -0
  312. package/dist/builder/scanner/api/member.extractor.js +270 -0
  313. package/dist/builder/scanner/api/pipe-api.extractor.d.ts +12 -0
  314. package/dist/builder/scanner/api/pipe-api.extractor.d.ts.map +1 -0
  315. package/dist/builder/scanner/api/pipe-api.extractor.js +52 -0
  316. package/dist/builder/scanner/api/service-api.extractor.d.ts +14 -0
  317. package/dist/builder/scanner/api/service-api.extractor.d.ts.map +1 -0
  318. package/dist/builder/scanner/api/service-api.extractor.js +119 -0
  319. package/dist/builder/scanner/api/setup.reader.d.ts +26 -0
  320. package/dist/builder/scanner/api/setup.reader.d.ts.map +1 -0
  321. package/dist/builder/scanner/api/setup.reader.js +89 -0
  322. package/dist/builder/scanner/api/type-collector.d.ts +24 -0
  323. package/dist/builder/scanner/api/type-collector.d.ts.map +1 -0
  324. package/dist/builder/scanner/api/type-collector.js +211 -0
  325. package/dist/builder/scanner/ast-utils.d.ts +8 -0
  326. package/dist/builder/scanner/ast-utils.d.ts.map +1 -1
  327. package/dist/builder/scanner/ast-utils.js +37 -1
  328. package/dist/builder/scanner/class-hierarchy.d.ts +5 -3
  329. package/dist/builder/scanner/class-hierarchy.d.ts.map +1 -1
  330. package/dist/builder/scanner/class-hierarchy.js +12 -6
  331. package/dist/builder/scanner/component.scanner.d.ts +60 -6
  332. package/dist/builder/scanner/component.scanner.d.ts.map +1 -1
  333. package/dist/builder/scanner/component.scanner.js +229 -58
  334. package/dist/builder/scanner/composition/compose-template.d.ts +36 -0
  335. package/dist/builder/scanner/composition/compose-template.d.ts.map +1 -0
  336. package/dist/builder/scanner/composition/compose-template.js +187 -0
  337. package/dist/builder/scanner/composition/declarables.d.ts +54 -0
  338. package/dist/builder/scanner/composition/declarables.d.ts.map +1 -0
  339. package/dist/builder/scanner/composition/declarables.js +182 -0
  340. package/dist/builder/scanner/composition/match-declarables.d.ts +43 -0
  341. package/dist/builder/scanner/composition/match-declarables.d.ts.map +1 -0
  342. package/dist/builder/scanner/composition/match-declarables.js +131 -0
  343. package/dist/builder/scanner/composition/read-composition.d.ts +77 -0
  344. package/dist/builder/scanner/composition/read-composition.d.ts.map +1 -0
  345. package/dist/builder/scanner/composition/read-composition.js +302 -0
  346. package/dist/builder/scanner/composition/template-elements.d.ts +12 -0
  347. package/dist/builder/scanner/composition/template-elements.d.ts.map +1 -0
  348. package/dist/builder/scanner/composition/template-elements.js +41 -0
  349. package/dist/builder/scanner/entry-point-discovery.d.ts +5 -0
  350. package/dist/builder/scanner/entry-point-discovery.d.ts.map +1 -1
  351. package/dist/builder/scanner/entry-point-discovery.js +14 -0
  352. package/dist/builder/scanner/entry-point.scanner.d.ts +3 -1
  353. package/dist/builder/scanner/entry-point.scanner.d.ts.map +1 -1
  354. package/dist/builder/scanner/entry-point.scanner.js +7 -6
  355. package/dist/builder/scanner/index.d.ts +4 -0
  356. package/dist/builder/scanner/index.d.ts.map +1 -1
  357. package/dist/builder/scanner/index.js +2 -0
  358. package/dist/builder/scanner/input.extractor.d.ts +31 -2
  359. package/dist/builder/scanner/input.extractor.d.ts.map +1 -1
  360. package/dist/builder/scanner/input.extractor.js +73 -17
  361. package/dist/builder/scanner/pipe.scanner.d.ts +29 -0
  362. package/dist/builder/scanner/pipe.scanner.d.ts.map +1 -0
  363. package/dist/builder/scanner/pipe.scanner.js +65 -0
  364. package/dist/builder/scanner/pseudo-states.d.ts +1 -0
  365. package/dist/builder/scanner/pseudo-states.d.ts.map +1 -1
  366. package/dist/builder/scanner/pseudo-states.js +1 -1
  367. package/dist/builder/scanner/scanner.d.ts +27 -3
  368. package/dist/builder/scanner/scanner.d.ts.map +1 -1
  369. package/dist/builder/scanner/scanner.js +68 -24
  370. package/dist/builder/scanner/service/angular-decorators.d.ts +80 -0
  371. package/dist/builder/scanner/service/angular-decorators.d.ts.map +1 -0
  372. package/dist/builder/scanner/service/angular-decorators.js +154 -0
  373. package/dist/builder/scanner/service/doc-tags.d.ts +13 -0
  374. package/dist/builder/scanner/service/doc-tags.d.ts.map +1 -0
  375. package/dist/builder/scanner/service/doc-tags.js +97 -0
  376. package/dist/builder/scanner/service/export-index.d.ts +18 -0
  377. package/dist/builder/scanner/service/export-index.d.ts.map +1 -0
  378. package/dist/builder/scanner/service/export-index.js +22 -0
  379. package/dist/builder/scanner/service/member.extractor.d.ts +65 -0
  380. package/dist/builder/scanner/service/member.extractor.d.ts.map +1 -0
  381. package/dist/builder/scanner/service/member.extractor.js +216 -0
  382. package/dist/builder/scanner/service/pipe-api.extractor.d.ts +12 -0
  383. package/dist/builder/scanner/service/pipe-api.extractor.d.ts.map +1 -0
  384. package/dist/builder/scanner/service/pipe-api.extractor.js +72 -0
  385. package/dist/builder/scanner/service/service-api.extractor.d.ts +14 -0
  386. package/dist/builder/scanner/service/service-api.extractor.d.ts.map +1 -0
  387. package/dist/builder/scanner/service/service-api.extractor.js +119 -0
  388. package/dist/builder/scanner/service/setup.reader.d.ts +26 -0
  389. package/dist/builder/scanner/service/setup.reader.d.ts.map +1 -0
  390. package/dist/builder/scanner/service/setup.reader.js +89 -0
  391. package/dist/builder/scanner/service/type-collector.d.ts +23 -0
  392. package/dist/builder/scanner/service/type-collector.d.ts.map +1 -0
  393. package/dist/builder/scanner/service/type-collector.js +210 -0
  394. package/dist/builder/scanner/service.scanner.d.ts +26 -0
  395. package/dist/builder/scanner/service.scanner.d.ts.map +1 -0
  396. package/dist/builder/scanner/service.scanner.js +61 -0
  397. package/dist/builder/scanner/showcase-diagnostics.d.ts +60 -1
  398. package/dist/builder/scanner/showcase-diagnostics.d.ts.map +1 -1
  399. package/dist/builder/scanner/showcase-diagnostics.js +123 -10
  400. package/dist/builder/scanner/showcase-states.d.ts +17 -0
  401. package/dist/builder/scanner/showcase-states.d.ts.map +1 -0
  402. package/dist/builder/scanner/showcase-states.js +58 -0
  403. package/dist/builder/scanner/source-file-cache.d.ts +26 -0
  404. package/dist/builder/scanner/source-file-cache.d.ts.map +1 -0
  405. package/dist/builder/scanner/source-file-cache.js +60 -0
  406. package/dist/builder/shared/prism-pipeline.d.ts +6 -0
  407. package/dist/builder/shared/prism-pipeline.d.ts.map +1 -1
  408. package/dist/builder/shared/prism-pipeline.js +71 -18
  409. package/dist/decorator/index.d.ts +1 -1
  410. package/dist/decorator/index.d.ts.map +1 -1
  411. package/dist/decorator/showcase.types.d.ts +102 -9
  412. package/dist/decorator/showcase.types.d.ts.map +1 -1
  413. package/dist/plugin/index.d.ts +6 -1
  414. package/dist/plugin/index.d.ts.map +1 -1
  415. package/dist/plugin/index.js +4 -0
  416. package/dist/plugin/pipe.types.d.ts +36 -0
  417. package/dist/plugin/pipe.types.d.ts.map +1 -0
  418. package/dist/plugin/pipe.types.js +1 -0
  419. package/dist/plugin/plugin.types.d.ts +184 -8
  420. package/dist/plugin/plugin.types.d.ts.map +1 -1
  421. package/dist/plugin/service.types.d.ts +124 -0
  422. package/dist/plugin/service.types.d.ts.map +1 -0
  423. package/dist/plugin/service.types.js +1 -0
  424. package/dist/plugin/status.d.ts +27 -0
  425. package/dist/plugin/status.d.ts.map +1 -0
  426. package/dist/plugin/status.js +26 -0
  427. package/dist/shared/composition.d.ts +30 -0
  428. package/dist/shared/composition.d.ts.map +1 -0
  429. package/dist/shared/composition.js +29 -0
  430. package/dist/shared/pseudo-state.type.d.ts +2 -1
  431. package/dist/shared/pseudo-state.type.d.ts.map +1 -1
  432. package/dist/shared/void-elements.d.ts +3 -0
  433. package/dist/shared/void-elements.d.ts.map +1 -0
  434. package/dist/shared/void-elements.js +2 -0
  435. package/package.json +1 -1
  436. package/src/builder/build/schema.json +6 -6
  437. package/src/builder/serve/schema.json +6 -6
@@ -1,11 +1,17 @@
1
1
  import ts from 'typescript';
2
2
  import { CANVAS_BGS } from '../../shared/canvas-bg.type.js';
3
3
  import { CANVAS_LAYOUTS } from '../../shared/canvas-layout.type.js';
4
- import { evaluateExpression, evaluateStatic, findDecorator, getDecoratorArgument, UNEVALUABLE } from './ast-utils.js';
4
+ import { isImportableName } from '../manifest/manifest-imports.js';
5
+ import { classifyShowcaseClass } from './api/angular-decorators.js';
6
+ import { extractComponentApi } from './api/component-api.extractor.js';
7
+ import { findSetupProperty } from './api/setup.reader.js';
8
+ import { evaluateStatic, findDecorator, getDecoratorArgument, readDecoratorField, UNEVALUABLE } from './ast-utils.js';
5
9
  import { getClassHierarchy } from './class-hierarchy.js';
10
+ import { readComposition } from './composition/read-composition.js';
6
11
  import { extractInputs, extractOutputs } from './input.extractor.js';
7
- import { readPseudoStates } from './pseudo-states.js';
8
- import { describeDeprecatedProviders, describeUnevaluable, describeUnreadableBase } from './showcase-diagnostics.js';
12
+ import { describeValue, readPseudoStates } from './pseudo-states.js';
13
+ import { describeDeprecatedProviders, describeLegacyPipeComponent, describeLegacyServiceComponent, describeSetupOnComponent, describeSetupOnLegacyComponent, describeShowcaseIssue, describeUnevaluable, describeUnreadableApi, describeUnreadableBase } from './showcase-diagnostics.js';
14
+ import { readShowcaseStates } from './showcase-states.js';
9
15
  const COMPONENT_STATUSES = ['stable', 'beta', 'wip', 'deprecated'];
10
16
  function isComponentStatus(value) {
11
17
  return typeof value === 'string' && COMPONENT_STATUSES.includes(value);
@@ -38,47 +44,96 @@ function isCanvasBg(value) {
38
44
  function isCanvasLayout(value) {
39
45
  return typeof value === 'string' && CANVAS_LAYOUTS.includes(value);
40
46
  }
47
+ function isShowcaseImport(value) {
48
+ const { name, from } = typeof value === 'object' && value !== null ? value : {};
49
+ return typeof name === 'string' && name !== '' && typeof from === 'string' && from !== '';
50
+ }
51
+ /**
52
+ * What is wrong with an import the generated manifest would write as `import { name } from 'from'`, `undefined` when
53
+ * nothing is: anything but an identifier there, `default` or a module path, is a syntax error in the whole manifest.
54
+ */
55
+ function importProblem(entry) {
56
+ return isImportableName(entry.name) ? undefined : `expected the name a class is exported under, got ${JSON.stringify(entry.name)}; it was dropped`;
57
+ }
58
+ function isHostTemplate(value) {
59
+ return typeof value === 'object' && value !== null && typeof value['template'] === 'string';
60
+ }
61
+ /** The position an element has in the source, given the positions before it that the evaluator dropped: the evaluated list is shorter by those. */
62
+ function sourceIndex(index, dropped) {
63
+ return [...dropped].sort((a, b) => a - b).reduce((position, gap) => (gap <= position ? position + 1 : position), index);
64
+ }
41
65
  /**
42
- * Scan exported symbols for Angular components annotated with @Showcase.
66
+ * The two ways a scan warns, each printing a message once however often it is
67
+ * raised: `report` for a dropped value, which is also collected in
68
+ * `diagnostics` and fails the build under `strictShowcase`, and `notify` for
69
+ * anything else worth saying.
70
+ */
71
+ export function createReporters(diagnostics, notices) {
72
+ return {
73
+ report: (message) => {
74
+ if (diagnostics.includes(message))
75
+ return;
76
+ diagnostics.push(message);
77
+ console.warn(`⚠ ng-prism: ${message}`);
78
+ },
79
+ notify: (message) => {
80
+ if (notices.has(message))
81
+ return;
82
+ notices.add(message);
83
+ console.warn(`⚠ ng-prism: ${message}`);
84
+ }
85
+ };
86
+ }
87
+ /**
88
+ * Read the Angular components among the showcased classes of an entry point.
89
+ * A class with `@Injectable` or `@Service` is a service and one with `@Pipe` a
90
+ * pipe, each left to its own scan, unless it declares fields only a component
91
+ * can use.
43
92
  *
44
93
  * Every @Showcase value the scan has to drop is printed and collected in
45
- * `diagnostics`, once: sharing the array across entry points keeps a
46
- * component exported from several of them from repeating its warnings.
47
- * `notices` does the same for warnings about what a component inherits,
48
- * which are not diagnostics.
94
+ * `diagnostics`, once. `notices` does the same for warnings about what a
95
+ * component inherits, which are not diagnostics.
49
96
  */
50
- export function scanComponents(exports, checker, diagnostics = [], notices = new Set()) {
97
+ export function scanComponents(showcased, checker, options = {}) {
98
+ const { diagnostics = [], notices = new Set(), exportIndex = new Map(), api: readApi = true, composition: compositionContext } = options;
51
99
  const components = [];
52
- const report = (message) => {
53
- if (diagnostics.includes(message))
54
- return;
55
- diagnostics.push(message);
56
- console.warn(`⚠ ng-prism: ${message}`);
57
- };
58
- const notify = (message) => {
59
- if (notices.has(message))
60
- return;
61
- notices.add(message);
62
- console.warn(`⚠ ng-prism: ${message}`);
63
- };
64
- for (const sym of exports) {
65
- const resolved = sym.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
66
- const classDecl = resolved.declarations?.find(ts.isClassDeclaration);
67
- if (!classDecl)
68
- continue;
69
- // Perf: cheap pre-filter that skips the full decorator walk for files that don't
70
- // mention Showcase at all. False positives (string-literal containing "@Showcase")
71
- // just lose the optimization for that file; correctness is unaffected.
72
- if (!classDecl.getSourceFile().text.includes('@Showcase'))
73
- continue;
74
- const showcaseDecorator = findDecorator(classDecl, 'Showcase');
75
- if (!showcaseDecorator)
100
+ const { report, notify } = createReporters(diagnostics, notices);
101
+ for (const { classDecl, decorator: showcaseDecorator, argument: showcaseArg, kind: classKind } of showcased) {
102
+ if (classKind.kind === 'service' || classKind.kind === 'pipe')
76
103
  continue;
77
104
  const className = classDecl.name?.text ?? 'Anonymous';
78
- const showcaseConfig = extractShowcaseConfig(showcaseDecorator, className, report, checker);
79
- if (!showcaseConfig)
105
+ const read = readShowcaseConfig(showcaseDecorator, className, report, checker);
106
+ if (!read || !showcaseArg)
80
107
  continue;
108
+ const { config: showcaseConfig, sources } = read;
109
+ // Not a diagnostic: the component still works, and strictShowcase must not fail the build over a notice about 23.0.0.
110
+ if (classKind.kind === 'legacy-component') {
111
+ notify(classKind.source === 'pipe'
112
+ ? describeLegacyPipeComponent(className, classKind.fields, classKind.standalone !== false)
113
+ : describeLegacyServiceComponent(className, classKind.fields));
114
+ }
115
+ const setup = findSetupProperty(showcaseArg);
116
+ if (setup)
117
+ report(classKind.kind === 'legacy-component' ? describeSetupOnLegacyComponent(className, setup, classKind.fields) : describeSetupOnComponent(className, setup));
81
118
  const componentMeta = extractComponentMeta(classDecl, checker);
119
+ // A string or an object host puts a directive on an element. A component has ignored it so far and keeps doing so, so that what a library renders stays as it is.
120
+ // Not a diagnostic: nothing is lost, and strictShowcase must not start failing a build over it.
121
+ if (!componentMeta.isDirective && showcaseConfig.host !== undefined && !isHostTemplate(showcaseConfig.host)) {
122
+ notify(describeShowcaseIssue(className, showcaseArg, ['host'], 'a string or object host has no effect on a component; use host: { template } to render it inside other markup. It was dropped.'));
123
+ delete showcaseConfig.host;
124
+ }
125
+ const host = showcaseConfig.host;
126
+ // The manifest imports the class of a directive's object host, as an import of the showcase.
127
+ if (componentMeta.isDirective && typeof host === 'object' && host !== null && !isHostTemplate(host) && host.import !== undefined) {
128
+ const hostImport = host.import;
129
+ const problem = isShowcaseImport(hostImport)
130
+ ? importProblem(hostImport)
131
+ : `expected { name, from } with a non-empty string each, got ${describeValue(hostImport)}; it was dropped`;
132
+ if (problem) {
133
+ report(describeShowcaseIssue(className, showcaseArg, ['host', 'import'], problem));
134
+ delete host.import;
135
+ }
136
+ }
82
137
  const hierarchy = getClassHierarchy(classDecl, checker);
83
138
  const inputs = extractInputs(classDecl, checker, hierarchy);
84
139
  const outputs = extractOutputs(classDecl, checker, hierarchy);
@@ -93,6 +148,28 @@ export function scanComponents(exports, checker, diagnostics = [], notices = new
93
148
  for (const base of hierarchy.unreadable) {
94
149
  notify(describeUnreadableBase(className, base));
95
150
  }
151
+ // The API only feeds the API page, which has a fallback for a component without one: a class the extractor
152
+ // cannot read must not take the scan down. A notice, not a diagnostic, so strictShowcase does not fail over it.
153
+ let api;
154
+ try {
155
+ if (readApi)
156
+ api = extractComponentApi(classDecl, inputs, outputs, hierarchy, checker, exportIndex);
157
+ }
158
+ catch (error) {
159
+ notify(describeUnreadableApi(className, error, 'component'));
160
+ }
161
+ const composition = compositionContext &&
162
+ readComposition({
163
+ className,
164
+ filePath,
165
+ selector: componentMeta.selector,
166
+ isDirective: componentMeta.isDirective,
167
+ standalone: componentMeta.standalone,
168
+ inputs,
169
+ config: showcaseConfig,
170
+ configNode: showcaseArg,
171
+ sources
172
+ }, compositionContext, { report, notify });
96
173
  components.push({
97
174
  className,
98
175
  filePath,
@@ -103,11 +180,38 @@ export function scanComponents(exports, checker, diagnostics = [], notices = new
103
180
  // Plugins look a base class up by name, so an anonymous one is of no use to them.
104
181
  baseClasses: hierarchy.classes
105
182
  .slice(1)
106
- .flatMap(({ classDecl: base }) => (base.name ? [{ className: base.name.text, filePath: base.getSourceFile().fileName }] : []))
183
+ .flatMap(({ classDecl: base }) => (base.name ? [{ className: base.name.text, filePath: base.getSourceFile().fileName }] : [])),
184
+ api,
185
+ ...(composition && { composition })
107
186
  });
108
187
  }
109
188
  return components;
110
189
  }
190
+ /**
191
+ * The classes with `@Showcase` among the exports of an entry point, each
192
+ * classified once: the component, the service and the pipe scan each keep
193
+ * the classes of their own kind.
194
+ */
195
+ export function findShowcasedClasses(exports, checker) {
196
+ return exports.flatMap((sym) => {
197
+ const showcased = findShowcasedClass(sym, checker);
198
+ return showcased ? [{ ...showcased, kind: classifyShowcaseClass(showcased.classDecl, showcased.argument, checker) }] : [];
199
+ });
200
+ }
201
+ /** The class an export resolves to, when it carries `@Showcase`. */
202
+ function findShowcasedClass(sym, checker) {
203
+ const symbol = sym.flags & ts.SymbolFlags.Alias ? checker.getAliasedSymbol(sym) : sym;
204
+ const classDecl = symbol.declarations?.find(ts.isClassDeclaration);
205
+ if (!classDecl)
206
+ return undefined;
207
+ // Perf: cheap pre-filter that skips the full decorator walk for files that don't
208
+ // mention Showcase at all. False positives (string-literal containing "@Showcase")
209
+ // just lose the optimization for that file; correctness is unaffected.
210
+ if (!classDecl.getSourceFile().text.includes('@Showcase'))
211
+ return undefined;
212
+ const decorator = findDecorator(classDecl, 'Showcase');
213
+ return decorator && { symbol, classDecl, decorator, argument: getDecoratorArgument(decorator) };
214
+ }
111
215
  function hasDecoratorInputs(classDecl) {
112
216
  for (const member of classDecl.members) {
113
217
  if (!ts.isPropertyDeclaration(member))
@@ -117,19 +221,41 @@ function hasDecoratorInputs(classDecl) {
117
221
  }
118
222
  return false;
119
223
  }
120
- function extractShowcaseConfig(decorator, className, report, checker) {
224
+ /**
225
+ * `setup` is read for services and pipes only, so a component's is never
226
+ * part of the config: the issue the evaluator raises for its function is
227
+ * swallowed here, and {@link scanComponents} says what is wrong with it instead.
228
+ */
229
+ export function extractShowcaseConfig(decorator, className, report, checker) {
230
+ return readShowcaseConfig(decorator, className, report, checker)?.config;
231
+ }
232
+ /** {@link extractShowcaseConfig}, and where the entries it kept are written. */
233
+ function readShowcaseConfig(decorator, className, report, checker) {
121
234
  const arg = getDecoratorArgument(decorator);
122
235
  if (!arg)
123
236
  return undefined;
124
237
  // Reported once for the whole field below, wherever it came from: the literal, a spread or a constant.
125
238
  let providers;
239
+ // A state the evaluator dropped whole leaves no element behind, so its position is noted to keep the later states where the source has them.
240
+ const unevaluableStates = new Set();
241
+ // The same for the elements of `imports` and `variants`, which are not put back but named by the position the source gives them.
242
+ const unevaluableElements = { imports: new Set(), variants: new Set() };
126
243
  const raw = evaluateStatic(arg, {
127
244
  checker,
128
245
  report: (issue) => {
246
+ if (issue.path[0] === 'setup')
247
+ return;
129
248
  if (issue.path[0] === 'providers') {
130
249
  providers ??= issue.node;
131
250
  return;
132
251
  }
252
+ if (issue.path[0] === 'states' && issue.path.length === 2 && typeof issue.path[1] === 'number')
253
+ unevaluableStates.add(issue.path[1]);
254
+ const [field, index] = issue.path;
255
+ // A spread that fails inside an element leaves the element behind, and one in the list leaves no telling how many.
256
+ const isElement = issue.path.length === 2 && !ts.isSpreadAssignment(issue.node) && !ts.isSpreadElement(issue.node);
257
+ if (isElement && (field === 'imports' || field === 'variants') && typeof index === 'number')
258
+ unevaluableElements[field].add(index);
133
259
  report(describeUnevaluable(className, arg, issue));
134
260
  }
135
261
  });
@@ -146,6 +272,7 @@ function extractShowcaseConfig(decorator, className, report, checker) {
146
272
  const config = {
147
273
  title: obj['title']
148
274
  };
275
+ const sources = { variants: [], imports: [] };
149
276
  if (obj['description'])
150
277
  config.description = obj['description'];
151
278
  if (obj['category'])
@@ -165,10 +292,27 @@ function extractShowcaseConfig(decorator, className, report, checker) {
165
292
  config.tags = obj['tags'];
166
293
  if (obj['meta'])
167
294
  config.meta = obj['meta'];
168
- if (obj['host'] !== undefined)
169
- config.host = obj['host'];
295
+ if (obj['host'] !== undefined) {
296
+ // An object with a `template` is meant as a host template, so one that is no string is not a host of another kind.
297
+ if (typeof obj['host'] === 'object' && obj['host'] !== null && 'template' in obj['host'] && !isHostTemplate(obj['host'])) {
298
+ report(describeShowcaseIssue(className, arg, ['host'], `expected { template: string }, got ${describeValue(obj['host'])}; it was dropped`));
299
+ }
300
+ else {
301
+ config.host = obj['host'];
302
+ }
303
+ }
170
304
  if (obj['renderPage'])
171
305
  config.renderPage = obj['renderPage'];
306
+ if (obj['states'] !== undefined) {
307
+ if (config.renderPage) {
308
+ report(`${className} declares states together with renderPage; a component page has no Overview to show them in. Skipping states.`);
309
+ }
310
+ else {
311
+ const states = readShowcaseStates(obj['states'], className, report, unevaluableStates);
312
+ if (states)
313
+ config.states = states;
314
+ }
315
+ }
172
316
  if (obj['status'] !== undefined) {
173
317
  if (isComponentStatus(obj['status'])) {
174
318
  config.status = obj['status'];
@@ -194,9 +338,17 @@ function extractShowcaseConfig(decorator, className, report, checker) {
194
338
  report(`${className} declares invalid canvasLayout "${String(obj['canvasLayout'])}", ` + `expected one of: ${CANVAS_LAYOUTS.join(', ')}. Skipping.`);
195
339
  }
196
340
  }
341
+ if (obj['imports'] !== undefined) {
342
+ const imports = readShowcaseImports(obj['imports'], className, arg, report, unevaluableElements.imports);
343
+ if (imports.length > 0) {
344
+ config.imports = imports.map(({ entry }) => entry);
345
+ sources.imports = imports.map(({ source }) => source);
346
+ }
347
+ }
197
348
  if (Array.isArray(obj['variants'])) {
198
- config.variants = obj['variants'].map((variant) => {
349
+ config.variants = obj['variants'].map((variant, index) => {
199
350
  const cleaned = { ...variant };
351
+ const reportVariant = (field, text) => report(describeShowcaseIssue(className, arg, ['variants', sourceIndex(index, unevaluableElements.variants), field], text));
200
352
  if (isCanvasBg(variant['bg'])) {
201
353
  warnDeprecatedBg(variant['bg'], `${className} variant "${String(variant['name'])}"`);
202
354
  }
@@ -218,10 +370,46 @@ function extractShowcaseConfig(decorator, className, report, checker) {
218
370
  else
219
371
  delete cleaned['pseudo'];
220
372
  }
373
+ if (variant['states'] !== undefined && variant['states'] !== false) {
374
+ report(`${className} variant "${String(variant['name'])}" declares invalid states ${describeValue(variant['states'])}, expected false. Skipping.`);
375
+ delete cleaned['states'];
376
+ }
377
+ if (variant['template'] !== undefined && typeof variant['template'] !== 'string') {
378
+ reportVariant('template', `expected a string, got ${describeValue(variant['template'])}; it was dropped`);
379
+ delete cleaned['template'];
380
+ }
381
+ if (cleaned['template'] !== undefined && variant['content'] !== undefined) {
382
+ reportVariant('content', 'set together with template; template wins and content was dropped');
383
+ delete cleaned['content'];
384
+ }
385
+ if (variant['host'] !== undefined && !isHostTemplate(variant['host'])) {
386
+ reportVariant('host', `expected { template: string }, got ${describeValue(variant['host'])}; it was dropped`);
387
+ delete cleaned['host'];
388
+ }
221
389
  return cleaned;
222
390
  });
391
+ sources.variants = (config.variants ?? []).map((_, index) => sourceIndex(index, unevaluableElements.variants));
392
+ }
393
+ return { config, sources };
394
+ }
395
+ /**
396
+ * `ShowcaseConfig.imports` as the scanner evaluated it, with every entry that is not a `{ name, from }` pair of
397
+ * non-empty strings reported and dropped. `unevaluable` holds the source positions the evaluator dropped, which keep
398
+ * the later entries named by the position they have in the source; `source` is that position for each kept entry.
399
+ */
400
+ function readShowcaseImports(value, className, config, report, unevaluable) {
401
+ if (!Array.isArray(value)) {
402
+ report(describeShowcaseIssue(className, config, ['imports'], `expected a list of { name, from }, got ${describeValue(value)}; it was dropped`));
403
+ return [];
223
404
  }
224
- return config;
405
+ return value.flatMap((entry, index) => {
406
+ const source = sourceIndex(index, unevaluable);
407
+ const text = isShowcaseImport(entry) ? importProblem(entry) : `expected { name, from } with a non-empty string each, got ${describeValue(entry)}; it was dropped`;
408
+ if (!text)
409
+ return [{ entry: { name: entry.name, from: entry.from }, source }];
410
+ report(describeShowcaseIssue(className, config, ['imports', source], text));
411
+ return [];
412
+ });
225
413
  }
226
414
  function extractComponentMeta(classDecl, checker) {
227
415
  const componentDecorator = findDecorator(classDecl, 'Component');
@@ -237,20 +425,3 @@ function extractComponentMeta(classDecl, checker) {
237
425
  isDirective
238
426
  };
239
427
  }
240
- /**
241
- * One field of `@Component`/`@Directive` metadata, read from its own
242
- * property where the literal has one, so that `imports`, `providers` and the
243
- * rest are not resolved only to be thrown away. A spread or a shorthand could
244
- * supply the field from elsewhere, so then the whole argument is evaluated.
245
- */
246
- function readDecoratorField(arg, key, checker) {
247
- if (ts.isObjectLiteralExpression(arg) && !arg.properties.some(ts.isSpreadAssignment)) {
248
- const prop = arg.properties.find((p) => p.name !== undefined && (ts.isIdentifier(p.name) || ts.isStringLiteral(p.name)) && p.name.text === key);
249
- if (!prop)
250
- return undefined;
251
- if (ts.isPropertyAssignment(prop))
252
- return evaluateExpression(prop.initializer, checker);
253
- }
254
- const raw = evaluateExpression(arg, checker);
255
- return typeof raw === 'object' && raw !== null ? raw[key] : undefined;
256
- }
@@ -0,0 +1,36 @@
1
+ import { type TmplAstNode } from '@angular/compiler';
2
+ export interface ComposeInput {
3
+ selector: string;
4
+ isDirective: boolean;
5
+ /** Public input name (alias ?? name) → member name. */
6
+ inputNames: ReadonlyMap<string, string>;
7
+ hostTemplate?: string;
8
+ /** Inner markup of the subject: the variant's template, or a directive's text content already escaped. */
9
+ content?: string;
10
+ }
11
+ export type ComposeResult = {
12
+ ok: true;
13
+ template: string;
14
+ ownedInputs: string[];
15
+ nodes: TmplAstNode[];
16
+ } | {
17
+ ok: false;
18
+ at: 'host' | 'template';
19
+ problem: string;
20
+ };
21
+ /**
22
+ * The template of a composition: the subject in its host template, or written from its selector without one, with
23
+ * `content` as what it holds. {@link COMPOSITION_SUBJECT_SLOT} marks the end of the subject's start tag, right after
24
+ * its last attribute or its tag name; whoever replaces it brings the leading space.
25
+ *
26
+ * In a host template the subject is the element marked with `prism-subject`, else the one element its selector
27
+ * matches. A directive whose selector does not match the marked element gets the attributes that make it match.
28
+ * The marker is removed, and `content` replaces what the subject holds in the host template. `ownedInputs` are the
29
+ * member names of the inputs the host template sets on the subject.
30
+ *
31
+ * What fails is reported against the field it comes from: `host` for the host template and finding the subject in
32
+ * it, `template` for the content and, when there is content, for what Angular's parser rejects in the composed
33
+ * template. Both are parsed as the generated wrapper holds them, inside a `@case`, where an element left open fails.
34
+ */
35
+ export declare function composeTemplate(input: ComposeInput): ComposeResult;
36
+ //# sourceMappingURL=compose-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose-template.d.ts","sourceRoot":"","sources":["../../../../src/builder/scanner/composition/compose-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,WAAW,EAInB,MAAM,mBAAmB,CAAC;AAM3B,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,uDAAuD;IACvD,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0GAA0G;IAC1G,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,GAAG,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAUlK;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,aAAa,CAYlE"}
@@ -0,0 +1,187 @@
1
+ import { CssSelector, parseTemplate, SelectorMatcher, TmplAstElement, TmplAstRecursiveVisitor, TmplAstTemplate, tmplAstVisitAll } from '@angular/compiler';
2
+ import { COMPOSITION_SUBJECT_SLOT, SUBJECT_MARKER_ATTR } from '../../../shared/composition.js';
3
+ import { VOID_ELEMENTS } from '../../../shared/void-elements.js';
4
+ import { selectorElement } from '../../manifest/selector-element.js';
5
+ import { elementSelector, isInputBinding, localName } from './template-elements.js';
6
+ /** The URL the parser files the composition under. A problem carries only Angular's `msg`, so it shows nowhere. */
7
+ const TEMPLATE_URL = 'prism-composition.html';
8
+ /**
9
+ * The template of a composition: the subject in its host template, or written from its selector without one, with
10
+ * `content` as what it holds. {@link COMPOSITION_SUBJECT_SLOT} marks the end of the subject's start tag, right after
11
+ * its last attribute or its tag name; whoever replaces it brings the leading space.
12
+ *
13
+ * In a host template the subject is the element marked with `prism-subject`, else the one element its selector
14
+ * matches. A directive whose selector does not match the marked element gets the attributes that make it match.
15
+ * The marker is removed, and `content` replaces what the subject holds in the host template. `ownedInputs` are the
16
+ * member names of the inputs the host template sets on the subject.
17
+ *
18
+ * What fails is reported against the field it comes from: `host` for the host template and finding the subject in
19
+ * it, `template` for the content and, when there is content, for what Angular's parser rejects in the composed
20
+ * template. Both are parsed as the generated wrapper holds them, inside a `@case`, where an element left open fails.
21
+ */
22
+ export function composeTemplate(input) {
23
+ const composed = input.hostTemplate === undefined ? composeWithoutHost(input) : composeInHost(input, input.hostTemplate);
24
+ if (!composed.ok)
25
+ return composed;
26
+ const template = composed.template.replace(COMPOSITION_SUBJECT_SLOT, '');
27
+ const parsed = parseTemplate(template, TEMPLATE_URL);
28
+ const problem = parsed.errors?.[0]?.msg ?? problemInCase(template);
29
+ // Without content the host template alone was parsed, so a remaining error is still its own.
30
+ if (problem)
31
+ return fail(input.content === undefined ? 'host' : 'template', problem);
32
+ return { ...composed, nodes: parsed.nodes };
33
+ }
34
+ /**
35
+ * What Angular rejects in `template` inside the `@case` of the generated wrapper, beyond what it rejects at the top
36
+ * level: there it closes an element left open at the end of the template, in a block it fails on the block's `}`.
37
+ */
38
+ function problemInCase(template) {
39
+ const error = parseTemplate(`@switch (0) {\n@case (0) {\n${template}\n}\n}`, TEMPLATE_URL).errors?.[0];
40
+ if (!error)
41
+ return undefined;
42
+ // The message is about the `}` ng-prism wrote, and names the element only in passing.
43
+ const unclosed = /Did you forget to close the (<[^>]+>) element\?/.exec(error.msg);
44
+ return unclosed ? `${unclosed[1]} is not closed` : `${error.msg}, in the @case that the generated wrapper puts the template in; an unclosed {{ or block can cause it`;
45
+ }
46
+ function composeWithoutHost({ selector, content }) {
47
+ const element = selectorElement(selector);
48
+ if (!element)
49
+ return fail('template', `the selector "${selector}" names no element to render the subject on`);
50
+ const { tag, attributes } = element;
51
+ const opening = `<${tag}${attributes ? ` ${attributes}` : ''}${COMPOSITION_SUBJECT_SLOT}`;
52
+ if (VOID_ELEMENTS.has(tag.toLowerCase())) {
53
+ return content ? voidContent(tag) : { ok: true, template: `${opening} />`, ownedInputs: [] };
54
+ }
55
+ return { ok: true, template: `${opening}>${content ?? ''}</${tag}>`, ownedInputs: [] };
56
+ }
57
+ function composeInHost(input, hostTemplate) {
58
+ const parsed = parseTemplate(hostTemplate, TEMPLATE_URL, { preserveWhitespaces: true });
59
+ const problem = parsed.errors?.[0]?.msg ?? problemInCase(hostTemplate);
60
+ if (problem)
61
+ return fail('host', problem);
62
+ const subject = findSubject(parsed.nodes, input.selector);
63
+ if ('problem' in subject)
64
+ return subject;
65
+ const { element, matched } = subject;
66
+ const tag = writtenTag(element, hostTemplate);
67
+ let added = '';
68
+ if (!matched) {
69
+ if (!input.isDirective)
70
+ return fail('host', `prism-subject marks <${tag}>, which the selector "${input.selector}" does not match`);
71
+ const fitting = selectorElement(input.selector, tag);
72
+ if (!fitting?.attributes)
73
+ return fail('host', `prism-subject marks <${tag}>, but no part of the selector "${input.selector}" fits a <${tag}>`);
74
+ added = ` ${fitting.attributes}`;
75
+ }
76
+ const isVoid = VOID_ELEMENTS.has(tag.toLowerCase());
77
+ if (isVoid && input.content)
78
+ return voidContent(tag);
79
+ const edits = [];
80
+ const startTagEnd = element.startSourceSpan.end.offset;
81
+ const slotAt = slotOffset(hostTemplate, startTagEnd);
82
+ const slot = { from: slotAt, to: slotAt, text: `${added}${COMPOSITION_SUBJECT_SLOT}` };
83
+ const marker = element.attributes.find((attribute) => attribute.name === SUBJECT_MARKER_ATTR);
84
+ if (marker) {
85
+ edits.push({ from: skipWhitespaceBack(hostTemplate, marker.sourceSpan.start.offset), to: marker.sourceSpan.end.offset, text: '' });
86
+ }
87
+ if (!isVoid && input.content !== undefined) {
88
+ if (!element.isSelfClosing) {
89
+ const childrenEnd = element.endSourceSpan?.start.offset ?? endOffset(element);
90
+ edits.push({ from: startTagEnd, to: childrenEnd, text: input.content });
91
+ }
92
+ else if (input.content) {
93
+ slot.to = startTagEnd;
94
+ slot.text += `>${input.content}</${tag}>`;
95
+ }
96
+ }
97
+ edits.push(slot);
98
+ return { ok: true, template: applyEdits(hostTemplate, edits), ownedInputs: ownedInputs(element, input) };
99
+ }
100
+ /** The subject of a host template, and whether its selector matches it, which only a marked element may fail. */
101
+ function findSubject(nodes, selector) {
102
+ const elements = collectElements(nodes);
103
+ const marked = elements.filter((element) => element.attributes.some((attribute) => attribute.name === SUBJECT_MARKER_ATTR));
104
+ if (marked.length > 1)
105
+ return fail('host', `prism-subject marks ${marked.length} elements of the host template; mark one`);
106
+ const matcher = new SelectorMatcher();
107
+ matcher.addSelectables(CssSelector.parse(selector));
108
+ const matches = (element) => matcher.match(elementSelector(element), null);
109
+ if (marked.length === 1)
110
+ return { element: marked[0], matched: matches(marked[0]) };
111
+ const matching = elements.filter(matches);
112
+ if (matching.length === 0)
113
+ return fail('host', `the selector "${selector}" matches no element of the host template`);
114
+ if (matching.length > 1)
115
+ return fail('host', `the selector "${selector}" matches ${matching.length} elements of the host template; mark one with prism-subject`);
116
+ return { element: matching[0], matched: true };
117
+ }
118
+ class ElementCollector extends TmplAstRecursiveVisitor {
119
+ elements = [];
120
+ visitElement(element) {
121
+ this.elements.push(element);
122
+ super.visitElement(element);
123
+ }
124
+ }
125
+ /** Every element of a template, also those in control flow blocks and in `<ng-template>`, in document order. */
126
+ function collectElements(nodes) {
127
+ const collector = new ElementCollector();
128
+ tmplAstVisitAll(collector, nodes);
129
+ return collector.elements;
130
+ }
131
+ /**
132
+ * The member names of the inputs that the host template sets on the subject, statically or by a property binding.
133
+ * An attribute without a value that the selector names is there to match it (`<button libTooltip>`), so ng-prism
134
+ * still binds the input of that name.
135
+ */
136
+ function ownedInputs(element, { selector, inputNames }) {
137
+ const selectorAttributes = new Set(CssSelector.parse(selector).flatMap((part) => part.attrs.filter((_, i) => i % 2 === 0)));
138
+ const written = new Set();
139
+ for (const attribute of element.attributes) {
140
+ if (attribute.value !== '' || !selectorAttributes.has(attribute.name))
141
+ written.add(attribute.name);
142
+ }
143
+ for (const bound of element.inputs) {
144
+ if (isInputBinding(bound.type))
145
+ written.add(bound.name);
146
+ }
147
+ return [...inputNames].filter(([publicName]) => written.has(publicName)).map(([, member]) => member);
148
+ }
149
+ /** The tag name as the host template writes it, which is what an end tag and a message repeat. */
150
+ function writtenTag(element, source) {
151
+ const start = element.startSourceSpan.start.offset;
152
+ return /^<([^\s/>]+)/.exec(source.slice(start, element.startSourceSpan.end.offset))?.[1] ?? localName(element.name);
153
+ }
154
+ /**
155
+ * Where a node ends in the source. The span of an element or `<ng-template>` whose end tag the parser implies (`<li>`
156
+ * before the next `<li>`, anything open at the end of the template) covers only its start tag, so it ends with its
157
+ * last descendant.
158
+ */
159
+ function endOffset(node) {
160
+ const end = node.sourceSpan.end.offset;
161
+ if (!(node instanceof TmplAstElement || node instanceof TmplAstTemplate) || node.endSourceSpan)
162
+ return end;
163
+ const last = node.children.at(-1);
164
+ return last ? Math.max(end, endOffset(last)) : end;
165
+ }
166
+ /** Where the slot goes in a start tag ending at `startTagEnd`: before its `>` or `/>` and the whitespace in front of it. */
167
+ function slotOffset(source, startTagEnd) {
168
+ let offset = startTagEnd - 1;
169
+ if (source[offset - 1] === '/')
170
+ offset--;
171
+ return skipWhitespaceBack(source, offset);
172
+ }
173
+ function skipWhitespaceBack(source, offset) {
174
+ while (offset > 0 && /\s/.test(source[offset - 1]))
175
+ offset--;
176
+ return offset;
177
+ }
178
+ /** Applies edits that do not overlap, from the last to the first, so that the offsets of the others stay valid. */
179
+ function applyEdits(source, edits) {
180
+ return [...edits].sort((a, b) => b.from - a.from).reduce((text, edit) => text.slice(0, edit.from) + edit.text + text.slice(edit.to), source);
181
+ }
182
+ function voidContent(tag) {
183
+ return fail('template', `<${tag}> is a void element and takes no content`);
184
+ }
185
+ function fail(at, problem) {
186
+ return { ok: false, at, problem };
187
+ }