@birdapi/velinstyle 1.1.0 → 1.2.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 (328) hide show
  1. package/README.de.md +89 -161
  2. package/README.md +187 -119
  3. package/cli/blueprint.js +98 -5
  4. package/cli/blueprints/app-chrome.html +18 -0
  5. package/cli/blueprints/benefits-grid.html +9 -0
  6. package/cli/blueprints/bottom-nav-mobile.html +2 -1
  7. package/cli/blueprints/cookie-consent.html +1 -1
  8. package/cli/blueprints/cta-band.html +6 -0
  9. package/cli/blueprints/faq-section.html +18 -0
  10. package/cli/blueprints/filter-bar.html +4 -4
  11. package/cli/blueprints/form-contact.html +6 -5
  12. package/cli/blueprints/hero-section.html +3 -3
  13. package/cli/blueprints/notification-center.html +1 -1
  14. package/cli/blueprints/onboarding.html +2 -1
  15. package/cli/blueprints/ops-console.html +29 -0
  16. package/cli/blueprints/pricing-band.html +37 -0
  17. package/cli/blueprints/process-steps.html +10 -0
  18. package/cli/blueprints/services-grid.html +9 -0
  19. package/cli/blueprints/settings-panel.html +8 -6
  20. package/cli/blueprints/split-hero.html +25 -0
  21. package/cli/blueprints/testimonials.html +8 -0
  22. package/cli/blueprints/trust-bar.html +10 -0
  23. package/cli/cli-manifest.json +81 -17
  24. package/cli/contrast-utils.js +97 -0
  25. package/cli/create.js +370 -0
  26. package/cli/docgen/extract-attributes.js +128 -10
  27. package/cli/docgen/extract-cli.js +3 -2
  28. package/cli/docgen/extract-components.js +61 -2
  29. package/cli/docgen/extract-utilities.js +10 -10
  30. package/cli/doctor.js +119 -0
  31. package/cli/index.js +560 -44
  32. package/cli/meta.js +84 -1
  33. package/cli/perf-audit.js +15 -2
  34. package/cli/prompt-engine.js +243 -0
  35. package/cli/review.js +268 -0
  36. package/cli/scaffold.js +119 -4
  37. package/cli/scanner-rules-data.js +7 -0
  38. package/cli/scanner.js +357 -4
  39. package/cli/serve.js +81 -0
  40. package/cli/skills.js +223 -0
  41. package/cli/transparency.js +221 -0
  42. package/cli/wc-api.js +89 -0
  43. package/cli/workflow.js +42 -0
  44. package/components/index.js +2 -0
  45. package/components/runtime/component-loaders.js +2 -0
  46. package/components/velin-accordion.js +62 -13
  47. package/components/velin-bottom-nav.js +10 -0
  48. package/components/velin-calendar.js +212 -0
  49. package/components/velin-command.js +18 -2
  50. package/components/velin-data-table.js +78 -1
  51. package/components/velin-dialog.js +4 -1
  52. package/components/velin-drawer.js +2 -4
  53. package/components/velin-file-dropzone.js +162 -0
  54. package/components/velin-icon.js +22 -1
  55. package/components/velin-lightbox.js +5 -3
  56. package/components/velin-modal.js +2 -4
  57. package/components/velin-search.js +1 -1
  58. package/components/velin-sheet.js +2 -4
  59. package/core/a11y/component-contracts.json +20 -3
  60. package/core/attributes/registry.js +14 -0
  61. package/core/meta/build.js +125 -5
  62. package/core/meta/design-constraints/contact.json +9 -0
  63. package/core/meta/design-constraints/faq.json +9 -0
  64. package/core/meta/design-constraints/hero.json +13 -0
  65. package/core/meta/knowledge/components.json +622 -0
  66. package/core/meta/knowledge/tokens.json +282 -0
  67. package/core/meta/pages/registry.json +294 -0
  68. package/core/meta/schema.js +13 -1
  69. package/core/meta/sections/registry.json +185 -0
  70. package/core/transparency/attach.js +74 -0
  71. package/core/transparency/claims.js +97 -0
  72. package/core/transparency/doctor.js +142 -0
  73. package/core/transparency/engine.js +75 -0
  74. package/core/transparency/export.js +98 -0
  75. package/core/transparency/index.js +30 -0
  76. package/core/transparency/migrate.js +130 -0
  77. package/core/transparency/normalize.js +125 -0
  78. package/core/transparency/policy.js +105 -0
  79. package/core/transparency/providers.js +235 -0
  80. package/core/transparency/registry.js +104 -0
  81. package/core/transparency/renderer.js +111 -0
  82. package/core/transparency/reporter.js +113 -0
  83. package/core/transparency/validator.js +112 -0
  84. package/dist/chunks/attach-H2ZSEAE6.js +365 -0
  85. package/dist/chunks/{attributes-STYCS3O5.js → attributes-A423NX5J.js} +3 -3
  86. package/dist/chunks/attributes-DZCXX2RZ.js +404 -0
  87. package/dist/chunks/{attributes-353XDOAX.js → attributes-F6UPIEVP.js} +1 -1
  88. package/dist/chunks/{attributes-ADOKLKA7.js → attributes-GLYXGGAL.js} +3 -3
  89. package/dist/chunks/{attributes-TPANLMLF.js → attributes-UFTYOSAU.js} +3 -3
  90. package/dist/chunks/attributes-XGLXLR2T.js +391 -0
  91. package/dist/chunks/attributes-YF4NI2QS.js +391 -0
  92. package/dist/chunks/browser-AUABBYUK.js +1544 -0
  93. package/dist/chunks/{chunk-RSMRR27R.js → chunk-2LSKX57P.js} +12 -10
  94. package/dist/chunks/{chunk-IEHKRARD.js → chunk-2TGCVDUL.js} +11 -9
  95. package/dist/chunks/{chunk-SRL6EWHP.js → chunk-5JWGUAPC.js} +17 -13
  96. package/dist/chunks/chunk-7YSO2OQ2.js +113 -0
  97. package/dist/chunks/{chunk-QVHYL3R4.js → chunk-BHR3ZG6U.js} +6 -6
  98. package/dist/chunks/chunk-CQMTCEI6.js +113 -0
  99. package/dist/chunks/{chunk-J472ERN2.js → chunk-JMSIHEYX.js} +15 -4
  100. package/dist/chunks/{chunk-MKZP2TBH.js → chunk-L7ZGUU4D.js} +2 -2
  101. package/dist/chunks/chunk-TUGIPKW5.js +113 -0
  102. package/dist/chunks/{highlight-GJHHV4KM.js → highlight-M2ELQNYK.js} +1 -1
  103. package/dist/chunks/runtime-entry.js +1 -1
  104. package/dist/chunks/{velin-accordion-FBIPAEXG.js → velin-accordion-WSY6BMLA.js} +64 -10
  105. package/dist/chunks/{velin-bottom-nav-7GEMPIM6.js → velin-bottom-nav-5RVRNGIP.js} +25 -0
  106. package/dist/chunks/{velin-bottom-nav-N3DFQR66.js → velin-bottom-nav-N5F4UO2I.js} +26 -1
  107. package/dist/chunks/velin-calendar-OFE6THUD.js +210 -0
  108. package/dist/chunks/velin-calendar-PGVNJTXK.js +217 -0
  109. package/dist/chunks/velin-calendar-XC7JRDSH.js +217 -0
  110. package/dist/chunks/{velin-code-block-CIAURDRJ.js → velin-code-block-ZGWG7JI5.js} +1 -1
  111. package/dist/chunks/{velin-combobox-NXS4QB4R.js → velin-combobox-56V2ZWT5.js} +1 -1
  112. package/dist/chunks/{velin-command-ONKO2A3J.js → velin-command-2HO2EKR6.js} +29 -2
  113. package/dist/chunks/{velin-command-TMLSRGIU.js → velin-command-ZJSLPK7B.js} +30 -3
  114. package/dist/chunks/{velin-copy-NYDBOKXT.js → velin-copy-XDQSV2XU.js} +1 -1
  115. package/dist/chunks/{velin-countdown-4ZVDGK4R.js → velin-countdown-V4Z5MA63.js} +1 -1
  116. package/dist/chunks/velin-data-table-UVR42UUM.js +372 -0
  117. package/dist/chunks/{velin-dialog-GTTZI564.js → velin-dialog-3YK2RPRV.js} +9 -2
  118. package/dist/chunks/{velin-dialog-ELFOZIXZ.js → velin-dialog-S24KAP4S.js} +3 -1
  119. package/dist/chunks/{velin-drawer-BE6TYN3H.js → velin-drawer-5PNU624J.js} +2 -4
  120. package/dist/chunks/{velin-drawer-DLL2GLT6.js → velin-drawer-CCM6S25D.js} +3 -5
  121. package/dist/chunks/{velin-email-RBX6ZR4S.js → velin-email-TNFONXPW.js} +1 -1
  122. package/dist/chunks/velin-file-dropzone-QRGF2JNA.js +154 -0
  123. package/dist/chunks/velin-file-dropzone-XIZMJ3NB.js +154 -0
  124. package/dist/chunks/{velin-icon-7M76DOPB.js → velin-icon-A6NCXGUK.js} +59 -17
  125. package/dist/chunks/{velin-icon-ZTSKUOVN.js → velin-icon-EC4B5XCM.js} +18 -5
  126. package/dist/chunks/{velin-lightbox-6E7CAATP.js → velin-lightbox-FFK4TUUP.js} +7 -6
  127. package/dist/chunks/{velin-lightbox-NXA3U2FM.js → velin-lightbox-P725FLTY.js} +5 -4
  128. package/dist/chunks/{velin-menubar-J66JXRWW.js → velin-menubar-6I2LM5HL.js} +1 -1
  129. package/dist/chunks/{velin-modal-5HYNNNUI.js → velin-modal-ICTMGRSU.js} +7 -8
  130. package/dist/chunks/{velin-modal-AEOTZ67O.js → velin-modal-JBNODH7D.js} +2 -4
  131. package/dist/chunks/{velin-popover-T72HK3DF.js → velin-popover-WZG2GHBL.js} +25 -4
  132. package/dist/chunks/{velin-rating-N4DI2XNL.js → velin-rating-QBBYRRBU.js} +1 -1
  133. package/dist/chunks/{velin-search-7B4KJ6TX.js → velin-search-B3L6J2RP.js} +2 -2
  134. package/dist/chunks/{velin-search-2XRQFBCS.js → velin-search-L3UG6NDQ.js} +5 -4
  135. package/dist/chunks/{velin-secure-field-6PV7RZDJ.js → velin-secure-field-DGYMP7OK.js} +1 -1
  136. package/dist/chunks/{velin-segmented-control-GYD5BIXQ.js → velin-segmented-control-P74GJPAR.js} +1 -1
  137. package/dist/chunks/{velin-sheet-R2Y67X6H.js → velin-sheet-M5GZZD7G.js} +2 -4
  138. package/dist/chunks/{velin-sheet-OUK6572T.js → velin-sheet-X7RXIWKV.js} +3 -5
  139. package/dist/chunks/{velin-stepper-X54WGHDG.js → velin-stepper-4YQJUHPC.js} +12 -5
  140. package/dist/chunks/{velin-toast-OMMOA2DK.js → velin-toast-UG5LWTG2.js} +5 -1
  141. package/dist/chunks/{velin-tooltip-BDHGRTQB.js → velin-tooltip-ZDH5SDLU.js} +1 -1
  142. package/dist/llms.txt +31 -8
  143. package/dist/search-index.json +182 -10
  144. package/dist/velin-agent.json +3980 -31
  145. package/dist/velinstyle-components.iife.js +1622 -286
  146. package/dist/velinstyle-components.js +1624 -286
  147. package/dist/velinstyle-components.min.js +262 -114
  148. package/dist/velinstyle.css +412 -67
  149. package/dist/velinstyle.d.ts +2 -0
  150. package/dist/velinstyle.min.css +1 -1
  151. package/package.json +21 -6
  152. package/packages/skill-engine/README.md +24 -0
  153. package/packages/skill-engine/package.json +7 -0
  154. package/packages/skill-engine/src/catalog.js +29 -0
  155. package/packages/skill-engine/src/index.js +5 -0
  156. package/packages/skill-engine/src/install.js +69 -0
  157. package/packages/skill-engine/src/registry.js +27 -0
  158. package/packages/skill-engine/src/resolve.js +68 -0
  159. package/packages/skill-engine/src/validate.js +40 -0
  160. package/packages/velinstyle-skills/README.md +6 -0
  161. package/packages/velinstyle-skills/adapter.json +8 -0
  162. package/packages/velinstyle-skills/bundles/landing-starter.bundle.yaml +12 -0
  163. package/packages/velinstyle-skills/bundles/review-suite.bundle.yaml +11 -0
  164. package/packages/velinstyle-skills/catalog.json +1004 -0
  165. package/packages/velinstyle-skills/graphs/component-ship.graph.yaml +14 -0
  166. package/packages/velinstyle-skills/graphs/landingpage.graph.yaml +21 -0
  167. package/packages/velinstyle-skills/graphs/release-gate.graph.yaml +15 -0
  168. package/packages/velinstyle-skills/index.js +22 -0
  169. package/packages/velinstyle-skills/package.json +7 -0
  170. package/packages/velinstyle-skills/packs/accessibility.pack.yaml +9 -0
  171. package/packages/velinstyle-skills/packs/design.pack.yaml +10 -0
  172. package/packages/velinstyle-skills/packs/documentation.pack.yaml +8 -0
  173. package/packages/velinstyle-skills/packs/enterprise.pack.yaml +10 -0
  174. package/packages/velinstyle-skills/packs/frontend.pack.yaml +10 -0
  175. package/packages/velinstyle-skills/packs/review.pack.yaml +9 -0
  176. package/packages/velinstyle-skills/projects/admin-panel.project.yaml +12 -0
  177. package/packages/velinstyle-skills/projects/blog.project.yaml +11 -0
  178. package/packages/velinstyle-skills/projects/documentation-portal.project.yaml +13 -0
  179. package/packages/velinstyle-skills/projects/ecommerce-shop.project.yaml +12 -0
  180. package/packages/velinstyle-skills/projects/landing-page.project.yaml +12 -0
  181. package/packages/velinstyle-skills/projects/laravel-dashboard.project.yaml +12 -0
  182. package/packages/velinstyle-skills/projects/marketing-website.project.yaml +14 -0
  183. package/packages/velinstyle-skills/projects/portfolio.project.yaml +12 -0
  184. package/packages/velinstyle-skills/registry.json +142 -0
  185. package/packages/velinstyle-skills/scripts/generate-assets.mjs +163 -0
  186. package/packages/velinstyle-skills/skills/velin-a11y-focus-keyboard/SKILL.md +57 -0
  187. package/packages/velinstyle-skills/skills/velin-a11y-page-checklist/SKILL.md +57 -0
  188. package/packages/velinstyle-skills/skills/velin-a11y-scan-fix/SKILL.md +57 -0
  189. package/packages/velinstyle-skills/skills/velin-ai-agent-briefing/SKILL.md +57 -0
  190. package/packages/velinstyle-skills/skills/velin-ai-plan-scaffold-review/SKILL.md +57 -0
  191. package/packages/velinstyle-skills/skills/velin-ai-skill-authoring/SKILL.md +57 -0
  192. package/packages/velinstyle-skills/skills/velin-components-accessibility-map/SKILL.md +57 -0
  193. package/packages/velinstyle-skills/skills/velin-components-api-contract/SKILL.md +57 -0
  194. package/packages/velinstyle-skills/skills/velin-components-recipe/SKILL.md +57 -0
  195. package/packages/velinstyle-skills/skills/velin-components-select-compose/SKILL.md +57 -0
  196. package/packages/velinstyle-skills/skills/velin-design-hero-compose/SKILL.md +57 -0
  197. package/packages/velinstyle-skills/skills/velin-design-section-rhythm/SKILL.md +57 -0
  198. package/packages/velinstyle-skills/skills/velin-design-surface-roles/SKILL.md +57 -0
  199. package/packages/velinstyle-skills/skills/velin-dev-component-wire/SKILL.md +57 -0
  200. package/packages/velinstyle-skills/skills/velin-dev-page-scaffold/SKILL.md +57 -0
  201. package/packages/velinstyle-skills/skills/velin-dev-plan-first/SKILL.md +57 -0
  202. package/packages/velinstyle-skills/skills/velin-docs-component-guide/SKILL.md +57 -0
  203. package/packages/velinstyle-skills/skills/velin-docs-generate-api/SKILL.md +57 -0
  204. package/packages/velinstyle-skills/skills/velin-dx-doctor-setup/SKILL.md +57 -0
  205. package/packages/velinstyle-skills/skills/velin-dx-project-init/SKILL.md +57 -0
  206. package/packages/velinstyle-skills/skills/velin-migration-legacy-wc/SKILL.md +57 -0
  207. package/packages/velinstyle-skills/skills/velin-migration-prefix-classes/SKILL.md +57 -0
  208. package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +57 -0
  209. package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +57 -0
  210. package/packages/velinstyle-skills/skills/velin-perf-audit-fix/SKILL.md +57 -0
  211. package/packages/velinstyle-skills/skills/velin-perf-runtime-tree-shake/SKILL.md +57 -0
  212. package/packages/velinstyle-skills/skills/velin-release-changelog-sync/SKILL.md +57 -0
  213. package/packages/velinstyle-skills/skills/velin-release-meta-rebuild/SKILL.md +57 -0
  214. package/packages/velinstyle-skills/skills/velin-review-conversion-hero/SKILL.md +57 -0
  215. package/packages/velinstyle-skills/skills/velin-review-page-gate/SKILL.md +57 -0
  216. package/packages/velinstyle-skills/skills/velin-review-seo-meta/SKILL.md +57 -0
  217. package/packages/velinstyle-skills/skills/velin-security-sanitize-html/SKILL.md +57 -0
  218. package/packages/velinstyle-skills/skills/velin-security-scan-pii/SKILL.md +57 -0
  219. package/packages/velinstyle-skills/skills/velin-testing-a11y-suite/SKILL.md +57 -0
  220. package/packages/velinstyle-skills/skills/velin-testing-visual-smoke/SKILL.md +57 -0
  221. package/packages/velinstyle-skills/skills/velin-themes-apply-token/SKILL.md +57 -0
  222. package/packages/velinstyle-skills/skills/velin-themes-contrast-check/SKILL.md +57 -0
  223. package/packages/velinstyle-skills/skills/velin-utilities-layout-apply/SKILL.md +57 -0
  224. package/packages/velinstyle-skills/skills/velin-utilities-prefix-fix/SKILL.md +57 -0
  225. package/packages/velinstyle-skills/skills/velin-utilities-token-map/SKILL.md +57 -0
  226. package/packages/velinstyle-skills/templates/admin-panel.template.yaml +12 -0
  227. package/packages/velinstyle-skills/templates/blog.template.yaml +12 -0
  228. package/packages/velinstyle-skills/templates/documentation-portal.template.yaml +12 -0
  229. package/packages/velinstyle-skills/templates/ecommerce-shop.template.yaml +13 -0
  230. package/packages/velinstyle-skills/templates/landing-page.template.yaml +12 -0
  231. package/packages/velinstyle-skills/templates/laravel-dashboard.template.yaml +11 -0
  232. package/packages/velinstyle-skills/templates/marketing-website.template.yaml +13 -0
  233. package/packages/velinstyle-skills/templates/portfolio.template.yaml +12 -0
  234. package/schemas/component-knowledge.schema.json +33 -0
  235. package/schemas/design-constraint.schema.json +15 -0
  236. package/schemas/design-intelligence.schema.json +19 -0
  237. package/schemas/design-rule.schema.json +19 -0
  238. package/schemas/page-template.schema.json +24 -0
  239. package/schemas/review-report.schema.json +36 -0
  240. package/schemas/section.schema.json +22 -0
  241. package/schemas/skill-bundle.schema.json +15 -0
  242. package/schemas/skill-graph.schema.json +25 -0
  243. package/schemas/skill-pack.schema.json +14 -0
  244. package/schemas/skill-project.schema.json +16 -0
  245. package/schemas/skill-record.schema.json +27 -0
  246. package/schemas/skill-registry.schema.json +17 -0
  247. package/schemas/skill-template.schema.json +17 -0
  248. package/schemas/token-graph.schema.json +27 -0
  249. package/schemas/utility.schema.json +166 -0
  250. package/src/components/alert.css +22 -1
  251. package/src/components/calendar-dropzone.css +5 -0
  252. package/src/components/transparency.css +138 -0
  253. package/src/layout/app-shell.css +33 -0
  254. package/src/tokens/shadow.css +13 -0
  255. package/src/utilities/border.css +2 -0
  256. package/src/utilities/display.css +1 -24
  257. package/src/utilities/responsive.css +16 -1
  258. package/src/utilities/spacing.css +32 -0
  259. package/src/velinstyle.css +3 -0
  260. package/dist/chunks/attributes-3BZLI7XF.js +0 -364
  261. package/dist/chunks/attributes-4N5JP4CG.js +0 -364
  262. package/dist/chunks/attributes-5Q2WXGRC.js +0 -374
  263. package/dist/chunks/attributes-AIR7SVLK.js +0 -364
  264. package/dist/chunks/attributes-BGRN5XZO.js +0 -364
  265. package/dist/chunks/attributes-BVSQAYLR.js +0 -364
  266. package/dist/chunks/attributes-CDYFUY7Y.js +0 -364
  267. package/dist/chunks/attributes-JMYJZBPE.js +0 -364
  268. package/dist/chunks/attributes-R5JY3X4O.js +0 -374
  269. package/dist/chunks/attributes-TNSPQTHX.js +0 -374
  270. package/dist/chunks/chunk-2354NEBP.js +0 -109
  271. package/dist/chunks/chunk-2VNA7G7S.js +0 -109
  272. package/dist/chunks/chunk-AQLRJSGG.js +0 -109
  273. package/dist/chunks/chunk-EWPSDMQT.js +0 -109
  274. package/dist/chunks/chunk-LA7264K4.js +0 -85
  275. package/dist/chunks/chunk-QTJJ3DPO.js +0 -109
  276. package/dist/chunks/chunk-RZQVWFHW.js +0 -109
  277. package/dist/chunks/chunk-U4XHMZ7D.js +0 -109
  278. package/dist/chunks/chunk-V5YIUA6G.js +0 -109
  279. package/dist/chunks/chunk-XIET2VSZ.js +0 -109
  280. package/dist/chunks/chunk-XYLJ2GCB.js +0 -205
  281. package/dist/chunks/chunk-ZPSPKUYD.js +0 -109
  282. package/dist/chunks/highlight-XTHRKBA3.js +0 -37
  283. package/dist/chunks/velin-bottom-nav-2N2TYWOF.js +0 -86
  284. package/dist/chunks/velin-carousel-Y5VCOABZ.js +0 -213
  285. package/dist/chunks/velin-code-block-ASUBTAQV.js +0 -119
  286. package/dist/chunks/velin-code-block-TSUKPY4C.js +0 -123
  287. package/dist/chunks/velin-code-block-Y6CM726Q.js +0 -119
  288. package/dist/chunks/velin-combobox-2KDTCQ7N.js +0 -155
  289. package/dist/chunks/velin-command-M7RNHUPR.js +0 -136
  290. package/dist/chunks/velin-copy-T5KDTDXP.js +0 -81
  291. package/dist/chunks/velin-countdown-5XSTN3BH.js +0 -101
  292. package/dist/chunks/velin-counter-ISCTEAHI.js +0 -118
  293. package/dist/chunks/velin-dialog-D2GUHSCD.js +0 -144
  294. package/dist/chunks/velin-dialog-IJLFDXAJ.js +0 -144
  295. package/dist/chunks/velin-dialog-TNS3WXMB.js +0 -144
  296. package/dist/chunks/velin-drawer-MJS6WCF7.js +0 -130
  297. package/dist/chunks/velin-email-N5B5ZYTE.js +0 -90
  298. package/dist/chunks/velin-icon-KZO3IEHG.js +0 -164
  299. package/dist/chunks/velin-lightbox-I75U6JF4.js +0 -140
  300. package/dist/chunks/velin-lightbox-QOTB4PRL.js +0 -140
  301. package/dist/chunks/velin-lightbox-UCD6N7HF.js +0 -140
  302. package/dist/chunks/velin-live-dot-XHUZCIDZ.js +0 -67
  303. package/dist/chunks/velin-menubar-SFEXJE56.js +0 -86
  304. package/dist/chunks/velin-modal-2HOBXE6F.js +0 -176
  305. package/dist/chunks/velin-modal-GLI2XZZB.js +0 -176
  306. package/dist/chunks/velin-popover-EXINRIGJ.js +0 -145
  307. package/dist/chunks/velin-popover-OXX7MRZ6.js +0 -145
  308. package/dist/chunks/velin-popover-YKCCROJG.js +0 -145
  309. package/dist/chunks/velin-rating-XRQJV4LO.js +0 -91
  310. package/dist/chunks/velin-scroll-top-F2FCZNYD.js +0 -58
  311. package/dist/chunks/velin-search-4YHJWYSS.js +0 -556
  312. package/dist/chunks/velin-search-LWHY23Q5.js +0 -474
  313. package/dist/chunks/velin-secure-field-H7FSBUJW.js +0 -95
  314. package/dist/chunks/velin-segmented-control-PQX6LKOJ.js +0 -109
  315. package/dist/chunks/velin-sheet-3OGI4HD7.js +0 -119
  316. package/dist/chunks/velin-sparkline-GVEANJVW.js +0 -184
  317. package/dist/chunks/velin-sparkline-KDA3GQAN.js +0 -162
  318. package/dist/chunks/velin-stepper-2ZIHLKGM.js +0 -141
  319. package/dist/chunks/velin-stepper-FYEUEWE6.js +0 -141
  320. package/dist/chunks/velin-stepper-wc-QU3KRVQR.js +0 -133
  321. package/dist/chunks/velin-theme-toggle-BNNS7WLV.js +0 -285
  322. package/dist/chunks/velin-theme-toggle-NO7V4TWI.js +0 -285
  323. package/dist/chunks/velin-theme-toggle-QELCJM2Q.js +0 -291
  324. package/dist/chunks/velin-toast-RCZ4CSUC.js +0 -109
  325. package/dist/chunks/velin-toast-WEUBTJG6.js +0 -109
  326. package/dist/chunks/velin-tooltip-664IOHZA.js +0 -112
  327. package/dist/chunks/velin-tooltip-wc-LXDVT6DE.js +0 -103
  328. package/dist/chunks/worker-client-R6DBYPFT.js +0 -46
