poveste 0.1.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 (251) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +11 -0
  3. package/bin.mjs +4 -0
  4. package/client.d.ts +19 -0
  5. package/client.js +15 -0
  6. package/dist/controls.d.ts +2 -0
  7. package/dist/controls.d.ts.map +1 -0
  8. package/dist/controls.js +1 -0
  9. package/dist/node/alias.d.ts +3 -0
  10. package/dist/node/alias.d.ts.map +1 -0
  11. package/dist/node/alias.js +5 -0
  12. package/dist/node/bin.d.ts +2 -0
  13. package/dist/node/bin.d.ts.map +1 -0
  14. package/dist/node/bin.js +35 -0
  15. package/dist/node/build-serialize.d.ts +22 -0
  16. package/dist/node/build-serialize.d.ts.map +1 -0
  17. package/dist/node/build-serialize.js +36 -0
  18. package/dist/node/build.d.ts +3 -0
  19. package/dist/node/build.d.ts.map +1 -0
  20. package/dist/node/build.js +228 -0
  21. package/dist/node/builtin-plugins/pinceau-tokens.d.ts +7 -0
  22. package/dist/node/builtin-plugins/pinceau-tokens.d.ts.map +1 -0
  23. package/dist/node/builtin-plugins/pinceau-tokens.js +505 -0
  24. package/dist/node/builtin-plugins/tailwind-tokens.d.ts +6 -0
  25. package/dist/node/builtin-plugins/tailwind-tokens.d.ts.map +1 -0
  26. package/dist/node/builtin-plugins/tailwind-tokens.js +523 -0
  27. package/dist/node/builtin-plugins/vanilla-support/MountStory.d.ts +15 -0
  28. package/dist/node/builtin-plugins/vanilla-support/MountStory.d.ts.map +1 -0
  29. package/dist/node/builtin-plugins/vanilla-support/MountStory.js +39 -0
  30. package/dist/node/builtin-plugins/vanilla-support/RenderStory.d.ts +39 -0
  31. package/dist/node/builtin-plugins/vanilla-support/RenderStory.d.ts.map +1 -0
  32. package/dist/node/builtin-plugins/vanilla-support/RenderStory.js +129 -0
  33. package/dist/node/builtin-plugins/vanilla-support/client.d.ts +4 -0
  34. package/dist/node/builtin-plugins/vanilla-support/client.d.ts.map +1 -0
  35. package/dist/node/builtin-plugins/vanilla-support/client.js +5 -0
  36. package/dist/node/builtin-plugins/vanilla-support/collect.d.ts +3 -0
  37. package/dist/node/builtin-plugins/vanilla-support/collect.d.ts.map +1 -0
  38. package/dist/node/builtin-plugins/vanilla-support/collect.js +33 -0
  39. package/dist/node/builtin-plugins/vanilla-support/plugin.d.ts +3 -0
  40. package/dist/node/builtin-plugins/vanilla-support/plugin.d.ts.map +1 -0
  41. package/dist/node/builtin-plugins/vanilla-support/plugin.js +29 -0
  42. package/dist/node/builtin-plugins/vanilla-support/types.d.ts +36 -0
  43. package/dist/node/builtin-plugins/vanilla-support/types.d.ts.map +1 -0
  44. package/dist/node/builtin-plugins/vanilla-support/types.js +3 -0
  45. package/dist/node/builtin-plugins/vanilla-support/vanilla.story.d.ts +4 -0
  46. package/dist/node/builtin-plugins/vanilla-support/vanilla.story.d.ts.map +1 -0
  47. package/dist/node/builtin-plugins/vanilla-support/vanilla.story.js +55 -0
  48. package/dist/node/collect/index.d.ts +14 -0
  49. package/dist/node/collect/index.d.ts.map +1 -0
  50. package/dist/node/collect/index.js +129 -0
  51. package/dist/node/collect/run.d.ts +3 -0
  52. package/dist/node/collect/run.d.ts.map +1 -0
  53. package/dist/node/collect/run.js +7 -0
  54. package/dist/node/collect/worker.d.ts +14 -0
  55. package/dist/node/collect/worker.d.ts.map +1 -0
  56. package/dist/node/collect/worker.js +64 -0
  57. package/dist/node/colors.d.ts +287 -0
  58. package/dist/node/colors.d.ts.map +1 -0
  59. package/dist/node/colors.js +324 -0
  60. package/dist/node/commands/build.d.ts +5 -0
  61. package/dist/node/commands/build.d.ts.map +1 -0
  62. package/dist/node/commands/build.js +9 -0
  63. package/dist/node/commands/dev.d.ts +8 -0
  64. package/dist/node/commands/dev.d.ts.map +1 -0
  65. package/dist/node/commands/dev.js +52 -0
  66. package/dist/node/commands/preview.d.ts +5 -0
  67. package/dist/node/commands/preview.d.ts.map +1 -0
  68. package/dist/node/commands/preview.js +15 -0
  69. package/dist/node/config.d.ts +40 -0
  70. package/dist/node/config.d.ts.map +1 -0
  71. package/dist/node/config.js +330 -0
  72. package/dist/node/context.d.ts +18 -0
  73. package/dist/node/context.d.ts.map +1 -0
  74. package/dist/node/context.js +28 -0
  75. package/dist/node/dom/dom-keys.d.ts +5 -0
  76. package/dist/node/dom/dom-keys.d.ts.map +1 -0
  77. package/dist/node/dom/dom-keys.js +233 -0
  78. package/dist/node/dom/env.d.ts +5 -0
  79. package/dist/node/dom/env.d.ts.map +1 -0
  80. package/dist/node/dom/env.js +47 -0
  81. package/dist/node/dom/util.d.ts +11 -0
  82. package/dist/node/dom/util.d.ts.map +1 -0
  83. package/dist/node/dom/util.js +65 -0
  84. package/dist/node/index.d.ts +12 -0
  85. package/dist/node/index.d.ts.map +1 -0
  86. package/dist/node/index.js +4 -0
  87. package/dist/node/load.d.ts +9 -0
  88. package/dist/node/load.d.ts.map +1 -0
  89. package/dist/node/load.js +42 -0
  90. package/dist/node/markdown.d.ts +11 -0
  91. package/dist/node/markdown.d.ts.map +1 -0
  92. package/dist/node/markdown.js +228 -0
  93. package/dist/node/plugin.d.ts +42 -0
  94. package/dist/node/plugin.d.ts.map +1 -0
  95. package/dist/node/plugin.js +67 -0
  96. package/dist/node/preview.d.ts +8 -0
  97. package/dist/node/preview.d.ts.map +1 -0
  98. package/dist/node/preview.js +41 -0
  99. package/dist/node/search.d.ts +17 -0
  100. package/dist/node/search.d.ts.map +1 -0
  101. package/dist/node/search.js +72 -0
  102. package/dist/node/server.d.ts +12 -0
  103. package/dist/node/server.d.ts.map +1 -0
  104. package/dist/node/server.js +189 -0
  105. package/dist/node/stories.d.ts +22 -0
  106. package/dist/node/stories.d.ts.map +1 -0
  107. package/dist/node/stories.js +125 -0
  108. package/dist/node/tree.d.ts +4 -0
  109. package/dist/node/tree.d.ts.map +1 -0
  110. package/dist/node/tree.js +117 -0
  111. package/dist/node/util/find-up.d.ts +2 -0
  112. package/dist/node/util/find-up.d.ts.map +1 -0
  113. package/dist/node/util/find-up.js +20 -0
  114. package/dist/node/util/fs.d.ts +2 -0
  115. package/dist/node/util/fs.d.ts.map +1 -0
  116. package/dist/node/util/fs.js +1 -0
  117. package/dist/node/util/log.d.ts +2 -0
  118. package/dist/node/util/log.d.ts.map +1 -0
  119. package/dist/node/util/log.js +9 -0
  120. package/dist/node/util/slugify.d.ts +2 -0
  121. package/dist/node/util/slugify.d.ts.map +1 -0
  122. package/dist/node/util/slugify.js +22 -0
  123. package/dist/node/util/vendors.d.ts +3 -0
  124. package/dist/node/util/vendors.d.ts.map +1 -0
  125. package/dist/node/util/vendors.js +22 -0
  126. package/dist/node/vendors/controls.d.ts +2 -0
  127. package/dist/node/vendors/controls.d.ts.map +1 -0
  128. package/dist/node/vendors/controls.js +1 -0
  129. package/dist/node/vendors/vue.d.ts +2 -0
  130. package/dist/node/vendors/vue.d.ts.map +1 -0
  131. package/dist/node/vendors/vue.js +1 -0
  132. package/dist/node/virtual/index.d.ts +38 -0
  133. package/dist/node/virtual/index.d.ts.map +1 -0
  134. package/dist/node/virtual/index.js +49 -0
  135. package/dist/node/virtual/markdown.d.ts +3 -0
  136. package/dist/node/virtual/markdown.d.ts.map +1 -0
  137. package/dist/node/virtual/markdown.js +19 -0
  138. package/dist/node/virtual/noop.d.ts +2 -0
  139. package/dist/node/virtual/noop.d.ts.map +1 -0
  140. package/dist/node/virtual/noop.js +1 -0
  141. package/dist/node/virtual/resolved-commands.d.ts +3 -0
  142. package/dist/node/virtual/resolved-commands.d.ts.map +1 -0
  143. package/dist/node/virtual/resolved-commands.js +32 -0
  144. package/dist/node/virtual/resolved-config.d.ts +3 -0
  145. package/dist/node/virtual/resolved-config.d.ts.map +1 -0
  146. package/dist/node/virtual/resolved-config.js +10 -0
  147. package/dist/node/virtual/resolved-generated-global-setup.d.ts +3 -0
  148. package/dist/node/virtual/resolved-generated-global-setup.d.ts.map +1 -0
  149. package/dist/node/virtual/resolved-generated-global-setup.js +23 -0
  150. package/dist/node/virtual/resolved-generated-setup-code.d.ts +3 -0
  151. package/dist/node/virtual/resolved-generated-setup-code.d.ts.map +1 -0
  152. package/dist/node/virtual/resolved-generated-setup-code.js +5 -0
  153. package/dist/node/virtual/resolved-markdown-files.d.ts +3 -0
  154. package/dist/node/virtual/resolved-markdown-files.d.ts.map +1 -0
  155. package/dist/node/virtual/resolved-markdown-files.js +17 -0
  156. package/dist/node/virtual/resolved-stories.d.ts +3 -0
  157. package/dist/node/virtual/resolved-stories.d.ts.map +1 -0
  158. package/dist/node/virtual/resolved-stories.js +42 -0
  159. package/dist/node/virtual/resolved-support-plugins-client.d.ts +3 -0
  160. package/dist/node/virtual/resolved-support-plugins-client.d.ts.map +1 -0
  161. package/dist/node/virtual/resolved-support-plugins-client.js +11 -0
  162. package/dist/node/virtual/resolved-support-plugins-collect.d.ts +3 -0
  163. package/dist/node/virtual/resolved-support-plugins-collect.d.ts.map +1 -0
  164. package/dist/node/virtual/resolved-support-plugins-collect.js +11 -0
  165. package/dist/node/virtual/resolved-theme.d.ts +3 -0
  166. package/dist/node/virtual/resolved-theme.d.ts.map +1 -0
  167. package/dist/node/virtual/resolved-theme.js +12 -0
  168. package/dist/node/virtual/story-source.d.ts +3 -0
  169. package/dist/node/virtual/story-source.d.ts.map +1 -0
  170. package/dist/node/virtual/story-source.js +16 -0
  171. package/dist/node/virtual/story.d.ts +3 -0
  172. package/dist/node/virtual/story.d.ts.map +1 -0
  173. package/dist/node/virtual/story.js +7 -0
  174. package/dist/node/virtual/util.d.ts +3 -0
  175. package/dist/node/virtual/util.d.ts.map +1 -0
  176. package/dist/node/virtual/util.js +4 -0
  177. package/dist/node/virtual/vite-plugin.d.ts +4 -0
  178. package/dist/node/virtual/vite-plugin.d.ts.map +1 -0
  179. package/dist/node/virtual/vite-plugin.js +126 -0
  180. package/dist/node/vite.d.ts +9 -0
  181. package/dist/node/vite.d.ts.map +1 -0
  182. package/dist/node/vite.js +337 -0
  183. package/index.d.ts +1 -0
  184. package/package.json +89 -0
  185. package/plugin.d.ts +3 -0
  186. package/plugin.js +11 -0
  187. package/src/controls.ts +1 -0
  188. package/src/node/__tests__/markdown/test1.story.md +7 -0
  189. package/src/node/__tests__/markdown/test2.story.md +5 -0
  190. package/src/node/__tests__/markdown.spec.ts +61 -0
  191. package/src/node/__tests__/tree.spec.ts +109 -0
  192. package/src/node/alias.ts +8 -0
  193. package/src/node/bin.ts +43 -0
  194. package/src/node/build-serialize.ts +62 -0
  195. package/src/node/build.ts +283 -0
  196. package/src/node/builtin-plugins/pinceau-tokens.ts +521 -0
  197. package/src/node/builtin-plugins/tailwind-tokens.ts +536 -0
  198. package/src/node/builtin-plugins/vanilla-support/MountStory.ts +49 -0
  199. package/src/node/builtin-plugins/vanilla-support/RenderStory.ts +164 -0
  200. package/src/node/builtin-plugins/vanilla-support/client.ts +6 -0
  201. package/src/node/builtin-plugins/vanilla-support/collect.ts +43 -0
  202. package/src/node/builtin-plugins/vanilla-support/plugin.ts +35 -0
  203. package/src/node/builtin-plugins/vanilla-support/types.ts +40 -0
  204. package/src/node/builtin-plugins/vanilla-support/vanilla.story.ts +63 -0
  205. package/src/node/collect/index.ts +160 -0
  206. package/src/node/collect/run.ts +9 -0
  207. package/src/node/collect/worker.ts +97 -0
  208. package/src/node/colors.ts +340 -0
  209. package/src/node/commands/build.ts +14 -0
  210. package/src/node/commands/dev.ts +67 -0
  211. package/src/node/commands/preview.ts +22 -0
  212. package/src/node/config.ts +385 -0
  213. package/src/node/context.ts +60 -0
  214. package/src/node/dom/dom-keys.ts +238 -0
  215. package/src/node/dom/env.ts +60 -0
  216. package/src/node/dom/util.ts +83 -0
  217. package/src/node/index.ts +12 -0
  218. package/src/node/load.ts +59 -0
  219. package/src/node/markdown.ts +267 -0
  220. package/src/node/plugin.ts +95 -0
  221. package/src/node/preview.ts +57 -0
  222. package/src/node/search.ts +84 -0
  223. package/src/node/server.ts +235 -0
  224. package/src/node/stories.ts +154 -0
  225. package/src/node/tree.ts +158 -0
  226. package/src/node/util/find-up.ts +24 -0
  227. package/src/node/util/fs.ts +1 -0
  228. package/src/node/util/log.ts +10 -0
  229. package/src/node/util/slugify.ts +26 -0
  230. package/src/node/util/vendors.ts +27 -0
  231. package/src/node/vendors/controls.ts +1 -0
  232. package/src/node/vendors/vue.ts +1 -0
  233. package/src/node/virtual/index.ts +50 -0
  234. package/src/node/virtual/markdown.ts +21 -0
  235. package/src/node/virtual/noop.ts +1 -0
  236. package/src/node/virtual/resolved-commands.ts +42 -0
  237. package/src/node/virtual/resolved-config.ts +12 -0
  238. package/src/node/virtual/resolved-generated-global-setup.ts +25 -0
  239. package/src/node/virtual/resolved-generated-setup-code.ts +7 -0
  240. package/src/node/virtual/resolved-markdown-files.ts +19 -0
  241. package/src/node/virtual/resolved-stories.ts +44 -0
  242. package/src/node/virtual/resolved-support-plugins-client.ts +14 -0
  243. package/src/node/virtual/resolved-support-plugins-collect.ts +14 -0
  244. package/src/node/virtual/resolved-theme.ts +14 -0
  245. package/src/node/virtual/story-source.ts +18 -0
  246. package/src/node/virtual/story.ts +9 -0
  247. package/src/node/virtual/util.ts +5 -0
  248. package/src/node/virtual/vite-plugin.ts +146 -0
  249. package/src/node/vite.ts +379 -0
  250. package/tsconfig.json +44 -0
  251. package/vitest.config.ts +10 -0
