generator-white-label 5.0.1 → 8.0.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 (299) hide show
  1. package/.editorconfig +15 -0
  2. package/.yarnrc.yml +6 -0
  3. package/CLI.md +82 -0
  4. package/LICENSE +9 -0
  5. package/PACKAGE_MANAGERS.md +35 -0
  6. package/README.md +204 -124
  7. package/app/404.tsx +28 -0
  8. package/app/README.md +66 -8
  9. package/app/assets/data/view/global.json +7 -47
  10. package/app/assets/data/view/index.json +9 -1
  11. package/app/assets/script/index.tsx +13 -0
  12. package/app/assets/script/tasks/TaskApplication.ts +77 -0
  13. package/app/assets/script/tasks/TaskMediator.ts +20 -0
  14. package/app/assets/script/tasks/TaskModel.ts +32 -0
  15. package/app/assets/script/tasks/TaskRouter.ts +30 -0
  16. package/app/assets/script/tasks/TaskView.tsx +24 -0
  17. package/app/assets/style/global.css +111 -0
  18. package/app/assets/style/print.css +8 -0
  19. package/app/assets/view/CodeBlock.tsx +17 -0
  20. package/app/assets/view/examples/tasks/TaskExample.tsx +63 -0
  21. package/app/assets/view/examples/tasks/task-state.ts +46 -0
  22. package/app/assets/view/layout/SiteFooter.tsx +11 -0
  23. package/app/assets/view/layout/SiteHeader.tsx +23 -0
  24. package/app/assets/view/page-data.ts +14 -0
  25. package/app/assets/view/sections/GettingStartedSection.tsx +27 -0
  26. package/app/assets/view/sections/HeroSection.tsx +21 -0
  27. package/app/assets/view/sections/LiveExampleSection.tsx +29 -0
  28. package/app/assets/view/sections/PackageDocsSection.tsx +69 -0
  29. package/app/assets/view/sections/SourceGuideSection.tsx +28 -0
  30. package/app/index.tsx +54 -0
  31. package/cli/index.ts +117 -0
  32. package/dist/app/404.d.ts +1 -0
  33. package/dist/app/404.js +6 -0
  34. package/dist/app/404.js.map +1 -0
  35. package/dist/app/assets/script/index.d.ts +8 -2
  36. package/dist/app/assets/script/index.js +11 -1
  37. package/dist/app/assets/script/index.js.map +1 -1
  38. package/dist/app/assets/script/tasks/TaskApplication.d.ts +20 -0
  39. package/dist/app/assets/script/tasks/TaskApplication.js +63 -0
  40. package/dist/app/assets/script/tasks/TaskApplication.js.map +1 -0
  41. package/dist/app/assets/script/tasks/TaskMediator.d.ts +15 -0
  42. package/dist/app/assets/script/tasks/TaskMediator.js +5 -0
  43. package/dist/app/assets/script/tasks/TaskMediator.js.map +1 -0
  44. package/dist/app/assets/script/tasks/TaskModel.d.ts +13 -0
  45. package/dist/app/assets/script/tasks/TaskModel.js +33 -0
  46. package/dist/app/assets/script/tasks/TaskModel.js.map +1 -0
  47. package/dist/app/assets/script/tasks/TaskRouter.d.ts +12 -0
  48. package/dist/app/assets/script/tasks/TaskRouter.js +28 -0
  49. package/dist/app/assets/script/tasks/TaskRouter.js.map +1 -0
  50. package/dist/app/assets/script/tasks/TaskView.d.ts +9 -0
  51. package/dist/app/assets/script/tasks/TaskView.js +24 -0
  52. package/dist/app/assets/script/tasks/TaskView.js.map +1 -0
  53. package/dist/app/assets/view/CodeBlock.d.ts +11 -0
  54. package/dist/app/assets/view/CodeBlock.js +12 -0
  55. package/dist/app/assets/view/CodeBlock.js.map +1 -0
  56. package/dist/app/assets/view/examples/tasks/TaskExample.d.ts +11 -0
  57. package/dist/app/assets/view/examples/tasks/TaskExample.js +16 -0
  58. package/dist/app/assets/view/examples/tasks/TaskExample.js.map +1 -0
  59. package/dist/app/assets/view/examples/tasks/task-state.d.ts +22 -0
  60. package/dist/app/assets/view/examples/tasks/task-state.js +30 -0
  61. package/dist/app/assets/view/examples/tasks/task-state.js.map +1 -0
  62. package/dist/app/assets/view/layout/SiteFooter.d.ts +2 -0
  63. package/dist/app/assets/view/layout/SiteFooter.js +6 -0
  64. package/dist/app/assets/view/layout/SiteFooter.js.map +1 -0
  65. package/dist/app/assets/view/layout/SiteHeader.d.ts +8 -0
  66. package/dist/app/assets/view/layout/SiteHeader.js +12 -0
  67. package/dist/app/assets/view/layout/SiteHeader.js.map +1 -0
  68. package/dist/app/assets/view/page-data.d.ts +16 -0
  69. package/dist/app/assets/view/page-data.js +2 -0
  70. package/dist/app/assets/view/page-data.js.map +1 -0
  71. package/dist/app/assets/view/sections/GettingStartedSection.d.ts +2 -0
  72. package/dist/app/assets/view/sections/GettingStartedSection.js +11 -0
  73. package/dist/app/assets/view/sections/GettingStartedSection.js.map +1 -0
  74. package/dist/app/assets/view/sections/HeroSection.d.ts +8 -0
  75. package/dist/app/assets/view/sections/HeroSection.js +12 -0
  76. package/dist/app/assets/view/sections/HeroSection.js.map +1 -0
  77. package/dist/app/assets/view/sections/LiveExampleSection.d.ts +6 -0
  78. package/dist/app/assets/view/sections/LiveExampleSection.js +13 -0
  79. package/dist/app/assets/view/sections/LiveExampleSection.js.map +1 -0
  80. package/dist/app/assets/view/sections/PackageDocsSection.d.ts +2 -0
  81. package/dist/app/assets/view/sections/PackageDocsSection.js +31 -0
  82. package/dist/app/assets/view/sections/PackageDocsSection.js.map +1 -0
  83. package/dist/app/assets/view/sections/SourceGuideSection.d.ts +7 -0
  84. package/dist/app/assets/view/sections/SourceGuideSection.js +11 -0
  85. package/dist/app/assets/view/sections/SourceGuideSection.js.map +1 -0
  86. package/dist/app/index.d.ts +8 -0
  87. package/dist/app/index.js +22 -0
  88. package/dist/app/index.js.map +1 -0
  89. package/dist/cli/index.d.ts +13 -0
  90. package/dist/cli/index.js +97 -0
  91. package/dist/cli/index.js.map +1 -0
  92. package/dist/scaffold/index.d.ts +64 -0
  93. package/dist/scaffold/index.js +109 -0
  94. package/dist/scaffold/index.js.map +1 -0
  95. package/dist/scripts/build.d.ts +5 -13
  96. package/dist/scripts/build.js +48 -79
  97. package/dist/scripts/build.js.map +1 -1
  98. package/package.json +77 -40
  99. package/pnpm-workspace.yaml +4 -0
  100. package/scaffold/index.ts +127 -0
  101. package/scaffold/no-jsx/README.md +47 -0
  102. package/scaffold/no-jsx/app/404.ts +10 -0
  103. package/scaffold/no-jsx/app/assets/script/index.ts +7 -0
  104. package/scaffold/no-jsx/app/assets/script/tasks/TaskView.ts +19 -0
  105. package/scaffold/no-jsx/app/assets/view/examples/tasks/TaskExample.ts +39 -0
  106. package/scaffold/no-jsx/app/index.ts +58 -0
  107. package/scripts/build.ts +55 -86
  108. package/server/handler.ts +75 -0
  109. package/template-test/site.test.js +233 -0
  110. package/tsconfig.site.json +6 -5
  111. package/tsconfig.site.no-jsx.json +24 -0
  112. package/app/404.hbs +0 -20
  113. package/app/assets/data/coutries.json +0 -992
  114. package/app/assets/data/states.json +0 -204
  115. package/app/assets/data/view/toolkit/colors.json +0 -17
  116. package/app/assets/data/view/toolkit/components.json +0 -39
  117. package/app/assets/data/view/toolkit/elements.json +0 -119
  118. package/app/assets/data/view/toolkit/grids.json +0 -17
  119. package/app/assets/data/view/toolkit/icons.json +0 -17
  120. package/app/assets/data/view/toolkit/index.json +0 -17
  121. package/app/assets/data/view/toolkit/type.json +0 -17
  122. package/app/assets/font/opensans/LICENSE.txt +0 -202
  123. package/app/assets/font/opensans/opensans-bold-webfont.woff2 +0 -0
  124. package/app/assets/font/opensans/opensans-bolditalic-webfont.woff2 +0 -0
  125. package/app/assets/font/opensans/opensans-extrabold-webfont.woff2 +0 -0
  126. package/app/assets/font/opensans/opensans-extrabolditalic-webfont.woff2 +0 -0
  127. package/app/assets/font/opensans/opensans-italic-webfont.woff2 +0 -0
  128. package/app/assets/font/opensans/opensans-light-webfont.woff2 +0 -0
  129. package/app/assets/font/opensans/opensans-lightitalic-webfont.woff2 +0 -0
  130. package/app/assets/font/opensans/opensans-regular-webfont.woff2 +0 -0
  131. package/app/assets/font/opensans/opensans-semibold-webfont.woff2 +0 -0
  132. package/app/assets/font/opensans/opensans-semibolditalic-webfont.woff2 +0 -0
  133. package/app/assets/font/opensans/stylesheet.css +0 -120
  134. package/app/assets/image/apple-touch-icon.png +0 -0
  135. package/app/assets/image/demo/fallback.avif +0 -0
  136. package/app/assets/image/demo/fallback.jpg +0 -0
  137. package/app/assets/image/demo/fallback.webp +0 -0
  138. package/app/assets/image/demo/large.avif +0 -0
  139. package/app/assets/image/demo/large.webp +0 -0
  140. package/app/assets/image/demo/small.avif +0 -0
  141. package/app/assets/image/demo/small.webp +0 -0
  142. package/app/assets/image/favicon.png +0 -0
  143. package/app/assets/image/graphic-css3.svg +0 -30
  144. package/app/assets/image/graphic-html5.svg +0 -29
  145. package/app/assets/markup/element/a.hbs +0 -29
  146. package/app/assets/markup/element/button.hbs +0 -30
  147. package/app/assets/markup/element/div.hbs +0 -11
  148. package/app/assets/markup/element/head.hbs +0 -78
  149. package/app/assets/markup/element/iframe.hbs +0 -20
  150. package/app/assets/markup/element/img.hbs +0 -30
  151. package/app/assets/markup/element/input.hbs +0 -43
  152. package/app/assets/markup/element/label.hbs +0 -14
  153. package/app/assets/markup/element/legend.hbs +0 -5
  154. package/app/assets/markup/element/meta.hbs +0 -11
  155. package/app/assets/markup/element/nav.hbs +0 -13
  156. package/app/assets/markup/element/p.hbs +0 -8
  157. package/app/assets/markup/element/picture.hbs +0 -58
  158. package/app/assets/markup/element/script.hbs +0 -3
  159. package/app/assets/markup/element/select.hbs +0 -35
  160. package/app/assets/markup/element/span.hbs +0 -8
  161. package/app/assets/markup/element/svg.hbs +0 -11
  162. package/app/assets/markup/element/table.hbs +0 -50
  163. package/app/assets/markup/element/textarea.hbs +0 -24
  164. package/app/assets/markup/element/ul.hbs +0 -13
  165. package/app/assets/markup/modal/modal-example-1.handlebars +0 -8
  166. package/app/assets/markup/toolkit/accessibility-skip-to-element-1.handlebars +0 -1
  167. package/app/assets/markup/toolkit/accessibility-speaker-1.handlebars +0 -1
  168. package/app/assets/markup/toolkit/anchor-1.handlebars +0 -1
  169. package/app/assets/markup/toolkit/button-1.handlebars +0 -1
  170. package/app/assets/markup/toolkit/footer-1.handlebars +0 -3
  171. package/app/assets/markup/toolkit/header-1.handlebars +0 -1
  172. package/app/assets/markup/toolkit/heading-1.handlebars +0 -1
  173. package/app/assets/markup/toolkit/heading-2.handlebars +0 -1
  174. package/app/assets/markup/toolkit/heading-3.handlebars +0 -1
  175. package/app/assets/markup/toolkit/heading-4.handlebars +0 -1
  176. package/app/assets/markup/toolkit/image-1.handlebars +0 -1
  177. package/app/assets/markup/toolkit/input-checkbox-1.handlebars +0 -1
  178. package/app/assets/markup/toolkit/input-error-1.handlebars +0 -8
  179. package/app/assets/markup/toolkit/input-radio-1.handlebars +0 -1
  180. package/app/assets/markup/toolkit/input-text-1.handlebars +0 -1
  181. package/app/assets/markup/toolkit/label-1.handlebars +0 -1
  182. package/app/assets/markup/toolkit/legend-1.handlebars +0 -1
  183. package/app/assets/markup/toolkit/list-1.handlebars +0 -1
  184. package/app/assets/markup/toolkit/modal-1.handlebars +0 -4
  185. package/app/assets/markup/toolkit/nav-1.handlebars +0 -1
  186. package/app/assets/markup/toolkit/picture-1.handlebars +0 -1
  187. package/app/assets/markup/toolkit/select-1.handlebars +0 -1
  188. package/app/assets/markup/toolkit/table-1.handlebars +0 -1
  189. package/app/assets/markup/toolkit/text-1.handlebars +0 -1
  190. package/app/assets/markup/toolkit/textarea-1.handlebars +0 -1
  191. package/app/assets/markup/toolkit/youtube-player-1.handlebars +0 -1
  192. package/app/assets/script/api/facebook.ts +0 -41
  193. package/app/assets/script/api/youtube.ts +0 -22
  194. package/app/assets/script/index.ts +0 -2
  195. package/app/assets/script/mediator/global.ts +0 -4
  196. package/app/assets/script/model/singletons/countries.ts +0 -5
  197. package/app/assets/script/model/singletons/global.ts +0 -5
  198. package/app/assets/script/model/singletons/states.ts +0 -5
  199. package/app/assets/script/model/user.ts +0 -4
  200. package/app/assets/script/toolkit.ts +0 -11
  201. package/app/assets/script/types.d.ts +0 -6
  202. package/app/assets/script/utility/ajax.ts +0 -15
  203. package/app/assets/script/utility/form.ts +0 -119
  204. package/app/assets/script/utility/regex.ts +0 -26
  205. package/app/assets/script/utility/share.ts +0 -77
  206. package/app/assets/script/utility/string.ts +0 -148
  207. package/app/assets/script/view/default.tsx +0 -14
  208. package/app/assets/script/view/toolkit/youtube-player-1.ts +0 -33
  209. package/app/assets/style/base/_toolkit.scss +0 -39
  210. package/app/assets/style/base/colors/_colors.scss +0 -18
  211. package/app/assets/style/base/components/_modal-1.scss +0 -80
  212. package/app/assets/style/base/components/_sticky-1.scss +0 -19
  213. package/app/assets/style/base/components/_tabpanel-1.scss +0 -115
  214. package/app/assets/style/base/components/_tabpanel-2.scss +0 -64
  215. package/app/assets/style/base/components/_tabpanel-base-1.scss +0 -13
  216. package/app/assets/style/base/components/_youtube-player-1.scss +0 -16
  217. package/app/assets/style/base/elements/_anchors.scss +0 -27
  218. package/app/assets/style/base/elements/_buttons.scss +0 -25
  219. package/app/assets/style/base/elements/_fieldsets.scss +0 -9
  220. package/app/assets/style/base/elements/_images.scss +0 -8
  221. package/app/assets/style/base/elements/_inputs.scss +0 -78
  222. package/app/assets/style/base/elements/_labels.scss +0 -16
  223. package/app/assets/style/base/elements/_landmarks.scss +0 -3
  224. package/app/assets/style/base/elements/_legends.scss +0 -11
  225. package/app/assets/style/base/elements/_lists.scss +0 -15
  226. package/app/assets/style/base/elements/_pictures.scss +0 -4
  227. package/app/assets/style/base/elements/_tables.scss +0 -39
  228. package/app/assets/style/base/layouts/_staggered-1.scss +0 -29
  229. package/app/assets/style/base/type/_fonts.scss +0 -125
  230. package/app/assets/style/base/type/_headings.scss +0 -36
  231. package/app/assets/style/base/type/_text.scss +0 -9
  232. package/app/assets/style/base/utilities/_accessibility.scss +0 -55
  233. package/app/assets/style/base/utilities/_functions.scss +0 -98
  234. package/app/assets/style/base/utilities/_scroll.scss +0 -11
  235. package/app/assets/style/base/utilities/_type.scss +0 -13
  236. package/app/assets/style/global.scss +0 -123
  237. package/app/assets/style/print.scss +0 -6
  238. package/app/assets/style/toolkit.scss +0 -387
  239. package/app/index.hbs +0 -21
  240. package/app/robots.txt +0 -1
  241. package/app/toolkit/colors.hbs +0 -102
  242. package/app/toolkit/components.hbs +0 -261
  243. package/app/toolkit/elements.hbs +0 -497
  244. package/app/toolkit/grids.hbs +0 -413
  245. package/app/toolkit/icons.hbs +0 -87
  246. package/app/toolkit/index.hbs +0 -144
  247. package/app/toolkit/type.hbs +0 -120
  248. package/dist/app/assets/data/coutries.json +0 -992
  249. package/dist/app/assets/data/states.json +0 -204
  250. package/dist/app/assets/script/api/facebook.d.ts +0 -8
  251. package/dist/app/assets/script/api/facebook.js +0 -42
  252. package/dist/app/assets/script/api/facebook.js.map +0 -1
  253. package/dist/app/assets/script/api/youtube.d.ts +0 -8
  254. package/dist/app/assets/script/api/youtube.js +0 -22
  255. package/dist/app/assets/script/api/youtube.js.map +0 -1
  256. package/dist/app/assets/script/mediator/global.d.ts +0 -4
  257. package/dist/app/assets/script/mediator/global.js +0 -4
  258. package/dist/app/assets/script/mediator/global.js.map +0 -1
  259. package/dist/app/assets/script/model/singletons/countries.d.ts +0 -4
  260. package/dist/app/assets/script/model/singletons/countries.js +0 -5
  261. package/dist/app/assets/script/model/singletons/countries.js.map +0 -1
  262. package/dist/app/assets/script/model/singletons/global.d.ts +0 -4
  263. package/dist/app/assets/script/model/singletons/global.js +0 -5
  264. package/dist/app/assets/script/model/singletons/global.js.map +0 -1
  265. package/dist/app/assets/script/model/singletons/states.d.ts +0 -4
  266. package/dist/app/assets/script/model/singletons/states.js +0 -5
  267. package/dist/app/assets/script/model/singletons/states.js.map +0 -1
  268. package/dist/app/assets/script/model/user.d.ts +0 -4
  269. package/dist/app/assets/script/model/user.js +0 -6
  270. package/dist/app/assets/script/model/user.js.map +0 -1
  271. package/dist/app/assets/script/toolkit.d.ts +0 -1
  272. package/dist/app/assets/script/toolkit.js +0 -7
  273. package/dist/app/assets/script/toolkit.js.map +0 -1
  274. package/dist/app/assets/script/utility/ajax.d.ts +0 -8
  275. package/dist/app/assets/script/utility/ajax.js +0 -17
  276. package/dist/app/assets/script/utility/ajax.js.map +0 -1
  277. package/dist/app/assets/script/utility/form.d.ts +0 -64
  278. package/dist/app/assets/script/utility/form.js +0 -111
  279. package/dist/app/assets/script/utility/form.js.map +0 -1
  280. package/dist/app/assets/script/utility/regex.d.ts +0 -14
  281. package/dist/app/assets/script/utility/regex.js +0 -27
  282. package/dist/app/assets/script/utility/regex.js.map +0 -1
  283. package/dist/app/assets/script/utility/share.d.ts +0 -68
  284. package/dist/app/assets/script/utility/share.js +0 -81
  285. package/dist/app/assets/script/utility/share.js.map +0 -1
  286. package/dist/app/assets/script/utility/string.d.ts +0 -64
  287. package/dist/app/assets/script/utility/string.js +0 -135
  288. package/dist/app/assets/script/utility/string.js.map +0 -1
  289. package/dist/app/assets/script/view/default.d.ts +0 -11
  290. package/dist/app/assets/script/view/default.js +0 -15
  291. package/dist/app/assets/script/view/default.js.map +0 -1
  292. package/dist/app/assets/script/view/toolkit/youtube-player-1.d.ts +0 -23
  293. package/dist/app/assets/script/view/toolkit/youtube-player-1.js +0 -34
  294. package/dist/app/assets/script/view/toolkit/youtube-player-1.js.map +0 -1
  295. package/dist/generators/app/index.d.ts +0 -18
  296. package/dist/generators/app/index.js +0 -59
  297. package/dist/generators/app/index.js.map +0 -1
  298. package/generators/app/index.js +0 -2
  299. package/generators/app/index.ts +0 -61
