@md-plugins/vite-ssg-plugin 0.1.0-beta.23

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.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 md-plugins
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,185 @@
1
+ # @md-plugins/vite-ssg-plugin
2
+
3
+ Static-site-generation infrastructure for Q-Press and md-plugins documentation sites.
4
+
5
+ This package currently focuses on route inventory and static route output:
6
+
7
+ - Normalize static route declarations.
8
+ - Discover Q-Press Markdown routes from a `src/markdown` folder.
9
+ - Generate a route manifest during Vite builds.
10
+ - Expose the same manifest through a virtual module.
11
+ - Emit route-specific HTML files from the built app shell so static hosts can serve deep
12
+ links without relying on a SPA fallback rewrite.
13
+ - Accept a custom per-route renderer when a project is ready to generate fully prerendered
14
+ route HTML.
15
+
16
+ By default, generated route HTML uses the built `index.html` app shell. That makes the output
17
+ usable on Netlify or other static hosts today. Q-Press projects can use `qpress-ssg` for
18
+ first-class Vue/Quasar build-time prerendering without enabling Quasar SSR mode.
19
+
20
+ ## Why SSG?
21
+
22
+ SSG turns known routes into static HTML at build time. A direct visit or browser refresh can receive
23
+ the route's own `index.html` file, then the Vue/Quasar client bundle hydrates the page and normal
24
+ SPA navigation takes over.
25
+
26
+ That gives docs sites a useful middle ground: static hosting without a runtime SSR server, but with
27
+ route-specific HTML, meta tags, headings, and body content in the first response. This can help SEO,
28
+ indexing crawlers, and social link previews because they no longer need to depend entirely on
29
+ client-side JavaScript rendering. SSG does not guarantee search ranking improvements by itself; it
30
+ simply makes the route content easier to read earlier and more reliably.
31
+
32
+ ## Usage
33
+
34
+ ```ts
35
+ import { viteSsgPlugin } from '@md-plugins/vite-ssg-plugin'
36
+
37
+ export default {
38
+ plugins: [
39
+ viteSsgPlugin({
40
+ routes: ['/', '/getting-started/introduction', '/other/releases'],
41
+ }),
42
+ ],
43
+ }
44
+ ```
45
+
46
+ For Q-Press-style Markdown docs:
47
+
48
+ ```ts
49
+ import { viteSsgPlugin } from '@md-plugins/vite-ssg-plugin'
50
+
51
+ export default {
52
+ plugins: [
53
+ viteSsgPlugin({
54
+ markdown: {
55
+ root: './src/markdown',
56
+ },
57
+ }),
58
+ ],
59
+ }
60
+ ```
61
+
62
+ The plugin emits `q-press-ssg-routes.json` by default:
63
+
64
+ ```json
65
+ {
66
+ "base": "/",
67
+ "routes": [
68
+ {
69
+ "path": "/",
70
+ "htmlFile": "index.html",
71
+ "id": "root",
72
+ "meta": {},
73
+ "params": {}
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ Route `meta`, `params`, and `data` values should stay JSON-safe because they are written
80
+ directly into the emitted manifest and the virtual module.
81
+
82
+ ## Route HTML
83
+
84
+ When Vite emits `index.html`, this plugin creates matching route HTML files such as:
85
+
86
+ ```txt
87
+ index.html
88
+ getting-started/introduction/index.html
89
+ other/releases/index.html
90
+ q-press-ssg-routes.json
91
+ ```
92
+
93
+ Each generated page receives a small JSON payload:
94
+
95
+ ```html
96
+ <script type="application/json" id="md-plugins-ssg-route">
97
+ ...
98
+ </script>
99
+ ```
100
+
101
+ That payload helps future hydration or diagnostics know which static route was generated.
102
+
103
+ Projects that need fully prerendered content can provide `renderRoute`:
104
+
105
+ ```ts
106
+ viteSsgPlugin({
107
+ routes: ['/', '/guide'],
108
+ async renderRoute(route, { appHtml }) {
109
+ return appHtml.replace('<div id="q-app"></div>', `<div id="q-app">${route.path}</div>`)
110
+ },
111
+ })
112
+ ```
113
+
114
+ ## Post-Build Prerendering
115
+
116
+ When a project has a renderer available outside the Vite build, use `prerenderSsgRoutes`.
117
+ This is the intended bridge for SSR-quality output:
118
+
119
+ ```ts
120
+ import { prerenderSsgRoutes } from '@md-plugins/vite-ssg-plugin'
121
+
122
+ await prerenderSsgRoutes({
123
+ outDir: 'dist/spa',
124
+ async renderRoute(route, { appHtml }) {
125
+ const renderedAppHtml = await renderMyAppAt(route.path)
126
+
127
+ return appHtml.replace('<div id="q-app"></div>', `<div id="q-app">${renderedAppHtml}</div>`)
128
+ },
129
+ })
130
+ ```
131
+
132
+ The helper reads `q-press-ssg-routes.json`, renders every route, and writes each route's
133
+ `index.html` file. The renderer can be a Vue SSR renderer, a Quasar SSR adapter, or any
134
+ project-specific static renderer.
135
+
136
+ ## Vue / Quasar Build-Time Rendering
137
+
138
+ For Q-Press apps, run the generated Q-Press command after a normal SPA build:
139
+
140
+ ```bash
141
+ pnpm build:ssg
142
+ ```
143
+
144
+ Projects that already have a Quasar SSR bundle can opt into that renderer with
145
+ `qpress-ssg --renderer quasar-ssr`, but it is not required for the default Q-Press SSG flow.
146
+
147
+ For lower-level Vue or Quasar apps, `createVueSsgRouteRenderer` adapts a per-route SSR app factory
148
+ into the generic `renderRoute` hook. This uses Vue's server renderer at build time only; the
149
+ published output can still be deployed as static files on Netlify or any other static host.
150
+
151
+ ```ts
152
+ import { prerenderVueSsgRoutes } from '@md-plugins/vite-ssg-plugin'
153
+ import { createQPressSsgApp } from './src/.q-press/ssg/create-app'
154
+
155
+ await prerenderVueSsgRoutes({
156
+ outDir: 'dist/spa',
157
+ createApp: createQPressSsgApp,
158
+ })
159
+ ```
160
+
161
+ Q-Press generates `src/.q-press/ssg/create-app` and `src/.q-press/ssg/prerender`, and the `qpress-ssg` binary uses that app factory for the common docs-site flow. Non-Q-Press projects can still provide their own app factory. Vue SSR dependencies are optional until this adapter is used. Projects that already build a Quasar SSR bundle can opt into that path with `qpress-ssg --renderer quasar-ssr`.
162
+
163
+ ## Local SSR / SSG Proving
164
+
165
+ It is reasonable to create a local branch or throwaway script that boots a Quasar/Vue SSR app and
166
+ feeds it into `prerenderVueSsgRoutes()` while the workflow is still being proven.
167
+
168
+ That scratch harness should not be committed as finalized docs-site code. Commit the reusable
169
+ plugin behavior, the documented options, the generated Q-Press app-factory template, and reusable
170
+ runner behavior such as `qpress-ssg`; leave one-off local test wiring out unless it belongs in the
171
+ shared tooling.
172
+
173
+ ## Virtual Module
174
+
175
+ Client or build tooling can import the generated manifest:
176
+
177
+ ```ts
178
+ import ssgRouteManifest, { ssgRoutes } from 'virtual:md-plugins/ssg-routes'
179
+ ```
180
+
181
+ ## Next Steps
182
+
183
+ - Add dynamic-route parameter expansion.
184
+ - Define lazy client hydration behavior for examples and browser-only components.
185
+ - Define how browser-only examples opt out of prerendering.
@@ -0,0 +1,224 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ type MaybePromise<T> = T | Promise<T>;
4
+ type JsonPrimitive = string | number | boolean | null;
5
+ type JsonValue = JsonPrimitive | JsonValue[] | {
6
+ [key: string]: JsonValue;
7
+ };
8
+ type SsgRouteParams = Record<string, JsonPrimitive | undefined>;
9
+ type SsgRouteMeta = Record<string, JsonValue | undefined>;
10
+ interface SsgRouteObject {
11
+ path: string;
12
+ meta?: SsgRouteMeta;
13
+ params?: SsgRouteParams;
14
+ data?: JsonValue;
15
+ }
16
+ type SsgRouteInput = string | SsgRouteObject;
17
+ interface SsgRoute {
18
+ path: string;
19
+ htmlFile: string;
20
+ id: string;
21
+ meta: SsgRouteMeta;
22
+ params: SsgRouteParams;
23
+ data?: JsonValue;
24
+ }
25
+ interface SsgRouteManifest {
26
+ base: string;
27
+ routes: SsgRoute[];
28
+ }
29
+ type SsgRouteSource = SsgRouteInput[] | (() => MaybePromise<SsgRouteInput[]>);
30
+ interface MarkdownSsgRoutesOptions {
31
+ /**
32
+ * Directory containing Markdown pages.
33
+ */
34
+ root: string;
35
+ /**
36
+ * Glob pattern or patterns to include.
37
+ */
38
+ include?: string | string[];
39
+ /**
40
+ * Glob pattern or patterns to exclude.
41
+ */
42
+ exclude?: string | string[];
43
+ /**
44
+ * Markdown file that should map to the site root.
45
+ */
46
+ landingPage?: string;
47
+ }
48
+ interface SsgRouteRenderContext {
49
+ appHtml: string;
50
+ manifest: SsgRouteManifest;
51
+ routeIndex: number;
52
+ }
53
+ type SsgRouteRenderer = (route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string | undefined>;
54
+ type SsgRouteHtmlTransformer = (html: string, route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string>;
55
+ interface SsgRouteHtmlOptions {
56
+ /**
57
+ * Optional per-route HTML renderer. Returning undefined falls back to the app shell.
58
+ */
59
+ renderRoute?: SsgRouteRenderer;
60
+ /**
61
+ * Optional per-route HTML transform after rendering or app-shell fallback.
62
+ */
63
+ transformHtml?: SsgRouteHtmlTransformer;
64
+ /**
65
+ * Injects a JSON payload for the current SSG route into generated HTML.
66
+ */
67
+ injectRoutePayload?: boolean;
68
+ }
69
+ interface PrerenderSsgRoutesOptions extends SsgRouteHtmlOptions {
70
+ /**
71
+ * Built output directory containing the app shell and route manifest.
72
+ */
73
+ outDir: string;
74
+ /**
75
+ * Built HTML file used as the app shell. Defaults to index.html.
76
+ */
77
+ appHtmlFile?: string;
78
+ /**
79
+ * Build asset path for the generated route manifest.
80
+ */
81
+ manifestFile?: string;
82
+ /**
83
+ * Manifest to use instead of reading one from disk.
84
+ */
85
+ manifest?: SsgRouteManifest;
86
+ }
87
+ interface PrerenderedSsgRoute {
88
+ path: string;
89
+ htmlFile: string;
90
+ bytes: number;
91
+ }
92
+ interface PrerenderSsgRoutesResult {
93
+ manifest: SsgRouteManifest;
94
+ outDir: string;
95
+ routes: PrerenderedSsgRoute[];
96
+ }
97
+ interface VueSsgRouterAdapter {
98
+ push?: (location: unknown) => MaybePromise<unknown>;
99
+ replace?: (location: unknown) => MaybePromise<unknown>;
100
+ isReady?: () => MaybePromise<unknown>;
101
+ }
102
+ interface VueSsgAppFactoryResult {
103
+ app: unknown;
104
+ router?: VueSsgRouterAdapter;
105
+ ssrContext?: Record<string, unknown>;
106
+ routeLocation?: unknown;
107
+ onRendered?: () => MaybePromise<void>;
108
+ }
109
+ type VueSsgAppFactory = (route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<VueSsgAppFactoryResult | unknown>;
110
+ type VueSsgRenderToString = (app: unknown, ssrContext?: Record<string, unknown>) => MaybePromise<string>;
111
+ type VueSsgRouteLocationResolver = (route: SsgRoute, context: SsgRouteRenderContext) => unknown;
112
+ type VueSsgAppHtmlReplacer = (appHtml: string, renderedAppHtml: string, route: SsgRoute, context: SsgRouteRenderContext) => string;
113
+ type VueSsgRenderedAppHtmlTransformer = (renderedAppHtml: string, route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string>;
114
+ interface VueSsgRouteRendererOptions {
115
+ /**
116
+ * Creates a fresh Vue/Quasar SSR app instance for each route.
117
+ */
118
+ createApp: VueSsgAppFactory;
119
+ /**
120
+ * Optional renderer. Defaults to lazy-loading @vue/server-renderer when used.
121
+ */
122
+ renderToString?: VueSsgRenderToString;
123
+ /**
124
+ * DOM id for the app mount element in the built shell. Defaults to q-app.
125
+ */
126
+ appMountId?: string;
127
+ /**
128
+ * Route location pushed into the returned router before rendering.
129
+ */
130
+ routeLocation?: VueSsgRouteLocationResolver;
131
+ /**
132
+ * Use router.replace instead of router.push when both are available.
133
+ */
134
+ useRouterReplace?: boolean;
135
+ /**
136
+ * Optional transform for the SSR-rendered app fragment before shell insertion.
137
+ */
138
+ transformRenderedAppHtml?: VueSsgRenderedAppHtmlTransformer;
139
+ /**
140
+ * Optional full shell replacer for projects with a custom app placeholder.
141
+ */
142
+ replaceAppHtml?: VueSsgAppHtmlReplacer;
143
+ }
144
+ interface PrerenderVueSsgRoutesOptions extends Omit<PrerenderSsgRoutesOptions, 'renderRoute'>, VueSsgRouteRendererOptions {
145
+ }
146
+ interface ViteSsgPluginOptions {
147
+ /**
148
+ * Enables manifest emission. The virtual module remains available either way.
149
+ */
150
+ enabled?: boolean;
151
+ /**
152
+ * Static route declarations or a function that resolves them.
153
+ */
154
+ routes?: SsgRouteSource;
155
+ /**
156
+ * Optional Markdown route discovery. This can be combined with explicit routes.
157
+ */
158
+ markdown?: MarkdownSsgRoutesOptions;
159
+ /**
160
+ * Base path used by the generated route manifest.
161
+ * Falls back to Vite's resolved base.
162
+ */
163
+ base?: string;
164
+ /**
165
+ * Emits static HTML files for each route. Defaults to true.
166
+ */
167
+ emitHtml?: boolean;
168
+ /**
169
+ * Built HTML file used as the app shell. Defaults to index.html.
170
+ */
171
+ appHtmlFile?: string;
172
+ /**
173
+ * Optional per-route HTML renderer/transform behavior.
174
+ */
175
+ renderRoute?: SsgRouteHtmlOptions['renderRoute'];
176
+ transformHtml?: SsgRouteHtmlOptions['transformHtml'];
177
+ injectRoutePayload?: SsgRouteHtmlOptions['injectRoutePayload'];
178
+ /**
179
+ * Build asset path for the generated route manifest.
180
+ */
181
+ manifestFile?: string;
182
+ /**
183
+ * Virtual module id used to import the generated route manifest.
184
+ */
185
+ virtualModuleId?: string;
186
+ }
187
+
188
+ declare function escapeJsonForHtml(json: string): string;
189
+ declare function createSsgRoutePayloadScript(route: SsgRoute): string;
190
+ declare function injectSsgRoutePayload(html: string, route: SsgRoute): string;
191
+ declare function createSsgRouteHtml(route: SsgRoute, context: SsgRouteRenderContext, { injectRoutePayload }?: {
192
+ injectRoutePayload?: boolean;
193
+ }): string;
194
+ declare function renderSsgRouteHtml(route: SsgRoute, context: SsgRouteRenderContext, options?: SsgRouteHtmlOptions): Promise<string>;
195
+
196
+ declare function markdownFileToRoutePath(markdownFile: string, { landingPage }?: Pick<MarkdownSsgRoutesOptions, 'landingPage'>): string;
197
+ declare function discoverMarkdownSsgRoutes({ root, include, exclude, landingPage, }: MarkdownSsgRoutesOptions): SsgRouteInput[];
198
+
199
+ declare function prerenderSsgRoutes({ outDir, appHtmlFile, manifestFile, manifest, renderRoute, transformHtml, injectRoutePayload, }: PrerenderSsgRoutesOptions): Promise<PrerenderSsgRoutesResult>;
200
+
201
+ declare const defaultSsgManifestFile = "q-press-ssg-routes.json";
202
+ declare const defaultSsgVirtualModuleId = "virtual:md-plugins/ssg-routes";
203
+ declare function normalizeSsgBase(base?: string): string;
204
+ declare function normalizeSsgRoutePath(path: string): string;
205
+ declare function routePathToHtmlFile(routePath: string): string;
206
+ declare function routePathToId(routePath: string): string;
207
+ declare function normalizeSsgRoute(input: SsgRouteInput): SsgRoute;
208
+ declare function createSsgRouteManifest(routeInputs: SsgRouteInput[], { base }?: {
209
+ base?: string;
210
+ }): SsgRouteManifest;
211
+
212
+ /**
213
+ * Creates a route renderer that turns a fresh Vue/Quasar SSR app into static HTML.
214
+ */
215
+ declare function createVueSsgRouteRenderer(options: VueSsgRouteRendererOptions): SsgRouteRenderer;
216
+ /**
217
+ * Convenience wrapper for projects that prerender after a normal Vite/Quasar build.
218
+ */
219
+ declare function prerenderVueSsgRoutes(options: PrerenderVueSsgRoutesOptions): Promise<PrerenderSsgRoutesResult>;
220
+
221
+ declare function viteSsgPlugin(options?: ViteSsgPluginOptions): Plugin;
222
+
223
+ export { createSsgRouteHtml, createSsgRouteManifest, createSsgRoutePayloadScript, createVueSsgRouteRenderer, defaultSsgManifestFile, defaultSsgVirtualModuleId, discoverMarkdownSsgRoutes, escapeJsonForHtml, injectSsgRoutePayload, markdownFileToRoutePath, normalizeSsgBase, normalizeSsgRoute, normalizeSsgRoutePath, prerenderSsgRoutes, prerenderVueSsgRoutes, renderSsgRouteHtml, routePathToHtmlFile, routePathToId, viteSsgPlugin };
224
+ export type { JsonPrimitive, JsonValue, MarkdownSsgRoutesOptions, MaybePromise, PrerenderSsgRoutesOptions, PrerenderSsgRoutesResult, PrerenderVueSsgRoutesOptions, PrerenderedSsgRoute, SsgRoute, SsgRouteHtmlOptions, SsgRouteHtmlTransformer, SsgRouteInput, SsgRouteManifest, SsgRouteMeta, SsgRouteObject, SsgRouteParams, SsgRouteRenderContext, SsgRouteRenderer, SsgRouteSource, ViteSsgPluginOptions, VueSsgAppFactory, VueSsgAppFactoryResult, VueSsgAppHtmlReplacer, VueSsgRenderToString, VueSsgRenderedAppHtmlTransformer, VueSsgRouteLocationResolver, VueSsgRouteRendererOptions, VueSsgRouterAdapter };
@@ -0,0 +1,224 @@
1
+ import { Plugin } from 'vite';
2
+
3
+ type MaybePromise<T> = T | Promise<T>;
4
+ type JsonPrimitive = string | number | boolean | null;
5
+ type JsonValue = JsonPrimitive | JsonValue[] | {
6
+ [key: string]: JsonValue;
7
+ };
8
+ type SsgRouteParams = Record<string, JsonPrimitive | undefined>;
9
+ type SsgRouteMeta = Record<string, JsonValue | undefined>;
10
+ interface SsgRouteObject {
11
+ path: string;
12
+ meta?: SsgRouteMeta;
13
+ params?: SsgRouteParams;
14
+ data?: JsonValue;
15
+ }
16
+ type SsgRouteInput = string | SsgRouteObject;
17
+ interface SsgRoute {
18
+ path: string;
19
+ htmlFile: string;
20
+ id: string;
21
+ meta: SsgRouteMeta;
22
+ params: SsgRouteParams;
23
+ data?: JsonValue;
24
+ }
25
+ interface SsgRouteManifest {
26
+ base: string;
27
+ routes: SsgRoute[];
28
+ }
29
+ type SsgRouteSource = SsgRouteInput[] | (() => MaybePromise<SsgRouteInput[]>);
30
+ interface MarkdownSsgRoutesOptions {
31
+ /**
32
+ * Directory containing Markdown pages.
33
+ */
34
+ root: string;
35
+ /**
36
+ * Glob pattern or patterns to include.
37
+ */
38
+ include?: string | string[];
39
+ /**
40
+ * Glob pattern or patterns to exclude.
41
+ */
42
+ exclude?: string | string[];
43
+ /**
44
+ * Markdown file that should map to the site root.
45
+ */
46
+ landingPage?: string;
47
+ }
48
+ interface SsgRouteRenderContext {
49
+ appHtml: string;
50
+ manifest: SsgRouteManifest;
51
+ routeIndex: number;
52
+ }
53
+ type SsgRouteRenderer = (route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string | undefined>;
54
+ type SsgRouteHtmlTransformer = (html: string, route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string>;
55
+ interface SsgRouteHtmlOptions {
56
+ /**
57
+ * Optional per-route HTML renderer. Returning undefined falls back to the app shell.
58
+ */
59
+ renderRoute?: SsgRouteRenderer;
60
+ /**
61
+ * Optional per-route HTML transform after rendering or app-shell fallback.
62
+ */
63
+ transformHtml?: SsgRouteHtmlTransformer;
64
+ /**
65
+ * Injects a JSON payload for the current SSG route into generated HTML.
66
+ */
67
+ injectRoutePayload?: boolean;
68
+ }
69
+ interface PrerenderSsgRoutesOptions extends SsgRouteHtmlOptions {
70
+ /**
71
+ * Built output directory containing the app shell and route manifest.
72
+ */
73
+ outDir: string;
74
+ /**
75
+ * Built HTML file used as the app shell. Defaults to index.html.
76
+ */
77
+ appHtmlFile?: string;
78
+ /**
79
+ * Build asset path for the generated route manifest.
80
+ */
81
+ manifestFile?: string;
82
+ /**
83
+ * Manifest to use instead of reading one from disk.
84
+ */
85
+ manifest?: SsgRouteManifest;
86
+ }
87
+ interface PrerenderedSsgRoute {
88
+ path: string;
89
+ htmlFile: string;
90
+ bytes: number;
91
+ }
92
+ interface PrerenderSsgRoutesResult {
93
+ manifest: SsgRouteManifest;
94
+ outDir: string;
95
+ routes: PrerenderedSsgRoute[];
96
+ }
97
+ interface VueSsgRouterAdapter {
98
+ push?: (location: unknown) => MaybePromise<unknown>;
99
+ replace?: (location: unknown) => MaybePromise<unknown>;
100
+ isReady?: () => MaybePromise<unknown>;
101
+ }
102
+ interface VueSsgAppFactoryResult {
103
+ app: unknown;
104
+ router?: VueSsgRouterAdapter;
105
+ ssrContext?: Record<string, unknown>;
106
+ routeLocation?: unknown;
107
+ onRendered?: () => MaybePromise<void>;
108
+ }
109
+ type VueSsgAppFactory = (route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<VueSsgAppFactoryResult | unknown>;
110
+ type VueSsgRenderToString = (app: unknown, ssrContext?: Record<string, unknown>) => MaybePromise<string>;
111
+ type VueSsgRouteLocationResolver = (route: SsgRoute, context: SsgRouteRenderContext) => unknown;
112
+ type VueSsgAppHtmlReplacer = (appHtml: string, renderedAppHtml: string, route: SsgRoute, context: SsgRouteRenderContext) => string;
113
+ type VueSsgRenderedAppHtmlTransformer = (renderedAppHtml: string, route: SsgRoute, context: SsgRouteRenderContext) => MaybePromise<string>;
114
+ interface VueSsgRouteRendererOptions {
115
+ /**
116
+ * Creates a fresh Vue/Quasar SSR app instance for each route.
117
+ */
118
+ createApp: VueSsgAppFactory;
119
+ /**
120
+ * Optional renderer. Defaults to lazy-loading @vue/server-renderer when used.
121
+ */
122
+ renderToString?: VueSsgRenderToString;
123
+ /**
124
+ * DOM id for the app mount element in the built shell. Defaults to q-app.
125
+ */
126
+ appMountId?: string;
127
+ /**
128
+ * Route location pushed into the returned router before rendering.
129
+ */
130
+ routeLocation?: VueSsgRouteLocationResolver;
131
+ /**
132
+ * Use router.replace instead of router.push when both are available.
133
+ */
134
+ useRouterReplace?: boolean;
135
+ /**
136
+ * Optional transform for the SSR-rendered app fragment before shell insertion.
137
+ */
138
+ transformRenderedAppHtml?: VueSsgRenderedAppHtmlTransformer;
139
+ /**
140
+ * Optional full shell replacer for projects with a custom app placeholder.
141
+ */
142
+ replaceAppHtml?: VueSsgAppHtmlReplacer;
143
+ }
144
+ interface PrerenderVueSsgRoutesOptions extends Omit<PrerenderSsgRoutesOptions, 'renderRoute'>, VueSsgRouteRendererOptions {
145
+ }
146
+ interface ViteSsgPluginOptions {
147
+ /**
148
+ * Enables manifest emission. The virtual module remains available either way.
149
+ */
150
+ enabled?: boolean;
151
+ /**
152
+ * Static route declarations or a function that resolves them.
153
+ */
154
+ routes?: SsgRouteSource;
155
+ /**
156
+ * Optional Markdown route discovery. This can be combined with explicit routes.
157
+ */
158
+ markdown?: MarkdownSsgRoutesOptions;
159
+ /**
160
+ * Base path used by the generated route manifest.
161
+ * Falls back to Vite's resolved base.
162
+ */
163
+ base?: string;
164
+ /**
165
+ * Emits static HTML files for each route. Defaults to true.
166
+ */
167
+ emitHtml?: boolean;
168
+ /**
169
+ * Built HTML file used as the app shell. Defaults to index.html.
170
+ */
171
+ appHtmlFile?: string;
172
+ /**
173
+ * Optional per-route HTML renderer/transform behavior.
174
+ */
175
+ renderRoute?: SsgRouteHtmlOptions['renderRoute'];
176
+ transformHtml?: SsgRouteHtmlOptions['transformHtml'];
177
+ injectRoutePayload?: SsgRouteHtmlOptions['injectRoutePayload'];
178
+ /**
179
+ * Build asset path for the generated route manifest.
180
+ */
181
+ manifestFile?: string;
182
+ /**
183
+ * Virtual module id used to import the generated route manifest.
184
+ */
185
+ virtualModuleId?: string;
186
+ }
187
+
188
+ declare function escapeJsonForHtml(json: string): string;
189
+ declare function createSsgRoutePayloadScript(route: SsgRoute): string;
190
+ declare function injectSsgRoutePayload(html: string, route: SsgRoute): string;
191
+ declare function createSsgRouteHtml(route: SsgRoute, context: SsgRouteRenderContext, { injectRoutePayload }?: {
192
+ injectRoutePayload?: boolean;
193
+ }): string;
194
+ declare function renderSsgRouteHtml(route: SsgRoute, context: SsgRouteRenderContext, options?: SsgRouteHtmlOptions): Promise<string>;
195
+
196
+ declare function markdownFileToRoutePath(markdownFile: string, { landingPage }?: Pick<MarkdownSsgRoutesOptions, 'landingPage'>): string;
197
+ declare function discoverMarkdownSsgRoutes({ root, include, exclude, landingPage, }: MarkdownSsgRoutesOptions): SsgRouteInput[];
198
+
199
+ declare function prerenderSsgRoutes({ outDir, appHtmlFile, manifestFile, manifest, renderRoute, transformHtml, injectRoutePayload, }: PrerenderSsgRoutesOptions): Promise<PrerenderSsgRoutesResult>;
200
+
201
+ declare const defaultSsgManifestFile = "q-press-ssg-routes.json";
202
+ declare const defaultSsgVirtualModuleId = "virtual:md-plugins/ssg-routes";
203
+ declare function normalizeSsgBase(base?: string): string;
204
+ declare function normalizeSsgRoutePath(path: string): string;
205
+ declare function routePathToHtmlFile(routePath: string): string;
206
+ declare function routePathToId(routePath: string): string;
207
+ declare function normalizeSsgRoute(input: SsgRouteInput): SsgRoute;
208
+ declare function createSsgRouteManifest(routeInputs: SsgRouteInput[], { base }?: {
209
+ base?: string;
210
+ }): SsgRouteManifest;
211
+
212
+ /**
213
+ * Creates a route renderer that turns a fresh Vue/Quasar SSR app into static HTML.
214
+ */
215
+ declare function createVueSsgRouteRenderer(options: VueSsgRouteRendererOptions): SsgRouteRenderer;
216
+ /**
217
+ * Convenience wrapper for projects that prerender after a normal Vite/Quasar build.
218
+ */
219
+ declare function prerenderVueSsgRoutes(options: PrerenderVueSsgRoutesOptions): Promise<PrerenderSsgRoutesResult>;
220
+
221
+ declare function viteSsgPlugin(options?: ViteSsgPluginOptions): Plugin;
222
+
223
+ export { createSsgRouteHtml, createSsgRouteManifest, createSsgRoutePayloadScript, createVueSsgRouteRenderer, defaultSsgManifestFile, defaultSsgVirtualModuleId, discoverMarkdownSsgRoutes, escapeJsonForHtml, injectSsgRoutePayload, markdownFileToRoutePath, normalizeSsgBase, normalizeSsgRoute, normalizeSsgRoutePath, prerenderSsgRoutes, prerenderVueSsgRoutes, renderSsgRouteHtml, routePathToHtmlFile, routePathToId, viteSsgPlugin };
224
+ export type { JsonPrimitive, JsonValue, MarkdownSsgRoutesOptions, MaybePromise, PrerenderSsgRoutesOptions, PrerenderSsgRoutesResult, PrerenderVueSsgRoutesOptions, PrerenderedSsgRoute, SsgRoute, SsgRouteHtmlOptions, SsgRouteHtmlTransformer, SsgRouteInput, SsgRouteManifest, SsgRouteMeta, SsgRouteObject, SsgRouteParams, SsgRouteRenderContext, SsgRouteRenderer, SsgRouteSource, ViteSsgPluginOptions, VueSsgAppFactory, VueSsgAppFactoryResult, VueSsgAppHtmlReplacer, VueSsgRenderToString, VueSsgRenderedAppHtmlTransformer, VueSsgRouteLocationResolver, VueSsgRouteRendererOptions, VueSsgRouterAdapter };
package/dist/index.mjs ADDED
@@ -0,0 +1,405 @@
1
+ import { globSync } from 'tinyglobby';
2
+ import { Buffer } from 'node:buffer';
3
+ import { readFile, mkdir, writeFile } from 'node:fs/promises';
4
+ import { resolve, join, dirname } from 'node:path';
5
+
6
+ function escapeJsonForHtml(json) {
7
+ return json.replace(/</g, "\\u003C").replace(/>/g, "\\u003E").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
8
+ }
9
+ function createSsgRoutePayloadScript(route) {
10
+ const payload = escapeJsonForHtml(JSON.stringify(route));
11
+ return `<script type="application/json" id="md-plugins-ssg-route">${payload}<\/script>`;
12
+ }
13
+ function injectSsgRoutePayload(html, route) {
14
+ const script = createSsgRoutePayloadScript(route);
15
+ if (html.includes('id="md-plugins-ssg-route"')) {
16
+ return html;
17
+ }
18
+ if (html.includes("</head>")) {
19
+ return html.replace("</head>", `${script}
20
+ </head>`);
21
+ }
22
+ return `${script}
23
+ ${html}`;
24
+ }
25
+ function createSsgRouteHtml(route, context, { injectRoutePayload = true } = {}) {
26
+ if (injectRoutePayload === false) {
27
+ return context.appHtml;
28
+ }
29
+ return injectSsgRoutePayload(context.appHtml, route);
30
+ }
31
+ async function renderSsgRouteHtml(route, context, options = {}) {
32
+ const renderedHtml = await options.renderRoute?.(route, context);
33
+ const routeHtml = renderedHtml ?? createSsgRouteHtml(route, context, {
34
+ injectRoutePayload: options.injectRoutePayload
35
+ });
36
+ const html = renderedHtml && options.injectRoutePayload !== false ? injectSsgRoutePayload(routeHtml, route) : routeHtml;
37
+ return await options.transformHtml?.(html, route, context) ?? html;
38
+ }
39
+
40
+ const markdownExtensionRE = /\.md$/i;
41
+ function normalizePatterns(patterns, fallback) {
42
+ if (patterns === void 0) {
43
+ return fallback;
44
+ }
45
+ return Array.isArray(patterns) ? patterns : [patterns];
46
+ }
47
+ function markdownFileToRoutePath(markdownFile, { landingPage = "landing-page.md" } = {}) {
48
+ const normalizedFile = markdownFile.replace(/\\/g, "/").replace(/^\.\//, "");
49
+ if (normalizedFile === landingPage.replace(/\\/g, "/").replace(/^\.\//, "")) {
50
+ return "/";
51
+ }
52
+ const routeParts = normalizedFile.replace(markdownExtensionRE, "").split("/");
53
+ const lastPart = routeParts.at(-1);
54
+ const parentPart = routeParts.at(-2);
55
+ if (routeParts.length > 1 && lastPart === parentPart) {
56
+ routeParts.pop();
57
+ }
58
+ return `/${routeParts.join("/")}`;
59
+ }
60
+ function discoverMarkdownSsgRoutes({
61
+ root,
62
+ include,
63
+ exclude,
64
+ landingPage
65
+ }) {
66
+ const files = globSync(normalizePatterns(include, ["**/*.md"]), {
67
+ cwd: root,
68
+ ignore: normalizePatterns(exclude, [])
69
+ }).sort();
70
+ return files.map((file) => ({
71
+ path: markdownFileToRoutePath(file, { landingPage }),
72
+ meta: {
73
+ source: "markdown",
74
+ file
75
+ }
76
+ }));
77
+ }
78
+
79
+ const defaultSsgManifestFile = "q-press-ssg-routes.json";
80
+ const defaultSsgVirtualModuleId = "virtual:md-plugins/ssg-routes";
81
+ function normalizeSsgBase(base = "/") {
82
+ const trimmed = base.trim();
83
+ if (trimmed === "" || trimmed === "/") {
84
+ return "/";
85
+ }
86
+ if (trimmed === "." || trimmed === "./") {
87
+ return "./";
88
+ }
89
+ if (/^[a-z]+:\/\//i.test(trimmed)) {
90
+ return trimmed.replace(/\/+$/, "");
91
+ }
92
+ const withLeadingSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
93
+ const withoutTrailingSlash = withLeadingSlash.replace(/\/+$/, "");
94
+ return withoutTrailingSlash || "/";
95
+ }
96
+ function normalizeSsgRoutePath(path) {
97
+ const trimmed = path.trim();
98
+ if (!trimmed) {
99
+ throw new Error("SSG route path cannot be empty");
100
+ }
101
+ const withoutHash = trimmed.split("#")[0] ?? "";
102
+ const withoutQuery = withoutHash.split("?")[0] ?? "";
103
+ const withLeadingSlash = withoutQuery.startsWith("/") ? withoutQuery : `/${withoutQuery}`;
104
+ const compacted = withLeadingSlash.replace(/\/{2,}/g, "/");
105
+ if (compacted === "/") {
106
+ return "/";
107
+ }
108
+ return compacted.replace(/\/+$/, "");
109
+ }
110
+ function routePathToHtmlFile(routePath) {
111
+ const normalized = normalizeSsgRoutePath(routePath);
112
+ if (normalized === "/") {
113
+ return "index.html";
114
+ }
115
+ return `${normalized.slice(1)}/index.html`;
116
+ }
117
+ function routePathToId(routePath) {
118
+ const normalized = normalizeSsgRoutePath(routePath);
119
+ if (normalized === "/") {
120
+ return "root";
121
+ }
122
+ return normalized.slice(1).replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "");
123
+ }
124
+ function normalizeSsgRoute(input) {
125
+ const route = typeof input === "string" ? {
126
+ path: input,
127
+ meta: {},
128
+ params: {}
129
+ } : input;
130
+ const path = normalizeSsgRoutePath(route.path);
131
+ const meta = route.meta ?? {};
132
+ const params = route.params ?? {};
133
+ return {
134
+ path,
135
+ htmlFile: routePathToHtmlFile(path),
136
+ id: routePathToId(path),
137
+ meta,
138
+ params,
139
+ ...Object.hasOwn(route, "data") ? { data: route.data } : {}
140
+ };
141
+ }
142
+ function createSsgRouteManifest(routeInputs, { base = "/" } = {}) {
143
+ const routes = routeInputs.map(normalizeSsgRoute);
144
+ const routePaths = /* @__PURE__ */ new Set();
145
+ for (const route of routes) {
146
+ if (routePaths.has(route.path)) {
147
+ throw new Error(`Duplicate SSG route path: ${route.path}`);
148
+ }
149
+ routePaths.add(route.path);
150
+ }
151
+ return {
152
+ base: normalizeSsgBase(base),
153
+ routes
154
+ };
155
+ }
156
+
157
+ async function readSsgRouteManifest(outDir, manifestFile) {
158
+ const manifestJson = await readFile(join(outDir, manifestFile), "utf8");
159
+ return JSON.parse(manifestJson);
160
+ }
161
+ async function prerenderSsgRoutes({
162
+ outDir,
163
+ appHtmlFile = "index.html",
164
+ manifestFile = defaultSsgManifestFile,
165
+ manifest,
166
+ renderRoute,
167
+ transformHtml,
168
+ injectRoutePayload
169
+ }) {
170
+ const resolvedOutDir = resolve(outDir);
171
+ const resolvedManifest = manifest ?? await readSsgRouteManifest(resolvedOutDir, manifestFile);
172
+ const appHtml = await readFile(join(resolvedOutDir, appHtmlFile), "utf8");
173
+ const routes = [];
174
+ for (const [routeIndex, route] of resolvedManifest.routes.entries()) {
175
+ const html = await renderSsgRouteHtml(
176
+ route,
177
+ {
178
+ appHtml,
179
+ manifest: resolvedManifest,
180
+ routeIndex
181
+ },
182
+ {
183
+ renderRoute,
184
+ transformHtml,
185
+ injectRoutePayload
186
+ }
187
+ );
188
+ const htmlPath = join(resolvedOutDir, route.htmlFile);
189
+ await mkdir(dirname(htmlPath), { recursive: true });
190
+ await writeFile(htmlPath, html);
191
+ routes.push({
192
+ path: route.path,
193
+ htmlFile: route.htmlFile,
194
+ bytes: Buffer.byteLength(html)
195
+ });
196
+ }
197
+ return {
198
+ manifest: resolvedManifest,
199
+ outDir: resolvedOutDir,
200
+ routes
201
+ };
202
+ }
203
+
204
+ const vueServerRendererPackage = "@vue/server-renderer";
205
+ function escapeRegExp(value) {
206
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
207
+ }
208
+ function isVueSsgAppFactoryResult(value) {
209
+ return typeof value === "object" && value !== null && "app" in value;
210
+ }
211
+ async function loadVueRenderToString() {
212
+ try {
213
+ const renderer = await import(vueServerRendererPackage);
214
+ if (typeof renderer.renderToString === "function") {
215
+ return renderer.renderToString;
216
+ }
217
+ } catch (error) {
218
+ throw new Error(
219
+ [
220
+ "Unable to load @vue/server-renderer for SSG rendering.",
221
+ "Install it in the app that calls createVueSsgRouteRenderer(),",
222
+ "or pass a custom renderToString option.",
223
+ error instanceof Error ? `Original error: ${error.message}` : void 0
224
+ ].filter(Boolean).join(" ")
225
+ );
226
+ }
227
+ throw new Error("@vue/server-renderer did not export renderToString.");
228
+ }
229
+ function replaceMountElement(appHtml, renderedAppHtml, appMountId) {
230
+ const mountId = escapeRegExp(appMountId);
231
+ const mountElementRE = new RegExp(
232
+ `<([a-zA-Z][\\w:-]*)([^>]*\\bid=["']${mountId}["'][^>]*)>\\s*</\\1>`
233
+ );
234
+ if (!mountElementRE.test(appHtml)) {
235
+ throw new Error(`Could not find empty app mount element with id "${appMountId}".`);
236
+ }
237
+ return appHtml.replace(mountElementRE, `<$1$2>${renderedAppHtml}</$1>`);
238
+ }
239
+ async function pushRouterLocation(appResult, route, context, options) {
240
+ const router = appResult.router;
241
+ if (!router) {
242
+ return;
243
+ }
244
+ const location = appResult.routeLocation ?? options.routeLocation?.(route, context) ?? route.path;
245
+ const navigate = options.useRouterReplace === true ? router.replace ?? router.push : router.push ?? router.replace;
246
+ if (navigate) {
247
+ await navigate.call(router, location);
248
+ }
249
+ await router.isReady?.();
250
+ }
251
+ function createVueSsgRouteRenderer(options) {
252
+ return async (route, context) => {
253
+ const createdApp = await options.createApp(route, context);
254
+ const appResult = isVueSsgAppFactoryResult(createdApp) ? createdApp : { app: createdApp };
255
+ await pushRouterLocation(appResult, route, context, options);
256
+ const renderToString = options.renderToString ?? await loadVueRenderToString();
257
+ const renderedAppHtml = await renderToString(appResult.app, appResult.ssrContext);
258
+ const transformedAppHtml = await options.transformRenderedAppHtml?.(renderedAppHtml, route, context) ?? renderedAppHtml;
259
+ const html = options.replaceAppHtml ? options.replaceAppHtml(context.appHtml, transformedAppHtml, route, context) : replaceMountElement(context.appHtml, transformedAppHtml, options.appMountId ?? "q-app");
260
+ await appResult.onRendered?.();
261
+ return html;
262
+ };
263
+ }
264
+ async function prerenderVueSsgRoutes(options) {
265
+ const {
266
+ createApp,
267
+ renderToString,
268
+ appMountId,
269
+ routeLocation,
270
+ useRouterReplace,
271
+ transformRenderedAppHtml,
272
+ replaceAppHtml,
273
+ ...prerenderOptions
274
+ } = options;
275
+ return prerenderSsgRoutes({
276
+ ...prerenderOptions,
277
+ renderRoute: createVueSsgRouteRenderer({
278
+ createApp,
279
+ renderToString,
280
+ appMountId,
281
+ routeLocation,
282
+ useRouterReplace,
283
+ transformRenderedAppHtml,
284
+ replaceAppHtml
285
+ })
286
+ });
287
+ }
288
+
289
+ function isBundleAsset(entry) {
290
+ return typeof entry === "object" && entry !== null && "type" in entry && entry.type === "asset" && "fileName" in entry && typeof entry.fileName === "string" && "source" in entry;
291
+ }
292
+ function assetSourceToString(source) {
293
+ return typeof source === "string" ? source : Buffer.from(source).toString("utf8");
294
+ }
295
+ function findHtmlAsset(bundle, fileName) {
296
+ return Object.values(bundle).find(
297
+ (entry) => isBundleAsset(entry) && entry.fileName === fileName
298
+ );
299
+ }
300
+ function serializeManifestModule(manifest) {
301
+ const serializedManifest = JSON.stringify(manifest, null, 2);
302
+ return [
303
+ `export const ssgRouteManifest = ${serializedManifest}`,
304
+ "export const ssgRoutes = ssgRouteManifest.routes",
305
+ "export default ssgRouteManifest",
306
+ ""
307
+ ].join("\n");
308
+ }
309
+ async function resolveRouteInputs(options) {
310
+ const routeSource = options.routes;
311
+ const markdownRoutes = options.markdown ? discoverMarkdownSsgRoutes(options.markdown) : [];
312
+ if (!routeSource) {
313
+ return markdownRoutes;
314
+ }
315
+ if (typeof routeSource === "function") {
316
+ return [...markdownRoutes, ...await routeSource()];
317
+ }
318
+ return [...markdownRoutes, ...routeSource];
319
+ }
320
+ function viteSsgPlugin(options = {}) {
321
+ const virtualModuleId = options.virtualModuleId ?? defaultSsgVirtualModuleId;
322
+ const resolvedVirtualModuleId = `\0${virtualModuleId}`;
323
+ let config;
324
+ let manifest;
325
+ async function refreshManifest() {
326
+ const routes = await resolveRouteInputs(options);
327
+ manifest = createSsgRouteManifest(routes, {
328
+ base: options.base ?? config?.base ?? "/"
329
+ });
330
+ return manifest;
331
+ }
332
+ async function getManifest() {
333
+ return manifest ?? refreshManifest();
334
+ }
335
+ return {
336
+ name: "@md-plugins/vite-ssg-plugin",
337
+ enforce: "post",
338
+ configResolved(resolvedConfig) {
339
+ config = resolvedConfig;
340
+ },
341
+ async buildStart() {
342
+ await refreshManifest();
343
+ },
344
+ resolveId(id) {
345
+ if (id === virtualModuleId) {
346
+ return resolvedVirtualModuleId;
347
+ }
348
+ return void 0;
349
+ },
350
+ async load(id) {
351
+ if (id !== resolvedVirtualModuleId) {
352
+ return void 0;
353
+ }
354
+ return serializeManifestModule(await getManifest());
355
+ },
356
+ async generateBundle(_outputOptions, bundle) {
357
+ if (options.enabled === false) {
358
+ return;
359
+ }
360
+ const resolvedManifest = await refreshManifest();
361
+ const appHtmlFile = options.appHtmlFile ?? "index.html";
362
+ const appHtmlAsset = findHtmlAsset(bundle, appHtmlFile);
363
+ this.emitFile({
364
+ type: "asset",
365
+ fileName: options.manifestFile ?? defaultSsgManifestFile,
366
+ source: `${JSON.stringify(resolvedManifest, null, 2)}
367
+ `
368
+ });
369
+ if (options.emitHtml === false) {
370
+ return;
371
+ }
372
+ const htmlAsset = appHtmlAsset;
373
+ if (!htmlAsset) {
374
+ this.warn(
375
+ `Could not find ${appHtmlFile}; skipped SSG route HTML generation. The route manifest was still emitted.`
376
+ );
377
+ return;
378
+ }
379
+ const appHtml = assetSourceToString(htmlAsset.source);
380
+ for (const [routeIndex, route] of resolvedManifest.routes.entries()) {
381
+ const context = {
382
+ appHtml,
383
+ manifest: resolvedManifest,
384
+ routeIndex
385
+ };
386
+ const transformedHtml = await renderSsgRouteHtml(route, context, {
387
+ renderRoute: options.renderRoute,
388
+ transformHtml: options.transformHtml,
389
+ injectRoutePayload: options.injectRoutePayload
390
+ });
391
+ if (route.htmlFile === appHtmlFile) {
392
+ htmlAsset.source = transformedHtml;
393
+ continue;
394
+ }
395
+ this.emitFile({
396
+ type: "asset",
397
+ fileName: route.htmlFile,
398
+ source: transformedHtml
399
+ });
400
+ }
401
+ }
402
+ };
403
+ }
404
+
405
+ export { createSsgRouteHtml, createSsgRouteManifest, createSsgRoutePayloadScript, createVueSsgRouteRenderer, defaultSsgManifestFile, defaultSsgVirtualModuleId, discoverMarkdownSsgRoutes, escapeJsonForHtml, injectSsgRoutePayload, markdownFileToRoutePath, normalizeSsgBase, normalizeSsgRoute, normalizeSsgRoutePath, prerenderSsgRoutes, prerenderVueSsgRoutes, renderSsgRouteHtml, routePathToHtmlFile, routePathToId, viteSsgPlugin };
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@md-plugins/vite-ssg-plugin",
3
+ "version": "0.1.0-beta.23",
4
+ "description": "A Vite plugin for @md-plugins static route inventory and future SSG output.",
5
+ "keywords": [
6
+ "markdown-it",
7
+ "quasarframework",
8
+ "ssg",
9
+ "static-site-generation",
10
+ "utils",
11
+ "vite",
12
+ "vite-plugin",
13
+ "vue"
14
+ ],
15
+ "homepage": "https://github.com/md-plugins",
16
+ "bugs": {
17
+ "url": "https://github.com/md-plugins/md-plugins/issues"
18
+ },
19
+ "license": "MIT",
20
+ "author": "hawkeye64 <galbraith64@gmail.com>",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/md-plugins/md-plugins.git"
24
+ },
25
+ "files": [
26
+ "./dist"
27
+ ],
28
+ "type": "module",
29
+ "module": "./dist/index.mjs",
30
+ "types": "./dist/index.d.ts",
31
+ "exports": {
32
+ ".": {
33
+ "types": "./dist/index.d.ts",
34
+ "import": "./dist/index.mjs",
35
+ "default": "./dist/index.mjs"
36
+ }
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "dependencies": {
42
+ "tinyglobby": "^0.2.17"
43
+ },
44
+ "devDependencies": {
45
+ "vite": "^8.0.16"
46
+ },
47
+ "peerDependencies": {
48
+ "@vue/server-renderer": "^3.5.0",
49
+ "vue": "^3.5.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "@vue/server-renderer": {
53
+ "optional": true
54
+ },
55
+ "vue": {
56
+ "optional": true
57
+ }
58
+ },
59
+ "scripts": {
60
+ "build": "unbuild",
61
+ "clean": "rm -rf dist/ node_modules/"
62
+ }
63
+ }