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,72 @@
1
+ import { noCase } from 'change-case';
2
+ export async function generateTitleSearchData(ctx) {
3
+ const searchIndex = [];
4
+ const { idMap, addToIdMap } = createIdMap();
5
+ for (const storyFile of ctx.storyFiles) {
6
+ if (storyFile.story) {
7
+ searchIndex.push({
8
+ id: addToIdMap(storyFile.story.id, 'story'),
9
+ text: convertTitleToSentence(storyFile.story.title),
10
+ });
11
+ for (const variant of storyFile.story.variants) {
12
+ searchIndex.push({
13
+ id: addToIdMap(`${storyFile.story.id}:${variant.id}`, 'variant'),
14
+ text: convertTitleToSentence(`${storyFile.story.title} ${variant.title}`),
15
+ });
16
+ }
17
+ }
18
+ }
19
+ return {
20
+ index: searchIndex,
21
+ idMap,
22
+ };
23
+ }
24
+ export async function generateDocSearchData(ctx) {
25
+ const searchIndex = [];
26
+ const { idMap, addToIdMap } = createIdMap();
27
+ for (const storyFile of ctx.storyFiles) {
28
+ if (storyFile.story && storyFile.story.docsText) {
29
+ searchIndex.push({
30
+ id: addToIdMap(storyFile.story.id, 'story'),
31
+ text: storyFile.story.docsText,
32
+ });
33
+ }
34
+ }
35
+ return {
36
+ index: searchIndex,
37
+ idMap,
38
+ };
39
+ }
40
+ function createIdMap() {
41
+ let uid = 0;
42
+ const idMap = {};
43
+ function addToIdMap(id, kind) {
44
+ const n = uid++;
45
+ idMap[n] = { id, kind };
46
+ return n;
47
+ }
48
+ return {
49
+ idMap,
50
+ addToIdMap,
51
+ };
52
+ }
53
+ function convertTitleToSentence(text) {
54
+ return text.split(' ').map(str => noCase(str)).join(' ');
55
+ }
56
+ // @TODO clear handlers when SearchPane unmounts
57
+ export function getSearchDataJS(data) {
58
+ return `export let searchData = ${JSON.stringify(data)}
59
+ const handlers = []
60
+ export function onUpdate (cb) {
61
+ handlers.push(cb)
62
+ }
63
+ if (import.meta.hot) {
64
+ import.meta.hot.accept(newModule => {
65
+ searchData = newModule.searchData
66
+ handlers.forEach(h => {
67
+ h(newModule.searchData)
68
+ newModule.onUpdate(h)
69
+ })
70
+ })
71
+ }`;
72
+ }
@@ -0,0 +1,12 @@
1
+ import type { Context } from './context.js';
2
+ export interface CreateServerOptions {
3
+ port?: number;
4
+ open?: boolean;
5
+ host?: string | boolean;
6
+ }
7
+ export declare function createServer(ctx: Context, options?: CreateServerOptions): Promise<{
8
+ server: import("vite").ViteDevServer;
9
+ viteConfigFile: string;
10
+ close: () => Promise<void>;
11
+ }>;
12
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/node/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAa3C,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACxB;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,mBAAwB;;;;GAsNjF"}
@@ -0,0 +1,189 @@
1
+ import { performance } from 'node:perf_hooks';
2
+ import pc from 'picocolors';
3
+ import { createServer as createViteServer, mergeConfig as mergeViteConfig } from 'vite';
4
+ import { useCollectStories } from './collect/index.js';
5
+ import { useModuleLoader } from './load.js';
6
+ import { createMarkdownFilesWatcher, onMarkdownListChange } from './markdown.js';
7
+ import { DevEventPluginApi, DevPluginApi } from './plugin.js';
8
+ import { onStoryChange, onStoryListChange, watchStories } from './stories.js';
9
+ import { wrapLogError } from './util/log.js';
10
+ import * as VirtualFiles from './virtual/index.js';
11
+ import { getViteConfigWithPlugins } from './vite.js';
12
+ export async function createServer(ctx, options = {}) {
13
+ const getViteServer = async (collecting) => {
14
+ const { viteConfig, viteConfigFile } = await getViteConfigWithPlugins(collecting, ctx);
15
+ if (!collecting) {
16
+ if (options.open) {
17
+ viteConfig.server.open = true;
18
+ }
19
+ if (options.host) {
20
+ viteConfig.server.host = options.host;
21
+ }
22
+ }
23
+ const server = await createViteServer(mergeViteConfig(viteConfig, {
24
+ optimizeDeps: { include: viteConfig.optimizeDeps?.include ?? [], noDiscovery: collecting },
25
+ }));
26
+ await server.pluginContainer.buildStart({});
27
+ return {
28
+ server,
29
+ viteConfigFile,
30
+ };
31
+ };
32
+ // Should be run sequentially to get a fresh vite.config.js each time
33
+ const { server: nodeServer } = await getViteServer(true); // Run before normal vite to prevent breaking HMR in Nuxt
34
+ const { server, viteConfigFile } = await getViteServer(false);
35
+ await watchStories(ctx);
36
+ const { stop: stopMdFileWatcher } = await createMarkdownFilesWatcher(ctx);
37
+ const moduleLoader = useModuleLoader({
38
+ server: nodeServer,
39
+ });
40
+ const pluginOnCleanups = [];
41
+ for (const plugin of ctx.config.plugins) {
42
+ if (plugin.onDev) {
43
+ const api = new DevPluginApi(ctx, plugin, moduleLoader);
44
+ const onCleanup = (cb) => {
45
+ pluginOnCleanups.push(cb);
46
+ };
47
+ await plugin.onDev(api, onCleanup);
48
+ }
49
+ }
50
+ // Custom dev events
51
+ server.ws.on(`histoire:dev-event`, async ({ event, payload }) => {
52
+ for (const plugin of ctx.config.plugins) {
53
+ if (plugin.onDevEvent) {
54
+ const api = new DevEventPluginApi(ctx, plugin, moduleLoader, event, payload);
55
+ const result = await plugin.onDevEvent(api);
56
+ if (!event.startsWith('on') && result !== undefined) {
57
+ server.ws.send(`histoire:dev-event-result`, { event, result });
58
+ break;
59
+ }
60
+ }
61
+ }
62
+ });
63
+ // Wait for pre-bundling (in `listen()`)
64
+ await server.listen(options.port ?? server.config.server?.port);
65
+ const { clearCache, executeStoryFile, destroy: destroyCollectStories, } = useCollectStories({
66
+ server: nodeServer,
67
+ mainServer: server,
68
+ }, ctx);
69
+ // onStoryChange debouncing
70
+ let queued = false;
71
+ let queuedFiles = [];
72
+ let currentFiles = [];
73
+ let queueTimer;
74
+ let collecting = false;
75
+ let didAllStoriesYet = false;
76
+ // Invalidate modules
77
+ const invalidateModule = (id) => {
78
+ const mod = server.moduleGraph.getModuleById(id);
79
+ if (!mod) {
80
+ return;
81
+ }
82
+ server.moduleGraph.invalidateModule(mod);
83
+ // Send HMR update
84
+ const timestamp = Date.now();
85
+ mod.lastHMRTimestamp = timestamp;
86
+ server.ws.send({
87
+ type: 'update',
88
+ updates: [
89
+ {
90
+ type: 'js-update',
91
+ acceptedPath: mod.url,
92
+ path: mod.url,
93
+ timestamp,
94
+ },
95
+ ],
96
+ });
97
+ };
98
+ onStoryChange(async (changedFile) => {
99
+ if (changedFile && !didAllStoriesYet) {
100
+ return;
101
+ }
102
+ if (changedFile) {
103
+ if (!queuedFiles.includes(changedFile)) {
104
+ queuedFiles.push(changedFile);
105
+ }
106
+ }
107
+ else {
108
+ queuedFiles = [];
109
+ }
110
+ if (!queued) {
111
+ queued = true;
112
+ if (!collecting) {
113
+ clearTimeout(queueTimer);
114
+ // Debounce
115
+ queueTimer = setTimeout(collect, 100);
116
+ }
117
+ else if (!changedFile && !currentFiles.length) {
118
+ // Full collect in progress
119
+ queued = false;
120
+ }
121
+ }
122
+ });
123
+ async function collect() {
124
+ collecting = true;
125
+ clearCache();
126
+ currentFiles = queuedFiles.slice();
127
+ queuedFiles = [];
128
+ queued = false;
129
+ console.log('Collect stories start', currentFiles.length ? currentFiles.map(f => f.fileName).join(', ') : 'all');
130
+ const time = performance.now();
131
+ if (currentFiles.length) {
132
+ await Promise.all(currentFiles.map(async (storyFile) => {
133
+ await executeStoryFile(storyFile);
134
+ if (storyFile.story) {
135
+ await invalidateModule(`/__resolved__virtual:story-source:${storyFile.story.id}`);
136
+ }
137
+ }));
138
+ }
139
+ else {
140
+ // Full update
141
+ // Progress tracking
142
+ const fileCount = ctx.storyFiles.length;
143
+ let loadedFilesCount = 0;
144
+ const sendProgress = () => {
145
+ server.ws.send('histoire:stories-loading-progress', {
146
+ loadedFileCount: loadedFilesCount,
147
+ totalFileCount: fileCount,
148
+ });
149
+ };
150
+ sendProgress();
151
+ await Promise.all(ctx.storyFiles.map(async (storyFile) => {
152
+ await executeStoryFile(storyFile);
153
+ loadedFilesCount++;
154
+ sendProgress();
155
+ }));
156
+ didAllStoriesYet = true;
157
+ server.ws.send('histoire:all-stories-loaded', {});
158
+ }
159
+ console.log(`Collect stories end ${pc.bold(pc.blue(Math.round(performance.now() - time)))}ms`);
160
+ invalidateModule(VirtualFiles.RESOLVED_STORIES_ID);
161
+ invalidateModule(VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID);
162
+ collecting = false;
163
+ if (queued) {
164
+ await collect();
165
+ }
166
+ }
167
+ onStoryListChange(() => {
168
+ invalidateModule(VirtualFiles.RESOLVED_STORIES_ID);
169
+ invalidateModule(VirtualFiles.RESOLVED_SEARCH_TITLE_DATA_ID);
170
+ });
171
+ onMarkdownListChange(() => {
172
+ invalidateModule(VirtualFiles.RESOLVED_MARKDOWN_FILES);
173
+ });
174
+ async function close() {
175
+ for (const cb of pluginOnCleanups) {
176
+ await wrapLogError('plugin.onDev.onCleanup', () => cb());
177
+ }
178
+ await wrapLogError('server.close', () => server.close());
179
+ await wrapLogError('nodeServer', () => nodeServer.close());
180
+ await wrapLogError('destroyCollectStories', () => destroyCollectStories());
181
+ await wrapLogError('stopMdFileWatcher', () => stopMdFileWatcher());
182
+ }
183
+ collect();
184
+ return {
185
+ server,
186
+ viteConfigFile,
187
+ close,
188
+ };
189
+ }
@@ -0,0 +1,22 @@
1
+ import type { ServerStoryFile } from '@poveste/shared';
2
+ import type { Context } from './context.js';
3
+ type StoryChangeHandler = (file?: ServerStoryFile) => unknown;
4
+ /**
5
+ * Called when a new story is added or modified. Collecting should be done.
6
+ * @param handler
7
+ */
8
+ export declare function onStoryChange(handler: StoryChangeHandler): void;
9
+ export declare function notifyStoryChange(file?: ServerStoryFile): void;
10
+ type StoryListChangeHandler = () => unknown;
11
+ /**
12
+ * Called when the story list has changed (ex: removed a story). No collecting should be needed.
13
+ * @param handler
14
+ */
15
+ export declare function onStoryListChange(handler: StoryListChangeHandler): void;
16
+ export declare function notifyStoryListChange(): void;
17
+ export declare function watchStories(newContext: Context): Promise<import("chokidar").FSWatcher>;
18
+ export declare function addStory(relativeFilePath: string, virtualModuleCode?: string): ServerStoryFile;
19
+ export declare function removeStory(relativeFilePath: string): void;
20
+ export declare function findAllStories(newContext: Context): Promise<void>;
21
+ export {};
22
+ //# sourceMappingURL=stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stories.d.ts","sourceRoot":"","sources":["../../src/node/stories.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACtD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAO3C,KAAK,kBAAkB,GAAG,CAAC,IAAI,CAAC,EAAE,eAAe,KAAK,OAAO,CAAA;AAG7D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,kBAAkB,QAExD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE,eAAe,QAIvD;AAED,KAAK,sBAAsB,GAAG,MAAM,OAAO,CAAA;AAG3C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,sBAAsB,QAEhE;AAED,wBAAgB,qBAAqB,SAIpC;AAID,wBAAsB,YAAY,CAAC,UAAU,EAAE,OAAO,yCA0CrD;AAMD,wBAAgB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,mBA0C5E;AAED,wBAAgB,WAAW,CAAC,gBAAgB,EAAE,MAAM,QAInD;AAED,wBAAsB,cAAc,CAAC,UAAU,EAAE,OAAO,iBAWvD"}
@@ -0,0 +1,125 @@
1
+ import { kebabCase } from 'change-case';
2
+ import chokidar from 'chokidar';
3
+ import { globby } from 'globby';
4
+ import micromatch from 'micromatch';
5
+ import { basename, resolve } from 'pathe';
6
+ const storyChangeHandlers = [];
7
+ /**
8
+ * Called when a new story is added or modified. Collecting should be done.
9
+ * @param handler
10
+ */
11
+ export function onStoryChange(handler) {
12
+ storyChangeHandlers.push(handler);
13
+ }
14
+ export function notifyStoryChange(file) {
15
+ for (const handler of storyChangeHandlers) {
16
+ handler(file);
17
+ }
18
+ }
19
+ const storyListChangeHandlers = [];
20
+ /**
21
+ * Called when the story list has changed (ex: removed a story). No collecting should be needed.
22
+ * @param handler
23
+ */
24
+ export function onStoryListChange(handler) {
25
+ storyListChangeHandlers.push(handler);
26
+ }
27
+ export function notifyStoryListChange() {
28
+ for (const handler of storyListChangeHandlers) {
29
+ handler();
30
+ }
31
+ }
32
+ let context;
33
+ export async function watchStories(newContext) {
34
+ context = newContext;
35
+ const baseWatchPaths = Array.from(new Set(context.config.storyMatch.map((pattern) => {
36
+ const segments = pattern.split('/');
37
+ return segments.slice(0, segments.findIndex(segment => segment.includes('*'))).join('/') || '.';
38
+ })));
39
+ const resolvedStoryIgnored = context.config.storyIgnored.map((pattern) => {
40
+ return resolve(context.root, pattern);
41
+ });
42
+ const resolveStoryMatch = context.config.storyMatch.map((pattern) => {
43
+ return resolve(context.root, pattern);
44
+ });
45
+ const watcher = chokidar.watch(baseWatchPaths, {
46
+ cwd: context.root,
47
+ ignored: (path, stats) => {
48
+ if (resolvedStoryIgnored.some(pattern => micromatch.isMatch(path, pattern))) {
49
+ return true;
50
+ }
51
+ if (resolveStoryMatch.some(pattern => micromatch.isMatch(path, pattern))) {
52
+ return false;
53
+ }
54
+ // Allow directories to be traversed, only ignore files that don't match
55
+ return stats?.isFile() ?? false;
56
+ },
57
+ });
58
+ watcher
59
+ .on('add', (file) => {
60
+ const storyFile = addStory(file);
61
+ setTimeout(() => notifyStoryChange(storyFile), 100); // Delay in case file renaming fired Add event before Unlink event
62
+ })
63
+ .on('unlink', (file) => {
64
+ removeStory(file);
65
+ notifyStoryListChange();
66
+ });
67
+ return watcher;
68
+ }
69
+ function getAbsoluteFilePath(relativeFilePath) {
70
+ return resolve(context.root, relativeFilePath);
71
+ }
72
+ export function addStory(relativeFilePath, virtualModuleCode) {
73
+ const absoluteFilePath = getAbsoluteFilePath(relativeFilePath);
74
+ for (const file of context.storyFiles) {
75
+ if (file.path === absoluteFilePath) {
76
+ return file;
77
+ }
78
+ }
79
+ const fileId = kebabCase(relativeFilePath.toLowerCase());
80
+ let fileName = basename(relativeFilePath);
81
+ if (fileName.includes('.')) {
82
+ fileName = fileName.substring(0, fileName.indexOf('.'));
83
+ }
84
+ let supportPluginId;
85
+ for (const p of context.config.supportMatch) {
86
+ if (micromatch.isMatch(absoluteFilePath, p.patterns, {
87
+ dot: true,
88
+ })) {
89
+ supportPluginId = p.pluginIds[0];
90
+ break;
91
+ }
92
+ }
93
+ if (!supportPluginId) {
94
+ throw new Error(`No support plugin found for file ${absoluteFilePath}`);
95
+ }
96
+ const file = {
97
+ id: fileId, // The file id will be changed by the story id after it is collected
98
+ path: absoluteFilePath,
99
+ relativePath: relativeFilePath,
100
+ fileName,
101
+ moduleId: virtualModuleCode ? `virtual:story:${absoluteFilePath}` : absoluteFilePath,
102
+ supportPluginId,
103
+ virtual: !!virtualModuleCode,
104
+ moduleCode: virtualModuleCode,
105
+ };
106
+ context.storyFiles.push(file);
107
+ return file;
108
+ }
109
+ export function removeStory(relativeFilePath) {
110
+ const absoluteFilePath = getAbsoluteFilePath(relativeFilePath);
111
+ const index = context.storyFiles.findIndex(file => file.path === absoluteFilePath);
112
+ if (index !== -1)
113
+ context.storyFiles.splice(index, 1);
114
+ }
115
+ export async function findAllStories(newContext) {
116
+ context = newContext;
117
+ const files = await globby(context.config.storyMatch, {
118
+ cwd: context.root,
119
+ ignore: context.config.storyIgnored,
120
+ });
121
+ context.storyFiles.length = 0;
122
+ for (const file of files) {
123
+ addStory(file);
124
+ }
125
+ }
@@ -0,0 +1,4 @@
1
+ import type { PovesteConfig, ServerStoryFile, ServerTree, ServerTreeFile } from '@poveste/shared';
2
+ export declare function createPath(config: PovesteConfig, file: ServerTreeFile): string[];
3
+ export declare function makeTree(config: PovesteConfig, files: ServerStoryFile[]): ServerTree;
4
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/node/tree.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,UAAU,EACV,cAAc,EAEf,MAAM,iBAAiB,CAAA;AAGxB,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,YAmBrE;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAE,cA+HvE"}
@@ -0,0 +1,117 @@
1
+ import pc from 'picocolors';
2
+ export function createPath(config, file) {
3
+ if (config.tree.file === 'title') {
4
+ return file.title.split('/');
5
+ }
6
+ if (config.tree.file === 'path') {
7
+ const paths = file.path.split('/').slice(0, -1);
8
+ // check if tree file path is a plugin
9
+ const index = paths.findIndex(p => p.includes('.histoire'));
10
+ if (index !== -1) {
11
+ return ['plugins', file.title];
12
+ }
13
+ return [...paths, file.title];
14
+ }
15
+ return config.tree.file(file);
16
+ }
17
+ export function makeTree(config, files) {
18
+ const groups = config.tree?.groups?.map(g => ({
19
+ groupConfig: g,
20
+ treeObject: {},
21
+ })) || [];
22
+ const defaultGroup = {
23
+ treeObject: {},
24
+ };
25
+ groups.push(defaultGroup);
26
+ files.forEach((file, index) => {
27
+ const group = getGroup(file);
28
+ setPath(file.treePath, index, group.treeObject);
29
+ });
30
+ let sortingFunction = (a, b) => a.localeCompare(b);
31
+ if (config.tree.order !== 'asc') {
32
+ sortingFunction = config.tree.order;
33
+ }
34
+ const result = [];
35
+ for (const group of groups) {
36
+ if (group === defaultGroup) {
37
+ result.push(...buildTree(group.treeObject));
38
+ }
39
+ else {
40
+ result.push({
41
+ group: true,
42
+ id: group.groupConfig.id,
43
+ title: group.groupConfig.title,
44
+ children: buildTree(group.treeObject),
45
+ });
46
+ }
47
+ }
48
+ return result;
49
+ function getGroup(file) {
50
+ if (file.story?.group) {
51
+ const group = groups.find(g => g.groupConfig?.id === file.story.group);
52
+ if (group) {
53
+ return group;
54
+ }
55
+ else {
56
+ console.error(pc.red(`Group ${file.story.group} not found for story ${file.path}`));
57
+ }
58
+ }
59
+ for (const group of groups) {
60
+ if (group.groupConfig?.include && group.groupConfig.include(file.treeFile)) {
61
+ return group;
62
+ }
63
+ }
64
+ return defaultGroup;
65
+ }
66
+ function setPath(path, value, tree) {
67
+ path.reduce((subtree, key, i) => {
68
+ if (i === path.length - 1) {
69
+ setKey(subtree, key, value);
70
+ }
71
+ else if (isLeaf(subtree[key])) {
72
+ setKey(subtree, key, subtree[key]);
73
+ subtree[key] = {};
74
+ }
75
+ else if (!subtree[key]) {
76
+ subtree[key] = {};
77
+ }
78
+ return subtree[key];
79
+ }, tree);
80
+ function isLeaf(element) {
81
+ return !Number.isNaN(Number(element));
82
+ }
83
+ }
84
+ function setKey(tree, key, value) {
85
+ if (isUndefined(tree[key])) {
86
+ tree[key] = value;
87
+ return;
88
+ }
89
+ let copyNumber = 1;
90
+ while (!isUndefined(tree[`${key}-${copyNumber}`])) {
91
+ copyNumber++;
92
+ }
93
+ tree[`${key}-${copyNumber}`] = value;
94
+ function isUndefined(element) {
95
+ return element === undefined;
96
+ }
97
+ }
98
+ function buildTree(treeObject) {
99
+ const tree = [];
100
+ for (const [key, element] of Object.entries(treeObject)) {
101
+ if (Number.isInteger(element)) {
102
+ tree.push({
103
+ title: key,
104
+ index: element,
105
+ });
106
+ }
107
+ else {
108
+ tree.push({
109
+ title: key,
110
+ children: buildTree(element),
111
+ });
112
+ }
113
+ }
114
+ tree.sort((a, b) => sortingFunction(a.title, b.title));
115
+ return tree;
116
+ }
117
+ }
@@ -0,0 +1,2 @@
1
+ export declare function findUp(cwd: string, fileNames: string[]): string;
2
+ //# sourceMappingURL=find-up.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-up.d.ts","sourceRoot":"","sources":["../../../src/node/util/find-up.ts"],"names":[],"mappings":"AAGA,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAsB,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,CAoB/E"}
@@ -0,0 +1,20 @@
1
+ import fs from 'node:fs';
2
+ import path from 'pathe';
3
+ export function findUp(cwd = process.cwd(), fileNames) {
4
+ let { root } = path.parse(cwd);
5
+ let dir = cwd;
6
+ // On Windows, it will for example return `C:`, we need to add the trailing `/`
7
+ if (root[1] === ':' && root[2] === undefined) {
8
+ root += '/';
9
+ }
10
+ while (dir !== root) {
11
+ for (const fileName of fileNames) {
12
+ const searchPath = path.join(dir, fileName);
13
+ if (fs.existsSync(searchPath)) {
14
+ return searchPath;
15
+ }
16
+ }
17
+ dir = path.dirname(dir);
18
+ }
19
+ return null;
20
+ }
@@ -0,0 +1,2 @@
1
+ export declare const slash: (str: string) => string;
2
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../../src/node/util/fs.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,QAAS,MAAM,WAA4B,CAAA"}
@@ -0,0 +1 @@
1
+ export const slash = (str) => str.replace(/\\/g, '/');
@@ -0,0 +1,2 @@
1
+ export declare function wrapLogError(id: string, cb: () => unknown): Promise<void>;
2
+ //# sourceMappingURL=log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/node/util/log.ts"],"names":[],"mappings":"AAEA,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,iBAO/D"}
@@ -0,0 +1,9 @@
1
+ import pc from 'picocolors';
2
+ export async function wrapLogError(id, cb) {
3
+ try {
4
+ await cb();
5
+ }
6
+ catch (e) {
7
+ console.error(pc.red(`[Error] ${id}: ${e}`));
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ export declare function slugify(str: string): string;
2
+ //# sourceMappingURL=slugify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slugify.d.ts","sourceRoot":"","sources":["../../../src/node/util/slugify.ts"],"names":[],"mappings":"AASA,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAgB3C"}
@@ -0,0 +1,22 @@
1
+ // From vitepress
2
+ // string.js slugify drops non ascii chars so we have to
3
+ // use a custom implementation here
4
+ import { remove as removeDiacritics } from 'diacritics';
5
+ // eslint-disable-next-line no-control-regex
6
+ const rControl = /[\u0000-\u001F]/g;
7
+ const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'<>,.?/]+/g;
8
+ export function slugify(str) {
9
+ return (removeDiacritics(str)
10
+ // Remove control characters
11
+ .replace(rControl, '')
12
+ // Replace special characters
13
+ .replace(rSpecial, '-')
14
+ // Remove continuous separators
15
+ .replace(/-{2,}/g, '-')
16
+ // Remove prefixing and trailing separators
17
+ .replace(/^-+|-+$/g, '')
18
+ // ensure it doesn't start with a number (#121)
19
+ .replace(/^(\d)/, '_$1')
20
+ // lowercase
21
+ .toLowerCase());
22
+ }
@@ -0,0 +1,3 @@
1
+ export declare const __dirname: string;
2
+ export declare function getInjectedImport(request: string): string;
3
+ //# sourceMappingURL=vendors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vendors.d.ts","sourceRoot":"","sources":["../../../src/node/util/vendors.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,SAAS,QAA+C,CAAA;AAQrE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,UAahD"}