@scaffold-ui-kit/preview 0.0.0-stage → 2.3.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.
- package/LICENSE +21 -0
- package/README.md +1868 -2
- package/application/host/bootstrap.ts +43 -0
- package/application/host/main.ts +31 -0
- package/application/host/shell-host.ts +47 -0
- package/application/index.html +12 -0
- package/application/lib/base-url.ts +15 -0
- package/application/lib/no-code-block.ts +7 -0
- package/application/lib/no-setup.ts +3 -0
- package/application/lib/no-views.ts +6 -0
- package/application/preview/code/code.html +12 -0
- package/application/preview/code/main.ts +89 -0
- package/application/preview/globals.ts +254 -0
- package/application/preview/html/main.ts +93 -0
- package/application/preview/html/preview.html +12 -0
- package/application/preview/react/main.tsx +146 -0
- package/application/preview/react/preview.html +12 -0
- package/application/preview/svelte/Preview.svelte +104 -0
- package/application/preview/svelte/main.ts +13 -0
- package/application/preview/svelte/preview.html +12 -0
- package/application/preview/svelte/story-props.ts +172 -0
- package/application/preview/view/main.ts +124 -0
- package/application/preview/view/view.html +12 -0
- package/application/preview/vue/main.ts +145 -0
- package/application/preview/vue/preview.html +12 -0
- package/application/shells/charcell/components/Application/index.css +37 -0
- package/application/shells/charcell/components/Application/index.tsx +65 -0
- package/application/shells/charcell/components/Bar/index.css +68 -0
- package/application/shells/charcell/components/Bar/index.tsx +60 -0
- package/application/shells/charcell/components/CodePane/index.css +60 -0
- package/application/shells/charcell/components/CodePane/index.tsx +113 -0
- package/application/shells/charcell/components/ComponentStage/index.css +26 -0
- package/application/shells/charcell/components/ComponentStage/index.tsx +110 -0
- package/application/shells/charcell/components/Control/index.css +20 -0
- package/application/shells/charcell/components/Control/index.tsx +118 -0
- package/application/shells/charcell/components/CopyLink/index.tsx +35 -0
- package/application/shells/charcell/components/Description/index.css +6 -0
- package/application/shells/charcell/components/Description/index.tsx +24 -0
- package/application/shells/charcell/components/EditorAddDialog/index.css +9 -0
- package/application/shells/charcell/components/EditorAddDialog/index.tsx +158 -0
- package/application/shells/charcell/components/EditorPanel/index.css +48 -0
- package/application/shells/charcell/components/EditorPanel/index.tsx +496 -0
- package/application/shells/charcell/components/EventsRow/index.css +42 -0
- package/application/shells/charcell/components/EventsRow/index.tsx +68 -0
- package/application/shells/charcell/components/HeadingRow/index.css +11 -0
- package/application/shells/charcell/components/HeadingRow/index.tsx +16 -0
- package/application/shells/charcell/components/Hint/index.css +16 -0
- package/application/shells/charcell/components/Hint/index.tsx +81 -0
- package/application/shells/charcell/components/HtmlWarnings/index.tsx +45 -0
- package/application/shells/charcell/components/KeyHints/index.css +27 -0
- package/application/shells/charcell/components/KeyHints/index.tsx +106 -0
- package/application/shells/charcell/components/KitCodeBlock/index.css +55 -0
- package/application/shells/charcell/components/KitCodeBlock/index.tsx +18 -0
- package/application/shells/charcell/components/Markdown/index.tsx +16 -0
- package/application/shells/charcell/components/Navigation/index.css +13 -0
- package/application/shells/charcell/components/Navigation/index.tsx +98 -0
- package/application/shells/charcell/components/NavigationSplit/index.css +16 -0
- package/application/shells/charcell/components/NavigationSplit/index.tsx +82 -0
- package/application/shells/charcell/components/OptionControls/index.tsx +93 -0
- package/application/shells/charcell/components/PaneStatus/index.css +7 -0
- package/application/shells/charcell/components/PaneStatus/index.tsx +47 -0
- package/application/shells/charcell/components/PaneWidth/index.tsx +45 -0
- package/application/shells/charcell/components/PreviewGrid/index.css +39 -0
- package/application/shells/charcell/components/PreviewGrid/index.tsx +344 -0
- package/application/shells/charcell/components/PreviewPane/index.css +127 -0
- package/application/shells/charcell/components/PreviewPane/index.tsx +182 -0
- package/application/shells/charcell/components/PromptBar/index.tsx +133 -0
- package/application/shells/charcell/components/ScenarioRow/index.css +36 -0
- package/application/shells/charcell/components/ScenarioRow/index.tsx +71 -0
- package/application/shells/charcell/components/Select/index.tsx +48 -0
- package/application/shells/charcell/components/SlotOutlet/index.css +7 -0
- package/application/shells/charcell/components/SlotOutlet/index.tsx +25 -0
- package/application/shells/charcell/components/StageBar/index.css +7 -0
- package/application/shells/charcell/components/StageBar/index.tsx +109 -0
- package/application/shells/charcell/components/StageSplit/index.css +11 -0
- package/application/shells/charcell/components/StageSplit/index.tsx +99 -0
- package/application/shells/charcell/components/StatusBar/index.tsx +30 -0
- package/application/shells/charcell/components/ViewControls/index.css +15 -0
- package/application/shells/charcell/components/ViewControls/index.tsx +58 -0
- package/application/shells/charcell/components/ViewHeading/index.css +13 -0
- package/application/shells/charcell/components/ViewHeading/index.tsx +8 -0
- package/application/shells/charcell/components/ViewStage/index.css +9 -0
- package/application/shells/charcell/components/ViewStage/index.tsx +25 -0
- package/application/shells/charcell/components/WrapToggle/index.tsx +27 -0
- package/application/shells/charcell/configuration.ts +45 -0
- package/application/shells/charcell/controller-context.ts +27 -0
- package/application/shells/charcell/fit-labels.ts +42 -0
- package/application/shells/charcell/html-warnings.ts +18 -0
- package/application/shells/charcell/index.tsx +82 -0
- package/application/shells/charcell/page-loading.html +57 -0
- package/application/shells/charcell/placement.ts +24 -0
- package/application/shells/charcell/shell-options.ts +23 -0
- package/application/shells/charcell/shell.css +37 -0
- package/application/shells/charcell/shell.tsx +25 -0
- package/application/shells/charcell/split-reset.ts +47 -0
- package/application/shells/charcell/stacked-rows.ts +117 -0
- package/application/shells/charcell/stage-toggles.ts +93 -0
- package/application/types/manifest.d.ts +6 -0
- package/application/types/preview-configuration.d.ts +10 -0
- package/application/types/preview-shell.d.ts +7 -0
- package/application/types/react-registry.d.ts +15 -0
- package/application/types/vue-registry.d.ts +6 -0
- package/dist/build.d.ts +24 -0
- package/dist/build.js +34 -0
- package/dist/check.d.ts +48 -0
- package/dist/check.js +781 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +88 -0
- package/dist/context.d.ts +179 -0
- package/dist/context.js +783 -0
- package/dist/controller/catalog.d.ts +339 -0
- package/dist/controller/catalog.js +367 -0
- package/dist/controller/create-preview-controller.d.ts +532 -0
- package/dist/controller/create-preview-controller.js +1707 -0
- package/dist/controller/editor-tree.d.ts +161 -0
- package/dist/controller/editor-tree.js +373 -0
- package/dist/controller/html-source.d.ts +62 -0
- package/dist/controller/html-source.js +61 -0
- package/dist/controller/index.d.ts +9 -0
- package/dist/controller/index.js +12 -0
- package/dist/controller/persistence.d.ts +191 -0
- package/dist/controller/persistence.js +315 -0
- package/dist/controller/regeneration.d.ts +30 -0
- package/dist/controller/regeneration.js +27 -0
- package/dist/controller/source.d.ts +80 -0
- package/dist/controller/source.js +236 -0
- package/dist/controller/store.d.ts +27 -0
- package/dist/controller/store.js +40 -0
- package/dist/declarations/application/shells/charcell/components/Application/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Bar/index.d.ts +11 -0
- package/dist/declarations/application/shells/charcell/components/CodePane/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/ComponentStage/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Control/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/CopyLink/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/Description/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/EditorAddDialog/index.d.ts +6 -0
- package/dist/declarations/application/shells/charcell/components/EditorPanel/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/EventsRow/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/HeadingRow/index.d.ts +6 -0
- package/dist/declarations/application/shells/charcell/components/Hint/index.d.ts +11 -0
- package/dist/declarations/application/shells/charcell/components/HtmlWarnings/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/KeyHints/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/KitCodeBlock/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/Markdown/index.d.ts +3 -0
- package/dist/declarations/application/shells/charcell/components/Navigation/index.d.ts +8 -0
- package/dist/declarations/application/shells/charcell/components/NavigationSplit/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/OptionControls/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/PaneStatus/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/PaneWidth/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/PreviewGrid/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/PreviewPane/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/PromptBar/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/ScenarioRow/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Select/index.d.ts +16 -0
- package/dist/declarations/application/shells/charcell/components/SlotOutlet/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/StageBar/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/StageSplit/index.d.ts +17 -0
- package/dist/declarations/application/shells/charcell/components/StatusBar/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/ViewControls/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/ViewHeading/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/ViewStage/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/WrapToggle/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/configuration.d.ts +31 -0
- package/dist/declarations/application/shells/charcell/controller-context.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/fit-labels.d.ts +18 -0
- package/dist/declarations/application/shells/charcell/html-warnings.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/index.d.ts +39 -0
- package/dist/declarations/application/shells/charcell/placement.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/shell-options.d.ts +15 -0
- package/dist/declarations/application/shells/charcell/shell.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/split-reset.d.ts +30 -0
- package/dist/declarations/application/shells/charcell/stacked-rows.d.ts +58 -0
- package/dist/declarations/application/shells/charcell/stage-toggles.d.ts +28 -0
- package/dist/declarations/src/controller/catalog.d.ts +339 -0
- package/dist/declarations/src/controller/create-preview-controller.d.ts +532 -0
- package/dist/declarations/src/controller/editor-tree.d.ts +161 -0
- package/dist/declarations/src/controller/html-source.d.ts +62 -0
- package/dist/declarations/src/controller/index.d.ts +9 -0
- package/dist/declarations/src/controller/persistence.d.ts +191 -0
- package/dist/declarations/src/controller/regeneration.d.ts +30 -0
- package/dist/declarations/src/controller/source.d.ts +80 -0
- package/dist/declarations/src/controller/store.d.ts +27 -0
- package/dist/declarations/src/emit/common.d.ts +103 -0
- package/dist/declarations/src/emit/manifest.d.ts +138 -0
- package/dist/declarations/src/emit/source.d.ts +87 -0
- package/dist/declarations/src/lib/jsx-roots.d.ts +22 -0
- package/dist/declarations/src/lib/module-of-source.d.ts +18 -0
- package/dist/declarations/src/lib/naming.d.ts +29 -0
- package/dist/declarations/src/lib/react-spelling.d.ts +68 -0
- package/dist/declarations/src/lib/scenario-story.d.ts +41 -0
- package/dist/declarations/src/lib/slot-fill.d.ts +15 -0
- package/dist/declarations/src/lib/types.d.ts +741 -0
- package/dist/declarations/src/options.d.ts +224 -0
- package/dist/declarations/src/protocol.d.ts +541 -0
- package/dist/declarations/src/react-view.d.ts +22 -0
- package/dist/declarations/src/react.d.ts +17 -0
- package/dist/declarations/src/shell.d.ts +99 -0
- package/dist/declarations/src/views.d.ts +152 -0
- package/dist/development-server.d.ts +121 -0
- package/dist/development-server.js +331 -0
- package/dist/emit/common.d.ts +103 -0
- package/dist/emit/common.js +170 -0
- package/dist/emit/html-source.d.ts +46 -0
- package/dist/emit/html-source.js +322 -0
- package/dist/emit/manifest.d.ts +138 -0
- package/dist/emit/manifest.js +74 -0
- package/dist/emit/react.d.ts +16 -0
- package/dist/emit/react.js +210 -0
- package/dist/emit/scratch.d.ts +40 -0
- package/dist/emit/scratch.js +116 -0
- package/dist/emit/source.d.ts +87 -0
- package/dist/emit/source.js +789 -0
- package/dist/emit/svelte.d.ts +9 -0
- package/dist/emit/svelte.js +177 -0
- package/dist/emit/vue.d.ts +2 -0
- package/dist/emit/vue.js +152 -0
- package/dist/enumerate.d.ts +2 -0
- package/dist/enumerate.js +162 -0
- package/dist/generate.d.ts +43 -0
- package/dist/generate.js +302 -0
- package/dist/html-stylesheet.d.ts +43 -0
- package/dist/html-stylesheet.js +145 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +21 -0
- package/dist/landing.d.ts +16 -0
- package/dist/landing.js +45 -0
- package/dist/lib/exported-types.d.ts +42 -0
- package/dist/lib/exported-types.js +86 -0
- package/dist/lib/html-attributes.d.ts +2 -0
- package/dist/lib/html-attributes.js +111 -0
- package/dist/lib/html-warnings.d.ts +19 -0
- package/dist/lib/html-warnings.js +79 -0
- package/dist/lib/jsx-roots.d.ts +22 -0
- package/dist/lib/jsx-roots.js +243 -0
- package/dist/lib/module-of-source.d.ts +18 -0
- package/dist/lib/module-of-source.js +24 -0
- package/dist/lib/naming.d.ts +29 -0
- package/dist/lib/naming.js +56 -0
- package/dist/lib/parse-type.d.ts +32 -0
- package/dist/lib/parse-type.js +103 -0
- package/dist/lib/react-spelling.d.ts +68 -0
- package/dist/lib/react-spelling.js +197 -0
- package/dist/lib/scenario-story.d.ts +41 -0
- package/dist/lib/scenario-story.js +84 -0
- package/dist/lib/slot-fill.d.ts +15 -0
- package/dist/lib/slot-fill.js +92 -0
- package/dist/lib/template-files.d.ts +14 -0
- package/dist/lib/template-files.js +25 -0
- package/dist/lib/types.d.ts +741 -0
- package/dist/lib/types.js +13 -0
- package/dist/lib/void-elements.d.ts +7 -0
- package/dist/lib/void-elements.js +13 -0
- package/dist/load.d.ts +37 -0
- package/dist/load.js +82 -0
- package/dist/model.d.ts +44 -0
- package/dist/model.js +464 -0
- package/dist/options.d.ts +224 -0
- package/dist/options.js +223 -0
- package/dist/prop-types.d.ts +26 -0
- package/dist/prop-types.js +102 -0
- package/dist/props-from.d.ts +84 -0
- package/dist/props-from.js +510 -0
- package/dist/protocol.d.ts +541 -0
- package/dist/protocol.js +819 -0
- package/dist/react-view.d.ts +22 -0
- package/dist/react-view.js +36 -0
- package/dist/react.d.ts +17 -0
- package/dist/react.js +23 -0
- package/dist/sass-importers.d.ts +26 -0
- package/dist/sass-importers.js +32 -0
- package/dist/shell-acceptance.d.ts +21 -0
- package/dist/shell-acceptance.js +37 -0
- package/dist/shell-page.d.ts +36 -0
- package/dist/shell-page.js +90 -0
- package/dist/shell-peers.d.ts +38 -0
- package/dist/shell-peers.js +61 -0
- package/dist/shell.d.ts +99 -0
- package/dist/shell.js +52 -0
- package/dist/shells/charcell/page.d.ts +8 -0
- package/dist/shells/charcell/page.js +69 -0
- package/dist/story-source.d.ts +113 -0
- package/dist/story-source.js +271 -0
- package/dist/story.d.ts +5 -0
- package/dist/story.js +28 -0
- package/dist/testing.d.ts +218 -0
- package/dist/testing.js +284 -0
- package/dist/views.d.ts +152 -0
- package/dist/views.js +7 -0
- package/dist/vite-configuration.d.ts +114 -0
- package/dist/vite-configuration.js +578 -0
- package/package.json +123 -3
- package/src/build.ts +51 -0
- package/src/check.ts +1062 -0
- package/src/cli.ts +123 -0
- package/src/context.ts +1168 -0
- package/src/controller/catalog.ts +719 -0
- package/src/controller/create-preview-controller.ts +2683 -0
- package/src/controller/editor-tree.ts +530 -0
- package/src/controller/html-source.ts +114 -0
- package/src/controller/index.ts +105 -0
- package/src/controller/persistence.ts +403 -0
- package/src/controller/regeneration.ts +55 -0
- package/src/controller/source.ts +333 -0
- package/src/controller/store.ts +55 -0
- package/src/development-server.ts +442 -0
- package/src/emit/common.ts +201 -0
- package/src/emit/html-source.ts +402 -0
- package/src/emit/manifest.ts +241 -0
- package/src/emit/react.ts +263 -0
- package/src/emit/scratch.ts +175 -0
- package/src/emit/source.ts +1094 -0
- package/src/emit/svelte.ts +230 -0
- package/src/emit/vue.ts +194 -0
- package/src/enumerate.ts +220 -0
- package/src/generate.ts +443 -0
- package/src/html-stylesheet.ts +173 -0
- package/src/index.ts +60 -0
- package/src/landing.ts +58 -0
- package/src/lib/exported-types.ts +114 -0
- package/src/lib/html-attributes.ts +113 -0
- package/src/lib/html-warnings.ts +81 -0
- package/src/lib/jsx-roots.ts +238 -0
- package/src/lib/module-of-source.ts +26 -0
- package/src/lib/naming.ts +65 -0
- package/src/lib/parse-type.ts +143 -0
- package/src/lib/react-spelling.ts +235 -0
- package/src/lib/scenario-story.ts +97 -0
- package/src/lib/slot-fill.ts +102 -0
- package/src/lib/template-files.ts +31 -0
- package/src/lib/types.ts +778 -0
- package/src/lib/void-elements.ts +15 -0
- package/src/load.ts +144 -0
- package/src/model.ts +568 -0
- package/src/options.ts +435 -0
- package/src/prop-types.ts +133 -0
- package/src/props-from.ts +678 -0
- package/src/protocol.ts +1135 -0
- package/src/react-view.ts +45 -0
- package/src/react.ts +34 -0
- package/src/sass-importers.ts +45 -0
- package/src/shell-acceptance.ts +45 -0
- package/src/shell-page.ts +133 -0
- package/src/shell-peers.ts +70 -0
- package/src/shell.ts +194 -0
- package/src/shells/charcell/page.ts +82 -0
- package/src/story-source.ts +391 -0
- package/src/story.ts +42 -0
- package/src/testing.ts +497 -0
- package/src/views.ts +183 -0
- package/src/vite-configuration.ts +675 -0
package/dist/generate.js
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// The preview generator: enumerate every source's component templates → build
|
|
2
|
+
// one target-agnostic model per component → emit a per-target
|
|
3
|
+
// render-registry + the host manifest into `<kitRoot>/.preview-generated/`. Pure
|
|
4
|
+
// function of the preview context - no kit names or paths are baked in; the
|
|
5
|
+
// kit supplies everything through its `preview` block (see context.ts).
|
|
6
|
+
//
|
|
7
|
+
// Every output is rendered before anything is written, so a kit module that
|
|
8
|
+
// fails to load leaves the previous output in place. A file is written only
|
|
9
|
+
// when its content differs from what is on disk, so a development server
|
|
10
|
+
// serving the tree reloads only for what changed.
|
|
11
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync, } from 'node:fs';
|
|
12
|
+
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
13
|
+
import { kitPaneWidths, loadKit } from './load.js';
|
|
14
|
+
import { landingProblems } from './landing.js';
|
|
15
|
+
import { scenarioStories, storyOnScenario } from './lib/scenario-story.js';
|
|
16
|
+
import { resolveStory } from './model.js';
|
|
17
|
+
import { REACT_ATTRIBUTE_NAMES } from '@js-template-engine/extension-react';
|
|
18
|
+
import { declaredAttributes } from './lib/react-spelling.js';
|
|
19
|
+
import { emitReactRegistry } from './emit/react.js';
|
|
20
|
+
import { emitVueRegistry } from './emit/vue.js';
|
|
21
|
+
import { emitSvelteRegistry, emitSvelteWrapper } from './emit/svelte.js';
|
|
22
|
+
import { buildManifest } from './emit/manifest.js';
|
|
23
|
+
import { writeScratchStubs } from './emit/scratch.js';
|
|
24
|
+
import { optionProblems } from './options.js';
|
|
25
|
+
import { htmlWarningLine, printHtmlSource, sourceStoryOf, } from './story-source.js';
|
|
26
|
+
import { htmlSourceResponse } from './html-stylesheet.js';
|
|
27
|
+
import { HTML_SOURCE_DIRECTORY, } from './controller/html-source.js';
|
|
28
|
+
import { exportedTypesOf } from './lib/exported-types.js';
|
|
29
|
+
import { sanitize } from './lib/naming.js';
|
|
30
|
+
import { moduleOfSource } from './lib/module-of-source.js';
|
|
31
|
+
const targets = ['react', 'vue', 'svelte'];
|
|
32
|
+
/** Every file under `directory`, as absolute paths. */
|
|
33
|
+
function filesUnder(directory) {
|
|
34
|
+
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
35
|
+
const path = join(directory, entry.name);
|
|
36
|
+
return entry.isDirectory() ? filesUnder(path) : [path];
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/** Writes `content` to `path` unless the file already holds exactly that. */
|
|
40
|
+
function writeIfChanged(path, content) {
|
|
41
|
+
const bytes = typeof content === 'string' ? Buffer.from(content) : content;
|
|
42
|
+
if (existsSync(path) && readFileSync(path).equals(bytes))
|
|
43
|
+
return false;
|
|
44
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
45
|
+
writeFileSync(path, bytes);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Generates the preview into `<kitRoot>/.preview-generated/`: a render
|
|
50
|
+
* registry per target, the Svelte wrappers, the module-resolution data the
|
|
51
|
+
* scenario editor reads, the host manifest, and the themes' stylesheets.
|
|
52
|
+
*
|
|
53
|
+
* @param context - The kit's preview context.
|
|
54
|
+
* @param options - Whether the generated tree is emptied first.
|
|
55
|
+
* @returns The files written and removed.
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* await generatePreview(loadPreviewContext(kitRoot));
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export async function generatePreview(context, options = {}) {
|
|
62
|
+
const { clean = true, htmlSources = false } = options;
|
|
63
|
+
const { generatedRoot, sources } = context;
|
|
64
|
+
const directory = {};
|
|
65
|
+
for (const target of targets) {
|
|
66
|
+
directory[target] = resolve(generatedRoot, target);
|
|
67
|
+
}
|
|
68
|
+
const { components } = await loadKit(context);
|
|
69
|
+
const hints = context.configuration.controlHints ?? {};
|
|
70
|
+
const problems = optionProblems(context.configuration.options);
|
|
71
|
+
if (problems.length > 0) {
|
|
72
|
+
throw new Error(`[preview] ${context.configurationPath} gives unsound preview.options:\n ${problems.join('\n ')}`);
|
|
73
|
+
}
|
|
74
|
+
const paneWidths = kitPaneWidths(context);
|
|
75
|
+
if (paneWidths.errors.length > 0)
|
|
76
|
+
throw new Error(`[preview] ${paneWidths.errors.join('\n[preview] ')}`);
|
|
77
|
+
// Each output, in the order it is written: a registry after the wrappers it
|
|
78
|
+
// imports, and the manifest, which names every story, last.
|
|
79
|
+
const outputs = [];
|
|
80
|
+
const themeSources = [];
|
|
81
|
+
// `moduleByName` remembers which module each component imports from, so the
|
|
82
|
+
// emitters group imports per source.
|
|
83
|
+
const moduleByName = new Map();
|
|
84
|
+
const importOverrideByName = new Map();
|
|
85
|
+
const exportByName = new Map();
|
|
86
|
+
for (const { component, source } of components) {
|
|
87
|
+
moduleByName.set(component.name, source.moduleBase);
|
|
88
|
+
if (component.importModule)
|
|
89
|
+
importOverrideByName.set(component.name, component.importModule);
|
|
90
|
+
if (component.exportName && component.exportName !== component.name) {
|
|
91
|
+
exportByName.set(component.name, component.exportName);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
const built = components.map(({ component, story, source }) => ({
|
|
95
|
+
...resolveStory(component, story, hints, context.configuration.labels, context.omitPattern, context.targets),
|
|
96
|
+
source: source.id,
|
|
97
|
+
}));
|
|
98
|
+
// A component's per-target import module: a per-component override (a
|
|
99
|
+
// playground fixture outside its source's published barrel) wins; otherwise
|
|
100
|
+
// the source's module for the target (`moduleOfSource`), defaulting slot children that belong to
|
|
101
|
+
// no registered source to the kit's own (first) source.
|
|
102
|
+
const defaultModule = sources[0].moduleBase;
|
|
103
|
+
const moduleFor = (name, target) => importOverrideByName.get(name)?.[target] ??
|
|
104
|
+
moduleOfSource(moduleByName.get(name) ?? defaultModule, target);
|
|
105
|
+
const exportFor = (name) => exportByName.get(name) ?? name;
|
|
106
|
+
// The names each component declares that React would otherwise respell
|
|
107
|
+
// (`class`, `style`, an attribute React renames): it takes them as they
|
|
108
|
+
// are, and every other attribute a story gives it as React spells it.
|
|
109
|
+
const declaredAttributesByName = new Map(components.map(({ component }) => [
|
|
110
|
+
component.name,
|
|
111
|
+
declaredAttributes(Object.keys(component.props), REACT_ATTRIBUTE_NAMES),
|
|
112
|
+
]));
|
|
113
|
+
const declaredAttributesOf = (name) => declaredAttributesByName.get(name) ?? [];
|
|
114
|
+
const declaredAttributesRecord = Object.fromEntries([...declaredAttributesByName].filter(([, names]) => names.length > 0));
|
|
115
|
+
// Browseable stories get registries + a nav entry; components that are not
|
|
116
|
+
// standalone (compound parts, shared blocks) are editor-only; omitted parts
|
|
117
|
+
// drop out entirely.
|
|
118
|
+
const stories = [];
|
|
119
|
+
const editorOnly = [];
|
|
120
|
+
const omitted = [];
|
|
121
|
+
for (const model of built) {
|
|
122
|
+
if (model.omit) {
|
|
123
|
+
omitted.push(model.name);
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
(model.standalone ? stories : editorOnly).push(model);
|
|
127
|
+
}
|
|
128
|
+
const landing = landingProblems(context.configuration.landing, stories);
|
|
129
|
+
if (landing.length > 0)
|
|
130
|
+
throw new Error(`[preview] ${landing.join('\n[preview] ')}`);
|
|
131
|
+
// Per-target registries (id → render unit) across ALL sources. A component
|
|
132
|
+
// renders only into the targets it declares within the kit's, so each
|
|
133
|
+
// target's registry sees only its own stories; a target the kit does not
|
|
134
|
+
// build gets an empty registry, so its iframe entry still builds.
|
|
135
|
+
// A scenario with slot content of its own is a story beside its
|
|
136
|
+
// component's, so its content renders as the component's does.
|
|
137
|
+
const forTarget = (target) => stories
|
|
138
|
+
.filter((model) => model.targets.includes(target))
|
|
139
|
+
.flatMap((model) => [model, ...scenarioStories(model)]);
|
|
140
|
+
for (const model of forTarget('svelte')) {
|
|
141
|
+
const wrapper = emitSvelteWrapper(model, moduleFor, exportFor);
|
|
142
|
+
outputs.push([resolve(directory.svelte, wrapper.fileName), wrapper.source]);
|
|
143
|
+
}
|
|
144
|
+
outputs.push([
|
|
145
|
+
resolve(directory.react, 'registry.tsx'),
|
|
146
|
+
emitReactRegistry(forTarget('react'), moduleFor, exportFor, declaredAttributesOf),
|
|
147
|
+
], [
|
|
148
|
+
resolve(directory.vue, 'registry.ts'),
|
|
149
|
+
emitVueRegistry(forTarget('vue'), moduleFor, exportFor),
|
|
150
|
+
], [
|
|
151
|
+
resolve(directory.svelte, 'registry.ts'),
|
|
152
|
+
emitSvelteRegistry(forTarget('svelte')),
|
|
153
|
+
]);
|
|
154
|
+
// The module-resolution data the scratch regeneration endpoint reads (it runs in the
|
|
155
|
+
// Vite dev middleware with no kit imports of its own).
|
|
156
|
+
const scratchModules = {
|
|
157
|
+
defaultModule,
|
|
158
|
+
moduleByName: Object.fromEntries(moduleByName),
|
|
159
|
+
importOverrideByName: Object.fromEntries(importOverrideByName),
|
|
160
|
+
exportByName: Object.fromEntries(exportByName),
|
|
161
|
+
targets: context.targets,
|
|
162
|
+
...(Object.keys(declaredAttributesRecord).length > 0
|
|
163
|
+
? { declaredAttributes: declaredAttributesRecord }
|
|
164
|
+
: {}),
|
|
165
|
+
};
|
|
166
|
+
outputs.push([
|
|
167
|
+
resolve(generatedRoot, 'modules.json'),
|
|
168
|
+
JSON.stringify(scratchModules, null, 2) + '\n',
|
|
169
|
+
]);
|
|
170
|
+
// Framework-neutral host manifest (nav, controls, color tokens) - stories
|
|
171
|
+
// plus the editor-only components (the editor reads both; the nav leaves
|
|
172
|
+
// those out).
|
|
173
|
+
const sourceMeta = sources.map((source) => ({
|
|
174
|
+
id: source.id,
|
|
175
|
+
label: source.label,
|
|
176
|
+
order: source.order,
|
|
177
|
+
moduleBase: source.moduleBase,
|
|
178
|
+
}));
|
|
179
|
+
// How a consumer imports each component, omitted ones included: a story's
|
|
180
|
+
// source in the browser names what its slot content holds.
|
|
181
|
+
const imports = {};
|
|
182
|
+
for (const { component } of components) {
|
|
183
|
+
const types = exportedTypesOf(component, context.targets);
|
|
184
|
+
imports[component.name] = {
|
|
185
|
+
exportName: exportFor(component.name),
|
|
186
|
+
...(declaredAttributesOf(component.name).length > 0
|
|
187
|
+
? { declaredAttributes: declaredAttributesOf(component.name) }
|
|
188
|
+
: {}),
|
|
189
|
+
modules: Object.fromEntries(context.targets.map((target) => [
|
|
190
|
+
target,
|
|
191
|
+
moduleFor(component.name, target),
|
|
192
|
+
])),
|
|
193
|
+
...(types ? { types } : {}),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const manifest = [
|
|
197
|
+
resolve(generatedRoot, 'manifest.json'),
|
|
198
|
+
JSON.stringify(buildManifest([...stories, ...editorOnly], sourceMeta, hints.colorTokens ?? [], context.kitName, context.configuration.labels, context.kitVersion, context.configuration.persistence, context.buildsHtml ? [...context.targets, 'html'] : context.targets, imports, context.configuration.codeBlock
|
|
199
|
+
? { framework: context.configuration.codeBlock.framework ?? 'dom' }
|
|
200
|
+
: undefined, paneWidths.paneWidths, context.targets.includes('svelte') ? context.svelteMode : undefined, context.targets.includes('react') ? REACT_ATTRIBUTE_NAMES : undefined, context.configuration.landing), null, 2) + '\n',
|
|
201
|
+
];
|
|
202
|
+
// Themes: copy each theme's compiled stylesheet (+ optional asset dir) into
|
|
203
|
+
// the served tree - `<generatedRoot>/public` is the Vite publicDir, so the iframes
|
|
204
|
+
// link `themes/<id>/theme.css` (under the URL the preview is served from) by convention in dev and static build alike.
|
|
205
|
+
for (const theme of context.configuration.themes) {
|
|
206
|
+
const themeDirectory = resolve(generatedRoot, 'public/themes', theme.id);
|
|
207
|
+
const cssSource = resolve(context.kitRoot, theme.css);
|
|
208
|
+
if (!existsSync(cssSource)) {
|
|
209
|
+
throw new Error(`[preview] theme '${theme.id}' stylesheet not found: ${cssSource}`);
|
|
210
|
+
}
|
|
211
|
+
themeSources.push(cssSource);
|
|
212
|
+
outputs.push([
|
|
213
|
+
resolve(themeDirectory, 'theme.css'),
|
|
214
|
+
readFileSync(cssSource),
|
|
215
|
+
]);
|
|
216
|
+
if (theme.assets) {
|
|
217
|
+
const assetsSource = resolve(context.kitRoot, theme.assets);
|
|
218
|
+
themeSources.push(assetsSource);
|
|
219
|
+
if (existsSync(assetsSource)) {
|
|
220
|
+
const assetsDestination = resolve(themeDirectory, basename(assetsSource));
|
|
221
|
+
const files = statSync(assetsSource).isDirectory()
|
|
222
|
+
? filesUnder(assetsSource)
|
|
223
|
+
: [assetsSource];
|
|
224
|
+
for (const file of files) {
|
|
225
|
+
outputs.push([
|
|
226
|
+
resolve(assetsDestination, relative(assetsSource, file)),
|
|
227
|
+
readFileSync(file),
|
|
228
|
+
]);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// The html of each story's scenarios, which the static build cannot print
|
|
234
|
+
// on request: one file per component, by scenario id, the anonymous
|
|
235
|
+
// default under ''.
|
|
236
|
+
if (htmlSources) {
|
|
237
|
+
const enumerated = components.map((entry) => entry.component);
|
|
238
|
+
for (const [index, model] of built.entries()) {
|
|
239
|
+
if (model.omit || !model.standalone)
|
|
240
|
+
continue;
|
|
241
|
+
const { component, story } = components[index];
|
|
242
|
+
const byScenario = {};
|
|
243
|
+
// What the html leaves out, once per story however many of its
|
|
244
|
+
// scenarios do.
|
|
245
|
+
const warnings = new Set();
|
|
246
|
+
const anonymous = { id: '', props: {} };
|
|
247
|
+
for (const scenario of [anonymous, ...model.scenarios]) {
|
|
248
|
+
const result = await printHtmlSource(context, enumerated, {
|
|
249
|
+
component,
|
|
250
|
+
// The html the panes render, the unfilled default slot's
|
|
251
|
+
// placeholder included, as the scripted panes show it, and the
|
|
252
|
+
// scenario's own slot content where it has any.
|
|
253
|
+
...sourceStoryOf(component, story, storyOnScenario(model, scenario), scenario.props ?? {}, { placeholder: true }),
|
|
254
|
+
});
|
|
255
|
+
if (result.markup !== undefined)
|
|
256
|
+
for (const warning of result.warnings)
|
|
257
|
+
warnings.add(warning);
|
|
258
|
+
byScenario[scenario.id] = htmlSourceResponse(context, enumerated, result);
|
|
259
|
+
}
|
|
260
|
+
if (warnings.size > 0)
|
|
261
|
+
console.warn(`[preview:generate] ${htmlWarningLine(model.name, [...warnings])}`);
|
|
262
|
+
outputs.push([
|
|
263
|
+
resolve(generatedRoot, 'public', HTML_SOURCE_DIRECTORY, `${sanitize(model.title)}.json`),
|
|
264
|
+
JSON.stringify(byScenario) + '\n',
|
|
265
|
+
]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
outputs.push(manifest);
|
|
269
|
+
// Everything rendered: only now is the tree touched.
|
|
270
|
+
if (clean)
|
|
271
|
+
rmSync(generatedRoot, { recursive: true, force: true });
|
|
272
|
+
for (const target of targets) {
|
|
273
|
+
mkdirSync(directory[target], { recursive: true });
|
|
274
|
+
}
|
|
275
|
+
// Empty scratch registries so the previews' static scratch imports resolve;
|
|
276
|
+
// the scenario editor overwrites these on each edit (see emit/scratch.ts),
|
|
277
|
+
// so a kept tree keeps the story it holds.
|
|
278
|
+
if (clean || !existsSync(resolve(generatedRoot, 'scratch'))) {
|
|
279
|
+
writeScratchStubs(generatedRoot);
|
|
280
|
+
}
|
|
281
|
+
const written = outputs
|
|
282
|
+
.filter(([path, content]) => writeIfChanged(path, content))
|
|
283
|
+
.map(([path]) => path);
|
|
284
|
+
const produced = new Set(outputs.map(([path]) => path));
|
|
285
|
+
const removed = targets
|
|
286
|
+
.flatMap((target) => filesUnder(directory[target]))
|
|
287
|
+
.filter((path) => !produced.has(path));
|
|
288
|
+
for (const path of removed)
|
|
289
|
+
rmSync(path, { force: true });
|
|
290
|
+
const sourceSummary = sources
|
|
291
|
+
.map((source) => `${source.id}=${source.moduleBase}`)
|
|
292
|
+
.join(', ');
|
|
293
|
+
console.log(`[preview:generate] ${stories.length} components × ${context.targets.length} targets → .preview-generated/ (sources: ${sourceSummary})`);
|
|
294
|
+
if (editorOnly.length > 0)
|
|
295
|
+
console.log(`[preview:generate] ${editorOnly.length} not standalone (editor-only): ${editorOnly.map((model) => model.name).join(', ')}`);
|
|
296
|
+
const unlisted = stories.filter((model) => model.unlisted);
|
|
297
|
+
if (unlisted.length > 0)
|
|
298
|
+
console.log(`[preview:generate] unlisted ${unlisted.length} (reachable at their address): ${unlisted.map((model) => model.name).join(', ')}`);
|
|
299
|
+
if (omitted.length > 0)
|
|
300
|
+
console.log(`[preview:generate] omitted ${omitted.length} (by omit or omitPattern): ${omitted.join(', ')}`);
|
|
301
|
+
return { written, removed, themeSources };
|
|
302
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { PreviewContext } from './context.js';
|
|
2
|
+
import type { HtmlSourceResponse } from './controller/html-source.js';
|
|
3
|
+
import type { HtmlSourceResult } from './emit/html-source.js';
|
|
4
|
+
import type { EnumeratedComponent } from './lib/types.js';
|
|
5
|
+
/** Where the kit's build writes the html target, relative to the kit root. */
|
|
6
|
+
export declare const HTML_DISTRIBUTION_DIRECTORY = "dist/html";
|
|
7
|
+
/**
|
|
8
|
+
* The `<style>` blocks of a page, joined in document order.
|
|
9
|
+
*
|
|
10
|
+
* @param page - A page's markup.
|
|
11
|
+
* @returns The CSS its style blocks hold, or `''` when it has none.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* styleBlocksOf('<style>.a { color: red; }</style><p class="a"></p>');
|
|
15
|
+
* // '.a { color: red; }'
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function styleBlocksOf(page: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* The CSS the kit's build wrote for the html target of each named
|
|
21
|
+
* component, in the order given: the `<style>` blocks of its page and its
|
|
22
|
+
* own stylesheet, when it has one. A component with no built output adds
|
|
23
|
+
* nothing.
|
|
24
|
+
*
|
|
25
|
+
* @param context - The kit's preview context.
|
|
26
|
+
* @param components - Every component of the kit.
|
|
27
|
+
* @param names - The components whose styles to read, by name.
|
|
28
|
+
* @returns The CSS, one comment-headed section per component, or `''`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function htmlComponentStylesheet(context: PreviewContext, components: readonly EnumeratedComponent[], names: readonly string[]): string;
|
|
31
|
+
/**
|
|
32
|
+
* A printed story as the html pane receives it: its markup with the styles
|
|
33
|
+
* of the components it renders and the warnings for what it leaves out,
|
|
34
|
+
* those one component gives for one reason counted on a single line, or
|
|
35
|
+
* what keeps it from having markup.
|
|
36
|
+
*
|
|
37
|
+
* @param context - The kit's preview context.
|
|
38
|
+
* @param components - Every component of the kit.
|
|
39
|
+
* @param result - The printed story.
|
|
40
|
+
* @returns The response the development server answers and the static
|
|
41
|
+
* build stores.
|
|
42
|
+
*/
|
|
43
|
+
export declare function htmlSourceResponse(context: PreviewContext, components: readonly EnumeratedComponent[], result: HtmlSourceResult): HtmlSourceResponse;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// The component styles the html pane shows its markup under: what the kit's
|
|
2
|
+
// build wrote for the html target, read from `dist/html` for the components a
|
|
3
|
+
// story renders. Under `in-file` each page carries its styles in `<style>`
|
|
4
|
+
// blocks; under `separate-file` each component has a stylesheet of its own,
|
|
5
|
+
// compiled when it is SCSS with the kit's own Sass and load paths. The markup
|
|
6
|
+
// is printed from the templates on request, so a component changed since the
|
|
7
|
+
// last build shows its last built styles until the kit builds again.
|
|
8
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
11
|
+
import { summarizeHtmlWarnings } from './lib/html-warnings.js';
|
|
12
|
+
import { kitImporters, kitPackageDirectories } from './sass-importers.js';
|
|
13
|
+
/** Where the kit's build writes the html target, relative to the kit root. */
|
|
14
|
+
export const HTML_DISTRIBUTION_DIRECTORY = 'dist/html';
|
|
15
|
+
const STYLE_BLOCK = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
|
|
16
|
+
/**
|
|
17
|
+
* The `<style>` blocks of a page, joined in document order.
|
|
18
|
+
*
|
|
19
|
+
* @param page - A page's markup.
|
|
20
|
+
* @returns The CSS its style blocks hold, or `''` when it has none.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* styleBlocksOf('<style>.a { color: red; }</style><p class="a"></p>');
|
|
24
|
+
* // '.a { color: red; }'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function styleBlocksOf(page) {
|
|
28
|
+
return [...page.matchAll(STYLE_BLOCK)]
|
|
29
|
+
.map((match) => match[1].trim())
|
|
30
|
+
.filter((css) => css !== '')
|
|
31
|
+
.join('\n');
|
|
32
|
+
}
|
|
33
|
+
/** A component name a built file can carry: an identifier, so it names a
|
|
34
|
+
* file in the html directory and nothing outside it. */
|
|
35
|
+
const BUILT_NAME = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
36
|
+
/** Each compiled SCSS sheet, by path, with the modification time it was
|
|
37
|
+
* compiled at. */
|
|
38
|
+
const compiledSheets = new Map();
|
|
39
|
+
/** The sheets already reported as left out, each reported once. */
|
|
40
|
+
const reportedSheets = new Set();
|
|
41
|
+
/** Compiles an SCSS file with the kit's own Sass, or says why it cannot.
|
|
42
|
+
* A sheet unchanged since it last compiled is not compiled again. */
|
|
43
|
+
function compileScss(path, context) {
|
|
44
|
+
const modified = statSync(path).mtimeMs;
|
|
45
|
+
const cached = compiledSheets.get(path);
|
|
46
|
+
if (cached && cached.modified === modified)
|
|
47
|
+
return { css: cached.css };
|
|
48
|
+
let sass;
|
|
49
|
+
try {
|
|
50
|
+
const kitRequire = createRequire(resolve(context.kitRoot, 'package.json'));
|
|
51
|
+
sass = kitRequire('sass');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return { problem: 'the kit has no sass installed to compile it' };
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const loadPaths = [
|
|
58
|
+
dirname(path),
|
|
59
|
+
...context.sassLoadPathsAbsolute,
|
|
60
|
+
...(context.configuration.scssLoadPaths ?? []).map((loadPath) => resolve(context.kitRoot, loadPath)),
|
|
61
|
+
];
|
|
62
|
+
// The kit's own `pkg:` URLs resolve through its package.json exports,
|
|
63
|
+
// as its build resolves them, and any other through Sass's own importer.
|
|
64
|
+
const importers = [
|
|
65
|
+
...kitImporters(context.kitRoot, kitPackageDirectories(context)),
|
|
66
|
+
...(sass.NodePackageImporter
|
|
67
|
+
? [new sass.NodePackageImporter(context.kitRoot)]
|
|
68
|
+
: []),
|
|
69
|
+
];
|
|
70
|
+
const css = sass.compile(path, { loadPaths, importers }).css;
|
|
71
|
+
compiledSheets.set(path, { modified, css });
|
|
72
|
+
return { css };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return { problem: error instanceof Error ? error.message : String(error) };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The CSS the kit's build wrote for the html target of each named
|
|
80
|
+
* component, in the order given: the `<style>` blocks of its page and its
|
|
81
|
+
* own stylesheet, when it has one. A component with no built output adds
|
|
82
|
+
* nothing.
|
|
83
|
+
*
|
|
84
|
+
* @param context - The kit's preview context.
|
|
85
|
+
* @param components - Every component of the kit.
|
|
86
|
+
* @param names - The components whose styles to read, by name.
|
|
87
|
+
* @returns The CSS, one comment-headed section per component, or `''`.
|
|
88
|
+
*/
|
|
89
|
+
export function htmlComponentStylesheet(context, components, names) {
|
|
90
|
+
const directory = resolve(context.kitRoot, HTML_DISTRIBUTION_DIRECTORY);
|
|
91
|
+
if (!existsSync(directory))
|
|
92
|
+
return '';
|
|
93
|
+
const sections = [];
|
|
94
|
+
for (const name of names) {
|
|
95
|
+
if (!components.some((candidate) => candidate.name === name))
|
|
96
|
+
continue;
|
|
97
|
+
if (!BUILT_NAME.test(name))
|
|
98
|
+
continue;
|
|
99
|
+
const parts = [];
|
|
100
|
+
const page = resolve(directory, `${name}.html`);
|
|
101
|
+
if (existsSync(page))
|
|
102
|
+
parts.push(styleBlocksOf(readFileSync(page, 'utf8')));
|
|
103
|
+
const css = resolve(directory, `${name}.css`);
|
|
104
|
+
if (existsSync(css))
|
|
105
|
+
parts.push(readFileSync(css, 'utf8').trim());
|
|
106
|
+
const scss = resolve(directory, `${name}.scss`);
|
|
107
|
+
if (existsSync(scss)) {
|
|
108
|
+
const compiled = compileScss(scss, context);
|
|
109
|
+
if ('css' in compiled)
|
|
110
|
+
parts.push(compiled.css.trim());
|
|
111
|
+
else if (!reportedSheets.has(scss)) {
|
|
112
|
+
reportedSheets.add(scss);
|
|
113
|
+
console.warn(`[preview] ${name}: the html pane leaves out ${name}.scss, as ${compiled.problem}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const styles = parts.filter((part) => part !== '').join('\n');
|
|
117
|
+
if (styles !== '')
|
|
118
|
+
sections.push(`/* ${name} */\n${styles}`);
|
|
119
|
+
}
|
|
120
|
+
return sections.join('\n\n');
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* A printed story as the html pane receives it: its markup with the styles
|
|
124
|
+
* of the components it renders and the warnings for what it leaves out,
|
|
125
|
+
* those one component gives for one reason counted on a single line, or
|
|
126
|
+
* what keeps it from having markup.
|
|
127
|
+
*
|
|
128
|
+
* @param context - The kit's preview context.
|
|
129
|
+
* @param components - Every component of the kit.
|
|
130
|
+
* @param result - The printed story.
|
|
131
|
+
* @returns The response the development server answers and the static
|
|
132
|
+
* build stores.
|
|
133
|
+
*/
|
|
134
|
+
export function htmlSourceResponse(context, components, result) {
|
|
135
|
+
if (result.markup === undefined)
|
|
136
|
+
return { missing: result.missing };
|
|
137
|
+
const stylesheet = htmlComponentStylesheet(context, components, result.components);
|
|
138
|
+
return {
|
|
139
|
+
markup: result.markup,
|
|
140
|
+
...(stylesheet === '' ? {} : { stylesheet }),
|
|
141
|
+
...(result.warnings.length === 0
|
|
142
|
+
? {}
|
|
143
|
+
: { warnings: summarizeHtmlWarnings(result.warnings) }),
|
|
144
|
+
};
|
|
145
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { jsonProblems, loadPreviewContext, type PreviewContext, type ResolvedSource, } from './context.js';
|
|
2
|
+
export { generatePreview } from './generate.js';
|
|
3
|
+
export { checkPreview, type PreviewCheckOptions, type PreviewCheckReport, } from './check.js';
|
|
4
|
+
export { storySource, type SourceTarget, type StorySource, type StorySourceOptions, } from './story-source.js';
|
|
5
|
+
export { loadKit, kitPaneWidths, type KitPaneWidths, type LoadedComponent, type LoadedKit, } from './load.js';
|
|
6
|
+
export { readPropsFrom, resolveManualComponent, type PropsFromResult, } from './props-from.js';
|
|
7
|
+
export { applicationRoot, buildViteConfiguration, type DevelopmentServerOverrides, } from './vite-configuration.js';
|
|
8
|
+
export { enumerateComponents } from './enumerate.js';
|
|
9
|
+
export { resolveStory } from './model.js';
|
|
10
|
+
export { propTypeForProp, defaultPropForProp } from './prop-types.js';
|
|
11
|
+
export { loadStory, isStructurallyOmitted } from './story.js';
|
|
12
|
+
export { emitReactRegistry } from './emit/react.js';
|
|
13
|
+
export { emitVueRegistry } from './emit/vue.js';
|
|
14
|
+
export { emitSvelteRegistry, emitSvelteWrapper } from './emit/svelte.js';
|
|
15
|
+
export { buildManifest, type Manifest, type ManifestComponent, type ManifestSource, } from './emit/manifest.js';
|
|
16
|
+
export { writeScratch, writeScratchStubs, SCRATCH_ID, type ScratchPayload, } from './emit/scratch.js';
|
|
17
|
+
export * from './lib/types.js';
|
|
18
|
+
export * from './options.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Programmatic surface: everything a consumer's own scripts (or tests) need -
|
|
2
|
+
// the context loader, the generator, the Vite configuration factory, and the model /
|
|
3
|
+
// emit layer the registries are built from.
|
|
4
|
+
export { jsonProblems, loadPreviewContext, } from './context.js';
|
|
5
|
+
export { generatePreview } from './generate.js';
|
|
6
|
+
export { checkPreview, } from './check.js';
|
|
7
|
+
export { storySource, } from './story-source.js';
|
|
8
|
+
export { loadKit, kitPaneWidths, } from './load.js';
|
|
9
|
+
export { readPropsFrom, resolveManualComponent, } from './props-from.js';
|
|
10
|
+
export { applicationRoot, buildViteConfiguration, } from './vite-configuration.js';
|
|
11
|
+
export { enumerateComponents } from './enumerate.js';
|
|
12
|
+
export { resolveStory } from './model.js';
|
|
13
|
+
export { propTypeForProp, defaultPropForProp } from './prop-types.js';
|
|
14
|
+
export { loadStory, isStructurallyOmitted } from './story.js';
|
|
15
|
+
export { emitReactRegistry } from './emit/react.js';
|
|
16
|
+
export { emitVueRegistry } from './emit/vue.js';
|
|
17
|
+
export { emitSvelteRegistry, emitSvelteWrapper } from './emit/svelte.js';
|
|
18
|
+
export { buildManifest, } from './emit/manifest.js';
|
|
19
|
+
export { writeScratch, writeScratchStubs, SCRATCH_ID, } from './emit/scratch.js';
|
|
20
|
+
export * from './lib/types.js';
|
|
21
|
+
export * from './options.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PreviewLandingConfiguration, ResolvedStory } from './lib/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* What is wrong with the landing entry a kit names, against its stories:
|
|
4
|
+
* a component with no story, or a scenario the story does not have. A
|
|
5
|
+
* view's id is not checked here. Empty when the entry is sound or unset.
|
|
6
|
+
*
|
|
7
|
+
* @param landing - The kit's `preview.landing`.
|
|
8
|
+
* @param stories - The kit's browseable stories: omitted components and those
|
|
9
|
+
* that are not standalone left out.
|
|
10
|
+
* @returns One message per problem.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* landingProblems({ component: 'components-button', scenario: 'primary' }, stories);
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function landingProblems(landing: PreviewLandingConfiguration | undefined, stories: readonly ResolvedStory[]): string[];
|
package/dist/landing.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// The entry a kit names for the preview to open on (`preview.landing`),
|
|
2
|
+
// checked against the kit's stories: the generator and the check both refuse
|
|
3
|
+
// a story or scenario the kit has none of. A view's id is the views module's,
|
|
4
|
+
// which only the browser loads, so the preview's controller checks that one.
|
|
5
|
+
import { sanitize } from './lib/naming.js';
|
|
6
|
+
/** The id of the synthetic scenario that renders a story with no content. */
|
|
7
|
+
const EMPTY_SCENARIO_ID = 'empty';
|
|
8
|
+
/**
|
|
9
|
+
* What is wrong with the landing entry a kit names, against its stories:
|
|
10
|
+
* a component with no story, or a scenario the story does not have. A
|
|
11
|
+
* view's id is not checked here. Empty when the entry is sound or unset.
|
|
12
|
+
*
|
|
13
|
+
* @param landing - The kit's `preview.landing`.
|
|
14
|
+
* @param stories - The kit's browseable stories: omitted components and those
|
|
15
|
+
* that are not standalone left out.
|
|
16
|
+
* @returns One message per problem.
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* landingProblems({ component: 'components-button', scenario: 'primary' }, stories);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function landingProblems(landing, stories) {
|
|
23
|
+
if (!landing || !('component' in landing))
|
|
24
|
+
return [];
|
|
25
|
+
const story = stories.find((candidate) => sanitize(candidate.title) === landing.component);
|
|
26
|
+
if (!story)
|
|
27
|
+
return [
|
|
28
|
+
`preview.landing names component '${landing.component}', which has no story; a story's id is the one the preview's address carries as component=`,
|
|
29
|
+
];
|
|
30
|
+
const scenario = landing.scenario;
|
|
31
|
+
if (scenario === undefined)
|
|
32
|
+
return [];
|
|
33
|
+
const hasContent = story.contentSlots.default || story.contentSlots.named.length > 0;
|
|
34
|
+
const scenarios = [
|
|
35
|
+
...(hasContent ? [EMPTY_SCENARIO_ID] : []),
|
|
36
|
+
...story.scenarios.map((candidate) => candidate.id),
|
|
37
|
+
];
|
|
38
|
+
return scenarios.includes(scenario)
|
|
39
|
+
? []
|
|
40
|
+
: [
|
|
41
|
+
`preview.landing names scenario '${scenario}' of '${landing.component}', which has ${scenarios.length > 0
|
|
42
|
+
? `the scenarios ${scenarios.join(', ')}`
|
|
43
|
+
: 'no scenarios'}`,
|
|
44
|
+
];
|
|
45
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Target } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The type names one module-scope line exports. A value-only export list
|
|
4
|
+
* (`export { a }`) names no type unless a member is marked `type`, as a value
|
|
5
|
+
* cannot be told from a type there.
|
|
6
|
+
*
|
|
7
|
+
* @param line - A verbatim module-scope line.
|
|
8
|
+
* @returns The type names it exports, in order.
|
|
9
|
+
*/
|
|
10
|
+
export declare function exportedTypeNamesOf(line: string): string[];
|
|
11
|
+
/** The parts of a template the exported types are read from. */
|
|
12
|
+
export interface ExportingTemplate {
|
|
13
|
+
imports?: string[];
|
|
14
|
+
extensions?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The type names a template's generated module exports in one scripted
|
|
18
|
+
* target: those its module-scope lines declare, the target's own `imports`
|
|
19
|
+
* merged in (or in their place, with `importsStrategy: 'replace'`).
|
|
20
|
+
*
|
|
21
|
+
* @param template - The component's template.
|
|
22
|
+
* @param target - The scripted target.
|
|
23
|
+
* @returns The exported type names, each once.
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* exportedTypeNames({ imports: ['export interface DateValue { day: string }'] }, 'react');
|
|
27
|
+
* // ['DateValue']
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function exportedTypeNames(template: ExportingTemplate, target: Target): string[];
|
|
31
|
+
/**
|
|
32
|
+
* The type names a component's generated module exports, per scripted
|
|
33
|
+
* target: none for a component written by hand, whose module the preview
|
|
34
|
+
* does not read.
|
|
35
|
+
*
|
|
36
|
+
* @param component - The component, with the template it was read from.
|
|
37
|
+
* @param targets - The scripted targets the kit builds.
|
|
38
|
+
* @returns The names per target that exports any, or `undefined` when none does.
|
|
39
|
+
*/
|
|
40
|
+
export declare function exportedTypesOf(component: {
|
|
41
|
+
template?: unknown;
|
|
42
|
+
}, targets: readonly Target[]): Partial<Record<Target, string[]>> | undefined;
|