docusaurus-plugin-docusynx 0.1.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 +201 -0
- package/README.md +81 -0
- package/dist/assets.d.ts +7 -0
- package/dist/assets.js +46 -0
- package/dist/canonical.d.ts +2 -0
- package/dist/canonical.js +21 -0
- package/dist/discover.d.ts +24 -0
- package/dist/discover.js +335 -0
- package/dist/html.d.ts +22 -0
- package/dist/html.js +329 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/markdown.d.ts +11 -0
- package/dist/markdown.js +334 -0
- package/dist/plugin.d.ts +24 -0
- package/dist/plugin.js +355 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.js +3 -0
- package/package.json +74 -0
- package/schema/document-bundle.schema.json +234 -0
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { AssetCollector } from './assets.js';
|
|
5
|
+
import { canonicalJson, contentHash } from './canonical.js';
|
|
6
|
+
import { discoverDocuments, matchesRoutePattern, normalizeRoute, readRenderedRoute, } from './discover.js';
|
|
7
|
+
import { renderedHtmlLinkSemantics, renderedHtmlToBlocks, } from './html.js';
|
|
8
|
+
import { loadComponentHandlers, markdownToBlocks } from './markdown.js';
|
|
9
|
+
export default function docusynxPlugin(context, options = {}) {
|
|
10
|
+
let allContent = {};
|
|
11
|
+
return {
|
|
12
|
+
name: 'docusaurus-plugin-docusynx',
|
|
13
|
+
allContentLoaded({ allContent: loadedContent }) {
|
|
14
|
+
allContent = loadedContent;
|
|
15
|
+
},
|
|
16
|
+
async postBuild({ outDir, routesPaths = [], siteConfig }) {
|
|
17
|
+
const strict = options.strict !== false;
|
|
18
|
+
const siteBaseUrl = `${siteConfig.url ?? context.siteConfig.url ?? ''}${siteConfig.baseUrl ?? context.siteConfig.baseUrl ?? '/'}`;
|
|
19
|
+
const outputDirectory = path.resolve(outDir, options.outputDirectory ?? 'docusynx');
|
|
20
|
+
await mkdir(outputDirectory, { recursive: true });
|
|
21
|
+
const assets = new AssetCollector(outputDirectory);
|
|
22
|
+
const handlers = await loadComponentHandlers(options.componentHandlers ?? []);
|
|
23
|
+
const candidates = await discoverDocuments({
|
|
24
|
+
allContent,
|
|
25
|
+
routePaths: routesPaths,
|
|
26
|
+
siteDir: context.siteDir,
|
|
27
|
+
outDir,
|
|
28
|
+
options,
|
|
29
|
+
});
|
|
30
|
+
const documents = [];
|
|
31
|
+
const renderedLinks = new Map();
|
|
32
|
+
for (const candidate of candidates) {
|
|
33
|
+
let title = candidate.title;
|
|
34
|
+
let blocks;
|
|
35
|
+
let rendered;
|
|
36
|
+
let renderedHtml;
|
|
37
|
+
if (strict ||
|
|
38
|
+
candidate.forceRendered ||
|
|
39
|
+
(!candidate.syntheticBlocks &&
|
|
40
|
+
!candidate.sourceAbsolutePath)) {
|
|
41
|
+
try {
|
|
42
|
+
renderedHtml = await readRenderedRoute(outDir, candidate.route);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (!candidate.syntheticBlocks)
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (strict && renderedHtml)
|
|
50
|
+
renderedLinks.set(candidate.id, renderedHtmlLinkSemantics({
|
|
51
|
+
html: renderedHtml,
|
|
52
|
+
selectors: options.htmlContentSelectors,
|
|
53
|
+
}));
|
|
54
|
+
if (renderedHtml &&
|
|
55
|
+
(candidate.forceRendered ||
|
|
56
|
+
(!candidate.syntheticBlocks &&
|
|
57
|
+
!candidate.sourceAbsolutePath)))
|
|
58
|
+
rendered = await renderedHtmlToBlocks({
|
|
59
|
+
html: renderedHtml,
|
|
60
|
+
outDir,
|
|
61
|
+
baseUrl: siteConfig.baseUrl ?? '/',
|
|
62
|
+
assets,
|
|
63
|
+
selectors: options.htmlContentSelectors,
|
|
64
|
+
route: candidate.route,
|
|
65
|
+
strict,
|
|
66
|
+
});
|
|
67
|
+
if (candidate.syntheticBlocks) {
|
|
68
|
+
blocks = candidate.syntheticBlocks;
|
|
69
|
+
}
|
|
70
|
+
else if (candidate.forceRendered) {
|
|
71
|
+
if (!rendered)
|
|
72
|
+
throw new Error(`no rendered HTML found for route ${candidate.route}`);
|
|
73
|
+
title = rendered.title ?? title;
|
|
74
|
+
blocks = rendered.blocks;
|
|
75
|
+
}
|
|
76
|
+
else if (candidate.sourceAbsolutePath) {
|
|
77
|
+
const parsed = matter(await readFile(candidate.sourceAbsolutePath, 'utf8'));
|
|
78
|
+
blocks = await markdownToBlocks({
|
|
79
|
+
source: parsed.content,
|
|
80
|
+
siteDir: context.siteDir,
|
|
81
|
+
sourcePath: candidate.sourcePath,
|
|
82
|
+
assets,
|
|
83
|
+
handlers,
|
|
84
|
+
strict,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
if (!rendered)
|
|
89
|
+
throw new Error(`no rendered HTML found for route ${candidate.route}`);
|
|
90
|
+
title = rendered.title ?? title;
|
|
91
|
+
blocks = rendered.blocks;
|
|
92
|
+
}
|
|
93
|
+
const mappedSourcePath = sourcePathMapping(candidate.route, options.sourcePathMappings ?? []);
|
|
94
|
+
const sourcePath = mappedSourcePath ??
|
|
95
|
+
(candidate.sourcePathIsRepositoryRelative
|
|
96
|
+
? candidate.sourcePath
|
|
97
|
+
.replaceAll('\\', '/')
|
|
98
|
+
.replace(/^\.\//, '')
|
|
99
|
+
: prefixedSourcePath(candidate.sourcePath, options.sourcePathPrefix));
|
|
100
|
+
const source = {
|
|
101
|
+
path: sourcePath,
|
|
102
|
+
...sourceUrl(sourcePath, options),
|
|
103
|
+
...(options.sourceCommit
|
|
104
|
+
? { commit: options.sourceCommit }
|
|
105
|
+
: {}),
|
|
106
|
+
};
|
|
107
|
+
const withoutHash = {
|
|
108
|
+
id: candidate.id,
|
|
109
|
+
title,
|
|
110
|
+
route: normalizeRoute(candidate.route),
|
|
111
|
+
...(candidate.parentId
|
|
112
|
+
? { parentId: candidate.parentId }
|
|
113
|
+
: {}),
|
|
114
|
+
order: candidate.order,
|
|
115
|
+
source,
|
|
116
|
+
blocks,
|
|
117
|
+
};
|
|
118
|
+
documents.push({
|
|
119
|
+
...withoutHash,
|
|
120
|
+
hash: contentHash(withoutHash),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
resolveDocumentLinks(documents, siteBaseUrl);
|
|
124
|
+
if (strict)
|
|
125
|
+
validateRenderedLinkParity({
|
|
126
|
+
documents,
|
|
127
|
+
renderedLinks,
|
|
128
|
+
siteBaseUrl,
|
|
129
|
+
});
|
|
130
|
+
for (const document of documents) {
|
|
131
|
+
const { hash: _oldHash, ...withoutHash } = document;
|
|
132
|
+
document.hash = contentHash(withoutHash);
|
|
133
|
+
}
|
|
134
|
+
documents.sort((left, right) => compareStrings(left.id, right.id));
|
|
135
|
+
const site = {
|
|
136
|
+
name: options.siteName ??
|
|
137
|
+
context.siteConfig.title ??
|
|
138
|
+
'Docusaurus',
|
|
139
|
+
baseUrl: siteBaseUrl,
|
|
140
|
+
...(options.sourceBaseUrl
|
|
141
|
+
? { sourceBaseUrl: options.sourceBaseUrl }
|
|
142
|
+
: {}),
|
|
143
|
+
...(options.sourceCommit
|
|
144
|
+
? { sourceCommit: options.sourceCommit }
|
|
145
|
+
: {}),
|
|
146
|
+
};
|
|
147
|
+
const withoutHash = {
|
|
148
|
+
schemaVersion: 1,
|
|
149
|
+
site,
|
|
150
|
+
documents,
|
|
151
|
+
assets: assets.values(),
|
|
152
|
+
};
|
|
153
|
+
const bundle = {
|
|
154
|
+
...withoutHash,
|
|
155
|
+
hash: contentHash(withoutHash),
|
|
156
|
+
};
|
|
157
|
+
await writeFile(path.join(outputDirectory, 'manifest.json'), `${canonicalJson(bundle)}\n`, 'utf8');
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function compareStrings(left, right) {
|
|
162
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
163
|
+
}
|
|
164
|
+
function prefixedSourcePath(sourcePath, prefix) {
|
|
165
|
+
const normalized = sourcePath.replaceAll('\\', '/').replace(/^\.\//, '');
|
|
166
|
+
if (!prefix || path.isAbsolute(normalized))
|
|
167
|
+
return normalized;
|
|
168
|
+
return `${prefix.replace(/^\/+|\/+$/g, '')}/${normalized}`;
|
|
169
|
+
}
|
|
170
|
+
function sourcePathMapping(route, mappings) {
|
|
171
|
+
const normalizedRoute = normalizeRoute(route);
|
|
172
|
+
const matches = mappings.filter((mapping) => matchesRoutePattern(normalizedRoute, mapping.routePattern));
|
|
173
|
+
if (matches.length > 1) {
|
|
174
|
+
throw new Error(`route ${normalizedRoute} matches multiple sourcePathMappings: ${matches.map((mapping) => mapping.routePattern).join(', ')}`);
|
|
175
|
+
}
|
|
176
|
+
const sourcePath = matches[0]?.sourcePath;
|
|
177
|
+
if (!sourcePath)
|
|
178
|
+
return undefined;
|
|
179
|
+
if (path.isAbsolute(sourcePath) || sourcePath.split('/').includes('..')) {
|
|
180
|
+
throw new Error(`sourcePathMappings sourcePath must be repository-relative: ${sourcePath}`);
|
|
181
|
+
}
|
|
182
|
+
return sourcePath.replaceAll('\\', '/').replace(/^\.\//, '');
|
|
183
|
+
}
|
|
184
|
+
function sourceUrl(sourcePath, options) {
|
|
185
|
+
if (sourcePath.startsWith('.docusynx/') ||
|
|
186
|
+
sourcePath.includes('/.docusynx/') ||
|
|
187
|
+
sourcePath.startsWith('.docusaurus/') ||
|
|
188
|
+
sourcePath.includes('/.docusaurus/') ||
|
|
189
|
+
sourcePath.includes('/.generated/'))
|
|
190
|
+
return {};
|
|
191
|
+
const template = options.sourceUrlTemplate ??
|
|
192
|
+
(options.sourceBaseUrl && options.sourceCommit
|
|
193
|
+
? `${options.sourceBaseUrl.replace(/\/$/, '')}/-/blob/{commit}/{path}`
|
|
194
|
+
: undefined);
|
|
195
|
+
if (!template)
|
|
196
|
+
return {};
|
|
197
|
+
return {
|
|
198
|
+
url: template
|
|
199
|
+
.replaceAll('{commit}', encodeURIComponent(options.sourceCommit ?? ''))
|
|
200
|
+
.replaceAll('{path}', sourcePath.split('/').map(encodeURIComponent).join('/')),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function resolveDocumentLinks(documents, siteBaseUrl) {
|
|
204
|
+
const index = documentLinkIndex(documents, siteBaseUrl);
|
|
205
|
+
for (const document of documents) {
|
|
206
|
+
visitBlocks(document.blocks, (inline) => {
|
|
207
|
+
if (inline.type !== 'link' || inline.target.kind !== 'url')
|
|
208
|
+
return;
|
|
209
|
+
const raw = inline.target.value;
|
|
210
|
+
const target = documentTarget(raw, document, index);
|
|
211
|
+
if (target) {
|
|
212
|
+
inline.target = target;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
if (!raw || /^(?:[a-z]+:|#)/i.test(raw))
|
|
216
|
+
return;
|
|
217
|
+
inline.target.value = absoluteDocusaurusUrl(raw, document, index);
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function documentLinkIndex(documents, siteBaseUrl) {
|
|
222
|
+
const byRoute = new Map();
|
|
223
|
+
const bySource = new Map();
|
|
224
|
+
for (const document of documents) {
|
|
225
|
+
byRoute.set(normalizeRoute(document.route), document.id);
|
|
226
|
+
bySource.set(stripExtension(document.source.path), document.id);
|
|
227
|
+
}
|
|
228
|
+
const siteUrl = new URL(siteBaseUrl || '/', 'https://docusynx.invalid/');
|
|
229
|
+
return {
|
|
230
|
+
byRoute,
|
|
231
|
+
bySource,
|
|
232
|
+
siteUrl,
|
|
233
|
+
routePrefix: normalizeRoute(siteUrl.pathname),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
function documentTarget(raw, document, index) {
|
|
237
|
+
if (!raw || raw.startsWith('#'))
|
|
238
|
+
return undefined;
|
|
239
|
+
let resolved;
|
|
240
|
+
try {
|
|
241
|
+
resolved = new URL(raw, documentUrl(document, index));
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
if (!['http:', 'https:'].includes(resolved.protocol))
|
|
247
|
+
return undefined;
|
|
248
|
+
if (resolved.origin !== index.siteUrl.origin)
|
|
249
|
+
return undefined;
|
|
250
|
+
for (const route of linkRouteCandidates(resolved.pathname, index)) {
|
|
251
|
+
const targetId = index.byRoute.get(route);
|
|
252
|
+
if (targetId)
|
|
253
|
+
return { kind: 'document', value: targetId };
|
|
254
|
+
}
|
|
255
|
+
if (/^(?:[a-z]+:|\/\/)/i.test(raw))
|
|
256
|
+
return undefined;
|
|
257
|
+
const withoutAnchor = raw.split(/[?#]/)[0] ?? raw;
|
|
258
|
+
const sourcePath = stripExtension(path.posix.normalize(path.posix.join(path.posix.dirname(document.source.path), withoutAnchor)));
|
|
259
|
+
const targetId = index.bySource.get(sourcePath);
|
|
260
|
+
return targetId ? { kind: 'document', value: targetId } : undefined;
|
|
261
|
+
}
|
|
262
|
+
function linkRouteCandidates(pathname, index) {
|
|
263
|
+
const candidates = new Set([normalizeRoute(pathname)]);
|
|
264
|
+
const prefix = index.routePrefix;
|
|
265
|
+
if (prefix !== '/' && normalizeRoute(pathname).startsWith(prefix)) {
|
|
266
|
+
candidates.add(normalizeRoute(normalizeRoute(pathname).slice(prefix.length)));
|
|
267
|
+
}
|
|
268
|
+
return [...candidates];
|
|
269
|
+
}
|
|
270
|
+
function documentUrl(document, index) {
|
|
271
|
+
const prefix = index.routePrefix === '/'
|
|
272
|
+
? ''
|
|
273
|
+
: index.routePrefix.replace(/\/$/, '');
|
|
274
|
+
return new URL(`${prefix}${normalizeRoute(document.route)}`, index.siteUrl);
|
|
275
|
+
}
|
|
276
|
+
function absoluteDocusaurusUrl(raw, document, index) {
|
|
277
|
+
if (raw.startsWith('//'))
|
|
278
|
+
return new URL(raw, index.siteUrl).href;
|
|
279
|
+
if (raw.startsWith('/') &&
|
|
280
|
+
index.routePrefix !== '/' &&
|
|
281
|
+
!normalizeRoute(raw).startsWith(index.routePrefix)) {
|
|
282
|
+
const prefix = index.routePrefix.replace(/\/$/, '');
|
|
283
|
+
return new URL(`${prefix}${raw}`, index.siteUrl.origin).href;
|
|
284
|
+
}
|
|
285
|
+
return new URL(raw, documentUrl(document, index)).href;
|
|
286
|
+
}
|
|
287
|
+
function validateRenderedLinkParity(input) {
|
|
288
|
+
const index = documentLinkIndex(input.documents, input.siteBaseUrl);
|
|
289
|
+
for (const document of input.documents) {
|
|
290
|
+
const rendered = input.renderedLinks.get(document.id);
|
|
291
|
+
if (!rendered)
|
|
292
|
+
continue;
|
|
293
|
+
const expected = new Map();
|
|
294
|
+
for (const link of rendered) {
|
|
295
|
+
const target = documentTarget(link.href, document, index);
|
|
296
|
+
if (target)
|
|
297
|
+
appendLinkText(expected, target.value, link.text);
|
|
298
|
+
}
|
|
299
|
+
const actual = new Map();
|
|
300
|
+
visitBlocks(document.blocks, (inline) => {
|
|
301
|
+
if (inline.type === 'link' && inline.target.kind === 'document')
|
|
302
|
+
appendLinkText(actual, inline.target.value, inlineText(inline.children));
|
|
303
|
+
});
|
|
304
|
+
const expectedSummary = linkTextSummary(expected);
|
|
305
|
+
const actualSummary = linkTextSummary(actual);
|
|
306
|
+
if (JSON.stringify(expectedSummary) === JSON.stringify(actualSummary))
|
|
307
|
+
continue;
|
|
308
|
+
throw new Error(`rendered internal link parity failed for route ${document.route}: expected ${JSON.stringify(expectedSummary)} but exported ${JSON.stringify(actualSummary)}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function appendLinkText(links, targetId, text) {
|
|
312
|
+
const values = links.get(targetId) ?? [];
|
|
313
|
+
values.push(text);
|
|
314
|
+
links.set(targetId, values);
|
|
315
|
+
}
|
|
316
|
+
function linkTextSummary(links) {
|
|
317
|
+
return [...links.entries()]
|
|
318
|
+
.sort(([left], [right]) => compareStrings(left, right))
|
|
319
|
+
.map(([targetId, text]) => ({
|
|
320
|
+
targetId,
|
|
321
|
+
text: normalizeLinkText(text.join('')),
|
|
322
|
+
}));
|
|
323
|
+
}
|
|
324
|
+
function inlineText(inlines) {
|
|
325
|
+
return inlines
|
|
326
|
+
.map((inline) => inline.type === 'text' ? inline.value : inlineText(inline.children))
|
|
327
|
+
.join('');
|
|
328
|
+
}
|
|
329
|
+
function normalizeLinkText(value) {
|
|
330
|
+
return value.replace(/\s+/g, '');
|
|
331
|
+
}
|
|
332
|
+
function visitBlocks(blocks, callback) {
|
|
333
|
+
const visitInlines = (inlines) => {
|
|
334
|
+
for (const inline of inlines) {
|
|
335
|
+
callback(inline);
|
|
336
|
+
if (inline.type === 'link')
|
|
337
|
+
visitInlines(inline.children);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
for (const block of blocks) {
|
|
341
|
+
if (block.type === 'paragraph' || block.type === 'heading')
|
|
342
|
+
visitInlines(block.inlines);
|
|
343
|
+
else if (block.type === 'table') {
|
|
344
|
+
block.header.forEach(visitInlines);
|
|
345
|
+
block.rows.flat().forEach(visitInlines);
|
|
346
|
+
}
|
|
347
|
+
else if (block.type === 'list')
|
|
348
|
+
block.items.forEach((item) => visitBlocks(item, callback));
|
|
349
|
+
else if (block.type === 'admonition')
|
|
350
|
+
visitBlocks(block.blocks, callback);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function stripExtension(value) {
|
|
354
|
+
return value.replace(/\.(?:md|mdx)$/i, '').replace(/\/index$/i, '');
|
|
355
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
export interface MdxAstNode {
|
|
2
|
+
type: string;
|
|
3
|
+
name?: string | null;
|
|
4
|
+
value?: string;
|
|
5
|
+
children?: MdxAstNode[];
|
|
6
|
+
attributes?: Array<{
|
|
7
|
+
name?: string;
|
|
8
|
+
type: string;
|
|
9
|
+
value?: unknown;
|
|
10
|
+
}>;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export type TextMark = 'bold' | 'italic' | 'strikethrough' | 'code';
|
|
14
|
+
export interface TextInline {
|
|
15
|
+
type: 'text';
|
|
16
|
+
value: string;
|
|
17
|
+
marks?: TextMark[];
|
|
18
|
+
}
|
|
19
|
+
export interface LinkInline {
|
|
20
|
+
type: 'link';
|
|
21
|
+
target: {
|
|
22
|
+
kind: 'url' | 'document';
|
|
23
|
+
value: string;
|
|
24
|
+
};
|
|
25
|
+
children: Inline[];
|
|
26
|
+
}
|
|
27
|
+
export type Inline = TextInline | LinkInline;
|
|
28
|
+
export type Block = {
|
|
29
|
+
type: 'paragraph';
|
|
30
|
+
inlines: Inline[];
|
|
31
|
+
} | {
|
|
32
|
+
type: 'heading';
|
|
33
|
+
level: number;
|
|
34
|
+
inlines: Inline[];
|
|
35
|
+
} | {
|
|
36
|
+
type: 'code';
|
|
37
|
+
language?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
value: string;
|
|
40
|
+
} | {
|
|
41
|
+
type: 'mermaid';
|
|
42
|
+
value: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'list';
|
|
45
|
+
ordered: boolean;
|
|
46
|
+
items: Block[][];
|
|
47
|
+
} | {
|
|
48
|
+
type: 'table';
|
|
49
|
+
header: Inline[][];
|
|
50
|
+
rows: Inline[][][];
|
|
51
|
+
} | {
|
|
52
|
+
type: 'admonition';
|
|
53
|
+
kind: string;
|
|
54
|
+
title?: string;
|
|
55
|
+
blocks: Block[];
|
|
56
|
+
} | {
|
|
57
|
+
type: 'image';
|
|
58
|
+
assetId: string;
|
|
59
|
+
alt?: string;
|
|
60
|
+
title?: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'thematicBreak';
|
|
63
|
+
} | {
|
|
64
|
+
type: 'extension';
|
|
65
|
+
name: string;
|
|
66
|
+
data: unknown;
|
|
67
|
+
};
|
|
68
|
+
export interface BundleSource {
|
|
69
|
+
path: string;
|
|
70
|
+
url?: string;
|
|
71
|
+
commit?: string;
|
|
72
|
+
}
|
|
73
|
+
export interface BundleDocument {
|
|
74
|
+
id: string;
|
|
75
|
+
title: string;
|
|
76
|
+
route: string;
|
|
77
|
+
parentId?: string;
|
|
78
|
+
order: number;
|
|
79
|
+
source: BundleSource;
|
|
80
|
+
blocks: Block[];
|
|
81
|
+
hash: string;
|
|
82
|
+
}
|
|
83
|
+
export interface BundleAsset {
|
|
84
|
+
id: string;
|
|
85
|
+
path: string;
|
|
86
|
+
mimeType: string;
|
|
87
|
+
hash: string;
|
|
88
|
+
}
|
|
89
|
+
export interface DocumentBundle {
|
|
90
|
+
schemaVersion: 1;
|
|
91
|
+
site: {
|
|
92
|
+
name: string;
|
|
93
|
+
baseUrl: string;
|
|
94
|
+
sourceBaseUrl?: string;
|
|
95
|
+
sourceCommit?: string;
|
|
96
|
+
};
|
|
97
|
+
documents: BundleDocument[];
|
|
98
|
+
assets: BundleAsset[];
|
|
99
|
+
hash: string;
|
|
100
|
+
}
|
|
101
|
+
export interface ComponentHandlerAssetInput {
|
|
102
|
+
path: string;
|
|
103
|
+
mimeType?: string;
|
|
104
|
+
}
|
|
105
|
+
export interface ComponentHandlerContext {
|
|
106
|
+
readonly node: MdxAstNode;
|
|
107
|
+
readonly props: Readonly<Record<string, unknown>>;
|
|
108
|
+
readonly children: readonly MdxAstNode[];
|
|
109
|
+
readonly siteDir: string;
|
|
110
|
+
readonly sourcePath: string;
|
|
111
|
+
readSiteFile(path: string): Promise<string>;
|
|
112
|
+
addAsset(input: ComponentHandlerAssetInput): Promise<string>;
|
|
113
|
+
transformChildren(): Promise<Block[]>;
|
|
114
|
+
}
|
|
115
|
+
export interface ComponentHandler {
|
|
116
|
+
transform(context: ComponentHandlerContext): Block | Block[] | Promise<Block | Block[]>;
|
|
117
|
+
}
|
|
118
|
+
export interface ComponentHandlerRegistration {
|
|
119
|
+
importSource: string;
|
|
120
|
+
exportName: string;
|
|
121
|
+
handler: string | ComponentHandler;
|
|
122
|
+
}
|
|
123
|
+
export interface PluginOptions {
|
|
124
|
+
siteName?: string;
|
|
125
|
+
outputDirectory?: string;
|
|
126
|
+
sourceBaseUrl?: string;
|
|
127
|
+
sourceCommit?: string;
|
|
128
|
+
sourcePathPrefix?: string;
|
|
129
|
+
sourceUrlTemplate?: string;
|
|
130
|
+
sourcePathMappings?: Array<{
|
|
131
|
+
routePattern: string;
|
|
132
|
+
sourcePath: string;
|
|
133
|
+
}>;
|
|
134
|
+
strict?: boolean;
|
|
135
|
+
componentHandlers?: ComponentHandlerRegistration[];
|
|
136
|
+
renderedRoutePatterns?: string[];
|
|
137
|
+
excludeRoutePatterns?: string[];
|
|
138
|
+
htmlContentSelectors?: string[];
|
|
139
|
+
}
|
|
140
|
+
export declare function defineComponentHandler(handler: ComponentHandler): ComponentHandler;
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "docusaurus-plugin-docusynx",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Export a deterministic Docusaurus document bundle for docusynx",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/dieend/docusynx.git",
|
|
9
|
+
"directory": "packages/docusaurus-plugin-docusynx"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/dieend/docusynx#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/dieend/docusynx/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"confluence",
|
|
17
|
+
"docusaurus",
|
|
18
|
+
"documentation",
|
|
19
|
+
"wiki"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./schema": "./schema/document-bundle.schema.json"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"schema",
|
|
35
|
+
"README.md"
|
|
36
|
+
],
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@docusaurus/core": "^3.10.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"@docusaurus/core": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public",
|
|
50
|
+
"registry": "https://registry.npmjs.org/"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"cheerio": "1.0.0",
|
|
54
|
+
"domhandler": "5.0.3",
|
|
55
|
+
"gray-matter": "4.0.3",
|
|
56
|
+
"mdast-util-to-string": "4.0.0",
|
|
57
|
+
"remark-directive": "4.0.0",
|
|
58
|
+
"remark-frontmatter": "5.0.0",
|
|
59
|
+
"remark-gfm": "4.0.1",
|
|
60
|
+
"remark-mdx": "3.1.1",
|
|
61
|
+
"remark-parse": "11.0.0",
|
|
62
|
+
"unified": "11.0.5"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "22.15.3",
|
|
66
|
+
"typescript": "5.8.3",
|
|
67
|
+
"vitest": "3.1.2"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"build": "tsc -p tsconfig.build.json",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
73
|
+
}
|
|
74
|
+
}
|