@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,130 @@
|
|
|
1
|
+
// Vendored from astrobook 0.13.3 (virtual-module/virtual-routes.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 emits into every generated route are absolute paths into ./lib-paths.ts rather
|
|
5
|
+
// than bare `astrobook/...` ids — see that file for why.
|
|
6
|
+
import path from 'node:path'
|
|
7
|
+
|
|
8
|
+
import type { AstroIntegrationLogger } from 'astro'
|
|
9
|
+
import slash from 'slash'
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
CLIENT_MODULE,
|
|
13
|
+
PREVIEW_PAGE,
|
|
14
|
+
STORY_PAGE,
|
|
15
|
+
WITH_DECORATORS_COMPONENT,
|
|
16
|
+
} from '../lib-paths.ts'
|
|
17
|
+
import type { Story, StoryModule } from '../../types/types.ts'
|
|
18
|
+
import { invariant } from '../utils/invariant.ts'
|
|
19
|
+
import type { PathBuilder } from '../utils/path-builder.ts'
|
|
20
|
+
|
|
21
|
+
import { getStoryModules } from './get-story-modules.ts'
|
|
22
|
+
|
|
23
|
+
export interface VirtualRoute {
|
|
24
|
+
pattern: string
|
|
25
|
+
/**
|
|
26
|
+
* The absolute path to the virtual entrypoint file. Posix slash format.
|
|
27
|
+
*
|
|
28
|
+
* It's important to use an absolute path here because we must ensure that we
|
|
29
|
+
* only have one `id`, so that Astro's CSS plugin can find the correct CSS
|
|
30
|
+
* content in the following line.
|
|
31
|
+
* https://github.com/withastro/astro/blob/bc2796436dc3810e988c27b71b7a66fcb1ae8bda/packages/astro/src/core/build/plugins/plugin-css.ts#L144
|
|
32
|
+
*/
|
|
33
|
+
entrypoint: string
|
|
34
|
+
storyModule: StoryModule
|
|
35
|
+
story: Story
|
|
36
|
+
props: {
|
|
37
|
+
hasSidebar: boolean
|
|
38
|
+
story: string
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function getVirtualRoutes(
|
|
43
|
+
rootDir: string,
|
|
44
|
+
codegenDir: string,
|
|
45
|
+
logger: AstroIntegrationLogger,
|
|
46
|
+
dashboardSubpath: string,
|
|
47
|
+
previewSubpath: string,
|
|
48
|
+
buildPath: PathBuilder,
|
|
49
|
+
): Promise<Map<string, VirtualRoute>> {
|
|
50
|
+
const routes: VirtualRoute[] = []
|
|
51
|
+
const storyModules = await getStoryModules(rootDir)
|
|
52
|
+
|
|
53
|
+
for (const storyModule of storyModules) {
|
|
54
|
+
logger.debug(
|
|
55
|
+
`Found ${storyModule.stories.length} stories in ${storyModule.importPath}`,
|
|
56
|
+
)
|
|
57
|
+
for (const story of storyModule.stories) {
|
|
58
|
+
invariant(
|
|
59
|
+
!story.id.startsWith('..'),
|
|
60
|
+
`Story ID cannot start with '..', but got '${story.id}'`,
|
|
61
|
+
)
|
|
62
|
+
invariant(
|
|
63
|
+
!story.id.startsWith('/'),
|
|
64
|
+
`Story ID cannot start with '/', but got '${story.id}'`,
|
|
65
|
+
)
|
|
66
|
+
routes.push(
|
|
67
|
+
{
|
|
68
|
+
pattern: buildPath(dashboardSubpath, story.id),
|
|
69
|
+
entrypoint: slash(
|
|
70
|
+
path.resolve(codegenDir, 'dashboard', story.id + '.astro'),
|
|
71
|
+
),
|
|
72
|
+
storyModule,
|
|
73
|
+
story,
|
|
74
|
+
props: { hasSidebar: true, story: story.id },
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
pattern: buildPath(previewSubpath, story.id),
|
|
78
|
+
entrypoint: slash(
|
|
79
|
+
path.resolve(codegenDir, 'stories', story.id + '.astro'),
|
|
80
|
+
),
|
|
81
|
+
storyModule,
|
|
82
|
+
story,
|
|
83
|
+
props: { hasSidebar: false, story: story.id },
|
|
84
|
+
},
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
logger.info(`Found ${routes.length} stories in ${storyModules.length} files`)
|
|
90
|
+
|
|
91
|
+
return new Map(routes.map((route) => [route.pattern, route]))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function createVirtualRouteComponent(route: VirtualRoute): string {
|
|
95
|
+
// A module name that's useful for debugging and error messages
|
|
96
|
+
const modName = `astrobook_module_${route.storyModule.id}`
|
|
97
|
+
.replaceAll(/\W+/g, '_')
|
|
98
|
+
.replaceAll(/_+/g, '_')
|
|
99
|
+
.replace(/_+$/, '')
|
|
100
|
+
|
|
101
|
+
// Divergence: upstream emits STORY_PAGE for both routes. The dashboard route (hasSidebar) is
|
|
102
|
+
// chrome plus preview and keeps it; the bare story route gets PREVIEW_PAGE, which carries the
|
|
103
|
+
// consumer's CSS and none of the lab's — decided 2026-09-22, see ../../ui/lab.css.
|
|
104
|
+
const page = route.props.hasSidebar ? STORY_PAGE : PREVIEW_PAGE
|
|
105
|
+
|
|
106
|
+
return `
|
|
107
|
+
---
|
|
108
|
+
// Automatically generated by Astrobook
|
|
109
|
+
|
|
110
|
+
import StoryPage from '${page}';
|
|
111
|
+
import WithDecorators from '${WITH_DECORATORS_COMPONENT}';
|
|
112
|
+
import { parseStoryDefaultExport, parseStoryNamedExport } from '${CLIENT_MODULE}';
|
|
113
|
+
|
|
114
|
+
import * as ${modName} from '${route.storyModule.importPath}';
|
|
115
|
+
|
|
116
|
+
const { isAstroComponent } = parseStoryDefaultExport(${modName}, '${route.storyModule.importPath}');
|
|
117
|
+
const { decorators, args } = parseStoryNamedExport(${modName}, '${route.storyModule.importPath}', '${route.story.name}');
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
<StoryPage story={'${route.props.story}'} hasSidebar={${route.props.hasSidebar}}>
|
|
121
|
+
<WithDecorators decorators={decorators}>
|
|
122
|
+
{isAstroComponent ? (
|
|
123
|
+
<${modName}.default.component {...args} />
|
|
124
|
+
) : (
|
|
125
|
+
<${modName}.default.component {...args} client:load />
|
|
126
|
+
)}
|
|
127
|
+
</WithDecorators>
|
|
128
|
+
</StoryPage>
|
|
129
|
+
`.trim()
|
|
130
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Vendored from astrobook 0.13.3 (virtual-module/vite-plugin.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 { resolve } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
import type { GlobalConfig } from '../../types/types.ts'
|
|
8
|
+
import type { AstroConfig, AstroIntegrationLogger } from 'astro'
|
|
9
|
+
import type { Plugin, ViteDevServer } from 'vite'
|
|
10
|
+
|
|
11
|
+
import { loadStoryModules } from './story-modules.ts'
|
|
12
|
+
import {
|
|
13
|
+
COMPONENT_HEAD_ID,
|
|
14
|
+
COMPONENT_HEAD_RESOLVED_ID,
|
|
15
|
+
COMPONENT_HOME_ID,
|
|
16
|
+
COMPONENT_HOME_RESOLVED_ID,
|
|
17
|
+
STORY_MODULES_ID,
|
|
18
|
+
STORY_MODULES_RESOLVED_ID,
|
|
19
|
+
GLOBAL_CONFIG_ID,
|
|
20
|
+
GLOBAL_CONFIG_RESOLVED_ID,
|
|
21
|
+
USER_CSS_RESOLVED_ID,
|
|
22
|
+
USER_CSS_ID,
|
|
23
|
+
} from './virtual-module-ids.ts'
|
|
24
|
+
|
|
25
|
+
export function createVirtualFilesPlugin(
|
|
26
|
+
rootDir: string,
|
|
27
|
+
config: GlobalConfig,
|
|
28
|
+
astroConfig: AstroConfig,
|
|
29
|
+
logger: AstroIntegrationLogger,
|
|
30
|
+
): Plugin {
|
|
31
|
+
const root = astroConfig.root
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resolves module IDs to a usable format:
|
|
35
|
+
* - Relative paths (e.g. `'./module.js'`) are resolved against `base` and formatted as an absolute path.
|
|
36
|
+
* - Package identifiers (e.g. `'module'`) are returned unchanged.
|
|
37
|
+
*
|
|
38
|
+
* By default, `base` is the project root directory.
|
|
39
|
+
*/
|
|
40
|
+
function resolveId(id: string, base = root) {
|
|
41
|
+
return JSON.stringify(
|
|
42
|
+
id.startsWith('.') ? resolve(fileURLToPath(base), id) : id,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let storyModules: string | undefined
|
|
47
|
+
let needToReload = false
|
|
48
|
+
let watcherInitialized = false
|
|
49
|
+
|
|
50
|
+
async function getStoryModules(): Promise<string> {
|
|
51
|
+
const newStoryModules = await loadStoryModules(rootDir)
|
|
52
|
+
if (storyModules && newStoryModules !== storyModules) {
|
|
53
|
+
needToReload = true
|
|
54
|
+
}
|
|
55
|
+
storyModules = newStoryModules
|
|
56
|
+
return storyModules
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function restartServerIfNeeded(server: ViteDevServer) {
|
|
60
|
+
await getStoryModules()
|
|
61
|
+
if (needToReload) {
|
|
62
|
+
needToReload = false
|
|
63
|
+
logger.info(`Restarting`)
|
|
64
|
+
await server.restart()
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function initializeNewFileWatcher(server: ViteDevServer) {
|
|
69
|
+
if (watcherInitialized || !server.watcher) return
|
|
70
|
+
watcherInitialized = true
|
|
71
|
+
|
|
72
|
+
server.watcher.on('add', async (filePath: string) => {
|
|
73
|
+
if (filePath.includes('.stories.')) {
|
|
74
|
+
logger.debug(`Potential story file added: ${filePath}`)
|
|
75
|
+
await restartServerIfNeeded(server)
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
server.watcher.on('unlink', async (filePath: string) => {
|
|
80
|
+
if (filePath.includes('.stories.')) {
|
|
81
|
+
logger.debug(`Potential story file deleted: ${filePath}`)
|
|
82
|
+
await restartServerIfNeeded(server)
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
logger.debug(`Initialized file watcher for story files`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
name: 'astrobook/virtual-files',
|
|
91
|
+
resolveId(id) {
|
|
92
|
+
switch (id) {
|
|
93
|
+
case STORY_MODULES_ID:
|
|
94
|
+
return STORY_MODULES_RESOLVED_ID
|
|
95
|
+
case GLOBAL_CONFIG_ID:
|
|
96
|
+
return GLOBAL_CONFIG_RESOLVED_ID
|
|
97
|
+
case COMPONENT_HEAD_ID:
|
|
98
|
+
return COMPONENT_HEAD_RESOLVED_ID
|
|
99
|
+
case COMPONENT_HOME_ID:
|
|
100
|
+
return COMPONENT_HOME_RESOLVED_ID
|
|
101
|
+
case USER_CSS_ID:
|
|
102
|
+
return USER_CSS_RESOLVED_ID
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
load(id) {
|
|
106
|
+
switch (id) {
|
|
107
|
+
case STORY_MODULES_RESOLVED_ID:
|
|
108
|
+
return getStoryModules()
|
|
109
|
+
case GLOBAL_CONFIG_RESOLVED_ID:
|
|
110
|
+
return `const config = ${JSON.stringify(config)}; export default config;`
|
|
111
|
+
case COMPONENT_HEAD_RESOLVED_ID:
|
|
112
|
+
return `export { default } from ${resolveId(config.head)};`
|
|
113
|
+
case COMPONENT_HOME_RESOLVED_ID:
|
|
114
|
+
return `export { default } from ${resolveId(config.home)};`
|
|
115
|
+
case USER_CSS_RESOLVED_ID:
|
|
116
|
+
return config.css.map((id) => `import ${resolveId(id)};`).join('')
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async handleHotUpdate(ctx) {
|
|
120
|
+
const { server } = ctx
|
|
121
|
+
initializeNewFileWatcher(server)
|
|
122
|
+
await restartServerIfNeeded(server)
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
}
|