package/package.json CHANGED
@@ -1,37 +1,62 @@
1
1
  {
2
2
  "name": "generator-white-label",
3
- "version": "5.0.1",
4
- "description": "Scaffolding for developing and building static sites.",
3
+ "version": "8.0.0",
4
+ "description": "Framework-independent TypeScript project generator for accessible, SEO-friendly sites with progressive enhancement, optional JSX, and a provider-neutral serverless handler example.",
5
5
  "type": "module",
6
- "main": "dist/generators/app/index.js",
6
+ "main": "dist/scaffold/index.js",
7
+ "bin": {
8
+ "generator-white-label": "dist/cli/index.js",
9
+ "white-label": "dist/cli/index.js"
10
+ },
7
11
  "engines": {
8
- "node": "^22.18.0 || >=24.11.0",
9
- "npm": ">=10.0"
12
+ "node": "^22.18.0 || >=24.11.0"
10
13
  },
11
14
  "scripts": {
12
15
  "build": "tsc -p tsconfig.json && node dist/scripts/build.js",
13
- "test": "npm run compile && npm run test:types && npm run test:unit",
16
+ "test": "node --run compile && node --run test:types && node --run test:unit",
14
17
  "audit": "npm audit --audit-level=low",
15
18
  "compile": "tsc -p tsconfig.json",
16
19
  "typecheck": "tsc -p tsconfig.json --noEmit",
17
20
  "test:unit": "node --test test/*.test.js",
18
- "coverage": "npm run compile && npm run test:types && c8 npm run test:unit",
19
- "prepack": "npm run compile",
20
- "test:types": "tsc -p tsconfig.consumer.json"
21
+ "coverage": "node --run compile && node --run test:types && c8 node --run test:unit",
22
+ "prepack": "node --run compile",
23
+ "test:types": "tsc -p tsconfig.consumer.json",
24
+ "lint": "eslint \"cli/**/*.ts\" \"scripts/**/*.ts\" \"scaffold/**/*.ts\" \"server/**/*.ts\" \"app/**/*.{ts,tsx}\" --max-warnings=0",
25
+ "lint:fix": "node --run lint -- --fix"
21
26
  },
22
27
  "files": [
28
+ ".editorconfig",
29
+ ".yarnrc.yml",
30
+ "pnpm-workspace.yaml",
23
31
  "app",
24
- "generators",
32
+ "cli",
33
+ "scaffold",
34
+ "server",
25
35
  "scripts",
36
+ "template-test",
26
37
  "README.md",
38
+ "CLI.md",
39
+ "PACKAGE_MANAGERS.md",
27
40
  "dist",
28
- "tsconfig.site.json"
41
+ "tsconfig.site.json",
42
+ "tsconfig.site.no-jsx.json"
29
43
  ],
30
44
  "keywords": [
31
- "handlebars",
32
- "sass",
45
+ "typescript",
46
+ "project-generator",
47
+ "static-site-generator",
48
+ "web-development",
49
+ "framework-independent",
50
+ "accessibility",
51
+ "seo",
52
+ "progressive-enhancement",
53
+ "serverless",
33
54
  "esbuild",
34
- "yeoman-generator"
55
+ "tailwindcss",
56
+ "jsx",
57
+ "cli",
58
+ "scaffolding",
59
+ "white-label"
35
60
  ],
36
61
  "author": "Bill Shackelford",
37
62
  "license": "MIT",
@@ -42,40 +67,38 @@
42
67
  "bugs": {
43
68
  "url": "https://github.com/bshack/white-label/issues"
44
69
  },
45
- "homepage": "https://github.com/bshack/white-label",
46
- "dependencies": {
47
- "@types/node": "24.13.3",
48
- "@yeoman/adapter": "5.0.0",
49
- "bootstrap": "5.3.8",
50
- "chalk": "6.0.0",
51
- "esbuild": "0.28.2",
52
- "events": "3.3.0",
53
- "handlebars": "4.7.9",
54
- "react": "19.2.8",
55
- "react-dom": "19.2.8",
56
- "sass": "1.104.0",
57
- "white-label-model": "3.0.0",
58
- "white-label-view": "4.0.0",
59
- "yeoman-generator": "8.3.1",
60
- "yosay": "3.0.0"
61
- },
70
+ "homepage": "https://whitelabeljs.org/docs/generator/",
71
+ "dependencies": {},
62
72
  "devDependencies": {
63
- "@types/react": "19.2.18",
64
- "@types/react-dom": "19.2.7",
65
- "@types/yosay": "2.0.3",
73
+ "@tailwindcss/cli": "4.3.3",
74
+ "@types/node": "24.13.3",
75
+ "axe-core": "4.13.0",
66
76
  "c8": "12.0.0",
77
+ "esbuild": "0.28.2",
78
+ "html-validate": "11.15.0",
67
79
  "jsdom": "30.0.1",
80
+ "tailwindcss": "4.3.3",
68
81
  "typescript": "7.0.2",
69
- "yeoman-environment": "7.0.0"
82
+ "white-label-mediator": "4.0.0",
83
+ "white-label-model": "6.0.0",
84
+ "white-label-router": "5.0.0",
85
+ "white-label-view": "5.1.0",
86
+ "@babel/core": "8.0.5",
87
+ "@babel/eslint-parser": "8.0.5",
88
+ "@babel/plugin-syntax-jsx": "8.0.1",
89
+ "@babel/preset-typescript": "8.0.1",
90
+ "@eslint/js": "10.0.1",
91
+ "eslint": "10.10.0"
70
92
  },
71
- "types": "dist/generators/app/index.d.ts",
93
+ "types": "dist/scaffold/index.d.ts",
72
94
  "c8": {
73
95
  "all": true,
74
96
  "include": [
97
+ "cli/**/*.ts",
75
98
  "scripts/**/*.ts",
76
- "generators/**/*.ts",
77
- "app/assets/script/**/*.ts",
78
- "app/assets/script/**/*.tsx"
99
+ "scaffold/**/*.ts",
100
+ "app/**/*.ts",
101
+ "app/**/*.tsx"
79
102
  ],
80
103
  "reporter": [
81
104
  "text",
@@ -91,7 +114,21 @@
91
114
  "statements": 100,
92
115
  "perFile": true,
93
116
  "exclude": [
94
- "**/*.d.ts"
117
+ "**/*.d.ts",
118
+ "app/assets/view/page-data.ts",
119
+ "scaffold/no-jsx/app/**"
95
120
  ]
121
+ },
122
+ "exports": {
123
+ ".": {
124
+ "types": "./dist/scaffold/index.d.ts",
125
+ "import": "./dist/scaffold/index.js",
126
+ "default": "./dist/scaffold/index.js"
127
+ },
128
+ "./scaffold": {
129
+ "types": "./dist/scaffold/index.d.ts",
130
+ "import": "./dist/scaffold/index.js",
131
+ "default": "./dist/scaffold/index.js"
132
+ }
96
133
  }
97
134
  }
@@ -0,0 +1,4 @@
1
+ onlyBuiltDependencies:
2
+ - '@parcel/watcher'
3
+ - esbuild
4
+ - white-label-view
@@ -0,0 +1,127 @@
1
+ /** @module scaffold */
2
+ import {cp, mkdir, writeFile} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+
6
+ const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
7
+
8
+ export interface ScaffoldFileSystem {
9
+ copy(source: string, destination: string): void | Promise<void>;
10
+ writeJSON(destination: string, value: unknown): void | Promise<void>;
11
+ }
12
+
13
+ export interface CreateProjectOptions {
14
+ destination: string;
15
+ fileSystem?: ScaffoldFileSystem;
16
+ jsx?: boolean;
17
+ }
18
+
19
+ const nodeFileSystem: ScaffoldFileSystem = {
20
+ async copy(source, destination) {
21
+ await mkdir(path.dirname(destination), {recursive: true});
22
+ await cp(source, destination, {recursive: true});
23
+ },
24
+ async writeJSON(destination, value) {
25
+ await mkdir(path.dirname(destination), {recursive: true});
26
+ await writeFile(destination, `${JSON.stringify(value, null, 2)}\n`);
27
+ }
28
+ };
29
+
30
+ /** Return the package manifest used by generated White Label projects. */
31
+ export function createSiteManifest() {
32
+ return {
33
+ name: 'white-label-site',
34
+ version: '1.0.0',
35
+ private: true,
36
+ type: 'module',
37
+ engines: {node: '^22.18.0 || >=24.11.0'},
38
+ scripts: {
39
+ build: 'tsc -p tsconfig.json && node dist/scripts/build.js',
40
+ typecheck: 'tsc -p tsconfig.json --noEmit',
41
+ test: 'node --run typecheck && node --run build -- --version=test --production=true --site-url=https://example.com && node --test --experimental-test-coverage --test-coverage-include=dist/app/assets/script/index.js --test-coverage-lines=100 --test-coverage-functions=100 --test-coverage-branches=100 test/*.test.js'
42
+ },
43
+ allowScripts: {
44
+ '@parcel/watcher@2.5.1': true,
45
+ 'esbuild@0.28.2': true,
46
+ 'white-label-view@5.1.0': true
47
+ },
48
+ dependenciesMeta: {
49
+ '@parcel/watcher@2.5.1': {built: true},
50
+ 'esbuild@0.28.2': {built: true},
51
+ 'white-label-view@5.1.0': {built: true}
52
+ },
53
+ devDependencies: {
54
+ '@tailwindcss/cli': '4.3.3',
55
+ '@types/node': '24.13.3',
56
+ 'axe-core': '4.13.0',
57
+ 'esbuild': '0.28.2',
58
+ 'html-validate': '11.15.0',
59
+ 'jsdom': '30.0.1',
60
+ 'tailwindcss': '4.3.3',
61
+ 'typescript': '7.0.2'
62
+ },
63
+ dependencies: {
64
+ 'white-label-mediator': '4.0.0',
65
+ 'white-label-model': '6.0.0',
66
+ 'white-label-router': '5.0.0',
67
+ 'white-label-view': '5.1.0'
68
+ }
69
+ };
70
+ }
71
+
72
+ const commonNoJsxCopies = [
73
+ ['app/assets/data', 'app/assets/data'],
74
+ ['app/assets/style', 'app/assets/style'],
75
+ ['app/assets/script/tasks/TaskApplication.ts', 'app/assets/script/tasks/TaskApplication.ts'],
76
+ ['app/assets/script/tasks/TaskMediator.ts', 'app/assets/script/tasks/TaskMediator.ts'],
77
+ ['app/assets/script/tasks/TaskModel.ts', 'app/assets/script/tasks/TaskModel.ts'],
78
+ ['app/assets/script/tasks/TaskRouter.ts', 'app/assets/script/tasks/TaskRouter.ts'],
79
+ ['app/assets/view/examples/tasks/task-state.ts', 'app/assets/view/examples/tasks/task-state.ts'],
80
+ ['app/package.json', 'app/package.json']
81
+ ] as const;
82
+
83
+ const noJsxTemplateCopies = [
84
+ ['scaffold/no-jsx/app/index.ts', 'app/index.ts'],
85
+ ['scaffold/no-jsx/app/404.ts', 'app/404.ts'],
86
+ ['scaffold/no-jsx/app/assets/script/index.ts', 'app/assets/script/index.ts'],
87
+ ['scaffold/no-jsx/app/assets/script/tasks/TaskView.ts', 'app/assets/script/tasks/TaskView.ts'],
88
+ ['scaffold/no-jsx/app/assets/view/examples/tasks/TaskExample.ts', 'app/assets/view/examples/tasks/TaskExample.ts'],
89
+ ['scaffold/no-jsx/README.md', 'README.md'],
90
+ ['tsconfig.site.no-jsx.json', 'tsconfig.json']
91
+ ] as const;
92
+
93
+ /**
94
+ * Create a White Label project.
95
+ *
96
+ * This is the shared implementation behind every creation interface. Adapters
97
+ * translate their environment into these options instead of owning templates or
98
+ * project-generation behavior themselves.
99
+ */
100
+ export async function createProject({destination, fileSystem = nodeFileSystem, jsx = true}: CreateProjectOptions) {
101
+ const copies = jsx ? [
102
+ ['.editorconfig', '.editorconfig'],
103
+ ['.yarnrc.yml', '.yarnrc.yml'],
104
+ ['pnpm-workspace.yaml', 'pnpm-workspace.yaml'],
105
+ ['app', 'app'],
106
+ ['app/README.md', 'README.md'],
107
+ ['server', 'server'],
108
+ ['scripts', 'scripts'],
109
+ ['template-test', 'test'],
110
+ ['tsconfig.site.json', 'tsconfig.json']
111
+ ] as const : [
112
+ ['.editorconfig', '.editorconfig'],
113
+ ['.yarnrc.yml', '.yarnrc.yml'],
114
+ ['pnpm-workspace.yaml', 'pnpm-workspace.yaml'],
115
+ ...commonNoJsxCopies,
116
+ ...noJsxTemplateCopies,
117
+ ['server', 'server'],
118
+ ['scripts', 'scripts'],
119
+ ['template-test', 'test']
120
+ ] as const;
121
+
122
+ for (const [source, target] of copies) {
123
+ await fileSystem.copy(path.join(packageRoot, source), path.join(destination, target));
124
+ }
125
+
126
+ await fileSystem.writeJSON(path.join(destination, 'package.json'), createSiteManifest());
127
+ }
@@ -0,0 +1,47 @@
1
+ # White Label generated site
2
+
3
+ This project was generated with the **plain TypeScript / no-JSX** template option.
4
+
5
+ - Pages and views are `.ts` files.
6
+ - Templates return HTML strings instead of using JSX/TSX syntax.
7
+ - React is not required.
8
+ - White Label Model, View, Router, and Mediator are used the same way as in the JSX template.
9
+ - npm, Yarn, and pnpm are supported.
10
+
11
+ This scaffold is also the right starting point when you want a third-party template engine. Install the renderer your application uses, then call it from the View `template` function instead of returning a hand-built string. White Label does not require a renderer adapter or change the rest of the application architecture.
12
+
13
+ See [Template engines and JSX options](https://whitelabeljs.org/docs/view/#template-engines) for the tested third-party engines, examples, rendering contract, and escaping/security guidance.
14
+
15
+ ## Commands
16
+
17
+ Use the package manager you prefer:
18
+
19
+ ```sh
20
+ npm install
21
+ npm run build
22
+ npm test
23
+ ```
24
+
25
+ ```sh
26
+ yarn install
27
+ yarn build
28
+ yarn test
29
+ ```
30
+
31
+ ```sh
32
+ pnpm install
33
+ pnpm build
34
+ pnpm test
35
+ ```
36
+
37
+ ## Serverless / function runtimes
38
+
39
+ `server/handler.ts` is the same provider-neutral serverless example included in the JSX scaffold. It uses Web `Request` and `Response`, request-scoped Model/View/Router/Mediator instances, and the server View entrypoint; it does not require JSX or a provider SDK.
40
+
41
+ Keep immutable configuration at module scope when useful, but create mutable White Label instances per request unless shared state is explicitly intended. Warm serverless processes may handle many requests, so module-level mutable application state can leak data between invocations.
42
+
43
+ Use a thin cloud adapter around the handler when a platform does not expose Web `Request`/`Response` directly. The generated tests exercise repeated and concurrent requests, browser-global absence, Web-target bundling, and serverless bundle/startup budgets.
44
+
45
+ The Web-target bundle check is a portability smoke test, not a blanket claim of compatibility with every edge runtime. Verify the provider runtime you deploy to.
46
+
47
+ If you prefer JSX syntax for templates, generate a new project with `--jsx` or answer **Yes** to the generator's JSX question. JSX and no-JSX projects provide equivalent White Label functionality; the choice is about template syntax and renderer ownership.
@@ -0,0 +1,10 @@
1
+ interface PageData {cdn: string; siteUrl: string; title: string; version: string}
2
+
3
+ function escapeHtml(value: unknown): string {
4
+ return String(value).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#39;');
5
+ }
6
+
7
+ export default function NotFoundPage(data: Record<string, unknown>): string {
8
+ const page = data as unknown as PageData;
9
+ return `<html lang="en-US"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Page not found | ${escapeHtml(page.title)}</title><meta name="robots" content="noindex,follow"><link rel="stylesheet" href="${escapeHtml(page.cdn)}release/${escapeHtml(page.version)}/assets/style/global.css"></head><body><a class="skip-link" href="#main">Skip to the message</a><main id="main" tabindex="-1"><h1>Page not found</h1><p>The requested page could not be found.</p><p><a href="${escapeHtml(page.siteUrl)}/">Return home</a></p></main></body></html>`;
10
+ }
@@ -0,0 +1,7 @@
1
+ /** @module app/assets/script/index */
2
+ import {initializeTaskApplication} from './tasks/TaskApplication.js';
3
+
4
+ export {initializeTaskApplication} from './tasks/TaskApplication.js';
5
+ export {normalizeTaskFilter} from './tasks/TaskRouter.js';
6
+
7
+ initializeTaskApplication(document);
@@ -0,0 +1,19 @@
1
+ import View from 'white-label-view';
2
+ import TaskExample from '../../view/examples/tasks/TaskExample.js';
3
+ import type {TaskState} from '../../view/examples/tasks/task-state.js';
4
+ import type TaskModel from './TaskModel.js';
5
+
6
+ /** Create the task view without JSX/TSX syntax. */
7
+ export function createTaskView(parentElement: HTMLElement, model: TaskModel): View {
8
+ const element = parentElement.querySelector<HTMLElement>('[data-task-app]');
9
+ if (!element) {throw new TypeError('Task example requires its static task-app root');}
10
+
11
+ return new View({
12
+ element,
13
+ model,
14
+ parentElement,
15
+ template(data) {
16
+ return TaskExample({state: data as TaskState});
17
+ }
18
+ }).initialize();
19
+ }
@@ -0,0 +1,39 @@
1
+ import {getVisibleTasks, type TaskFilter, type TaskState} from './task-state.js';
2
+
3
+ const filters: TaskFilter[] = ['all', 'active', 'completed'];
4
+
5
+ function escapeHtml(value: unknown): string {
6
+ return String(value)
7
+ .replaceAll('&', '&amp;')
8
+ .replaceAll('<', '&lt;')
9
+ .replaceAll('>', '&gt;')
10
+ .replaceAll('"', '&quot;')
11
+ .replaceAll("'", '&#39;');
12
+ }
13
+
14
+ /** Render the task example with plain TypeScript and HTML strings. */
15
+ export default function TaskExample({state}: {state: TaskState}): string {
16
+ const visibleTasks = getVisibleTasks(state);
17
+ const completed = state.tasks.filter(task => task.complete).length;
18
+ const filterLinks = filters.map(filter => `
19
+ <a href="/?tasks=${filter}#example" data-task-filter="${filter}" data-pushstate aria-current="${state.filter === filter ? 'page' : 'false'}">${filter.charAt(0).toUpperCase()}${filter.slice(1)}</a>
20
+ `).join('');
21
+ const tasks = visibleTasks.map(task => `
22
+ <li><label><input type="checkbox" ${task.complete ? 'checked ' : ''}data-task-toggle data-task-id="${task.id}"><span>${escapeHtml(task.title)}</span></label></li>
23
+ `).join('');
24
+
25
+ return `<section class="task-app" data-task-app aria-label="Interactive task example">
26
+ <form class="task-form" data-task-form action="#example" method="get">
27
+ <label for="task-title">New task</label>
28
+ <div class="task-form__controls"><input id="task-title" name="task" type="text" autocomplete="off" required><button type="submit">Add task</button></div>
29
+ </form>
30
+ <nav class="task-filters" aria-label="Filter tasks">${filterLinks}</nav>
31
+ <ul class="task-list">${tasks}</ul>
32
+ <dl class="demo__trace">
33
+ <div><dt>Router</dt><dd>/?tasks=${state.filter}</dd></div>
34
+ <div><dt>Mediator</dt><dd>task:* application events</dd></div>
35
+ <div><dt>Model</dt><dd>${state.tasks.length} tasks · ${completed} complete</dd></div>
36
+ <div><dt>View</dt><dd>${visibleTasks.length} tasks rendered</dd></div>
37
+ </dl>
38
+ </section>`;
39
+ }
@@ -0,0 +1,58 @@
1
+ import TaskExample from './assets/view/examples/tasks/TaskExample.js';
2
+ import {createInitialTaskState, describeTaskStatus} from './assets/view/examples/tasks/task-state.js';
3
+
4
+ interface PageData {
5
+ cdn: string;
6
+ meta: {description: string};
7
+ siteUrl: string;
8
+ structuredData: Record<string, unknown>;
9
+ title: string;
10
+ version: string;
11
+ }
12
+
13
+ function escapeHtml(value: unknown): string {
14
+ return String(value)
15
+ .replaceAll('&', '&amp;')
16
+ .replaceAll('<', '&lt;')
17
+ .replaceAll('>', '&gt;')
18
+ .replaceAll('"', '&quot;')
19
+ .replaceAll("'", '&#39;');
20
+ }
21
+
22
+ /** Render the generated starter using plain TypeScript and HTML strings. */
23
+ export default function IndexPage(data: Record<string, unknown>): string {
24
+ const page = data as unknown as PageData;
25
+ const taskState = createInitialTaskState();
26
+ const taskExample = TaskExample({state: taskState});
27
+ const taskStatus = describeTaskStatus(taskState);
28
+ const structuredData = JSON.stringify(page.structuredData).replaceAll('<', '\\u003c');
29
+
30
+ return `<html id="index" lang="en-US" dir="ltr">
31
+ <head>
32
+ <meta charset="utf-8">
33
+ <meta name="viewport" content="width=device-width, initial-scale=1">
34
+ <title>${escapeHtml(page.title)}</title>
35
+ <meta name="description" content="${escapeHtml(page.meta.description)}">
36
+ <meta name="robots" content="index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1">
37
+ <link rel="canonical" href="${escapeHtml(page.siteUrl)}/">
38
+ <meta property="og:title" content="${escapeHtml(page.title)}">
39
+ <meta property="og:description" content="${escapeHtml(page.meta.description)}">
40
+ <meta property="og:type" content="website">
41
+ <meta property="og:url" content="${escapeHtml(page.siteUrl)}/">
42
+ <link rel="stylesheet" href="${escapeHtml(page.cdn)}release/${escapeHtml(page.version)}/assets/style/global.css" media="all">
43
+ <link rel="stylesheet" href="${escapeHtml(page.cdn)}release/${escapeHtml(page.version)}/assets/style/print.css" media="print">
44
+ <script type="application/ld+json">${structuredData}</script>
45
+ </head>
46
+ <body itemscope itemtype="https://schema.org/WebPage">
47
+ <a class="skip-link" href="#main">Skip to content</a>
48
+ <header><nav aria-label="Primary"><a href="/">White Label</a></nav></header>
49
+ <main id="main" tabindex="-1">
50
+ <section class="hero"><p class="eyebrow">White Label starter</p><h1>Composable web primitives without a framework lock-in.</h1><p>State, rendering, routing, and application events stay small, explicit, and independently understandable.</p></section>
51
+ <section id="example" data-task-example><h2>Interactive task example</h2>${taskExample}<p class="visually-hidden" role="status" aria-live="polite" aria-atomic="true" data-task-status>${escapeHtml(taskStatus)}</p></section>
52
+ <section><h2>Plain TypeScript templates</h2><p>This project was generated without JSX. Pages and views return HTML strings from ordinary TypeScript functions.</p></section>
53
+ </main>
54
+ <footer><p>Built with White Label.</p></footer>
55
+ <script src="${escapeHtml(page.cdn)}release/${escapeHtml(page.version)}/assets/script/index.compiled.js" defer></script>
56
+ </body>
57
+ </html>`;
58
+ }