@vmz/vmz 0.1.12 → 0.1.13
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/dist/build-assemble.js +3 -4
- package/dist/cdn-policy.js +4 -5
- package/dist/cli.js +15 -50
- package/dist/content-addressed-assets.d.ts +2 -8
- package/dist/content-addressed-assets.js +34 -111
- package/dist/delivery-profile.d.ts +1 -11
- package/dist/delivery-profile.js +1 -70
- package/dist/dev-session.d.ts +0 -1
- package/dist/dev-session.js +65 -268
- package/dist/document-build.d.ts +1 -2
- package/dist/document-build.js +82 -104
- package/dist/document-cmd.js +9 -2
- package/dist/document-enrich.d.ts +1 -2
- package/dist/document-enrich.js +4 -15
- package/dist/document-integrate.js +21 -29
- package/dist/embedded-packaging.js +1 -2
- package/dist/index.d.ts +1 -15
- package/dist/index.js +3 -59
- package/dist/locale-check.js +61 -28
- package/dist/locale-cmd.js +42 -10
- package/dist/locale-route-emit.d.ts +1 -4
- package/dist/locale-route-emit.js +32 -7
- package/dist/locale-router.js +8 -26
- package/dist/pack.js +2 -3
- package/dist/production-observability.js +2 -3
- package/dist/production-test-pack.js +3 -4
- package/dist/release-pack.js +18 -5
- package/dist/server-artifact.js +3 -4
- package/dist/site-delivery.js +3 -4
- package/dist/static-emit.js +97 -118
- package/dist/test-cmd.js +1 -2
- package/package.json +12 -12
- package/dist/dev-watch-roots.d.ts +0 -80
- package/dist/dev-watch-roots.js +0 -245
- package/dist/document-layout-render.d.ts +0 -20
- package/dist/document-layout-render.js +0 -87
- package/dist/document-routing-config.d.ts +0 -13
- package/dist/document-routing-config.js +0 -40
- package/dist/native-addon.d.ts +0 -9
- package/dist/native-addon.js +0 -84
- package/dist/pretty-json.d.ts +0 -19
- package/dist/pretty-json.js +0 -43
- package/dist/route-path.d.ts +0 -35
- package/dist/route-path.js +0 -77
- package/dist/wechat-packaging.d.ts +0 -22
- package/dist/wechat-packaging.js +0 -59
package/dist/document-build.js
CHANGED
|
@@ -9,27 +9,21 @@ import { resolveDocumentDesignsCss } from './document-designs.js';
|
|
|
9
9
|
import { enrichDocumentContent, pageHtmlRel } from './document-enrich.js';
|
|
10
10
|
import { enrichDocumentEvidence } from './document-evidence.js';
|
|
11
11
|
import { artifactHrefFromHtml, buildDocumentIslands, buildDocumentSearch, collectFenceBodies, renderIslandShellsHtml, } from './document-interactive.js';
|
|
12
|
-
import { assertIntegratedDistReady, renderCompiledDocumentLayout } from './document-layout-render.js';
|
|
13
12
|
import { resolveMarkdownEngine } from './document-markdown.js';
|
|
14
|
-
import { loadLocalesRouting } from './document-routing-config.js';
|
|
15
13
|
import { DOCUMENT_VIEW_SCHEMA } from './document-schema.js';
|
|
16
14
|
import { createWorkspace } from './index.js';
|
|
17
|
-
import { requireNativeAddon } from './native-addon.js';
|
|
18
|
-
import { writePrettyJsonFile } from './pretty-json.js';
|
|
19
15
|
/**
|
|
20
|
-
* @param {{ projectRoot: string, outDir?: string,
|
|
16
|
+
* @param {{ projectRoot: string, outDir?: string, strict?: boolean, engines?: { markdown?: string } }} opts
|
|
21
17
|
*/
|
|
22
18
|
export async function buildDocuments(opts) {
|
|
23
19
|
const projectRoot = path.resolve(opts.projectRoot);
|
|
24
20
|
const outDir = path.resolve(opts.outDir || path.join(projectRoot, 'dist', 'documents'));
|
|
25
21
|
const strict = Boolean(opts.strict);
|
|
26
22
|
const manifest = checkDocuments({ projectRoot, strict });
|
|
27
|
-
const routing = loadLocalesRouting(projectRoot) || { strategy: 'prefix' };
|
|
28
23
|
const engine = await resolveMarkdownEngine({ engines: opts.engines, projectRoot });
|
|
29
24
|
const enriched = enrichDocumentContent(manifest, {
|
|
30
25
|
analyzeMarkdown: engine.analyzeMarkdown,
|
|
31
26
|
projectRoot,
|
|
32
|
-
routing,
|
|
33
27
|
});
|
|
34
28
|
manifest.diagnostics = enriched.diagnostics;
|
|
35
29
|
const evidence = await enrichDocumentEvidence(manifest, {
|
|
@@ -64,12 +58,8 @@ export async function buildDocuments(opts) {
|
|
|
64
58
|
});
|
|
65
59
|
manifest.search = search;
|
|
66
60
|
manifest.islands = islands;
|
|
67
|
-
const
|
|
68
|
-
const
|
|
69
|
-
const useCompiledShell = Boolean(integratedMount && appDistDir);
|
|
70
|
-
if (integratedMount && appDistDir) {
|
|
71
|
-
assertIntegratedDistReady(appDistDir);
|
|
72
|
-
}
|
|
61
|
+
const hostChrome = resolveHostSiteChrome(projectRoot);
|
|
62
|
+
const useHostShell = Boolean(hostChrome) && (manifest.mounts || []).some((m) => m.mode === 'integrated');
|
|
73
63
|
fs.mkdirSync(outDir, { recursive: true });
|
|
74
64
|
const designs = resolveDocumentDesignsCss(projectRoot);
|
|
75
65
|
/** @type {string | null} */
|
|
@@ -100,20 +90,6 @@ export async function buildDocuments(opts) {
|
|
|
100
90
|
pageKey: page.identity.pageKey,
|
|
101
91
|
locale: page.identity.locale,
|
|
102
92
|
});
|
|
103
|
-
const slotHtml = buildDocumentSlotHtml({
|
|
104
|
-
nav,
|
|
105
|
-
bodyHtml: info.html,
|
|
106
|
-
headings: info.headings,
|
|
107
|
-
htmlRel,
|
|
108
|
-
route: info.route,
|
|
109
|
-
routing,
|
|
110
|
-
searchShellHtml: shells.searchHtml,
|
|
111
|
-
playgroundShellHtml: shells.playgroundHtml,
|
|
112
|
-
});
|
|
113
|
-
let compiledLayoutHtml = null;
|
|
114
|
-
if (useCompiledShell) {
|
|
115
|
-
compiledLayoutHtml = await renderCompiledDocumentLayout(appDistDir, page.identity.locale, slotHtml);
|
|
116
|
-
}
|
|
117
93
|
const view = {
|
|
118
94
|
schema: DOCUMENT_VIEW_SCHEMA,
|
|
119
95
|
pageKey: page.identity.pageKey,
|
|
@@ -127,7 +103,7 @@ export async function buildDocuments(opts) {
|
|
|
127
103
|
designsCss: designsHref,
|
|
128
104
|
noJsReadable: true,
|
|
129
105
|
hydrate: 'island-only',
|
|
130
|
-
hostShell:
|
|
106
|
+
hostShell: useHostShell,
|
|
131
107
|
islands: ['DocumentSearch'].concat((islands.islands || [])
|
|
132
108
|
.filter((isl) => isl.kind === 'playground' &&
|
|
133
109
|
isl.fence?.locale === page.identity.locale &&
|
|
@@ -137,7 +113,7 @@ export async function buildDocuments(opts) {
|
|
|
137
113
|
const viewRel = path.posix.join('views', page.identity.locale, `${page.identity.pageKey === 'index' ? 'index' : page.identity.pageKey}.view.json`);
|
|
138
114
|
const viewAbs = path.join(outDir, viewRel);
|
|
139
115
|
fs.mkdirSync(path.dirname(viewAbs), { recursive: true });
|
|
140
|
-
|
|
116
|
+
fs.writeFileSync(viewAbs, JSON.stringify(view, null, 2) + '\n', 'utf8');
|
|
141
117
|
const html = renderStaticHtml({
|
|
142
118
|
title: info.title,
|
|
143
119
|
locale: page.identity.locale,
|
|
@@ -149,9 +125,7 @@ export async function buildDocuments(opts) {
|
|
|
149
125
|
htmlRel,
|
|
150
126
|
searchShellHtml: shells.searchHtml,
|
|
151
127
|
playgroundShellHtml: shells.playgroundHtml,
|
|
152
|
-
|
|
153
|
-
compiledLayoutHtml,
|
|
154
|
-
useCompiledShell,
|
|
128
|
+
hostChrome: useHostShell ? hostChrome : null,
|
|
155
129
|
});
|
|
156
130
|
fs.writeFileSync(htmlAbs, html, 'utf8');
|
|
157
131
|
written.push({ route: info.route, htmlPath: htmlRel, viewPath: viewRel });
|
|
@@ -167,38 +141,39 @@ export async function buildDocuments(opts) {
|
|
|
167
141
|
outDir: path.relative(projectRoot, outDir).replace(/\\/g, '/') || '.',
|
|
168
142
|
designs: designs.source,
|
|
169
143
|
designsCss: designsHref,
|
|
170
|
-
hostShell: useCompiledShell ? 'compiled-layout' : 'standalone',
|
|
171
144
|
pages: written,
|
|
172
145
|
evidence: 'document.evidence.json',
|
|
173
146
|
search: 'document.search.json',
|
|
174
147
|
islands: 'document.islands.json',
|
|
175
148
|
},
|
|
176
149
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
150
|
+
fs.writeFileSync(path.join(outDir, 'document.manifest.json'), JSON.stringify(manifestOut, null, 2) + '\n', 'utf8');
|
|
151
|
+
fs.writeFileSync(path.join(outDir, 'document.evidence.json'), JSON.stringify(evidence.evidence, null, 2) + '\n', 'utf8');
|
|
152
|
+
fs.writeFileSync(path.join(outDir, 'document.search.json'), JSON.stringify(search, null, 2) + '\n', 'utf8');
|
|
153
|
+
fs.writeFileSync(path.join(outDir, 'document.islands.json'), JSON.stringify(islands, null, 2) + '\n', 'utf8');
|
|
181
154
|
return { ok: true, manifest: manifestOut, outDir, pages: written, search, islands };
|
|
182
155
|
}
|
|
183
156
|
/**
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*/
|
|
187
|
-
function resolveAppDistDir(opts, outDir) {
|
|
188
|
-
if (opts.appDistDir) {
|
|
189
|
-
const p = path.resolve(opts.appDistDir);
|
|
190
|
-
return fs.existsSync(path.join(p, 'vmz-dom.js')) ? p : null;
|
|
191
|
-
}
|
|
192
|
-
return fs.existsSync(path.join(outDir, 'vmz-dom.js')) ? outDir : null;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Document main column + sidebar (injected into DocumentLayout slot).
|
|
157
|
+
* No-JS readable static HTML: nav + main landmarks, Island shells without scripts.
|
|
158
|
+
* Integrated mounts reuse host SiteHeader/SiteFooter templates when present.
|
|
196
159
|
*/
|
|
197
|
-
function
|
|
160
|
+
function renderStaticHtml({ title, locale, route, nav, bodyHtml, headings, designsHref, htmlRel, searchShellHtml = '', playgroundShellHtml = '', hostChrome = null, }) {
|
|
198
161
|
const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
162
|
+
const depth = htmlRel.split('/').length - 1;
|
|
163
|
+
const prefix = depth > 0 ? '../'.repeat(depth) : './';
|
|
164
|
+
/** @type {string[]} */
|
|
165
|
+
const cssHrefs = [];
|
|
166
|
+
if (hostChrome) {
|
|
167
|
+
// Integrated documents are served with pretty directory URLs. Root
|
|
168
|
+
// absolute assets remain correct for both emitted files and rewrites.
|
|
169
|
+
cssHrefs.push('/vmz.css');
|
|
170
|
+
}
|
|
171
|
+
if (designsHref)
|
|
172
|
+
cssHrefs.push(hostChrome ? `/${designsHref}` : prefix + designsHref);
|
|
173
|
+
const cssLink = cssHrefs.map((href) => ` <link rel="stylesheet" href="${esc(href)}" />`).join('\n') + (cssHrefs.length ? '\n' : '');
|
|
199
174
|
const navItems = nav
|
|
200
175
|
.map((n) => {
|
|
201
|
-
const href =
|
|
176
|
+
const href = relativeHref(htmlRel, n.href, route);
|
|
202
177
|
const current = n.href === route ? ' aria-current="page"' : '';
|
|
203
178
|
return ` <li><a href="${esc(href)}"${current}>${esc(n.title)}</a></li>`;
|
|
204
179
|
})
|
|
@@ -213,7 +188,21 @@ function buildDocumentSlotHtml({ nav, bodyHtml, headings, htmlRel, route, routin
|
|
|
213
188
|
${navItems}
|
|
214
189
|
</ul>
|
|
215
190
|
</nav>`;
|
|
216
|
-
|
|
191
|
+
if (hostChrome) {
|
|
192
|
+
const header = hostChrome.header.replace(/(<a\s+href="\/d\/?")([^>]*>文档<\/a>)/, '$1 aria-current="page"$2');
|
|
193
|
+
return `<!DOCTYPE html>
|
|
194
|
+
<html lang="${esc(locale)}">
|
|
195
|
+
<head>
|
|
196
|
+
<meta charset="utf-8" />
|
|
197
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
198
|
+
<title>${esc(title)}</title>
|
|
199
|
+
${cssLink}</head>
|
|
200
|
+
<body data-vmz-hydrate="island-only">
|
|
201
|
+
<div class="site site--docs">
|
|
202
|
+
<a class="skip-link" href="#main">Skip to content</a>
|
|
203
|
+
${header}
|
|
204
|
+
<div class="doc-body">
|
|
205
|
+
<aside class="doc-sidebar">
|
|
217
206
|
${docsNav}
|
|
218
207
|
${searchShellHtml}
|
|
219
208
|
</aside>
|
|
@@ -222,65 +211,54 @@ ${searchShellHtml}
|
|
|
222
211
|
${bodyHtml}
|
|
223
212
|
${playgroundShellHtml}
|
|
224
213
|
</main>
|
|
225
|
-
</div
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
233
|
-
const depth = htmlRel.split('/').length - 1;
|
|
234
|
-
const prefix = depth > 0 ? '../'.repeat(depth) : './';
|
|
235
|
-
/** @type {string[]} */
|
|
236
|
-
const cssHrefs = [];
|
|
237
|
-
if (useCompiledShell) {
|
|
238
|
-
cssHrefs.push('/vmz.css');
|
|
239
|
-
}
|
|
240
|
-
if (designsHref)
|
|
241
|
-
cssHrefs.push(useCompiledShell ? `/${designsHref}` : prefix + designsHref);
|
|
242
|
-
/** @type {string} */
|
|
243
|
-
let bodyInner;
|
|
244
|
-
if (useCompiledShell) {
|
|
245
|
-
bodyInner = compiledLayoutHtml;
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
${hostChrome.footer}
|
|
217
|
+
</div>
|
|
218
|
+
</body>
|
|
219
|
+
</html>
|
|
220
|
+
`;
|
|
246
221
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
.map((h) => ` <li class="h${h.level}"><a href="#${esc(h.id)}">${esc(h.text)}</a></li>`)
|
|
258
|
-
.join('\n')}\n </ol>\n </nav>\n`
|
|
259
|
-
: '';
|
|
260
|
-
bodyInner = ` <a class="skip-link" href="#main">Skip to content</a>
|
|
261
|
-
<nav aria-label="Documents" class="doc-subnav">
|
|
262
|
-
<ul>
|
|
263
|
-
${navItems}
|
|
264
|
-
</ul>
|
|
265
|
-
</nav>
|
|
222
|
+
return `<!DOCTYPE html>
|
|
223
|
+
<html lang="${esc(locale)}">
|
|
224
|
+
<head>
|
|
225
|
+
<meta charset="utf-8" />
|
|
226
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
227
|
+
<title>${esc(title)}</title>
|
|
228
|
+
${cssLink}</head>
|
|
229
|
+
<body data-vmz-hydrate="island-only">
|
|
230
|
+
<a class="skip-link" href="#main">Skip to content</a>
|
|
231
|
+
${docsNav}
|
|
266
232
|
${searchShellHtml}
|
|
267
233
|
${toc}<main id="main">
|
|
268
234
|
${bodyHtml}
|
|
269
235
|
${playgroundShellHtml}
|
|
270
236
|
</main>
|
|
237
|
+
</body>
|
|
238
|
+
</html>
|
|
271
239
|
`;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Integrated DocumentMount: reuse host SiteHeader / SiteFooter .vmz templates.
|
|
243
|
+
* @param {string} projectRoot
|
|
244
|
+
* @returns {{ header: string, footer: string } | null}
|
|
245
|
+
*/
|
|
246
|
+
function resolveHostSiteChrome(projectRoot) {
|
|
247
|
+
const headerPath = path.join(projectRoot, 'src', 'components', 'SiteHeader.vmz');
|
|
248
|
+
const footerPath = path.join(projectRoot, 'src', 'components', 'SiteFooter.vmz');
|
|
249
|
+
if (!fs.existsSync(headerPath) || !fs.existsSync(footerPath))
|
|
250
|
+
return null;
|
|
251
|
+
const header = extractVmzTemplateHtml(headerPath);
|
|
252
|
+
const footer = extractVmzTemplateHtml(footerPath);
|
|
253
|
+
if (!header || !footer)
|
|
254
|
+
return null;
|
|
255
|
+
return { header, footer };
|
|
256
|
+
}
|
|
257
|
+
/** @param {string} filePath */
|
|
258
|
+
function extractVmzTemplateHtml(filePath) {
|
|
259
|
+
const src = fs.readFileSync(filePath, 'utf8');
|
|
260
|
+
const m = src.match(/<template>([\s\S]*?)<\/template>/);
|
|
261
|
+
return m ? m[1].trim() : '';
|
|
284
262
|
}
|
|
285
263
|
function relativeHref(fromHtmlRel, toRoute, _fromRoute) {
|
|
286
264
|
const toParts = String(toRoute).replace(/^\//, '').split('/').filter(Boolean);
|
package/dist/document-cmd.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* `vmz document` / `vmz docs` CLI .
|
|
4
4
|
*/
|
|
5
|
+
import fs from 'node:fs';
|
|
5
6
|
import path from 'node:path';
|
|
6
7
|
import { buildDocuments } from './document-build.js';
|
|
7
8
|
import { checkDocuments, manifestHasErrors } from './document-check.js';
|
|
@@ -11,7 +12,6 @@ import { resolveMarkdownEngine } from './document-markdown.js';
|
|
|
11
12
|
import { createWorkspace } from './index.js';
|
|
12
13
|
import { log } from './log.js';
|
|
13
14
|
import { parseArgs } from './cli.js';
|
|
14
|
-
import { emitPrettyJson } from './pretty-json.js';
|
|
15
15
|
function printDocumentHelp() {
|
|
16
16
|
console.log(`vmz document — project /documents domain
|
|
17
17
|
|
|
@@ -95,7 +95,14 @@ async function cmdDocumentCheck(args) {
|
|
|
95
95
|
}
|
|
96
96
|
const jsonOut = args.json;
|
|
97
97
|
if (jsonOut) {
|
|
98
|
-
|
|
98
|
+
const text = JSON.stringify(manifest, null, 2);
|
|
99
|
+
if (typeof jsonOut === 'string') {
|
|
100
|
+
fs.writeFileSync(jsonOut, text + '\n', 'utf8');
|
|
101
|
+
log.info(`wrote ${jsonOut}`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.log(text);
|
|
105
|
+
}
|
|
99
106
|
}
|
|
100
107
|
else {
|
|
101
108
|
for (const d of manifest.diagnostics) {
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* @param {string} routeBase e.g. /docs
|
|
3
3
|
* @param {string} locale
|
|
4
4
|
* @param {string} pageKey
|
|
5
|
-
* @param {{ strategy?: string }} [routing]
|
|
6
5
|
*/
|
|
7
|
-
export declare function pageRoute(routeBase: any, locale: any, pageKey: any
|
|
6
|
+
export declare function pageRoute(routeBase: any, locale: any, pageKey: any): string;
|
|
8
7
|
/**
|
|
9
8
|
* Static file path relative to out dir (posix).
|
|
10
9
|
* @param {string} routeBase
|
package/dist/document-enrich.js
CHANGED
|
@@ -9,16 +9,10 @@ import { DIAG } from './document-schema.js';
|
|
|
9
9
|
* @param {string} routeBase e.g. /docs
|
|
10
10
|
* @param {string} locale
|
|
11
11
|
* @param {string} pageKey
|
|
12
|
-
* @param {{ strategy?: string }} [routing]
|
|
13
12
|
*/
|
|
14
|
-
export function pageRoute(routeBase, locale, pageKey
|
|
13
|
+
export function pageRoute(routeBase, locale, pageKey) {
|
|
15
14
|
const base = String(routeBase || '/').replace(/\/$/, '') || '';
|
|
16
15
|
const key = pageKey === 'index' ? '' : pageKey.replace(/\\/g, '/');
|
|
17
|
-
const strategy = routing.strategy || 'prefix';
|
|
18
|
-
if (strategy === 'none' || strategy === 'domain') {
|
|
19
|
-
const parts = [base.replace(/^\//, ''), key].filter((p) => p !== '');
|
|
20
|
-
return '/' + (parts.length ? parts.join('/') : '');
|
|
21
|
-
}
|
|
22
16
|
const parts = [base.replace(/^\//, ''), locale, key].filter((p) => p !== '');
|
|
23
17
|
return '/' + parts.join('/');
|
|
24
18
|
}
|
|
@@ -41,7 +35,6 @@ export function pageHtmlRel(routeBase, locale, pageKey) {
|
|
|
41
35
|
*/
|
|
42
36
|
export function enrichDocumentContent(manifest, ctx) {
|
|
43
37
|
const routeBase = manifest.mounts?.[0]?.routeBase || '/docs';
|
|
44
|
-
const routing = ctx.routing || { strategy: 'prefix' };
|
|
45
38
|
/** @type {Map<string, { html: string, headings: any[], links: any[], title: string, route: string, anchors: string[] }>} */
|
|
46
39
|
const byId = new Map();
|
|
47
40
|
/** @type {import('./document-schema.js').DocumentDiagnostic[]} */
|
|
@@ -52,7 +45,7 @@ export function enrichDocumentContent(manifest, ctx) {
|
|
|
52
45
|
const abs = path.isAbsolute(page.sourcePath) ? page.sourcePath : path.join(manifest.root, page.sourcePath);
|
|
53
46
|
const source = fs.existsSync(abs) ? fs.readFileSync(abs, 'utf8') : '';
|
|
54
47
|
const analyzed = ctx.analyzeMarkdown(source);
|
|
55
|
-
const route = pageRoute(routeBase, page.identity.locale, page.identity.pageKey
|
|
48
|
+
const route = pageRoute(routeBase, page.identity.locale, page.identity.pageKey);
|
|
56
49
|
const anchors = analyzed.headings.map((h) => h.id);
|
|
57
50
|
const title = analyzed.headings.find((h) => h.level === 1)?.text || analyzed.headings[0]?.text || page.identity.pageKey;
|
|
58
51
|
// Duplicate anchors on page
|
|
@@ -68,11 +61,7 @@ export function enrichDocumentContent(manifest, ctx) {
|
|
|
68
61
|
}
|
|
69
62
|
seen.add(id);
|
|
70
63
|
}
|
|
71
|
-
|
|
72
|
-
if (routing.strategy === 'none' || routing.strategy === 'domain') {
|
|
73
|
-
routeOwners.set(route, owner);
|
|
74
|
-
}
|
|
75
|
-
else if (routeOwners.has(route)) {
|
|
64
|
+
if (routeOwners.has(route)) {
|
|
76
65
|
diagnostics.push({
|
|
77
66
|
code: DIAG.ROUTE_DUPLICATE,
|
|
78
67
|
severity: 'error',
|
|
@@ -81,7 +70,7 @@ export function enrichDocumentContent(manifest, ctx) {
|
|
|
81
70
|
});
|
|
82
71
|
}
|
|
83
72
|
else {
|
|
84
|
-
routeOwners.set(route,
|
|
73
|
+
routeOwners.set(route, `${page.identity.locale}:${page.identity.pageKey}`);
|
|
85
74
|
}
|
|
86
75
|
page.route = route;
|
|
87
76
|
page.anchors = anchors;
|
|
@@ -7,10 +7,7 @@ import fs from 'node:fs';
|
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { buildDocuments } from './document-build.js';
|
|
9
9
|
import { resolveDocumentsRoot } from './document-check.js';
|
|
10
|
-
import { loadLocalesRouting } from './document-routing-config.js';
|
|
11
|
-
import { pageHtmlRel } from './document-enrich.js';
|
|
12
10
|
import { log } from './log.js';
|
|
13
|
-
import { requireNativeAddon } from './native-addon.js';
|
|
14
11
|
/**
|
|
15
12
|
* @param {string} projectRoot
|
|
16
13
|
*/
|
|
@@ -33,7 +30,6 @@ export async function buildIntegratedDocuments(opts) {
|
|
|
33
30
|
const result = await buildDocuments({
|
|
34
31
|
projectRoot,
|
|
35
32
|
outDir,
|
|
36
|
-
appDistDir: outDir,
|
|
37
33
|
strict: Boolean(opts.strict),
|
|
38
34
|
});
|
|
39
35
|
if (!result.ok) {
|
|
@@ -43,7 +39,7 @@ export async function buildIntegratedDocuments(opts) {
|
|
|
43
39
|
}
|
|
44
40
|
return { ok: false, error: 'document diagnostics', pages: 0 };
|
|
45
41
|
}
|
|
46
|
-
writeMountRootRedirects(result.manifest, outDir
|
|
42
|
+
writeMountRootRedirects(result.manifest, outDir);
|
|
47
43
|
log.info(`document mount: pages=${result.pages.length} → ${path.relative(process.cwd(), outDir) || '.'}`);
|
|
48
44
|
return { ok: true, pages: result.pages.length };
|
|
49
45
|
}
|
|
@@ -54,43 +50,39 @@ export async function buildIntegratedDocuments(opts) {
|
|
|
54
50
|
}
|
|
55
51
|
}
|
|
56
52
|
/**
|
|
57
|
-
* Emit `{routeBase}/index.html` for
|
|
58
|
-
* `routing.strategy: none` → copy default-locale docs index (LocaleId is Host state).
|
|
59
|
-
* prefix strategy → redirect HTML to `{routeBase}/{defaultLocale}/`.
|
|
53
|
+
* Emit `{routeBase}/index.html` → defaultLocale landing (for /d/ and /docs/).
|
|
60
54
|
* @param {import('./document-schema.js').DocumentManifest} manifest
|
|
61
55
|
* @param {string} outDir
|
|
62
|
-
* @param {string} projectRoot
|
|
63
56
|
*/
|
|
64
|
-
function writeMountRootRedirects(manifest, outDir
|
|
57
|
+
function writeMountRootRedirects(manifest, outDir) {
|
|
65
58
|
const defaultLocale = manifest.defaultLocale || manifest.locales?.[0];
|
|
66
59
|
if (!defaultLocale)
|
|
67
60
|
return;
|
|
68
|
-
const routing = loadLocalesRouting(projectRoot) || { strategy: 'prefix' };
|
|
69
61
|
for (const mount of manifest.mounts || []) {
|
|
70
62
|
if (!mount?.routeBase || mount.routeBase === '/')
|
|
71
63
|
continue;
|
|
72
64
|
const base = String(mount.routeBase).replace(/\/$/, '');
|
|
65
|
+
const target = `${base}/${defaultLocale}/`;
|
|
73
66
|
const relDir = base.replace(/^\//, '');
|
|
74
67
|
const abs = path.join(outDir, relDir, 'index.html');
|
|
75
68
|
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const html = native.generateRedirectHtml({
|
|
90
|
-
lang: defaultLocale,
|
|
91
|
-
target,
|
|
92
|
-
title: 'Documents',
|
|
93
|
-
});
|
|
69
|
+
const html = `<!DOCTYPE html>
|
|
70
|
+
<html lang="${escapeAttr(defaultLocale)}">
|
|
71
|
+
<head>
|
|
72
|
+
<meta charset="utf-8" />
|
|
73
|
+
<meta http-equiv="refresh" content="0;url=${escapeAttr(target)}" />
|
|
74
|
+
<link rel="canonical" href="${escapeAttr(target)}" />
|
|
75
|
+
<title>Documents</title>
|
|
76
|
+
</head>
|
|
77
|
+
<body>
|
|
78
|
+
<p><a href="${escapeAttr(target)}">Continue to ${escapeAttr(defaultLocale)} docs</a></p>
|
|
79
|
+
</body>
|
|
80
|
+
</html>
|
|
81
|
+
`;
|
|
94
82
|
fs.writeFileSync(abs, html, 'utf8');
|
|
95
83
|
}
|
|
96
84
|
}
|
|
85
|
+
/** @param {string} s */
|
|
86
|
+
function escapeAttr(s) {
|
|
87
|
+
return String(s).replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
88
|
+
}
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import crypto from 'node:crypto';
|
|
7
7
|
import fs from 'node:fs';
|
|
8
8
|
import path from 'node:path';
|
|
9
|
-
import { writePrettyJsonFile } from './pretty-json.js';
|
|
10
9
|
export const EMBEDDED_RESOURCE_INDEX_SCHEMA = 'vmz.embedded.resource_index.v0';
|
|
11
10
|
/** Paths that must never enter the embedded baseline closure. */
|
|
12
11
|
const SKIP_NAMES = new Set(['vmz-serve-host.mjs', 'vmz-serve-host.js', 'node_modules', '.git']);
|
|
@@ -56,7 +55,7 @@ export function emitEmbeddedPackaging(outDir, opts = {}) {
|
|
|
56
55
|
};
|
|
57
56
|
index.indexDigest = sha256Hex(canonicalJson({ ...index, indexDigest: undefined }));
|
|
58
57
|
const indexPath = path.join(vmzDir, 'embedded-resource-index.json');
|
|
59
|
-
|
|
58
|
+
fs.writeFileSync(indexPath, `${JSON.stringify(index, null, 2)}\n`, 'utf8');
|
|
60
59
|
// Optional include_bytes entry point for Rust packaging adapters
|
|
61
60
|
const rsPath = path.join(vmzDir, 'embedded_site.rs');
|
|
62
61
|
fs.writeFileSync(rsPath, `// @generated by vmz — rust-embedded packaging adapter (do not edit)
|
package/dist/index.d.ts
CHANGED
|
@@ -53,14 +53,6 @@ export declare function handshake(host?: {
|
|
|
53
53
|
* @returns {string | null}
|
|
54
54
|
*/
|
|
55
55
|
export declare function resolveCoreRuntimeDist(): string;
|
|
56
|
-
/** Runtime companions required by dist/vmz-serve-host.mjs relative imports. */
|
|
57
|
-
export declare const SERVE_HOST_RUNTIME_FILES: string[][];
|
|
58
|
-
/**
|
|
59
|
-
* Copy serve-host + registry bootstrap modules from `@vmz/core` into app outDir.
|
|
60
|
-
* @param {string} outDir
|
|
61
|
-
* @param {string} [coreDist]
|
|
62
|
-
*/
|
|
63
|
-
export declare function materializeServeHostRuntime(outDir: any, coreDist?: string): void;
|
|
64
56
|
/**
|
|
65
57
|
* @typedef {object} WorkspaceOptions
|
|
66
58
|
* @property {string} root
|
|
@@ -92,7 +84,6 @@ export declare function lowerMiniprogramBindingEventJson(rootPath: any): any;
|
|
|
92
84
|
export declare function lowerMiniprogramStructureJson(rootPath: any): any;
|
|
93
85
|
export declare function lowerMiniprogramRouteServerStyleJson(rootPath: any): any;
|
|
94
86
|
export declare function lowerMiniprogramToolingDeployJson(rootPath: any): any;
|
|
95
|
-
export declare function lowerMiniprogramWechatPackagingJson(rootPath: any): any;
|
|
96
87
|
export declare function lowerMiniprogramMultiAdapterJson(rootPath: any): any;
|
|
97
88
|
import { createMiniHost } from './mini-host.js';
|
|
98
89
|
export { createMiniHost };
|
|
@@ -155,7 +146,6 @@ export declare function checkApplicationHostCompositionJson(hostRoot: any, packa
|
|
|
155
146
|
*/
|
|
156
147
|
export declare function checkApplicationDevTestDeployJson(hostRoot: any, packageRoots: any, dirtyPaths?: any[]): any;
|
|
157
148
|
export { createDevSession, listWatchedFiles, srcFingerprint } from './dev-session.js';
|
|
158
|
-
export { coalesceRootBurst, collectDevWatchRoots, mergeDirtySets, localLinkDependencyRoots, watchRootForSourceFile, } from './dev-watch-roots.js';
|
|
159
149
|
export { findAvailablePort } from './port.js';
|
|
160
150
|
export { runCli, parseArgs, printHelp, printGlobalHelp, printProjectHelp } from './cli.js';
|
|
161
151
|
export { findNearestProjectVmz, getInvocationContext, isGlobalAllowedCommand, isUnderNodeModules, resolveThisPackageRoot, resolveVmzBin, gateGlobalProjectCommand, } from './invocation.js';
|
|
@@ -171,8 +161,7 @@ export { CDN_POLICY_MANIFEST_SCHEMA, CDN_ADAPTER_PROJECTION_SCHEMA, CACHE_HTML,
|
|
|
171
161
|
export { SITE_DELIVERY_CONTRACT_SCHEMA, SITE_DELIVERY_RESOLUTION_SCHEMA, defineSite, normalizeSiteDelivery, normalizeSourceProbe, resolveSiteRelease, probeReleaseDirectory, emitSiteDelivery, } from './site-delivery.js';
|
|
172
162
|
export { EMBEDDED_RESOURCE_INDEX_SCHEMA, emitEmbeddedPackaging, } from './embedded-packaging.js';
|
|
173
163
|
export { SERVER_LANG_IDS, SERVER_LANG_ALIASES, SERVER_LANGUAGE_BACKENDS, resolveServerLanguage, assertLangRuntimePair, } from './server-language-backend.js';
|
|
174
|
-
export {
|
|
175
|
-
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, pickDeliveryPackaging, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
164
|
+
export { DELIVERY_PROFILE_AUTHORING_SCHEMA, BUILD_PROFILE_SELECTION_SCHEMA, ASSEMBLIES, SERVER_RUNTIMES, BUILTIN_PROFILES, pickSiteAuthoring, normalizeDeliveryAuthoring, selectBuildProfile, semanticIdsForAssembly, } from './delivery-profile.js';
|
|
176
165
|
export { PACK_MANIFEST_SCHEMA, packFromDeploymentIr, ensureRuntimeCompanions } from './pack.js';
|
|
177
166
|
export { SERVER_ARTIFACT_SCHEMA, HTTP_CONTRACT_SCHEMA, SERVER_RUNTIME_ADAPTER_SCHEMA, emitServerArtifact, projectServerRuntimeAdapter, } from './server-artifact.js';
|
|
178
167
|
export { BUILD_PROOF_SCHEMA, ASSEMBLE_MANIFEST_SCHEMA, assembleDelivery, emitBuildProof, } from './build-assemble.js';
|
|
@@ -242,8 +231,6 @@ declare const _default: {
|
|
|
242
231
|
expectedProtocol: typeof expectedProtocol;
|
|
243
232
|
resolveNativePath: typeof resolveNativePath;
|
|
244
233
|
resolveCoreRuntimeDist: typeof resolveCoreRuntimeDist;
|
|
245
|
-
materializeServeHostRuntime: typeof materializeServeHostRuntime;
|
|
246
|
-
SERVE_HOST_RUNTIME_FILES: string[][];
|
|
247
234
|
loadNative: typeof loadNative;
|
|
248
235
|
getProtocolVersions: typeof getProtocolVersions;
|
|
249
236
|
handshake: typeof handshake;
|
|
@@ -257,7 +244,6 @@ declare const _default: {
|
|
|
257
244
|
lowerMiniprogramStructureJson: typeof lowerMiniprogramStructureJson;
|
|
258
245
|
lowerMiniprogramRouteServerStyleJson: typeof lowerMiniprogramRouteServerStyleJson;
|
|
259
246
|
lowerMiniprogramToolingDeployJson: typeof lowerMiniprogramToolingDeployJson;
|
|
260
|
-
lowerMiniprogramWechatPackagingJson: typeof lowerMiniprogramWechatPackagingJson;
|
|
261
247
|
lowerMiniprogramMultiAdapterJson: typeof lowerMiniprogramMultiAdapterJson;
|
|
262
248
|
createMiniHost: typeof createMiniHost;
|
|
263
249
|
queryProfileProtocolCatalog: typeof queryProfileProtocolCatalog;
|