@@ -0,0 +1,185 @@
1
+ {
2
+ "version": 1,
3
+ "sections": [
4
+ {
5
+ "id": "hero",
6
+ "role": "hero",
7
+ "blueprintFile": "hero-section.html",
8
+ "inputs": ["title", "subtitle", "cta", "brand"],
9
+ "requiredContent": ["headline", "primaryCta"],
10
+ "optionalContent": ["image", "secondaryCta"],
11
+ "designRules": ["hero-headline-lines", "hero-cta-max", "hero-contrast"],
12
+ "a11yRules": ["one h1", "cta is real button/link"],
13
+ "seoRules": ["h1 matches primary intent"],
14
+ "compatiblePrev": [],
15
+ "compatibleNext": ["trust-bar", "benefits", "services"],
16
+ "examplePrompts": ["modern hero with two CTAs"],
17
+ "commonMistakes": ["three CTAs", "headline longer than two lines"]
18
+ },
19
+ {
20
+ "id": "trust-bar",
21
+ "role": "trust-bar",
22
+ "blueprintFile": "trust-bar.html",
23
+ "inputs": ["logos", "claim"],
24
+ "requiredContent": ["trustItems"],
25
+ "optionalContent": ["claim"],
26
+ "designRules": [],
27
+ "a11yRules": ["alt text for logos"],
28
+ "seoRules": [],
29
+ "compatiblePrev": ["hero"],
30
+ "compatibleNext": ["benefits", "services"],
31
+ "examplePrompts": ["trusted by brands bar"],
32
+ "commonMistakes": ["low-contrast logos"]
33
+ },
34
+ {
35
+ "id": "benefits",
36
+ "role": "benefits",
37
+ "blueprintFile": "benefits-grid.html",
38
+ "inputs": ["items"],
39
+ "requiredContent": ["benefitItems"],
40
+ "optionalContent": [],
41
+ "designRules": [],
42
+ "a11yRules": ["headings per benefit"],
43
+ "seoRules": [],
44
+ "compatiblePrev": ["hero", "trust-bar"],
45
+ "compatibleNext": ["services", "process"],
46
+ "examplePrompts": ["three benefits"],
47
+ "commonMistakes": ["walls of text"]
48
+ },
49
+ {
50
+ "id": "services",
51
+ "role": "services",
52
+ "blueprintFile": "services-grid.html",
53
+ "inputs": ["items"],
54
+ "requiredContent": ["serviceItems"],
55
+ "optionalContent": [],
56
+ "designRules": [],
57
+ "a11yRules": ["card titles as headings"],
58
+ "seoRules": ["service names as keywords"],
59
+ "compatiblePrev": ["benefits", "trust-bar", "hero"],
60
+ "compatibleNext": ["process", "testimonials", "pricing"],
61
+ "examplePrompts": ["services grid for tax advisor"],
62
+ "commonMistakes": ["vague service titles"]
63
+ },
64
+ {
65
+ "id": "process",
66
+ "role": "process",
67
+ "blueprintFile": "process-steps.html",
68
+ "inputs": ["steps"],
69
+ "requiredContent": ["steps"],
70
+ "optionalContent": [],
71
+ "designRules": [],
72
+ "a11yRules": ["ordered list semantics"],
73
+ "seoRules": [],
74
+ "compatiblePrev": ["services", "benefits"],
75
+ "compatibleNext": ["testimonials", "pricing", "faq"],
76
+ "examplePrompts": ["how it works in 4 steps"],
77
+ "commonMistakes": ["more than 6 steps"]
78
+ },
79
+ {
80
+ "id": "testimonials",
81
+ "role": "testimonials",
82
+ "blueprintFile": "testimonials.html",
83
+ "inputs": ["quotes"],
84
+ "requiredContent": ["quotes"],
85
+ "optionalContent": ["avatars"],
86
+ "designRules": [],
87
+ "a11yRules": ["cite attribution"],
88
+ "seoRules": [],
89
+ "compatiblePrev": ["services", "process"],
90
+ "compatibleNext": ["pricing", "faq", "contact"],
91
+ "examplePrompts": ["client testimonials"],
92
+ "commonMistakes": ["anonymous quotes only"]
93
+ },
94
+ {
95
+ "id": "pricing",
96
+ "role": "pricing",
97
+ "blueprintFile": "pricing-table.html",
98
+ "inputs": ["plans"],
99
+ "requiredContent": ["plans"],
100
+ "optionalContent": [],
101
+ "designRules": [],
102
+ "a11yRules": ["table or card semantics clear"],
103
+ "seoRules": [],
104
+ "compatiblePrev": ["services", "testimonials"],
105
+ "compatibleNext": ["faq", "cta"],
106
+ "examplePrompts": ["three pricing tiers"],
107
+ "commonMistakes": ["unclear currency"]
108
+ },
109
+ {
110
+ "id": "faq",
111
+ "role": "faq",
112
+ "blueprintFile": "faq-section.html",
113
+ "inputs": ["items"],
114
+ "requiredContent": ["questions"],
115
+ "optionalContent": [],
116
+ "designRules": ["faq-questions", "faq-pattern"],
117
+ "a11yRules": ["accordion keyboard support"],
118
+ "seoRules": ["FAQPage-ready question text"],
119
+ "compatiblePrev": ["testimonials", "pricing", "process"],
120
+ "compatibleNext": ["contact", "cta", "footer"],
121
+ "examplePrompts": ["FAQ with accordion"],
122
+ "commonMistakes": ["non-questions as titles"]
123
+ },
124
+ {
125
+ "id": "contact",
126
+ "role": "contact",
127
+ "blueprintFile": "form-contact.html",
128
+ "inputs": ["fields"],
129
+ "requiredContent": ["name", "email", "message"],
130
+ "optionalContent": ["phone"],
131
+ "designRules": ["contact-labels", "contact-summary"],
132
+ "a11yRules": ["labels", "form-summary"],
133
+ "seoRules": [],
134
+ "compatiblePrev": ["faq", "testimonials"],
135
+ "compatibleNext": ["footer", "cta"],
136
+ "examplePrompts": ["contact form with validation summary"],
137
+ "commonMistakes": ["placeholder-only labels"]
138
+ },
139
+ {
140
+ "id": "cta",
141
+ "role": "cta",
142
+ "blueprintFile": "cta-band.html",
143
+ "inputs": ["title", "cta"],
144
+ "requiredContent": ["headline", "primaryCta"],
145
+ "optionalContent": ["secondaryCta"],
146
+ "designRules": ["hero-cta-max"],
147
+ "a11yRules": ["button semantics"],
148
+ "seoRules": [],
149
+ "compatiblePrev": ["faq", "pricing", "testimonials"],
150
+ "compatibleNext": ["footer"],
151
+ "examplePrompts": ["final CTA band"],
152
+ "commonMistakes": ["competing CTAs"]
153
+ },
154
+ {
155
+ "id": "footer",
156
+ "role": "footer",
157
+ "blueprintFile": "footer-simple.html",
158
+ "inputs": ["brand", "links"],
159
+ "requiredContent": ["brand"],
160
+ "optionalContent": ["legal", "social"],
161
+ "designRules": [],
162
+ "a11yRules": ["contentinfo landmark"],
163
+ "seoRules": ["legal links"],
164
+ "compatiblePrev": ["cta", "contact", "faq"],
165
+ "compatibleNext": [],
166
+ "examplePrompts": ["site footer"],
167
+ "commonMistakes": ["missing legal links on regulated niches"]
168
+ },
169
+ {
170
+ "id": "navbar",
171
+ "role": "navbar",
172
+ "blueprintFile": "navbar-header.html",
173
+ "inputs": ["brand", "links"],
174
+ "requiredContent": ["brand"],
175
+ "optionalContent": ["cta", "search"],
176
+ "designRules": [],
177
+ "a11yRules": ["nav landmark"],
178
+ "seoRules": ["internal links"],
179
+ "compatiblePrev": [],
180
+ "compatibleNext": ["hero"],
181
+ "examplePrompts": ["marketing navbar"],
182
+ "commonMistakes": ["too many links"]
183
+ }
184
+ ]
185
+ }
@@ -0,0 +1,74 @@
1
+ import { normalizeDisclosure } from './normalize.js';
2
+ import { renderDisclosure } from './renderer.js';
3
+ import { createRegistry } from './registry.js';
4
+
5
+ const defaultRegistry = createRegistry();
6
+
7
+ /**
8
+ * Attach a disclosure to an element (browser API).
9
+ * @param {HTMLElement} el
10
+ * @param {Record<string, unknown>} options
11
+ * @param {{ registry?: ReturnType<typeof createRegistry>, lang?: string }} [ctx]
12
+ */
13
+ export function attach(el, options = {}, ctx = {}) {
14
+ if (!el) throw new Error('VelinTransparency.attach requires an element');
15
+ const registry = ctx.registry || defaultRegistry;
16
+ const draft = {
17
+ ...options,
18
+ tag: el.tagName,
19
+ src: el.getAttribute?.('src') || el.getAttribute?.('href') || options.src,
20
+ selector: el.id ? `#${el.id}` : options.selector,
21
+ id: options.id || el.getAttribute?.('velin-transparency-id') || el.id,
22
+ provider: options.provider || 'api',
23
+ };
24
+ // Mirror useful attributes if present
25
+ if (el.hasAttribute?.('velin-transparency') || el.hasAttribute?.('velin-disclosure')) {
26
+ draft.type = draft.type || el.getAttribute('velin-type') || 'ai';
27
+ draft.status = draft.status || el.getAttribute('velin-status');
28
+ draft.review = draft.review || el.getAttribute('velin-review');
29
+ draft.license = draft.license || el.getAttribute('velin-license');
30
+ draft.label = draft.label || el.getAttribute('velin-label');
31
+ draft.description = draft.description || el.getAttribute('velin-description');
32
+ draft.overlay = draft.overlay || el.getAttribute('velin-overlay') || el.getAttribute('velin-renderer');
33
+ draft.provenance = {
34
+ createdBy: el.getAttribute('velin-created-by'),
35
+ createdAt: el.getAttribute('velin-created-at'),
36
+ reviewedAt: el.getAttribute('velin-reviewed-at'),
37
+ approvedBy: el.getAttribute('velin-approved-by'),
38
+ source: el.getAttribute('velin-source'),
39
+ license: el.getAttribute('velin-license'),
40
+ version: el.getAttribute('velin-version'),
41
+ publishedAt: el.getAttribute('velin-published-at'),
42
+ ...(options.provenance || {}),
43
+ };
44
+ }
45
+ const record = normalizeDisclosure(draft, { provider: draft.provider, lang: ctx.lang });
46
+ registry.register(record);
47
+ if (!el.hasAttribute('velin-transparency')) el.setAttribute('velin-transparency', '');
48
+ if (!el.hasAttribute('velin-transparency-id')) el.setAttribute('velin-transparency-id', record.id);
49
+ renderDisclosure(el, record);
50
+ return record;
51
+ }
52
+
53
+ /**
54
+ * Enhance all [velin-transparency] under root.
55
+ * @param {ParentNode} [root]
56
+ */
57
+ export function enhanceAll(root = typeof document !== 'undefined' ? document : null) {
58
+ if (!root?.querySelectorAll) return [];
59
+ const out = [];
60
+ root.querySelectorAll('[velin-transparency], [velin-disclosure]').forEach((el) => {
61
+ out.push(attach(el, {}, { registry: defaultRegistry }));
62
+ });
63
+ return out;
64
+ }
65
+
66
+ export function getDefaultRegistry() {
67
+ return defaultRegistry;
68
+ }
69
+
70
+ export const VelinTransparency = {
71
+ attach,
72
+ enhanceAll,
73
+ getRegistry: getDefaultRegistry,
74
+ };
@@ -0,0 +1,97 @@
1
+ /** Standardized claim taxonomy for Velin Transparency Framework. */
2
+
3
+ export const CLAIM_CATALOG = {
4
+ 'ai.generated': { pillar: 'ai', label: { en: 'AI generated', de: 'KI-generiert' } },
5
+ 'ai.assisted': { pillar: 'ai', label: { en: 'AI assisted', de: 'KI-unterstützt' } },
6
+ 'review.human': { pillar: 'ai', label: { en: 'Human reviewed', de: 'Mensch geprüft' } },
7
+ 'review.verified': { pillar: 'trust', label: { en: 'Verified', de: 'Verifiziert' } },
8
+ 'security.checked': { pillar: 'trust', label: { en: 'Security checked', de: 'Security geprüft' } },
9
+ 'accessibility.checked': { pillar: 'trust', label: { en: 'Accessibility checked', de: 'Barrierefreiheit geprüft' } },
10
+ 'trust.official': { pillar: 'trust', label: { en: 'Official', de: 'Offiziell' } },
11
+ 'trust.signed': { pillar: 'trust', label: { en: 'Signed', de: 'Signiert' } },
12
+ 'trust.opensource': { pillar: 'trust', label: { en: 'Open source', de: 'Open Source' } },
13
+ 'privacy.gdpr': { pillar: 'compliance', label: { en: 'GDPR', de: 'DSGVO' } },
14
+ 'license.cc-by': { pillar: 'compliance', label: { en: 'CC BY', de: 'CC BY' } },
15
+ 'license.mit': { pillar: 'compliance', label: { en: 'MIT', de: 'MIT' } },
16
+ 'license.apache-2': { pillar: 'compliance', label: { en: 'Apache-2.0', de: 'Apache-2.0' } },
17
+ 'content.updated': { pillar: 'metadata', label: { en: 'Updated', de: 'Aktualisiert' } },
18
+ 'content.author': { pillar: 'metadata', label: { en: 'Author', de: 'Autor' } },
19
+ 'content.source': { pillar: 'metadata', label: { en: 'Source', de: 'Quelle' } },
20
+ 'content.language': { pillar: 'metadata', label: { en: 'Language', de: 'Sprache' } },
21
+ 'version.current': { pillar: 'metadata', label: { en: 'Version', de: 'Version' } },
22
+ 'provenance.complete': { pillar: 'provenance', label: { en: 'Provenance complete', de: 'Nachweis vollständig' } },
23
+ };
24
+
25
+ const STATUS_TO_CLAIM = {
26
+ generated: 'ai.generated',
27
+ assisted: 'ai.assisted',
28
+ 'ai-assisted': 'ai.assisted',
29
+ 'human-reviewed': 'review.human',
30
+ 'human-edited': 'review.human',
31
+ verified: 'review.verified',
32
+ edited: 'review.human',
33
+ draft: null,
34
+ };
35
+
36
+ const REVIEW_TO_CLAIM = {
37
+ human: 'review.human',
38
+ 'human-reviewed': 'review.human',
39
+ verified: 'review.verified',
40
+ none: null,
41
+ };
42
+
43
+ const LICENSE_TO_CLAIM = {
44
+ 'cc by 4.0': 'license.cc-by',
45
+ 'cc-by': 'license.cc-by',
46
+ 'cc-by-4.0': 'license.cc-by',
47
+ mit: 'license.mit',
48
+ 'apache-2.0': 'license.apache-2',
49
+ apache: 'license.apache-2',
50
+ };
51
+
52
+ /**
53
+ * @param {string} [status]
54
+ * @param {string} [review]
55
+ * @param {string} [license]
56
+ * @param {string[]} [extra]
57
+ */
58
+ export function deriveClaims({ status, review, license, claims = [] } = {}) {
59
+ const out = new Set(Array.isArray(claims) ? claims.filter(Boolean) : []);
60
+ const statusClaim = STATUS_TO_CLAIM[String(status || '').toLowerCase()];
61
+ if (statusClaim) out.add(statusClaim);
62
+ const reviewClaim = REVIEW_TO_CLAIM[String(review || '').toLowerCase()];
63
+ if (reviewClaim) out.add(reviewClaim);
64
+ if (license) {
65
+ const key = String(license).toLowerCase().trim();
66
+ const mapped = LICENSE_TO_CLAIM[key] || (key.startsWith('cc') ? 'license.cc-by' : null);
67
+ if (mapped) out.add(mapped);
68
+ }
69
+ return [...out];
70
+ }
71
+
72
+ /**
73
+ * @param {string} claim
74
+ * @param {'en'|'de'} [lang]
75
+ */
76
+ export function claimLabel(claim, lang = 'en') {
77
+ const entry = CLAIM_CATALOG[claim];
78
+ if (!entry) return claim;
79
+ return entry.label[lang] || entry.label.en || claim;
80
+ }
81
+
82
+ /**
83
+ * @param {string[]} claims
84
+ * @param {'en'|'de'} [lang]
85
+ */
86
+ export function primaryLabel(claims = [], lang = 'en') {
87
+ const order = ['ai.generated', 'ai.assisted', 'review.human', 'review.verified', 'trust.official', 'license.cc-by', 'license.mit'];
88
+ for (const c of order) {
89
+ if (claims.includes(c)) return claimLabel(c, lang);
90
+ }
91
+ if (claims[0]) return claimLabel(claims[0], lang);
92
+ return lang === 'de' ? 'Transparenz' : 'Transparency';
93
+ }
94
+
95
+ export function pillarForClaim(claim) {
96
+ return CLAIM_CATALOG[claim]?.pillar || (String(claim).startsWith('custom.') ? 'custom' : 'metadata');
97
+ }
@@ -0,0 +1,142 @@
1
+ import { collectAllDisclosures } from './providers.js';
2
+ import { validateRecords, inferMediaKind } from './validator.js';
3
+ import { mediaRequirement, requiredProvenanceFields } from './policy.js';
4
+ import { createRegistry } from './registry.js';
5
+ import { pillarForClaim } from './claims.js';
6
+
7
+ /**
8
+ * Run transparency doctor on HTML string (or precollected context).
9
+ * @param {string} html
10
+ * @param {{ policy: object, file?: string, lang?: string, meta?: object }} ctx
11
+ */
12
+ export async function transparencyDoctor(html, ctx) {
13
+ const { records, conflicts } = await collectAllDisclosures(html, ctx);
14
+ const registry = createRegistry();
15
+ for (const r of records) registry.register(r);
16
+
17
+ const findings = [];
18
+ for (const c of conflicts) {
19
+ findings.push({
20
+ severity: 'warning',
21
+ code: 'conflict',
22
+ message: `Conflicting fields [${c.keys.join(', ')}] from providers ${(c.providers || []).join(' > ')}`,
23
+ id: c.id,
24
+ });
25
+ }
26
+ findings.push(...validateRecords(records, ctx.policy));
27
+
28
+ // Media coverage
29
+ const media = scanMediaTargets(html);
30
+ const coveredSrc = new Set(
31
+ records.map((r) => (r.target?.src || '').split('?')[0].toLowerCase()).filter(Boolean),
32
+ );
33
+ const coveredSelectors = new Set(records.map((r) => r.target?.selector).filter(Boolean));
34
+
35
+ for (const item of media) {
36
+ const req = mediaRequirement(item.kind, ctx.policy);
37
+ if (req !== 'required') continue;
38
+ const srcKey = (item.src || '').split('?')[0].toLowerCase();
39
+ const has =
40
+ (item.id && coveredSelectors.has(`#${item.id}`))
41
+ || (srcKey && coveredSrc.has(srcKey))
42
+ || records.some((r) => r.target?.tag === item.tag && !r.target?.src && item.kind === inferMediaKind(r));
43
+ // Better: check if element itself has velin-transparency in opening tag
44
+ if (item.disclosed) continue;
45
+ if (!has) {
46
+ findings.push({
47
+ severity: 'error',
48
+ code: `missing-disclosure.${item.kind}`,
49
+ message: `Required ${item.kind} lacks velin-transparency (${item.tag}${item.src ? ` ${item.src}` : ''})`,
50
+ id: item.id || null,
51
+ target: item,
52
+ });
53
+ }
54
+ }
55
+
56
+ const scores = computeScores(records, findings, media, ctx.policy);
57
+ return {
58
+ ok: !findings.some((f) => f.severity === 'error'),
59
+ file: ctx.file || null,
60
+ registry: registry.export(),
61
+ findings,
62
+ scores,
63
+ summary: {
64
+ disclosures: records.length,
65
+ media: media.length,
66
+ errors: findings.filter((f) => f.severity === 'error').length,
67
+ warnings: findings.filter((f) => f.severity === 'warning').length,
68
+ info: findings.filter((f) => f.severity === 'info').length,
69
+ },
70
+ };
71
+ }
72
+
73
+ function scanMediaTargets(html) {
74
+ const out = [];
75
+ const re = /<(img|video|audio|a|embed|object)(\s[^>]*)?>/gi;
76
+ let m;
77
+ while ((m = re.exec(html))) {
78
+ const tag = m[1].toUpperCase();
79
+ const attrs = m[2] || '';
80
+ const src = attrs.match(/\b(?:src|href)=["']([^"']+)["']/i)?.[1] || '';
81
+ const id = attrs.match(/\bid=["']([^"']+)["']/i)?.[1];
82
+ const disclosed = /\bvelin-transparency\b/i.test(attrs) || /\bvelin-disclosure\b/i.test(attrs);
83
+ let kind = 'text';
84
+ if (tag === 'IMG') kind = 'images';
85
+ else if (tag === 'VIDEO') kind = 'videos';
86
+ else if (tag === 'AUDIO') kind = 'audio';
87
+ else if (/\.pdf(\?|$)/i.test(src) || /application\/pdf/i.test(attrs)) kind = 'pdf';
88
+ else if (tag === 'A' && !/\.pdf(\?|$)/i.test(src)) continue;
89
+ else if (tag === 'EMBED' || tag === 'OBJECT') {
90
+ if (/\.pdf/i.test(src) || /pdf/i.test(attrs)) kind = 'pdf';
91
+ else continue;
92
+ }
93
+ out.push({ tag, src, id, kind, disclosed });
94
+ }
95
+ return out;
96
+ }
97
+
98
+ function computeScores(records, findings, media, policy) {
99
+ const pillars = { ai: [], trust: [], compliance: [], metadata: [], provenance: [] };
100
+ for (const r of records) {
101
+ for (const c of r.claims || []) {
102
+ const p = pillarForClaim(c);
103
+ if (pillars[p]) pillars[p].push(true);
104
+ }
105
+ const kind = inferMediaKind(r);
106
+ const req = requiredCount(kind, policy);
107
+ const have = Object.keys(r.provenance || {}).length;
108
+ pillars.provenance.push(req === 0 ? true : have >= req);
109
+ }
110
+
111
+ const requiredMedia = media.filter((m) => mediaRequirement(m.kind, policy) === 'required');
112
+ const missingMedia = findings.filter((f) => String(f.code).startsWith('missing-disclosure.')).length;
113
+ const coverage = requiredMedia.length
114
+ ? Math.round(((requiredMedia.length - missingMedia) / requiredMedia.length) * 100)
115
+ : 100;
116
+
117
+ const pillarScore = (arr) => {
118
+ if (!arr.length) return records.length ? 100 : coverage;
119
+ return Math.round((arr.filter(Boolean).length / arr.length) * 100);
120
+ };
121
+
122
+ const errors = findings.filter((f) => f.severity === 'error').length;
123
+ const transparency = Math.max(0, Math.min(100, Math.round(
124
+ (coverage * 0.45)
125
+ + (pillarScore(pillars.provenance) * 0.25)
126
+ + (Math.max(0, 100 - errors * 8) * 0.3),
127
+ )));
128
+
129
+ return {
130
+ transparency,
131
+ ai: pillarScore(pillars.ai),
132
+ trust: pillarScore(pillars.trust),
133
+ metadata: pillarScore(pillars.metadata),
134
+ compliance: pillarScore(pillars.compliance),
135
+ provenance: pillarScore(pillars.provenance),
136
+ coverage,
137
+ };
138
+ }
139
+
140
+ function requiredCount(kind, policy) {
141
+ return requiredProvenanceFields(kind, policy).length;
142
+ }
@@ -0,0 +1,75 @@
1
+ import { normalizePolicy } from './policy.js';
2
+ import { createRegistry } from './registry.js';
3
+ import { collectAllDisclosures } from './providers.js';
4
+ import { validateRecords } from './validator.js';
5
+ import { transparencyDoctor } from './doctor.js';
6
+ import { buildTransparencyReports } from './reporter.js';
7
+ import { exportDisclosures } from './export.js';
8
+ import { transparencyMigrate } from './migrate.js';
9
+ import { normalizeDisclosure } from './normalize.js';
10
+
11
+ /**
12
+ * Create a Transparency Engine instance.
13
+ * @param {{ policy?: object, lang?: 'en'|'de' }} [options]
14
+ */
15
+ export function createTransparencyEngine(options = {}) {
16
+ const policy = normalizePolicy(options.policy);
17
+ const registry = createRegistry();
18
+ const lang = options.lang === 'de' ? 'de' : 'en';
19
+
20
+ return {
21
+ policy,
22
+ registry,
23
+ lang,
24
+
25
+ /**
26
+ * Collect → validate → register from HTML string / DOM / JSON.
27
+ */
28
+ async ingest(root, ctx = {}) {
29
+ const { records, conflicts } = await collectAllDisclosures(root, {
30
+ policy,
31
+ lang,
32
+ file: ctx.file,
33
+ meta: ctx.meta,
34
+ apiDisclosures: ctx.apiDisclosures,
35
+ });
36
+ registry.clear();
37
+ for (const r of records) registry.register(r);
38
+ const findings = validateRecords(records, policy);
39
+ return { records, conflicts, findings, registry: registry.export() };
40
+ },
41
+
42
+ register(draft, ctx = {}) {
43
+ const record = normalizeDisclosure(draft, { provider: draft.provider || 'api', lang, file: ctx.file });
44
+ return registry.register(record);
45
+ },
46
+
47
+ async doctor(html, ctx = {}) {
48
+ return transparencyDoctor(html, { policy, lang, ...ctx });
49
+ },
50
+
51
+ async validate(html, ctx = {}) {
52
+ const report = await transparencyDoctor(html, { policy, lang, ...ctx });
53
+ return {
54
+ ok: report.ok && !report.findings.some((f) => f.severity === 'error'),
55
+ findings: report.findings,
56
+ scores: report.scores,
57
+ };
58
+ },
59
+
60
+ async report(html, ctx = {}) {
61
+ const doctor = await transparencyDoctor(html, { policy, lang, ...ctx });
62
+ return buildTransparencyReports(doctor, { title: ctx.title });
63
+ },
64
+
65
+ export(format = 'json') {
66
+ return exportDisclosures(registry.list(), format);
67
+ },
68
+
69
+ async migrate(html, ctx = {}) {
70
+ return transparencyMigrate(html, { policy, lang, ...ctx });
71
+ },
72
+ };
73
+ }
74
+
75
+ export const TransparencyMIME = 'application/vnd.velinstyle.transparency+json';
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Export registry items to interoperable formats.
3
+ * @param {import('./registry.js').DisclosureRecord[]} items
4
+ * @param {'json'|'json-ld'|'csv'|'html'} format
5
+ */
6
+ export function exportDisclosures(items, format = 'json') {
7
+ switch (format) {
8
+ case 'json-ld':
9
+ return JSON.stringify(toJsonLd(items), null, 2);
10
+ case 'csv':
11
+ return toCsv(items);
12
+ case 'html':
13
+ return toHtmlTable(items);
14
+ case 'json':
15
+ default:
16
+ return JSON.stringify({
17
+ schema: 'velinstyle.transparency.export',
18
+ mime: 'application/vnd.velinstyle.transparency+json',
19
+ version: 1,
20
+ exportedAt: new Date().toISOString(),
21
+ items,
22
+ }, null, 2);
23
+ }
24
+ }
25
+
26
+ function toJsonLd(items) {
27
+ return {
28
+ '@context': 'https://schema.org',
29
+ '@graph': items.map((r) => ({
30
+ '@type': 'CreativeWork',
31
+ '@id': r.id,
32
+ name: r.label,
33
+ description: r.description,
34
+ creativeWorkStatus: r.status,
35
+ dateCreated: r.provenance?.createdAt,
36
+ dateModified: r.updated || r.provenance?.reviewedAt,
37
+ version: r.provenance?.version,
38
+ license: r.provenance?.license,
39
+ author: r.provenance?.createdBy
40
+ ? { '@type': 'Person', name: r.provenance.createdBy }
41
+ : undefined,
42
+ contributor: r.provenance?.approvedBy
43
+ ? { '@type': 'Person', name: r.provenance.approvedBy }
44
+ : undefined,
45
+ isBasedOn: r.provenance?.source,
46
+ additionalProperty: (r.claims || []).map((c) => ({
47
+ '@type': 'PropertyValue',
48
+ name: 'velin.claim',
49
+ value: c,
50
+ })),
51
+ })),
52
+ };
53
+ }
54
+
55
+ function toCsv(items) {
56
+ const headers = [
57
+ 'id', 'type', 'status', 'review', 'label', 'claims',
58
+ 'createdBy', 'createdAt', 'reviewedAt', 'approvedBy', 'source', 'license', 'version', 'publishedAt',
59
+ ];
60
+ const lines = [headers.join(',')];
61
+ for (const r of items) {
62
+ const p = r.provenance || {};
63
+ const row = [
64
+ r.id, r.type, r.status, r.review, r.label, (r.claims || []).join('|'),
65
+ p.createdBy, p.createdAt, p.reviewedAt, p.approvedBy, p.source, p.license, p.version, p.publishedAt,
66
+ ].map(csvEscape);
67
+ lines.push(row.join(','));
68
+ }
69
+ return `${lines.join('\n')}\n`;
70
+ }
71
+
72
+ function csvEscape(v) {
73
+ const s = String(v ?? '');
74
+ if (/[",\n]/.test(s)) return `"${s.replace(/"/g, '""')}"`;
75
+ return s;
76
+ }
77
+
78
+ function toHtmlTable(items) {
79
+ const rows = items.map((r) => {
80
+ const p = r.provenance || {};
81
+ return `<tr>
82
+ <td>${esc(r.id)}</td><td>${esc(r.label)}</td><td>${esc((r.claims || []).join(', '))}</td>
83
+ <td>${esc(p.createdBy)}</td><td>${esc(p.createdAt)}</td><td>${esc(p.approvedBy)}</td>
84
+ <td>${esc(p.license)}</td><td>${esc(p.version)}</td><td>${esc(p.source)}</td>
85
+ </tr>`;
86
+ }).join('');
87
+ return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><title>Transparency export</title></head>
88
+ <body><table border="1" cellpadding="6">
89
+ <thead><tr><th>Id</th><th>Label</th><th>Claims</th><th>Created by</th><th>Created</th><th>Approved by</th><th>License</th><th>Version</th><th>Source</th></tr></thead>
90
+ <tbody>${rows}</tbody></table></body></html>`;
91
+ }
92
+
93
+ function esc(s) {
94
+ return String(s ?? '')
95
+ .replace(/&/g, '&amp;')
96
+ .replace(/</g, '&lt;')
97
+ .replace(/>/g, '&gt;');
98
+ }