@@ -0,0 +1,164 @@
1
+ import type { Story, Variant } from '@poveste/shared'
2
+ import type { PropType as _PropType } from '@poveste/vendors/vue'
3
+ import type { App, MountApi, VanillaApi } from './types'
4
+ import {
5
+ defineComponent as _defineComponent,
6
+ h as _h,
7
+ onBeforeUnmount as _onBeforeUnmount,
8
+ onMounted as _onMounted,
9
+ ref as _ref,
10
+ watch as _watch,
11
+ } from '@poveste/vendors/vue'
12
+ // @ts-expect-error virtual module id
13
+ import * as generatedSetup from 'virtual:$histoire-generated-global-setup'
14
+ // @ts-expect-error virtual module id
15
+ import * as setup from 'virtual:$histoire-setup'
16
+
17
+ export default _defineComponent({
18
+ name: 'RenderStory',
19
+
20
+ props: {
21
+ variant: {
22
+ type: Object as _PropType<Variant>,
23
+ required: true,
24
+ },
25
+
26
+ story: {
27
+ type: Object as _PropType<Story>,
28
+ required: true,
29
+ },
30
+
31
+ slotName: {
32
+ type: String,
33
+ default: 'default',
34
+ },
35
+ },
36
+
37
+ emits: {
38
+ ready: () => true,
39
+ },
40
+
41
+ setup(props, { emit }) {
42
+ const sandbox = _ref<HTMLDivElement>()
43
+ let mounting = false
44
+ let app: App
45
+ let appHooks: Record<'onUpdate' | 'onUnmount', (() => unknown)[]>
46
+
47
+ async function unmountVariant() {
48
+ if (app) {
49
+ await app.onUnmount?.()
50
+ if (appHooks) {
51
+ for (const hook of appHooks.onUnmount) {
52
+ await hook()
53
+ }
54
+ }
55
+
56
+ app.el.parentNode.removeChild(app.el)
57
+ app = null
58
+ }
59
+ }
60
+
61
+ async function mountVariant() {
62
+ if (mounting) return
63
+ mounting = true
64
+
65
+ await unmountVariant()
66
+
67
+ app = {
68
+ el: document.createElement('div'),
69
+ }
70
+
71
+ if (typeof generatedSetup?.setupVanilla === 'function') {
72
+ await generatedSetup.setupVanilla({
73
+ app,
74
+ story: props.story,
75
+ variant: props.variant,
76
+ })
77
+ }
78
+
79
+ if (typeof setup?.setupVanilla === 'function') {
80
+ await setup.setupVanilla({
81
+ app,
82
+ story: props.story,
83
+ variant: props.variant,
84
+ })
85
+ }
86
+
87
+ if (typeof props.variant.setupApp === 'function') {
88
+ await props.variant.setupApp({
89
+ app,
90
+ story: props.story,
91
+ variant: props.variant,
92
+ })
93
+ }
94
+
95
+ await app.onMount?.()
96
+
97
+ appHooks = {
98
+ onUpdate: [],
99
+ onUnmount: [],
100
+ }
101
+
102
+ const api: MountApi = {
103
+ el: app.el,
104
+ state: props.variant.state,
105
+ onUpdate: (cb) => {
106
+ appHooks.onUpdate.push(cb)
107
+ },
108
+ onUnmount: (cb) => {
109
+ appHooks.onUnmount.push(cb)
110
+ },
111
+ }
112
+
113
+ const onMount = props.variant.slots()[props.slotName] as VanillaApi['onMount'] | VanillaApi['onMountControls']
114
+ await onMount(api)
115
+
116
+ sandbox.value.appendChild(app.el)
117
+
118
+ emit('ready')
119
+ }
120
+
121
+ _onMounted(async () => {
122
+ if (props.variant.configReady) {
123
+ await mountVariant()
124
+ }
125
+ })
126
+
127
+ _watch(() => props.variant, async (value) => {
128
+ if (value.configReady && !mounting) {
129
+ if (!app) {
130
+ await mountVariant()
131
+ }
132
+ else {
133
+ // @TODO check if need to refresh here
134
+ }
135
+ }
136
+ }, {
137
+ deep: true,
138
+ })
139
+
140
+ _watch(() => props.variant.state, async () => {
141
+ if (appHooks) {
142
+ for (const hook of appHooks.onUpdate) {
143
+ await hook()
144
+ }
145
+ }
146
+ }, {
147
+ deep: true,
148
+ })
149
+
150
+ _onBeforeUnmount(() => {
151
+ unmountVariant()
152
+ })
153
+
154
+ return {
155
+ sandbox,
156
+ }
157
+ },
158
+
159
+ render() {
160
+ return _h('div', {
161
+ ref: 'sandbox',
162
+ })
163
+ },
164
+ })
@@ -0,0 +1,6 @@
1
+ export { default as MountStory } from './MountStory'
2
+ export { default as RenderStory } from './RenderStory'
3
+
4
+ export function generateSourceCode() {
5
+ // noop
6
+ }
@@ -0,0 +1,43 @@
1
+ import type { ServerRunPayload, ServerStory, ServerVariant } from '@poveste/shared'
2
+ import type { StoryOptions, VariantOptions } from './types'
3
+
4
+ export async function run({ file, storyData }: ServerRunPayload) {
5
+ const { default: Comp } = await import(/* @vite-ignore */ file.moduleId)
6
+
7
+ const options = Comp as StoryOptions
8
+
9
+ let rawVariants: VariantOptions[] = []
10
+
11
+ if (options.onMount) {
12
+ // Implicit variant
13
+ rawVariants = [{
14
+ id: '_default',
15
+ title: 'default',
16
+ }]
17
+ }
18
+ else {
19
+ rawVariants = options.variants
20
+ }
21
+
22
+ const story: ServerStory = {
23
+ id: options.id ?? file.id,
24
+ title: options.title ?? file.fileName,
25
+ group: options.group,
26
+ layout: options.layout ?? { type: 'single', iframe: true },
27
+ icon: options.icon,
28
+ iconColor: options.iconColor,
29
+ docsOnly: options.docsOnly ?? false,
30
+ variants: null,
31
+ }
32
+
33
+ const variants: ServerVariant[] = rawVariants.map((v, index) => ({
34
+ id: v.id ?? `${story.id}-${index}`,
35
+ title: v.title ?? 'untitled',
36
+ icon: v.icon ?? options.icon,
37
+ iconColor: v.iconColor ?? options.iconColor,
38
+ }))
39
+
40
+ story.variants = variants
41
+
42
+ storyData.push(story)
43
+ }
@@ -0,0 +1,35 @@
1
+ import type { Plugin } from '@poveste/shared'
2
+ import { fileURLToPath } from 'node:url'
3
+ import { dirname } from 'pathe'
4
+
5
+ const __dirname = dirname(fileURLToPath(import.meta.url))
6
+
7
+ export function vanillaSupport(): Plugin {
8
+ return {
9
+ name: 'builtin:vanilla-support',
10
+
11
+ defaultConfig() {
12
+ return {
13
+ supportMatch: [
14
+ {
15
+ id: 'vanilla',
16
+ patterns: ['**/*.js'],
17
+ pluginIds: ['vanilla'],
18
+ },
19
+ ],
20
+ }
21
+ },
22
+
23
+ supportPlugin: {
24
+ id: 'vanilla',
25
+ moduleName: __dirname,
26
+ setupFn: 'setupVanilla',
27
+ importStoryComponent: (file, index) => `import Comp${index} from ${JSON.stringify(file.moduleId)}`, // @TODO code-splitting
28
+ },
29
+
30
+ // onDev (api) {
31
+ // // Test vanilla story
32
+ // api.addStoryFile(resolve(__dirname, './vanilla.story.js'))
33
+ // },
34
+ }
35
+ }
@@ -0,0 +1,40 @@
1
+ import type { Awaitable, Story, StoryProps, Variant, VariantProps } from '@poveste/shared'
2
+
3
+ export interface App {
4
+ el: HTMLElement
5
+ onMount?: () => void
6
+ onUpdate?: () => void
7
+ onUnmount?: () => void
8
+ }
9
+
10
+ export interface MountApi {
11
+ el: HTMLElement
12
+ state: Record<string, any>
13
+ onUpdate: (cb: () => unknown) => Awaitable<void>
14
+ onUnmount: (cb: () => unknown) => Awaitable<void>
15
+ }
16
+
17
+ export interface VanillaApi {
18
+ onMount?: (api: MountApi) => Awaitable<void>
19
+ onMountControls?: (api: MountApi) => Awaitable<void>
20
+ }
21
+
22
+ interface CommonProps {
23
+ setupApp?: (payload: { app: App, story: Story, variant: Variant }) => unknown
24
+ }
25
+
26
+ export type StoryOptions = Omit<StoryProps, 'setupApp'> & CommonProps & ((VanillaApi & {
27
+ variants?: never
28
+ }) | {
29
+ variants?: VariantOptions[]
30
+ onMount?: never
31
+ onMountControls?: never
32
+ })
33
+
34
+ export interface VariantOptions extends Omit<VariantProps, 'setupApp'>, CommonProps, VanillaApi {
35
+
36
+ }
37
+
38
+ export function defineStory(story: StoryOptions) {
39
+ return story
40
+ }
@@ -0,0 +1,63 @@
1
+ import type { StoryOptions } from './types'
2
+
3
+ export default {
4
+ title: 'Vanilla story',
5
+ icon: 'ion:logo-nodejs',
6
+ variants: [
7
+ {
8
+ title: 'Hello',
9
+ onMount: ({ el, state, onUpdate }) => {
10
+ state.count = 0
11
+
12
+ const div = document.createElement('div')
13
+ div.innerHTML = '<h1>Hello World</h1>'
14
+ el.appendChild(div)
15
+
16
+ const counter = document.createElement('pre')
17
+ counter.innerHTML = `Counter: ${state.counter}`
18
+ div.appendChild(counter)
19
+
20
+ onUpdate(() => {
21
+ counter.innerHTML = `Counter: ${state.count}`
22
+ })
23
+ },
24
+ onMountControls: ({ el, state, onUnmount }) => {
25
+ const add = () => {
26
+ state.count++
27
+ }
28
+
29
+ Object.assign(el.style, {
30
+ padding: '8px',
31
+ })
32
+
33
+ const btn = document.createElement('button')
34
+ btn.innerHTML = '+1'
35
+ Object.assign(btn.style, {
36
+ padding: '6px',
37
+ borderRadius: '3px',
38
+ backgroundColor: '#a7f3d0',
39
+ })
40
+ btn.addEventListener('click', add)
41
+ el.appendChild(btn)
42
+
43
+ onUnmount(() => {
44
+ btn.removeEventListener('click', add)
45
+ })
46
+ },
47
+ },
48
+ {
49
+ title: 'Meow',
50
+ onMount: ({ el, onUpdate, onUnmount }) => {
51
+ const div = document.createElement('div')
52
+ div.innerHTML = '<h1>Meow</h1>'
53
+ el.appendChild(div)
54
+ onUpdate(() => {
55
+ console.log('update')
56
+ })
57
+ onUnmount(() => {
58
+ el.removeChild(div)
59
+ })
60
+ },
61
+ },
62
+ ],
63
+ } as StoryOptions
@@ -0,0 +1,160 @@
1
+ import type { ServerStoryFile } from '@poveste/shared'
2
+ import type { ViteDevServer } from 'vite'
3
+ import type { FetchFunction, ResolveIdFunction } from 'vite-node'
4
+ import type { Context } from '../context.js'
5
+ import type { Payload, ReturnData } from './worker.js'
6
+ import { cpus } from 'node:os'
7
+ import { MessageChannel } from 'node:worker_threads'
8
+ import Tinypool from '@akryum/tinypool'
9
+ import { createBirpc } from 'birpc'
10
+ import path, { relative } from 'pathe'
11
+ import pc from 'picocolors'
12
+ import { ViteNodeServer } from 'vite-node/server'
13
+ import { TEMP_PATH } from '../alias.js'
14
+ import { createPath } from '../tree.js'
15
+ import { slash } from '../util/fs.js'
16
+
17
+ export interface UseCollectStoriesOptions {
18
+ server: ViteDevServer
19
+ mainServer?: ViteDevServer
20
+ throws?: boolean
21
+ }
22
+
23
+ export function useCollectStories(options: UseCollectStoriesOptions, ctx: Context) {
24
+ const { server, mainServer } = options
25
+
26
+ const node = new ViteNodeServer(server as any, {
27
+ deps: {
28
+ inline: [
29
+ /histoire\/dist/,
30
+ /histoire\/client/,
31
+ /@histoire\/[\w-]+\/dist/,
32
+ /histoire-[\w-]+\/dist/,
33
+ /@vue\/devtools-api/,
34
+ /vuetify/,
35
+ // @TODO temporary fix for https://github.com/histoire-dev/histoire/issues/409
36
+ /vite\w*\/dist\/client\/(client|env).mjs/,
37
+ ...ctx.config.viteNodeInlineDeps ?? [],
38
+ new RegExp(path.resolve(TEMP_PATH, 'plugins')),
39
+ ],
40
+ fallbackCJS: true,
41
+ },
42
+ transformMode: ctx.config.viteNodeTransformMode,
43
+ })
44
+
45
+ const maxThreads = ctx.config.collectMaxThreads ?? cpus().length
46
+
47
+ const threadsCount = ctx.mode === 'dev'
48
+ ? Math.max(Math.min(maxThreads, Math.floor(cpus().length / 2)), 1)
49
+ : Math.max(Math.min(maxThreads, cpus().length - 1), 1)
50
+ console.log(pc.blue(`Using ${threadsCount} thread${threadsCount === 1 ? '' : 's'} for story collection`))
51
+
52
+ const threadPool = new Tinypool({
53
+ filename: new URL('./worker.js', import.meta.url).href,
54
+ // WebContainer compatibility (Stackblitz)
55
+ useAtomics: typeof process.versions.webcontainer !== 'string',
56
+ minThreads: threadsCount,
57
+ maxThreads: threadsCount,
58
+ })
59
+
60
+ function clearCache() {
61
+ server.moduleGraph.invalidateAll()
62
+ node.fetchCache.clear()
63
+ }
64
+
65
+ function createChannel() {
66
+ const channel = new MessageChannel()
67
+ const port = channel.port2
68
+ const workerPort = channel.port1
69
+
70
+ createBirpc<Record<string, never>, {
71
+ fetchModule: FetchFunction
72
+ resolveId: ResolveIdFunction
73
+ }>({
74
+ fetchModule: id => node.fetchModule(id),
75
+ resolveId: (id, importer) => node.resolveId(id, importer),
76
+ }, {
77
+ post: data => port.postMessage(data),
78
+ on: data => port.on('message', data),
79
+ })
80
+
81
+ return {
82
+ port,
83
+ workerPort,
84
+ }
85
+ }
86
+
87
+ if (mainServer) {
88
+ mainServer.watcher.on('change', (file) => {
89
+ file = slash(file)
90
+ threadPool.broadcastMessage({
91
+ kind: 'hst:invalidate',
92
+ file,
93
+ })
94
+ })
95
+ }
96
+
97
+ async function executeStoryFile(storyFile: ServerStoryFile) {
98
+ try {
99
+ const { workerPort } = createChannel()
100
+ const payload: Payload = {
101
+ root: server.config.root,
102
+ base: server.config.base,
103
+ storyFile,
104
+ port: workerPort,
105
+ }
106
+ const { storyData } = await threadPool.run(payload, {
107
+ transferList: [
108
+ workerPort,
109
+ ],
110
+ }) as ReturnData
111
+ if (storyData.length === 0) {
112
+ console.warn(pc.yellow(`⚠️ No story found for ${storyFile.path}`))
113
+ return
114
+ }
115
+ else if (storyData.length > 1) {
116
+ console.warn(pc.yellow(`⚠️ Multiple stories not supported: ${storyFile.path}`))
117
+ }
118
+
119
+ const finalData = storyData[0]
120
+
121
+ // Default props
122
+ if (ctx.config.defaultStoryProps) {
123
+ for (const key in ctx.config.defaultStoryProps) {
124
+ if (finalData[key] == null) {
125
+ finalData[key] = ctx.config.defaultStoryProps[key]
126
+ }
127
+ }
128
+ }
129
+
130
+ if (!finalData.layout) {
131
+ finalData.layout = { type: 'single', iframe: true }
132
+ }
133
+
134
+ storyFile.id = finalData.id
135
+ storyFile.story = finalData
136
+ storyFile.treeFile = {
137
+ title: finalData.title,
138
+ path: relative(server.config.root, storyFile.path),
139
+ }
140
+ storyFile.treePath = createPath(ctx.config, storyFile.treeFile)
141
+ storyFile.story.title = storyFile.treePath[storyFile.treePath.length - 1]
142
+ }
143
+ catch (e) {
144
+ console.error(pc.red(`Error while collecting story ${storyFile.path}:\n${e.frame ? `${pc.bold(e.message)}\n${e.frame}` : e.stack}`))
145
+ if (options.throws) {
146
+ throw e
147
+ }
148
+ }
149
+ }
150
+
151
+ async function destroy() {
152
+ await threadPool.destroy()
153
+ }
154
+
155
+ return {
156
+ clearCache,
157
+ executeStoryFile,
158
+ destroy,
159
+ }
160
+ }
@@ -0,0 +1,9 @@
1
+ import type { ServerRunPayload } from '@poveste/shared'
2
+ // @ts-expect-error virtual module
3
+ import { collectSupportPlugins } from 'virtual:$histoire-support-plugins-collect'
4
+
5
+ export async function run(payload: ServerRunPayload) {
6
+ const { run } = await collectSupportPlugins[payload.file.supportPluginId]()
7
+ const result = await run(payload)
8
+ return result
9
+ }
@@ -0,0 +1,97 @@
1
+ import type { ServerRunPayload, ServerStory, ServerStoryFile } from '@poveste/shared'
2
+ import type { MessagePort } from 'node:worker_threads'
3
+ import type { FetchFunction, ResolveIdFunction } from 'vite-node'
4
+ import { performance } from 'node:perf_hooks'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { parentPort } from 'node:worker_threads'
7
+ import { createBirpc } from 'birpc'
8
+ import { dirname, resolve } from 'pathe'
9
+ import pc from 'picocolors'
10
+ import { ModuleCacheMap, ViteNodeRunner } from 'vite-node/client'
11
+ import { createDomEnv } from '../dom/env.js'
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url))
14
+
15
+ export interface Payload {
16
+ root: string
17
+ base: string
18
+ port: MessagePort
19
+ storyFile: ServerStoryFile
20
+ }
21
+
22
+ export interface ReturnData {
23
+ storyData: ServerStory[]
24
+ }
25
+
26
+ const _moduleCache = new ModuleCacheMap()
27
+ let _runner: ViteNodeRunner
28
+ let _rpc: ReturnType<typeof createBirpc<{
29
+ fetchModule: FetchFunction
30
+ resolveId: ResolveIdFunction
31
+ }>>
32
+
33
+ // Cleanup module cache
34
+ parentPort.on('message', (message) => {
35
+ if (message?.kind === 'hst:invalidate') {
36
+ _moduleCache.delete(message.file)
37
+ }
38
+ })
39
+
40
+ export default async (payload: Payload): Promise<ReturnData> => {
41
+ const startTime = performance.now()
42
+ process.env.HST_COLLECT = 'true'
43
+
44
+ _rpc = createBirpc<{
45
+ fetchModule: FetchFunction
46
+ resolveId: ResolveIdFunction
47
+ }>({}, {
48
+ post: data => payload.port.postMessage(data),
49
+ on: data => payload.port.on('message', data),
50
+ })
51
+
52
+ const runner = _runner ?? (_runner = new ViteNodeRunner({
53
+ root: payload.root,
54
+ base: payload.base,
55
+ moduleCache: _moduleCache,
56
+ fetchModule(id) {
57
+ return _rpc.fetchModule(id)
58
+ },
59
+ resolveId(id, importer) {
60
+ return _rpc.resolveId(id, importer)
61
+ },
62
+ }))
63
+
64
+ const { destroy: destroyDomEnv } = createDomEnv()
65
+
66
+ const el = window.document.createElement('div')
67
+
68
+ const beforeExecuteTime = performance.now()
69
+ // Mount app to collect stories/variants
70
+ const { run } = (await runner.executeFile(resolve(__dirname, './run.js'))) as { run: (payload: ServerRunPayload) => Promise<any> }
71
+ const afterExecuteTime = performance.now()
72
+ const storyData: ServerStory[] = []
73
+ await run({
74
+ file: payload.storyFile,
75
+ storyData,
76
+ el,
77
+ })
78
+ const afterRunTime = performance.now()
79
+
80
+ if (payload.storyFile.markdownFile) {
81
+ const el = document.createElement('div')
82
+ el.innerHTML = payload.storyFile.markdownFile.html
83
+ const text = el.textContent
84
+ storyData.forEach((s) => {
85
+ s.docsText = text
86
+ })
87
+ }
88
+
89
+ destroyDomEnv()
90
+
91
+ const endTime = performance.now()
92
+ console.log(pc.dim(`${payload.storyFile.relativePath} ${Math.round(endTime - startTime)}ms (setup:${Math.round(beforeExecuteTime - startTime)}ms, execute:${Math.round(afterExecuteTime - beforeExecuteTime)}ms, run:${Math.round(afterRunTime - afterExecuteTime)}ms)`))
93
+
94
+ return {
95
+ storyData,
96
+ }
97
+ }