@mermaid-js/mermaid-cli 11.14.0 → 11.16.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.
Files changed (77) hide show
  1. package/README.md +17 -11
  2. package/dist/index.html +0 -2
  3. package/dist-types/src/index.d.ts +19 -5
  4. package/dist-types/src/index.d.ts.map +1 -1
  5. package/dist-types/src/puppeteerIntercept.d.ts +17 -14
  6. package/dist-types/src/puppeteerIntercept.d.ts.map +1 -1
  7. package/dist-types/src/version.d.ts +1 -1
  8. package/dist-types/src/version.d.ts.map +1 -1
  9. package/package.json +22 -18
  10. package/src/cli.js +5 -3
  11. package/src/index.js +626 -303
  12. package/src/puppeteerIntercept.js +101 -54
  13. package/src/version.js +1 -1
  14. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  15. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  16. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  17. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  18. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  19. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  20. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  21. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  22. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  23. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  24. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  25. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  26. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  27. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  28. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  29. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  30. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  31. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  32. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  33. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  34. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  35. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  36. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  37. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  38. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  39. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  40. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  41. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  42. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  43. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  44. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  45. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  46. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  47. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  48. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  49. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  50. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  51. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  52. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  53. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  54. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  55. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  56. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  57. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  58. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  59. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  60. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  61. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  62. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  63. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  64. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  65. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  66. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  67. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  68. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  69. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  70. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  71. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  72. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  73. package/dist/assets/fa-brands-400-BdzBFuGj.woff2 +0 -0
  74. package/dist/assets/fa-regular-400-DQuI-phE.woff2 +0 -0
  75. package/dist/assets/fa-solid-900-BLm1ImsD.woff2 +0 -0
  76. package/dist/assets/index-DxLypzbC.js +0 -10
  77. package/src/index.js.bak +0 -540
@@ -2,9 +2,33 @@
2
2
  * @import puppeteer from 'puppeteer';
3
3
  */
4
4
 
5
- import { readFile, realpath } from 'node:fs/promises'
6
- import path from 'node:path'
7
- import url from 'node:url'
5
+ import { readFile, realpath } from "node:fs/promises";
6
+ import path from "node:path";
7
+ import url from "node:url";
8
+ import { DEFAULT_INTERCEPT_RESOLUTION_PRIORITY } from "puppeteer";
9
+
10
+ /**
11
+ * Guesses the MIME-type of a file based on its extension.
12
+ *
13
+ * I've hardcoded the bare minimum number of MIME-types to support for security reasons.
14
+ *
15
+ * @param {string} filePath - The file path to guess the MIME-type for.
16
+ */
17
+ function getContentTypeFromFileExtension(filePath) {
18
+ const ext = path.extname(filePath).toLowerCase();
19
+ switch (ext) {
20
+ case ".css":
21
+ // Make sure to set UTF-8, since sometimes Puppeteer can parse it as Latin-1.
22
+ return "text/css;charset=UTF-8";
23
+ case ".js":
24
+ case ".mjs":
25
+ return "application/javascript";
26
+ case ".woff2":
27
+ return "font/woff2";
28
+ default:
29
+ throw new Error(`Unsupported file extension for intercept: ${ext}`);
30
+ }
31
+ }
8
32
 
9
33
  /**
10
34
  * Puppeteer doesn't allow importing ESM modules from `file://` URLs.
@@ -13,79 +37,102 @@ import url from 'node:url'
13
37
  * instead intercepts dummy `https://mermaid-cli-intercept.invalid` requests.
14
38
  */
