@orbytes/astrolab 0.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 +37 -0
- package/README.md +410 -0
- package/bin/lab-cull.mjs +401 -0
- package/bin/pin-gallery.mjs +121 -0
- package/defaults.mjs +120 -0
- package/dist/core/astro-integration.js +130 -0
- package/dist/core/index.js +6 -0
- package/dist/core/lib-paths.js +29 -0
- package/dist/core/options.js +173 -0
- package/dist/core/utils/get-exports.js +52 -0
- package/dist/core/utils/invariant.js +12 -0
- package/dist/core/utils/kebab-case.js +15 -0
- package/dist/core/utils/path-builder.js +22 -0
- package/dist/core/utils/path.js +53 -0
- package/dist/core/virtual-module/get-story-modules.js +60 -0
- package/dist/core/virtual-module/story-modules.js +8 -0
- package/dist/core/virtual-module/virtual-module-ids.js +22 -0
- package/dist/core/virtual-module/virtual-routes.js +83 -0
- package/dist/core/virtual-module/vite-plugin.js +98 -0
- package/docs/PIN-CONTRACT.md +263 -0
- package/docs/PIN.md +429 -0
- package/index.d.ts +279 -0
- package/index.mjs +347 -0
- package/package.json +93 -0
- package/src/Empty.astro +4 -0
- package/src/Home.astro +298 -0
- package/src/LabHead.astro +1102 -0
- package/src/core/LICENSE-astrobook +166 -0
- package/src/core/astro-integration.ts +166 -0
- package/src/core/client.ts +89 -0
- package/src/core/index.ts +7 -0
- package/src/core/lib/components/empty.astro +1 -0
- package/src/core/lib/components/head.astro +1 -0
- package/src/core/lib/components/home.astro +8 -0
- package/src/core/lib/components/with-decorators.astro +22 -0
- package/src/core/lib/pages/app.astro +19 -0
- package/src/core/lib/pages/preview.astro +17 -0
- package/src/core/lib/pages/story.astro +16 -0
- package/src/core/lib-paths.ts +72 -0
- package/src/core/options.ts +262 -0
- package/src/core/utils/get-exports.ts +59 -0
- package/src/core/utils/invariant.ts +13 -0
- package/src/core/utils/kebab-case.ts +30 -0
- package/src/core/utils/path-builder.ts +45 -0
- package/src/core/utils/path.ts +80 -0
- package/src/core/virtual-module/get-story-modules.ts +110 -0
- package/src/core/virtual-module/story-modules.ts +9 -0
- package/src/core/virtual-module/virtual-module-ids.ts +17 -0
- package/src/core/virtual-module/virtual-routes.ts +130 -0
- package/src/core/virtual-module/vite-plugin.ts +125 -0
- package/src/pin/board.mjs +1521 -0
- package/src/pin/index.mjs +666 -0
- package/src/pin/shot.mjs +427 -0
- package/src/pin/source-stamp.mjs +159 -0
- package/src/pin/tickets.mjs +697 -0
- package/src/pin/toolbar.js +3181 -0
- package/src/shell/Browse.astro +371 -0
- package/src/shell/CardGrid.astro +297 -0
- package/src/shell/Viewport.astro +1330 -0
- package/src/shell/index.json.ts +12 -0
- package/src/shell/lab-index.ts +344 -0
- package/src/shell/lab-params.ts +245 -0
- package/src/shell/live-files.mjs +164 -0
- package/src/shell/marks.mjs +136 -0
- package/src/types/index.ts +6 -0
- package/src/types/types.ts +239 -0
- package/src/types/virtual.d.ts +29 -0
- package/src/ui/components/app.astro +13 -0
- package/src/ui/components/build-path.ts +13 -0
- package/src/ui/components/build-tree.ts +108 -0
- package/src/ui/components/collapse-duration.ts +28 -0
- package/src/ui/components/compress-terms.ts +10 -0
- package/src/ui/components/dashboard-layout.astro +39 -0
- package/src/ui/components/home.astro +65 -0
- package/src/ui/components/layout.astro +110 -0
- package/src/ui/components/preview-layout.astro +109 -0
- package/src/ui/components/sidebar-button-fullscreen.astro +38 -0
- package/src/ui/components/sidebar-button-search.astro +23 -0
- package/src/ui/components/sidebar-button-theme.astro +9 -0
- package/src/ui/components/sidebar-button.astro +24 -0
- package/src/ui/components/sidebar-resize-handle.astro +74 -0
- package/src/ui/components/sidebar-search-panel.astro +41 -0
- package/src/ui/components/sidebar-search-script.ts +103 -0
- package/src/ui/components/sidebar-title.astro +17 -0
- package/src/ui/components/sidebar-tree-node.astro +143 -0
- package/src/ui/components/sidebar-tree.astro +84 -0
- package/src/ui/components/sidebar.astro +29 -0
- package/src/ui/components/theme-message.ts +26 -0
- package/src/ui/components/theme-script.astro +71 -0
- package/src/ui/components/theme-toggle.astro +63 -0
- package/src/ui/components/theme.ts +32 -0
- package/src/ui/index.ts +4 -0
- package/src/ui/lab.css +549 -0
- package/virtual.d.ts +42 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Everything under src/core/, src/ui/ and src/types/ is vendored from Astrobook.
|
|
2
|
+
|
|
3
|
+
Upstream: https://github.com/ocavue/astrobook
|
|
4
|
+
Version: 0.13.3
|
|
5
|
+
Commit: a79f03cdfd32eb08330b33fa7d5830ac506f9272
|
|
6
|
+
|
|
7
|
+
This notice lives under src/core/ for historical reasons — that was the only vendored directory
|
|
8
|
+
when it was written, on 2026-09-21 — and it governs all three. What each one is:
|
|
9
|
+
|
|
10
|
+
src/core/ the upstream package `@astrobook/core` (packages/core/src/ → src/core/) plus the
|
|
11
|
+
hand-written Astro components of the `astrobook` package (packages/astrobook/lib/
|
|
12
|
+
→ src/core/lib/).
|
|
13
|
+
src/ui/ the upstream package `@astrobook/ui` (packages/ui/src/ → src/ui/), vendored
|
|
14
|
+
2026-09-22.
|
|
15
|
+
src/types/ the upstream package `@astrobook/types` (packages/types/lib/ → src/types/),
|
|
16
|
+
vendored 2026-09-22.
|
|
17
|
+
|
|
18
|
+
So this package depends on no astrobook npm package at all, and on nothing outside Astro itself.
|
|
19
|
+
The upstream layout is mirrored in each case so a future `diff -r` against an upstream tag stays
|
|
20
|
+
possible.
|
|
21
|
+
|
|
22
|
+
THE CONVENTION, UNCHANGED: a file here is byte-identical to upstream unless it opens with a
|
|
23
|
+
`// Vendored from astrobook 0.13.3 (…)` header, and that header names what changed in it. So
|
|
24
|
+
`diff -r` against a future upstream checkout shows real upstream changes, and the headers are the
|
|
25
|
+
list of what to re-apply. Four files carry no header and no change: core/utils/get-exports.ts,
|
|
26
|
+
core/utils/invariant.ts, core/utils/path.ts, core/virtual-module/virtual-module-ids.ts. Under
|
|
27
|
+
core/lib/, four of the six .astro files are unchanged (components/head.astro,
|
|
28
|
+
components/empty.astro, components/with-decorators.astro, and — apart from one import — nothing
|
|
29
|
+
else); every file under src/ui/ and src/types/ carries a header, because every one of them
|
|
30
|
+
changed.
|
|
31
|
+
|
|
32
|
+
THE VIRTUAL MODULE IDS ARE UPSTREAM'S AND MUST STAY THAT WAY. The vendored core emits
|
|
33
|
+
`virtual:astrobook/story-modules.mjs` and its siblings (core/virtual-module/virtual-module-ids.ts)
|
|
34
|
+
and the vendored UI imports them by name. Both sides are ours now, so renaming them to
|
|
35
|
+
`virtual:orbytes-lab/*` is possible — it is pure churn with silent-breakage risk, so it is later
|
|
36
|
+
cleanup and deliberately not part of the 2026-09-22 pass.
|
|
37
|
+
|
|
38
|
+
--------------------------------------------------------------------------------
|
|
39
|
+
Every deliberate divergence in src/core/
|
|
40
|
+
--------------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
1. Relative imports carry the `.ts` extension. Upstream is bundled by tsdown before it ships;
|
|
43
|
+
this package ships source, and node cannot resolve an extensionless specifier. Astro loads
|
|
44
|
+
astro.config.mjs with a plain node import() first, so this graph has to load under node.
|
|
45
|
+
2. `src/core/lib-paths.ts` is new. It resolves the vendored `.astro` files and client.ts to
|
|
46
|
+
absolute posix paths from `import.meta.url`, replacing the bare `astrobook/pages/story.astro`,
|
|
47
|
+
`astrobook/components/with-decorators.astro`, `astrobook/client`,
|
|
48
|
+
`astrobook/components/{head,home,empty}.astro` and `astrobook/pages/app.astro` specifiers that
|
|
49
|
+
upstream emits into generated routes, injects as a route entrypoint, and uses as option
|
|
50
|
+
defaults. A bare specifier resolves to the wrong checkout's copy in an agent git worktree
|
|
51
|
+
(measured on a real consuming site); an absolute path cannot.
|
|
52
|
+
3. `src/core/utils/kebab-case.ts` is new: `just-kebab-case@4.2.0`, inlined. Upstream imports it
|
|
53
|
+
but declares it only as a devDependency, because tsdown bundles it into the published artifact.
|
|
54
|
+
Nothing bundles here, so it is inlined from that artifact instead.
|
|
55
|
+
4. `options.ts` is rewritten in plain TypeScript. Upstream expresses it as a valibot schema;
|
|
56
|
+
valibot is 1.8 MB for one caller. Same option names, same defaults, same `home: false`
|
|
57
|
+
transform, same resolved shape, same thrown-message layout. The upstream version string used
|
|
58
|
+
for the home page's version-badge label is inlined as `0.13.3`.
|
|
59
|
+
5. `picomatch` is declared by upstream `@astrobook/core` and imported nowhere in it, so it is not
|
|
60
|
+
carried over.
|
|
61
|
+
6. The `*.spec.ts` / `*.test.ts` files are not vendored — this package has no test runner.
|
|
62
|
+
7. Type imports point at `src/types/` by relative path rather than at the `@astrobook/types`
|
|
63
|
+
package (2026-09-22).
|
|
64
|
+
8. `src/core/lib/pages/preview.astro` is new, and `virtual-routes.ts` picks between it and
|
|
65
|
+
`story.astro` per route (2026-09-22). Upstream routes the dashboard and the bare story through
|
|
66
|
+
one page, so a bare story also received the lab's chrome. Splitting them is what lets the
|
|
67
|
+
lab's own styling stop at the preview's edge — see src/ui/lab.css.
|
|
68
|
+
|
|
69
|
+
--------------------------------------------------------------------------------
|
|
70
|
+
Every deliberate divergence in src/ui/ (all of it added 2026-09-22)
|
|
71
|
+
--------------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
9. NO UNOCSS. Upstream's UI is written in UnoCSS atomic classes (`:uno: flex shrink-0 …`) and
|
|
74
|
+
three shortcuts, compiled by `unocss --rewrite` at publish time into a 24 KB `style.css` of
|
|
75
|
+
hashed `astrobook-7fpo4s` class names. This package ships source and has no build step, so
|
|
76
|
+
every utility string is replaced by a semantic class — `.lab-sidebar__nav`, `.lab-tree-row`,
|
|
77
|
+
`.lab-search__input` — and every rule lives in one hand-written stylesheet, `src/ui/lab.css`.
|
|
78
|
+
Upstream's `src/style.css` (a placeholder for the generated file) and `uno.config.ts` are not
|
|
79
|
+
vendored. Neither are the icon classes: `presetIcons` turned `i-fluent-search-16-regular` and
|
|
80
|
+
friends into background images at build time, so each is now an inline `<svg>`.
|
|
81
|
+
10. THE CHROME NO LONGER RECEIVES THE CONSUMER'S CSS OR HEAD (decided 2026-09-22: the lab's own
|
|
82
|
+
furniture looks the same in every repo it is installed in, and only the rendered story takes
|
|
83
|
+
the site's styling). Upstream's `layout.astro` imported `virtual:astrobook/user-css.mjs` last, "so it
|
|
84
|
+
can override built-in styles". Here the consumer's stylesheets and head component reach the
|
|
85
|
+
PREVIEW only. Three layouts where upstream had one:
|
|
86
|
+
layout.astro the chrome shell. No consumer CSS, no consumer head. `/lab`.
|
|
87
|
+
dashboard-layout.astro NEW. The chrome plus the story inside it — the one document that
|
|
88
|
+
carries both stylesheets, because it is both things at once.
|
|
89
|
+
preview-layout.astro NEW. The bare story: consumer CSS and head, none of the lab's own.
|
|
90
|
+
`layout.astro` also gained a `<slot name="head" />` so a wrapping layout can add to the head
|
|
91
|
+
without this file importing anything. Full reasoning: src/ui/lab.css.
|
|
92
|
+
11. `astro-theme-toggle` is vendored, not depended on: `theme-script.astro`, `theme-toggle.astro`
|
|
93
|
+
and `theme.ts` are written for this package. Same `theme-toggle` localStorage key, same
|
|
94
|
+
`.dark` class, `data-theme` and `color-scheme` on <html>, same `astro:after-swap` re-apply, so
|
|
95
|
+
an existing reader's stored preference carries over. Dropped: the ripple
|
|
96
|
+
`startViewTransition` animation. Why the dependency went, at length: theme-script.astro.
|
|
97
|
+
12. `customElements.define` calls are guarded with `customElements.get`, so a second definition on
|
|
98
|
+
a view-transition swap cannot throw.
|
|
99
|
+
13. `build-path.ts` imports `createPathBuilder` from the vendored core by relative path rather
|
|
100
|
+
than from `@astrobook/core/client`, and the `import '@astrobook/types'` side-effect lines are
|
|
101
|
+
gone — the ambient declarations they pulled in live in src/types/virtual.d.ts.
|
|
102
|
+
|
|
103
|
+
--------------------------------------------------------------------------------
|
|
104
|
+
Every deliberate divergence in src/types/ (all of it added 2026-09-22)
|
|
105
|
+
--------------------------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
14. `lib/types.d.ts` → `types.ts` and `lib/index.d.ts` + `lib/index.js` → one `index.ts`. The
|
|
108
|
+
bodies are interfaces and one `declare global`, so they emit nothing at runtime and every
|
|
109
|
+
importer uses `import type`; a plain `.ts` is what the vendored core can import by relative
|
|
110
|
+
path without `allowImportingTsExtensions`. `virtual.d.ts` keeps its extension and its module
|
|
111
|
+
ids, and its one internal import is spelled `./types.js` as node16 resolution requires.
|
|
112
|
+
15. The option doc comments for `css` and `head` gained a line saying they now reach the preview
|
|
113
|
+
only. Nothing else in the text changed.
|
|
114
|
+
|
|
115
|
+
--------------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
MIT License
|
|
118
|
+
|
|
119
|
+
Copyright (c) 2024 ocavue
|
|
120
|
+
|
|
121
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
122
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
123
|
+
in the Software without restriction, including without limitation the rights
|
|
124
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
125
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
126
|
+
furnished to do so, subject to the following conditions:
|
|
127
|
+
|
|
128
|
+
The above copyright notice and this permission notice shall be included in all
|
|
129
|
+
copies or substantial portions of the Software.
|
|
130
|
+
|
|
131
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
132
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
133
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
134
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
135
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
136
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
137
|
+
SOFTWARE.
|
|
138
|
+
|
|
139
|
+
--------------------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
astro-theme-toggle (vendored in part — see divergence 11 above)
|
|
142
|
+
|
|
143
|
+
Upstream: https://github.com/ocavue/astro-theme-toggle
|
|
144
|
+
Version: 0.8.2
|
|
145
|
+
|
|
146
|
+
MIT License
|
|
147
|
+
|
|
148
|
+
Copyright (c) 2025 ocavue
|
|
149
|
+
|
|
150
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
151
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
152
|
+
in the Software without restriction, including without limitation the rights
|
|
153
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
154
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
155
|
+
furnished to do so, subject to the following conditions:
|
|
156
|
+
|
|
157
|
+
The above copyright notice and this permission notice shall be included in all
|
|
158
|
+
copies or substantial portions of the Software.
|
|
159
|
+
|
|
160
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
161
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
162
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
163
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
164
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
165
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
166
|
+
SOFTWARE.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Vendored from astrobook 0.13.3 (astro-integration.ts) — see ./LICENSE-astrobook.
|
|
2
|
+
// Divergence: relative imports carry the .ts extension so node can load this graph directly
|
|
3
|
+
// (upstream is bundled before it ships; this package is not).
|
|
4
|
+
// Divergence: the specifiers this file injects as a route entrypoint are absolute paths into ./lib-paths.ts rather
|
|
5
|
+
// than bare `astrobook/...` ids — see that file for why.
|
|
6
|
+
import fs from 'node:fs/promises'
|
|
7
|
+
import path from 'node:path'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
|
|
10
|
+
import type { IntegrationOptions } from '../types/types.ts'
|
|
11
|
+
import type { AstroIntegration } from 'astro'
|
|
12
|
+
import colors from 'yoctocolors'
|
|
13
|
+
|
|
14
|
+
import { APP_PAGE } from './lib-paths.ts'
|
|
15
|
+
import { resolveOptions } from './options.ts'
|
|
16
|
+
import { createPathBuilder } from './utils/path-builder.ts'
|
|
17
|
+
import {
|
|
18
|
+
createVirtualRouteComponent,
|
|
19
|
+
getVirtualRoutes,
|
|
20
|
+
} from './virtual-module/virtual-routes.ts'
|
|
21
|
+
import { createVirtualFilesPlugin } from './virtual-module/vite-plugin.ts'
|
|
22
|
+
|
|
23
|
+
export type { IntegrationOptions }
|
|
24
|
+
|
|
25
|
+
export function createAstrobookIntegration(
|
|
26
|
+
userOptions?: IntegrationOptions,
|
|
27
|
+
): AstroIntegration {
|
|
28
|
+
let astrobookBaseForLogging: string | undefined
|
|
29
|
+
|
|
30
|
+
const resolvedOptions = resolveOptions(userOptions)
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
name: 'astrobook',
|
|
34
|
+
hooks: {
|
|
35
|
+
'astro:config:setup': async ({
|
|
36
|
+
updateConfig,
|
|
37
|
+
injectRoute,
|
|
38
|
+
createCodegenDir,
|
|
39
|
+
config,
|
|
40
|
+
logger,
|
|
41
|
+
command,
|
|
42
|
+
}) => {
|
|
43
|
+
const rootDir = path.resolve(
|
|
44
|
+
fileURLToPath(config.root),
|
|
45
|
+
resolvedOptions.directory,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
const astroBase = config.base || ''
|
|
49
|
+
|
|
50
|
+
// The subpaths are relative to the Astro base path.
|
|
51
|
+
const astrobookSubpath = resolvedOptions.subpath
|
|
52
|
+
|
|
53
|
+
const buildPath = createPathBuilder({
|
|
54
|
+
trailingSlash: config.trailingSlash,
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const dashboardSubpath = buildPath(
|
|
58
|
+
astrobookSubpath,
|
|
59
|
+
resolvedOptions.dashboardSubpath,
|
|
60
|
+
)
|
|
61
|
+
const previewSubpath = buildPath(
|
|
62
|
+
astrobookSubpath,
|
|
63
|
+
resolvedOptions.previewSubpath,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if (dashboardSubpath === previewSubpath) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
'[Astrobook] The dashboard and preview subpaths cannot be the same. Please set different values for `dashboardSubpath` and `previewSubpath` options.',
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const astrobookBase = buildPath(astroBase, astrobookSubpath)
|
|
73
|
+
const dashboardBase = buildPath(astroBase, dashboardSubpath)
|
|
74
|
+
const storyBase = buildPath(astroBase, previewSubpath)
|
|
75
|
+
|
|
76
|
+
// If subpath is set, Astrobook is only part of the current Astro
|
|
77
|
+
// project. In this case, we want to print the URL of the Astrobook
|
|
78
|
+
// entrypoint for easy access.
|
|
79
|
+
if (astrobookSubpath && command === 'dev') {
|
|
80
|
+
astrobookBaseForLogging = astrobookBase
|
|
81
|
+
} else {
|
|
82
|
+
astrobookBaseForLogging = undefined
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
logger.debug(`Creating dedicated folder`)
|
|
86
|
+
const codegenDir: string = fileURLToPath(createCodegenDir())
|
|
87
|
+
|
|
88
|
+
logger.debug(`Created dedicated folder at ${codegenDir}`)
|
|
89
|
+
|
|
90
|
+
logger.debug(`Scanning for stories in ${rootDir}`)
|
|
91
|
+
|
|
92
|
+
const routes = await getVirtualRoutes(
|
|
93
|
+
rootDir,
|
|
94
|
+
codegenDir,
|
|
95
|
+
logger,
|
|
96
|
+
dashboardSubpath,
|
|
97
|
+
previewSubpath,
|
|
98
|
+
buildPath,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
logger.debug(`Writing files to ${codegenDir}`)
|
|
102
|
+
await Promise.all(
|
|
103
|
+
Array.from(routes.values(), async (route) => {
|
|
104
|
+
const filePath = route.entrypoint
|
|
105
|
+
const fileContent = createVirtualRouteComponent(route)
|
|
106
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
107
|
+
await fs.writeFile(filePath, fileContent, { encoding: 'utf-8' })
|
|
108
|
+
}),
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
updateConfig({
|
|
112
|
+
vite: {
|
|
113
|
+
plugins: [
|
|
114
|
+
createVirtualFilesPlugin(
|
|
115
|
+
rootDir,
|
|
116
|
+
{
|
|
117
|
+
astrobookBase,
|
|
118
|
+
dashboardBase,
|
|
119
|
+
storyBase,
|
|
120
|
+
head: resolvedOptions.head,
|
|
121
|
+
home: resolvedOptions.home,
|
|
122
|
+
homeContent: resolvedOptions.homeContent,
|
|
123
|
+
css: resolvedOptions.css,
|
|
124
|
+
title: resolvedOptions.title,
|
|
125
|
+
trailingSlash: config.trailingSlash,
|
|
126
|
+
},
|
|
127
|
+
config,
|
|
128
|
+
logger,
|
|
129
|
+
),
|
|
130
|
+
],
|
|
131
|
+
},
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
logger.debug(`Injecting routes`)
|
|
135
|
+
for (const route of routes.values()) {
|
|
136
|
+
injectRoute({
|
|
137
|
+
pattern: route.pattern,
|
|
138
|
+
entrypoint: route.entrypoint,
|
|
139
|
+
prerender: true,
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
injectRoute({
|
|
143
|
+
pattern: astrobookSubpath,
|
|
144
|
+
entrypoint: APP_PAGE,
|
|
145
|
+
prerender: true,
|
|
146
|
+
})
|
|
147
|
+
},
|
|
148
|
+
'astro:server:start': ({ logger, address }) => {
|
|
149
|
+
if (astrobookBaseForLogging) {
|
|
150
|
+
const url = new URL(
|
|
151
|
+
astrobookBaseForLogging,
|
|
152
|
+
`http://localhost:${address.port}`,
|
|
153
|
+
)
|
|
154
|
+
const message =
|
|
155
|
+
colors.bgGreen(colors.white(colors.bold(' astrobook '))) +
|
|
156
|
+
' is available at ' +
|
|
157
|
+
colors.cyan(url.href)
|
|
158
|
+
// Get a logger that don't print the label and the current time
|
|
159
|
+
// https://github.com/withastro/astro/blob/ff72ebe/packages/astro/src/core/logger/core.ts#L38
|
|
160
|
+
const plainLogger = logger.fork('SKIP_FORMAT')
|
|
161
|
+
plainLogger.info(message)
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Vendored from astrobook 0.13.3 (client.ts) — see LICENSE-astrobook.
|
|
2
|
+
// Divergence: relative imports carry the .ts extension so node can load this graph directly
|
|
3
|
+
// (upstream is bundled before it ships; this package is not).
|
|
4
|
+
import type { StoryNamedExport } from '../types/types.ts'
|
|
5
|
+
import type { AstroComponentFactory } from 'astro/runtime/server/index.js'
|
|
6
|
+
|
|
7
|
+
export { createPathBuilder, type PathBuilder } from './utils/path-builder.ts'
|
|
8
|
+
|
|
9
|
+
// Copy from https://github.com/withastro/astro/blob/astro@5.0.0/packages/astro/src/runtime/server/render/astro/factory.ts#L15
|
|
10
|
+
function isAstroComponentFactory(obj: unknown): obj is AstroComponentFactory {
|
|
11
|
+
return obj == null
|
|
12
|
+
? false
|
|
13
|
+
: (obj as Record<string, unknown>).isAstroComponentFactory === true
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export function parseStoryDefaultExport(
|
|
20
|
+
module: Record<string, unknown>,
|
|
21
|
+
importPath: string,
|
|
22
|
+
): {
|
|
23
|
+
isAstroComponent: boolean
|
|
24
|
+
} {
|
|
25
|
+
const defaultExport = 'default' in module ? module['default'] : undefined
|
|
26
|
+
if (!defaultExport) {
|
|
27
|
+
throw new TypeError(
|
|
28
|
+
`[astrobook] '${importPath}' should have a default export`,
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
if (typeof defaultExport !== 'object') {
|
|
32
|
+
throw new TypeError(
|
|
33
|
+
`[astrobook] '${importPath}' default export should be an object, but got ${typeof defaultExport}`,
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const component =
|
|
38
|
+
'component' in defaultExport ? defaultExport.component : undefined
|
|
39
|
+
if (!component) {
|
|
40
|
+
throw new TypeError(
|
|
41
|
+
`[astrobook] '${importPath}' default export should have a component property`,
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Whether the component is an Astro component or not (e.g. React, Vue, etc.)
|
|
46
|
+
const isAstroComponent: boolean = isAstroComponentFactory(component)
|
|
47
|
+
|
|
48
|
+
return { isAstroComponent }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export function parseStoryNamedExport(
|
|
55
|
+
module: Record<string, unknown>,
|
|
56
|
+
importPath: string,
|
|
57
|
+
storyName: string,
|
|
58
|
+
): StoryNamedExport {
|
|
59
|
+
const storyObject: unknown =
|
|
60
|
+
module && typeof module === 'object' ? module[storyName] : undefined
|
|
61
|
+
if (!storyObject) {
|
|
62
|
+
throw new Error(
|
|
63
|
+
`[astrobook] Unable to find named export '${storyName}' from '${importPath}'`,
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
if (typeof storyObject !== 'object') {
|
|
67
|
+
throw new TypeError(
|
|
68
|
+
`[astrobook] Named export '${storyName}' from '${importPath}' should be an object, but got ${typeof storyObject}`,
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const decorators =
|
|
73
|
+
'decorators' in storyObject ? storyObject.decorators : undefined
|
|
74
|
+
|
|
75
|
+
if (decorators != null && !Array.isArray(decorators)) {
|
|
76
|
+
throw new TypeError(
|
|
77
|
+
`[astrobook] The 'decorators' property of the named export '${storyName}' from '${importPath}' should be an array or undefined, but got ${typeof decorators}`,
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const args = 'args' in storyObject ? storyObject.args : undefined
|
|
82
|
+
if (args != null && typeof args !== 'object') {
|
|
83
|
+
throw new TypeError(
|
|
84
|
+
`[astrobook] The 'args' property of the named export '${storyName}' from '${importPath}' should be an object or undefined, but got ${typeof args}`,
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { decorators, args }
|
|
89
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Vendored from astrobook 0.13.3 (index.ts) — see LICENSE-astrobook.
|
|
2
|
+
// Divergence: relative imports carry the .ts extension so node can load this graph directly
|
|
3
|
+
// (upstream is bundled before it ships; this package is not).
|
|
4
|
+
export {
|
|
5
|
+
createAstrobookIntegration,
|
|
6
|
+
type IntegrationOptions,
|
|
7
|
+
} from './astro-integration.ts'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!-- Empty home component, used when `home: false` is set in the Astrobook integration options -->
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<slot />
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Vendored from astrobook 0.13.3 (packages/astrobook/lib/components/home.astro) — see
|
|
3
|
+
// ../../LICENSE-astrobook.
|
|
4
|
+
// Divergence: `@astrobook/ui/components/home.astro` → the vendored UI, by relative path.
|
|
5
|
+
import Home from '../../../ui/components/home.astro'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<Home />
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Decorator {
|
|
3
|
+
component: any
|
|
4
|
+
props?: any
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
decorators?: Decorator[] | null | undefined
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const decorators: Decorator[] = (Astro.props.decorators || []).slice().reverse()
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
{
|
|
15
|
+
decorators.reduce(
|
|
16
|
+
(children, decorator) => {
|
|
17
|
+
const Decorator = decorator.component
|
|
18
|
+
return <Decorator {...decorator?.props}>{children}</Decorator>
|
|
19
|
+
},
|
|
20
|
+
<slot />,
|
|
21
|
+
)
|
|
22
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Vendored from astrobook 0.13.3 (packages/astrobook/lib/pages/app.astro) — see
|
|
3
|
+
// ../../LICENSE-astrobook.
|
|
4
|
+
// Divergence: `@astrobook/ui/components/app.astro` → the vendored UI, by relative path.
|
|
5
|
+
import AppComponent from '../../../ui/components/app.astro'
|
|
6
|
+
import type { GetStaticPathsResult } from 'astro'
|
|
7
|
+
|
|
8
|
+
export function getStaticPaths(): GetStaticPathsResult {
|
|
9
|
+
return [
|
|
10
|
+
{
|
|
11
|
+
params: {
|
|
12
|
+
path: undefined,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<AppComponent />
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
// The bare story page — <subpath>/stories/<id>. New in this package: upstream routed the preview
|
|
3
|
+
// through the same `story.astro` as the dashboard, so a bare story also received the lab's
|
|
4
|
+
// chrome stylesheet, its head and its scripts.
|
|
5
|
+
//
|
|
6
|
+
// ../../virtual-module/virtual-routes.ts picks this page for the preview route and ./story.astro
|
|
7
|
+
// for the dashboard route. The split exists so the lab's own styling stops at the preview's edge
|
|
8
|
+
// (decided 2026-09-22 — ../../../ui/lab.css).
|
|
9
|
+
import LayoutComponent from '../../../ui/components/preview-layout.astro'
|
|
10
|
+
import type { ComponentProps } from 'astro/types'
|
|
11
|
+
|
|
12
|
+
type Props = ComponentProps<typeof LayoutComponent>
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<LayoutComponent {...Astro.props}>
|
|
16
|
+
<slot />
|
|
17
|
+
</LayoutComponent>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
// Vendored from astrobook 0.13.3 (packages/astrobook/lib/pages/story.astro) — see
|
|
3
|
+
// ../../LICENSE-astrobook.
|
|
4
|
+
// Divergence: `@astrobook/ui/components/layout.astro` → the vendored UI's DASHBOARD layout, by
|
|
5
|
+
// relative path. Upstream used one layout for the dashboard and the bare story alike; this page
|
|
6
|
+
// is now the dashboard only (chrome + the story inside it), and the bare story route renders
|
|
7
|
+
// through ./preview.astro. Why the two split: ../../../ui/lab.css.
|
|
8
|
+
import LayoutComponent from '../../../ui/components/dashboard-layout.astro'
|
|
9
|
+
import type { ComponentProps } from 'astro/types'
|
|
10
|
+
|
|
11
|
+
type Props = ComponentProps<typeof LayoutComponent>
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<LayoutComponent {...Astro.props}>
|
|
15
|
+
<slot />
|
|
16
|
+
</LayoutComponent>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// Absolute paths to the vendored .astro files in ./lib/ — the one file in src/core/ with no
|
|
2
|
+
// upstream counterpart.
|
|
3
|
+
//
|
|
4
|
+
// Upstream emits BARE specifiers for these ('astrobook/pages/story.astro' and friends), which
|
|
5
|
+
// node resolves by walking up for a node_modules directory. In an agent git worktree that walk
|
|
6
|
+
// leaves the checkout and finds the MAIN clone's copy, so the worktree's own edits are silently
|
|
7
|
+
// ignored — measured 2026-09-06 on a real consuming site. An absolute path computed from
|
|
8
|
+
// import.meta.url cannot go wrong
|
|
9
|
+
// that way: it names this file's own neighbour, in whichever checkout this file was loaded from.
|
|
10
|
+
//
|
|
11
|
+
// Posix slashes via slash(), matching how virtual-routes.ts normalises the entrypoints it
|
|
12
|
+
// generates; Vite resolves an absolute fs path in an import specifier, which is already how
|
|
13
|
+
// upstream emits the story module's own import.
|
|
14
|
+
import { fileURLToPath } from 'node:url'
|
|
15
|
+
|
|
16
|
+
import slash from 'slash'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The base these paths resolve against — ALWAYS `src/core/`, even when this module is the compiled
|
|
20
|
+
* copy in `dist/core/`.
|
|
21
|
+
*
|
|
22
|
+
* Why it cannot just be `import.meta.url`. For npm, `scripts/build-core.mjs` compiles this tree to
|
|
23
|
+
* `dist/core/` so Node can load it from inside `node_modules` (Node refuses to strip types there).
|
|
24
|
+
* The `.astro` files named below do NOT move with it, and must not: they import sideways into
|
|
25
|
+
* `../../ui/`, so a copy under `dist/` would need a second copy of the whole UI beside it — and
|
|
26
|
+
* two copies of the UI in one build means duplicate components and duplicate CSS in the
|
|
27
|
+
* consumer's output. Measured: moving them produced
|
|
28
|
+
* `Could not resolve '../../../ui/components/app.astro'`.
|
|
29
|
+
*
|
|
30
|
+
* So the compiled copy reaches back across the two directories to the real ones. `endsWith` rather
|
|
31
|
+
* than `includes`, so a consumer whose own project path happens to contain `dist/core` cannot
|
|
32
|
+
* trip it.
|
|
33
|
+
*/
|
|
34
|
+
const LIB_BASE = new URL(
|
|
35
|
+
import.meta.url.endsWith('/dist/core/lib-paths.js') ? '../../src/core/' : './',
|
|
36
|
+
import.meta.url,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
function libFile(relative: string): string {
|
|
40
|
+
return slash(fileURLToPath(new URL(relative, LIB_BASE)))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The vendored `@astrobook/core` client helpers, imported by every generated route. */
|
|
44
|
+
export const CLIENT_MODULE = libFile('./client.ts')
|
|
45
|
+
|
|
46
|
+
/** `astrobook/pages/story.astro` — the DASHBOARD page (chrome + the story inside it). */
|
|
47
|
+
export const STORY_PAGE = libFile('./lib/pages/story.astro')
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The BARE STORY page. No upstream counterpart: upstream routes both the dashboard and the
|
|
51
|
+
* preview through `story.astro`, so a bare story also received the lab's chrome. Splitting them
|
|
52
|
+
* is what lets the lab's own styling stop at the preview's edge (decided 2026-09-22) — see
|
|
53
|
+
* ../ui/lab.css and ./virtual-module/virtual-routes.ts, which picks between the two.
|
|
54
|
+
*/
|
|
55
|
+
export const PREVIEW_PAGE = libFile('./lib/pages/preview.astro')
|
|
56
|
+
|
|
57
|
+
/** `astrobook/pages/app.astro` */
|
|
58
|
+
export const APP_PAGE = libFile('./lib/pages/app.astro')
|
|
59
|
+
|
|
60
|
+
/** `astrobook/components/with-decorators.astro` */
|
|
61
|
+
export const WITH_DECORATORS_COMPONENT = libFile(
|
|
62
|
+
'./lib/components/with-decorators.astro',
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
/** `astrobook/components/head.astro` */
|
|
66
|
+
export const HEAD_COMPONENT = libFile('./lib/components/head.astro')
|
|
67
|
+
|
|
68
|
+
/** `astrobook/components/home.astro` */
|
|
69
|
+
export const HOME_COMPONENT = libFile('./lib/components/home.astro')
|
|
70
|
+
|
|
71
|
+
/** `astrobook/components/empty.astro` */
|
|
72
|
+
export const EMPTY_COMPONENT = libFile('./lib/components/empty.astro')
|