docusaurus-plugin-docusynx 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -59,6 +59,10 @@ export default defineComponentHandler({
59
59
  The handler key is the exact `importSource` and `exportName`. An unknown imported
60
60
  MDX component stops the build. The plugin does not execute an unknown component.
61
61
 
62
+ Mermaid rendering is included. Excalidraw rendering requires the optional
63
+ `@excalidraw/utils@0.1.5` peer dependency. Install it only when the documentation
64
+ contains an Excalidraw diagram that Docusynx must render.
65
+
62
66
  `sourcePathPrefix` changes site-relative paths into repository-relative paths.
63
67
  The `source_path` or `docusynx_source_path` frontmatter field overrides the path
64
68
  with an already repository-relative value. The prefix is not applied to an
package/dist/assets.d.ts CHANGED
@@ -3,5 +3,6 @@ export declare class AssetCollector {
3
3
  #private;
4
4
  constructor(outputDirectory: string);
5
5
  add(sourcePath: string, mimeType?: string): Promise<string>;
6
+ addBytes(content: string | Uint8Array, extension: string, mimeType?: string): Promise<string>;
6
7
  values(): BundleAsset[];
7
8
  }
package/dist/assets.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { copyFile, mkdir, readFile } from 'node:fs/promises';
2
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
+ import { assertSafeSvg } from './svg.js';
4
5
  const MIME_BY_EXTENSION = {
5
6
  '.gif': 'image/gif',
6
7
  '.jpeg': 'image/jpeg',
@@ -17,21 +18,47 @@ export class AssetCollector {
17
18
  }
18
19
  async add(sourcePath, mimeType) {
19
20
  const bytes = await readFile(sourcePath);
21
+ return this.addBytes(bytes, path.extname(sourcePath).toLowerCase(), mimeType);
22
+ }
23
+ async addBytes(content, extension, mimeType) {
24
+ if (!/^\.[a-z0-9]+$/.test(extension)) {
25
+ throw new Error(`invalid asset extension ${JSON.stringify(extension)}`);
26
+ }
27
+ const bytes = typeof content === 'string' ? Buffer.from(content, 'utf8') : content;
20
28
  const digest = createHash('sha256').update(bytes).digest('hex');
21
- const extension = path.extname(sourcePath).toLowerCase();
22
29
  const id = `sha256:${digest}`;
23
30
  const relativePath = `assets/${digest}${extension}`;
24
- if (!this.#assets.has(id)) {
31
+ const resolvedMimeType = mimeType ??
32
+ MIME_BY_EXTENSION[extension] ??
33
+ 'application/octet-stream';
34
+ if (extension === '.svg' ||
35
+ resolvedMimeType.split(';', 1)[0]?.trim().toLowerCase() ===
36
+ 'image/svg+xml') {
37
+ let svg;
38
+ try {
39
+ svg = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
40
+ }
41
+ catch {
42
+ throw new Error('unsafe SVG content: invalid UTF-8');
43
+ }
44
+ assertSafeSvg(svg);
45
+ }
46
+ const existing = this.#assets.get(id);
47
+ if (existing) {
48
+ if (existing.path !== relativePath ||
49
+ existing.mimeType !== resolvedMimeType) {
50
+ throw new Error(`asset metadata conflicts for ${id}`);
51
+ }
52
+ }
53
+ else {
25
54
  await mkdir(path.join(this.#outputDirectory, 'assets'), {
26
55
  recursive: true,
27
56
  });
28
- await copyFile(sourcePath, path.join(this.#outputDirectory, relativePath));
57
+ await writeFile(path.join(this.#outputDirectory, relativePath), bytes);
29
58
  this.#assets.set(id, {
30
59
  id,
31
60
  path: relativePath,
32
- mimeType: mimeType ??
33
- MIME_BY_EXTENSION[extension] ??
34
- 'application/octet-stream',
61
+ mimeType: resolvedMimeType,
35
62
  hash: id,
36
63
  });
37
64
  }
package/dist/markdown.js CHANGED
@@ -184,7 +184,9 @@ async function transformComponent(node, context) {
184
184
  siteDir: context.siteDir,
185
185
  sourcePath: context.sourcePath,
186
186
  readSiteFile: async (requestedPath) => readFile(resolveSitePath(context.siteDir, requestedPath), 'utf8'),
187
- addAsset: async (input) => context.assets.add(resolveSitePath(context.siteDir, input.path), input.mimeType),
187
+ addAsset: async (input) => 'path' in input
188
+ ? context.assets.add(resolveSitePath(context.siteDir, input.path), input.mimeType)
189
+ : context.assets.addBytes(input.content, input.extension, input.mimeType),
188
190
  transformChildren: async () => transformBlockChildren(children, context),
189
191
  };
190
192
  const result = await handler.transform(handlerContext);
package/dist/types.d.ts CHANGED
@@ -98,10 +98,14 @@ export interface DocumentBundle {
98
98
  assets: BundleAsset[];
99
99
  hash: string;
100
100
  }
101
- export interface ComponentHandlerAssetInput {
101
+ export type ComponentHandlerAssetInput = {
102
102
  path: string;
103
103
  mimeType?: string;
104
- }
104
+ } | {
105
+ content: string | Uint8Array;
106
+ extension: '.svg';
107
+ mimeType: 'image/svg+xml';
108
+ };
105
109
  export interface ComponentHandlerContext {
106
110
  readonly node: MdxAstNode;
107
111
  readonly props: Readonly<Record<string, unknown>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-plugin-docusynx",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Export a deterministic Docusaurus document bundle for docusynx",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -38,11 +38,15 @@
38
38
  "node": ">=22.13"
39
39
  },
40
40
  "peerDependencies": {
41
- "@docusaurus/core": "^3.10.0"
41
+ "@docusaurus/core": "^3.10.0",
42
+ "@excalidraw/utils": "0.1.5"
42
43
  },
43
44
  "peerDependenciesMeta": {
44
45
  "@docusaurus/core": {
45
46
  "optional": true
47
+ },
48
+ "@excalidraw/utils": {
49
+ "optional": true
46
50
  }
47
51
  },
48
52
  "publishConfig": {
@@ -50,7 +54,6 @@
50
54
  "registry": "https://registry.npmjs.org/"
51
55
  },
52
56
  "dependencies": {
53
- "@excalidraw/utils": "0.1.5",
54
57
  "cheerio": "1.0.0",
55
58
  "css-tree": "2.3.1",
56
59
  "domhandler": "5.0.3",
@@ -68,6 +71,7 @@
68
71
  "unified": "11.0.5"
69
72
  },
70
73
  "devDependencies": {
74
+ "@excalidraw/utils": "0.1.5",
71
75
  "@types/jsdom": "21.1.7",
72
76
  "@types/node": "22.15.3",
73
77
  "@types/svgdom": "0.1.2",