marked-katex-extension 2.1.0 → 3.0.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/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Render [katex](https://katex.org/) code in marked
4
4
 
5
- Note: Block level katex requires at least 2 `$` at the beginning and end.
6
-
7
5
  ```markdown
8
6
  This is inline katex: $c = \\pm\\sqrt{a^2 + b^2}$
9
7
 
@@ -17,7 +15,7 @@ $$
17
15
  You will still need to include the css in your html document to allow katex styles.
18
16
 
19
17
  ```html
20
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.2/dist/katex.min.css" integrity="sha384-bYdxxUwYipFNohQlHt0bjN/LCpueqWz13HufFEV1SUatKs1cm4L6fFgCi1jT643X" crossorigin="anonymous">
18
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">
21
19
  ```
22
20
 
23
21
  # Usage
@@ -41,6 +39,25 @@ marked.parse("katex: $c = \\pm\\sqrt{a^2 + b^2}$");
41
39
 
42
40
  ![image](https://user-images.githubusercontent.com/97994/188899567-e6e8268c-209e-4067-8f44-0ada16caacdd.png)
43
41
 
42
+ ## Block level
43
+
44
+ You can include newlines in block level katex. Block level katex must contain starting and ending delimiters on their own line.
45
+
46
+ ```js
47
+ marked.parse(`
48
+ $$
49
+ \\begin{array}{cc}
50
+ a & b \\\\
51
+ c & d
52
+ \\end{array}
53
+ $$
54
+ `);
55
+ ```
56
+
57
+ ## DisplayMode
58
+
59
+ [`displayMode`](https://katex.org/docs/options.html) will be on by default when using two dollar signs (`$$`) in inline or block katex. And it will be off by default for a single dollar sign (`$`) in inline or block katex.
60
+
44
61
  ## `options`
45
62
 
46
- Options are sent directly to [`katex.renderToString`](https://katex.org/docs/api.html#server-side-rendering-or-rendering-to-a-string)
63
+ Options are sent directly to [`katex`](https://katex.org/docs/options.html)
package/lib/index.cjs CHANGED
@@ -2,54 +2,71 @@
2
2
 
3
3
  var katex = require('katex');
4
4
 
5
+ const inlineStartRule = /(?<=\s|^)\${1,2}(?!\$)/;
6
+ const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])+?)(?<!\$)\1(?=\s|$)/;
7
+ const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/;
8
+
5
9
  function index(options = {}) {
6
10
  return {
7
11
  extensions: [
8
- inlineKatex(options),
9
- blockKatex(options)
12
+ inlineKatex(options, createRenderer(options, false)),
13
+ blockKatex(options, createRenderer(options, true))
10
14
  ]
11
15
  };
12
16
  }
13
17
 
14
- function inlineKatex(options) {
18
+ function createRenderer(options, newlineAfter) {
19
+ return (token) => katex.renderToString(token.text, { ...options, displayMode: token.displayMode }) + (newlineAfter ? '\n' : '');
20
+ }
21
+
22
+ function inlineKatex(options, renderer) {
15
23
  return {
16
24
  name: 'inlineKatex',
17
25
  level: 'inline',
18
- start(src) { return src.indexOf('$'); },
26
+ start(src) {
27
+ const match = src.match(inlineStartRule);
28
+ if (!match) {
29
+ return;
30
+ }
31
+
32
+ const possibleKatex = src.substring(match.index);
33
+
34
+ if (possibleKatex.match(inlineRule)) {
35
+ return match.index;
36
+ }
37
+ },
19
38
  tokenizer(src, tokens) {
20
- const match = src.match(/^\$+([^$\n]+?)\$+/);
39
+ const match = src.match(inlineRule);
21
40
  if (match) {
22
41
  return {
23
42
  type: 'inlineKatex',
24
43
  raw: match[0],
25
- text: match[1].trim()
44
+ text: match[2].trim(),
45
+ displayMode: match[1].length === 2
26
46
  };
27
47
  }
28
48
  },
29
- renderer(token) {
30
- return katex.renderToString(token.text, options);
31
- }
49
+ renderer
32
50
  };
33
51
  }
34
52
 
35
- function blockKatex(options) {
53
+ function blockKatex(options, renderer) {
36
54
  return {
37
55
  name: 'blockKatex',
38
56
  level: 'block',
39
- start(src) { return src.indexOf('\n$$'); },
57
+ start(src) { return src.indexOf('\n$'); },
40
58
  tokenizer(src, tokens) {
41
- const match = src.match(/^\$\$+\n([^$]+?)\n\$\$+\n/);
59
+ const match = src.match(blockRule);
42
60
  if (match) {
43
61
  return {
44
62
  type: 'blockKatex',
45
63
  raw: match[0],
46
- text: match[1].trim()
64
+ text: match[2].trim(),
65
+ displayMode: match[1].length === 2
47
66
  };
48
67
  }
49
68
  },
50
- renderer(token) {
51
- return `<p>${katex.renderToString(token.text, options)}</p>`;
52
- }
69
+ renderer
53
70
  };
54
71
  }
55
72
 
package/lib/index.umd.js CHANGED
@@ -96,13 +96,19 @@
96
96
  * about where in the source string the problem occurred.
97
97
  */
98
98
  class ParseError {
99
- // Error position based on passed-in Token or ParseNode.
99
+ // Error start position based on passed-in Token or ParseNode.
100
+ // Length of affected text based on passed-in Token or ParseNode.
101
+ // The underlying error message without any context added.
100
102
  constructor(message, // The error message
101
103
  token // An object providing position information
102
104
  ) {
105
+ this.name = void 0;
103
106
  this.position = void 0;
107
+ this.length = void 0;
108
+ this.rawMessage = void 0;
104
109
  var error = "KaTeX parse error: " + message;
105
110
  var start;
111
+ var end;
106
112
  var loc = token && token.loc;
107
113
 
108
114
  if (loc && loc.start <= loc.end) {
@@ -111,7 +117,7 @@
111
117
  var input = loc.lexer.input; // Prepend some information
112
118
 
113
119
  start = loc.start;
114
- var end = loc.end;
120
+ end = loc.end;
115
121
 
116
122
  if (start === input.length) {
117
123
  error += " at end of input: ";
@@ -141,14 +147,20 @@
141
147
  error += left + underlined + right;
142
148
  } // Some hackery to make ParseError a prototype of Error
143
149
  // See http://stackoverflow.com/a/8460753
150
+ // $FlowFixMe
144
151
 
145
152
 
146
153
  var self = new Error(error);
147
154
  self.name = "ParseError"; // $FlowFixMe
148
155
 
149
- self.__proto__ = ParseError.prototype; // $FlowFixMe
150
-
156
+ self.__proto__ = ParseError.prototype;
151
157
  self.position = start;
158
+
159
+ if (start != null && end != null) {
160
+ self.length = end - start;
161
+ }
162
+
163
+ self.rawMessage = message;
152
164
  return self;
153
165
  }
154
166
 
@@ -18303,7 +18315,7 @@
18303
18315
  /**
18304
18316
  * Current KaTeX version
18305
18317
  */
18306
- version: "0.16.7",
18318
+ version: "0.16.8",
18307
18319
 
18308
18320
  /**
18309
18321
  * Renders the given LaTeX into an HTML+MathML combination, and adds
@@ -18397,54 +18409,71 @@
18397
18409
  }
18398
18410
  };
18399
18411
 
18412
+ const inlineStartRule = /(?<=\s|^)\${1,2}(?!\$)/;
18413
+ const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])+?)(?<!\$)\1(?=\s|$)/;
18414
+ const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/;
18415
+
18400
18416
  function index(options = {}) {
18401
18417
  return {
18402
18418
  extensions: [
18403
- inlineKatex(options),
18404
- blockKatex(options)
18419
+ inlineKatex(options, createRenderer(options, false)),
18420
+ blockKatex(options, createRenderer(options, true))
18405
18421
  ]
18406
18422
  };
18407
18423
  }
18408
18424
 
18409
- function inlineKatex(options) {
18425
+ function createRenderer(options, newlineAfter) {
18426
+ return (token) => katex.renderToString(token.text, { ...options, displayMode: token.displayMode }) + (newlineAfter ? '\n' : '');
18427
+ }
18428
+
18429
+ function inlineKatex(options, renderer) {
18410
18430
  return {
18411
18431
  name: 'inlineKatex',
18412
18432
  level: 'inline',
18413
- start(src) { return src.indexOf('$'); },
18433
+ start(src) {
18434
+ const match = src.match(inlineStartRule);
18435
+ if (!match) {
18436
+ return;
18437
+ }
18438
+
18439
+ const possibleKatex = src.substring(match.index);
18440
+
18441
+ if (possibleKatex.match(inlineRule)) {
18442
+ return match.index;
18443
+ }
18444
+ },
18414
18445
  tokenizer(src, tokens) {
18415
- const match = src.match(/^\$+([^$\n]+?)\$+/);
18446
+ const match = src.match(inlineRule);
18416
18447
  if (match) {
18417
18448
  return {
18418
18449
  type: 'inlineKatex',
18419
18450
  raw: match[0],
18420
- text: match[1].trim()
18451
+ text: match[2].trim(),
18452
+ displayMode: match[1].length === 2
18421
18453
  };
18422
18454
  }
18423
18455
  },
18424
- renderer(token) {
18425
- return katex.renderToString(token.text, options);
18426
- }
18456
+ renderer
18427
18457
  };
18428
18458
  }
18429
18459
 
18430
- function blockKatex(options) {
18460
+ function blockKatex(options, renderer) {
18431
18461
  return {
18432
18462
  name: 'blockKatex',
18433
18463
  level: 'block',
18434
- start(src) { return src.indexOf('\n$$'); },
18464
+ start(src) { return src.indexOf('\n$'); },
18435
18465
  tokenizer(src, tokens) {
18436
- const match = src.match(/^\$\$+\n([^$]+?)\n\$\$+\n/);
18466
+ const match = src.match(blockRule);
18437
18467
  if (match) {
18438
18468
  return {
18439
18469
  type: 'blockKatex',
18440
18470
  raw: match[0],
18441
- text: match[1].trim()
18471
+ text: match[2].trim(),
18472
+ displayMode: match[1].length === 2
18442
18473
  };
18443
18474
  }
18444
18475
  },
18445
- renderer(token) {
18446
- return `<p>${katex.renderToString(token.text, options)}</p>`;
18447
- }
18476
+ renderer
18448
18477
  };
18449
18478
  }
18450
18479
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marked-katex-extension",
3
- "version": "2.1.0",
3
+ "version": "3.0.0",
4
4
  "description": "MarkedJS extesion to render katex",
5
5
  "main": "./lib/index.cjs",
6
6
  "module": "./src/index.js",
@@ -27,7 +27,8 @@
27
27
  "test:cover": "jest --coverage",
28
28
  "test:types": "tsd -f spec/index.test-d.ts -t src/index.d.ts",
29
29
  "lint": "eslint .",
30
- "build": "rollup -c rollup.config.js"
30
+ "build": "rollup -c rollup.config.js",
31
+ "update-specs": "node ./update-specs.js"
31
32
  },
32
33
  "repository": {
33
34
  "type": "git",
@@ -43,30 +44,32 @@
43
44
  "marked": "^4 || ^5"
44
45
  },
45
46
  "devDependencies": {
46
- "@babel/core": "^7.21.8",
47
- "@babel/preset-env": "^7.21.5",
48
- "@rollup/plugin-node-resolve": "^15.0.2",
47
+ "@babel/core": "^7.22.6",
48
+ "@babel/preset-env": "^7.22.6",
49
+ "@rollup/plugin-node-resolve": "^15.1.0",
49
50
  "@semantic-release/changelog": "^6.0.3",
50
- "@semantic-release/commit-analyzer": "^9.0.2",
51
+ "@semantic-release/commit-analyzer": "^10.0.1",
51
52
  "@semantic-release/git": "^10.0.1",
52
- "@semantic-release/github": "^8.0.7",
53
- "@semantic-release/npm": "^10.0.3",
54
- "@semantic-release/release-notes-generator": "^11.0.1",
53
+ "@semantic-release/github": "^9.0.3",
54
+ "@semantic-release/npm": "^10.0.4",
55
+ "@semantic-release/release-notes-generator": "^11.0.4",
55
56
  "@types/marked": "^5.0.0",
56
- "babel-jest": "^29.5.0",
57
- "eslint": "^8.41.0",
58
- "eslint-config-standard": "^17.0.0",
57
+ "babel-jest": "^29.6.0",
58
+ "cheerio": "^1.0.0-rc.12",
59
+ "eslint": "^8.44.0",
60
+ "eslint-config-standard": "^17.1.0",
59
61
  "eslint-plugin-import": "^2.27.5",
60
- "eslint-plugin-n": "^15.7.0",
62
+ "eslint-plugin-n": "^16.0.1",
61
63
  "eslint-plugin-promise": "^6.1.1",
62
- "jest-cli": "^29.5.0",
63
- "marked": "^5.0.2",
64
- "rollup": "^3.23.0",
65
- "semantic-release": "^21.0.2",
64
+ "jest-cli": "^29.6.0",
65
+ "marked": "^5.1.0",
66
+ "node-fetch": "^3.3.1",
67
+ "rollup": "^3.26.1",
68
+ "semantic-release": "^21.0.7",
66
69
  "tsd": "^0.28.1"
67
70
  },
68
71
  "dependencies": {
69
72
  "@types/katex": "^0.16.0",
70
- "katex": "^0.16.7"
73
+ "katex": "^0.16.8"
71
74
  }
72
75
  }
package/src/index.js CHANGED
@@ -1,52 +1,69 @@
1
1
  import katex from 'katex';
2
2
 
3
+ const inlineStartRule = /(?<=\s|^)\${1,2}(?!\$)/;
4
+ const inlineRule = /^(\${1,2})(?!\$)((?:\\.|[^\\\n])+?)(?<!\$)\1(?=\s|$)/;
5
+ const blockRule = /^(\${1,2})\n((?:\\[^]|[^\\])+?)\n\1(?:\n|$)/;
6
+
3
7
  export default function(options = {}) {
4
8
  return {
5
9
  extensions: [
6
- inlineKatex(options),
7
- blockKatex(options)
10
+ inlineKatex(options, createRenderer(options, false)),
11
+ blockKatex(options, createRenderer(options, true))
8
12
  ]
9
13
  };
10
14
  }
11
15
 
12
- function inlineKatex(options) {
16
+ function createRenderer(options, newlineAfter) {
17
+ return (token) => katex.renderToString(token.text, { ...options, displayMode: token.displayMode }) + (newlineAfter ? '\n' : '');
18
+ }
19
+
20
+ function inlineKatex(options, renderer) {
13
21
  return {
14
22
  name: 'inlineKatex',
15
23
  level: 'inline',
16
- start(src) { return src.indexOf('$'); },
24
+ start(src) {
25
+ const match = src.match(inlineStartRule);
26
+ if (!match) {
27
+ return;
28
+ }
29
+
30
+ const possibleKatex = src.substring(match.index);
31
+
32
+ if (possibleKatex.match(inlineRule)) {
33
+ return match.index;
34
+ }
35
+ },
17
36
  tokenizer(src, tokens) {
18
- const match = src.match(/^\$+([^$\n]+?)\$+/);
37
+ const match = src.match(inlineRule);
19
38
  if (match) {
20
39
  return {
21
40
  type: 'inlineKatex',
22
41
  raw: match[0],
23
- text: match[1].trim()
42
+ text: match[2].trim(),
43
+ displayMode: match[1].length === 2
24
44
  };
25
45
  }
26
46
  },
27
- renderer(token) {
28
- return katex.renderToString(token.text, options);
29
- }
47
+ renderer
30
48
  };
31
49
  }
32
50
 
33
- function blockKatex(options) {
51
+ function blockKatex(options, renderer) {
34
52
  return {
35
53
  name: 'blockKatex',
36
54
  level: 'block',
37
- start(src) { return src.indexOf('\n$$'); },
55
+ start(src) { return src.indexOf('\n$'); },
38
56
  tokenizer(src, tokens) {
39
- const match = src.match(/^\$\$+\n([^$]+?)\n\$\$+\n/);
57
+ const match = src.match(blockRule);
40
58
  if (match) {
41
59
  return {
42
60
  type: 'blockKatex',
43
61
  raw: match[0],
44
- text: match[1].trim()
62
+ text: match[2].trim(),
63
+ displayMode: match[1].length === 2
45
64
  };
46
65
  }
47
66
  },
48
- renderer(token) {
49
- return `<p>${katex.renderToString(token.text, options)}</p>`;
50
- }
67
+ renderer
51
68
  };
52
69
  }