15
39
  export class Interceptor {
16
- #INTERCEPT_ORIGIN = 'https://mermaid-cli-intercept.invalid'
40
+ #INTERCEPT_ORIGIN = "https://mermaid-cli-intercept.invalid";
17
41
 
18
42
  /**
19
- * Set of allowed file directories that can be intercepted.
20
- *
21
- * This is used to prevent arbitrary file access through the intercept mechanism.
22
- *
23
- * Make sure to use `realpath` to resolve any symlinks.
24
- *
25
- * @type {Set<string>}
26
- */
27
- #allowedDirs = new Set()
43
+ * Set of allowed file directories that can be intercepted.
44
+ *
45
+ * This is used to prevent arbitrary file access through the intercept mechanism.
46
+ *
47
+ * Make sure to use `realpath` to resolve any symlinks.
48
+ *
49
+ * @type {Set<string>}
50
+ */
51
+ #allowedDirs = new Set();
28
52
 
29
53
  /**
30
- * @param {URL | `file://${string}`} fileUrl - File URL
31
- */
32
- async fileUrlToInterceptUrl (fileUrl) {
33
- fileUrl = new URL(fileUrl)
34
- if (fileUrl.protocol !== 'file:') {
35
- throw new Error(`Invalid file URL: ${fileUrl}`)
54
+ * @param {URL | `file://${string}`} fileUrl - File URL
55
+ * @param {Object} [options] - Optional options.
56
+ * @param {number} [options.allowParentDirectoryLevel] - Number of parent directory levels to allow access to.
57
+ */
58
+ async fileUrlToInterceptUrl(fileUrl, { allowParentDirectoryLevel = 1 } = {}) {
59
+ fileUrl = new URL(fileUrl);
60
+ if (fileUrl.protocol !== "file:") {
61
+ throw new Error(`Invalid file URL: ${fileUrl}`);
62
+ }
63
+ let parentDirectory = await realpath(url.fileURLToPath(fileUrl));
64
+ while (allowParentDirectoryLevel-- >= 0) {
65
+ parentDirectory = path.dirname(parentDirectory);
36
66
  }
37
- this.#allowedDirs.add(path.dirname(await realpath(url.fileURLToPath(fileUrl))))
38
- return `${this.#INTERCEPT_ORIGIN}${fileUrl.pathname}`
67
+ this.#allowedDirs.add(parentDirectory);
68
+ return `${this.#INTERCEPT_ORIGIN}${fileUrl.pathname}`;
39
69
  }
40
70
 
41
71
  /**
42
- *
43
- * @param {URL | string} interceptUrl
44
- * @throws {Error} If the URL is not a valid intercept URL
45
- */
46
- async interceptUrlToFileUrl (interceptUrl) {
47
- interceptUrl = new URL(interceptUrl)
72
+ *
73
+ * @param {URL | string} interceptUrl
74
+ * @throws {Error} If the URL is not a valid intercept URL
75
+ */
76
+ async interceptUrlToFileUrl(interceptUrl) {
77
+ interceptUrl = new URL(interceptUrl);
48
78
  if (interceptUrl.origin !== this.#INTERCEPT_ORIGIN) {
49
- throw new Error(`Invalid intercept URL: ${interceptUrl}`)
79
+ throw new Error(`Invalid intercept URL: ${interceptUrl}`);
50
80
  }
51
- const fileUrl = new URL(interceptUrl.href.slice(this.#INTERCEPT_ORIGIN.length), 'file://')
52
- const filePath = await realpath(url.fileURLToPath(fileUrl))
53
- if (![...this.#allowedDirs].some(dir => path.relative(filePath, dir).startsWith('..'))) {
54
- throw new Error(`Intercept URL is not in an allowed directory: ${interceptUrl}`)
81
+ const fileUrl = new URL(
82
+ interceptUrl.href.slice(this.#INTERCEPT_ORIGIN.length),
83
+ "file://",
84
+ );
85
+ const filePath = await realpath(url.fileURLToPath(fileUrl));
86
+ if (
87
+ ![...this.#allowedDirs].some((dir) =>
88
+ path.relative(filePath, dir).startsWith(".."),
89
+ )
90
+ ) {
91
+ throw new Error(
92
+ `Intercept URL is not in an allowed directory: ${interceptUrl}`,
93
+ );
55
94
  }
56
- return fileUrl
95
+ return fileUrl;
57
96
  }
58
97
 
59
98
  /**
60
- * @param {puppeteer.HTTPRequest} request - The intercepted request
61
- */
62
- async #interceptRequestHandler (request) {
99
+ * @param {import('puppeteer').HTTPRequest} request - The intercepted request
100
+ */
101
+ async #interceptRequestHandler(request) {
63
102
  try {
64
103
  if (request.url().startsWith(this.#INTERCEPT_ORIGIN)) {
65
- const fileUrl = await this.interceptUrlToFileUrl(request.url())
66
- return request.respond({
67
- status: 200,
68
- headers: {
69
- 'Access-Control-Allow-Origin': '*'
104
+ const fileUrl = await this.interceptUrlToFileUrl(request.url());
105
+ return request.respond(
106
+ {
107
+ status: 200,
108
+ headers: {
109
+ "Access-Control-Allow-Origin": "*",
110
+ },
111
+ contentType: getContentTypeFromFileExtension(
112
+ url.fileURLToPath(fileUrl),
113
+ ),
114
+ body: await readFile(fileUrl),
70
115
  },
71
- contentType: 'application/javascript',
72
- body: await readFile(fileUrl)
73
- })
116
+ DEFAULT_INTERCEPT_RESOLUTION_PRIORITY,
117
+ );
74
118
  }
75
119
  } catch (error) {
76
- console.error(`Error handling intercept request for ${request.url()}:`, error)
77
- request.abort()
120
+ console.error(
121
+ `Error handling intercept request for ${request.url()}:`,
122
+ error,
123
+ );
124
+ return request.abort(undefined, DEFAULT_INTERCEPT_RESOLUTION_PRIORITY);
78
125
  }
79
- request.continue()
126
+ request.continue(undefined, DEFAULT_INTERCEPT_RESOLUTION_PRIORITY);
80
127
  }
81
128
 
82
129
  /**
83
- * Intercepts requests to `https://mermaid-cli-intercept.invalid`
84
- * and serves the corresponding file content.
85
- *
86
- * @return {puppeteer.Handler<puppeteer.HTTPRequest>}
87
- */
88
- get interceptRequestHandler () {
89
- return this.#interceptRequestHandler.bind(this)
130
+ * Intercepts requests to `https://mermaid-cli-intercept.invalid`
131
+ * and serves the corresponding file content.
132
+ *
133
+ * @return {import('puppeteer').Handler<import('puppeteer').HTTPRequest>}
134
+ */
135
+ get interceptRequestHandler() {
136
+ return this.#interceptRequestHandler.bind(this);
90
137
  }
91
138
  }
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const version = '11.14.0'
1
+ export const version = "11.16.0";