@cobapen/markdown 0.1.0 → 0.2.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 +6 -1
- package/dist/code/fence-custom.d.ts +1 -1
- package/dist/code/fence-custom.js +37 -37
- package/dist/code/highlight.js +37 -41
- package/dist/code/info-string.d.ts +21 -21
- package/dist/code/info-string.js +121 -141
- package/dist/index.d.ts +29 -3
- package/dist/index.js +49 -39
- package/dist/math/mathjax.d.ts +1 -1
- package/dist/math/mathjax.js +27 -25
- package/dist/math/mdmath.js +6 -6
- package/dist/math/mdparser.js +116 -116
- package/package.json +6 -9
package/README.md
CHANGED
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
A markdown converter for the cobapen website.
|
|
4
4
|
|
|
5
|
+
[](https://github.com/cobapen/markdown/actions/workflows/actions.yml)
|
|
6
|
+
|
|
7
|
+
https://cobapen.github.io/markdown
|
|
8
|
+
|
|
5
9
|
## Features
|
|
6
10
|
|
|
7
11
|
- toc
|
|
8
12
|
- anchor & footnote
|
|
9
13
|
- deflist
|
|
10
|
-
- fenced code block with filename, line-number
|
|
14
|
+
- fenced code block with filename, line-number support
|
|
15
|
+
- server side syntax highlighting
|
|
11
16
|
- server side math rendering
|
|
12
17
|
|
|
@@ -2,7 +2,7 @@ import { Options } from "markdown-it/index.mjs";
|
|
|
2
2
|
import Renderer from "markdown-it/lib/renderer.mjs";
|
|
3
3
|
import Token from "markdown-it/lib/token.mjs";
|
|
4
4
|
interface Env {
|
|
5
|
-
|
|
5
|
+
showCodeTitleByDefault?: boolean;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Custom fence renderer for markdown-it.
|
|
@@ -6,46 +6,46 @@ import { InfoString } from "./info-string.js";
|
|
|
6
6
|
* see: markdown-it/lib/renderer.mjs
|
|
7
7
|
*/
|
|
8
8
|
export function fence_custom(tokens, idx, options, env, slf) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
const token = tokens[idx];
|
|
10
|
+
const info_str = token.info ? unescapeAll(token.info).trim() : "";
|
|
11
|
+
const info = new InfoString(info_str);
|
|
12
|
+
const langName = info.lang;
|
|
13
|
+
const langAttrs = info.attrs.join(" ");
|
|
14
|
+
let highlighted;
|
|
15
|
+
if (options.highlight) {
|
|
16
|
+
highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
highlighted = escapeHtml(token.content);
|
|
20
|
+
}
|
|
21
|
+
if (highlighted.indexOf("<pre") === 0) {
|
|
22
|
+
return highlighted + "\n";
|
|
23
|
+
}
|
|
24
|
+
// If language exists, inject class gently, without modifying original token.
|
|
25
|
+
// May be, one day we will add .deepClone() for token and simplify this part, but
|
|
26
|
+
// now we prefer to keep things local.
|
|
27
|
+
if (info.hasLang) {
|
|
28
|
+
const i = token.attrIndex("class");
|
|
29
|
+
const tmpAttrs = token.attrs ? token.attrs.slice() : [];
|
|
30
|
+
if (i < 0) {
|
|
31
|
+
tmpAttrs.push(["class", options.langPrefix + langName]);
|
|
17
32
|
}
|
|
18
33
|
else {
|
|
19
|
-
|
|
34
|
+
tmpAttrs[i] = tmpAttrs[i].slice();
|
|
35
|
+
tmpAttrs[i][1] += " " + options.langPrefix + langName;
|
|
20
36
|
}
|
|
21
|
-
|
|
22
|
-
|
|
37
|
+
// Fake token just to render attributes
|
|
38
|
+
const tmpToken = {
|
|
39
|
+
attrs: tmpAttrs
|
|
40
|
+
};
|
|
41
|
+
if (info.title.length > 0) {
|
|
42
|
+
const style = (env.showCodeTitleByDefault === true)
|
|
43
|
+
? ""
|
|
44
|
+
: " style=\"visibility:hidden;\"";
|
|
45
|
+
return `<pre><code${slf.renderAttrs(tmpToken)}>${highlighted}</code><span class="title"${style}>${info.title}</span></pre>\n`;
|
|
23
46
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if (info.hasLang) {
|
|
28
|
-
var i = token.attrIndex("class");
|
|
29
|
-
var tmpAttrs = token.attrs ? token.attrs.slice() : [];
|
|
30
|
-
if (i < 0) {
|
|
31
|
-
tmpAttrs.push(["class", options.langPrefix + langName]);
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
tmpAttrs[i] = tmpAttrs[i].slice();
|
|
35
|
-
tmpAttrs[i][1] += " " + options.langPrefix + langName;
|
|
36
|
-
}
|
|
37
|
-
// Fake token just to render attributes
|
|
38
|
-
var tmpToken = {
|
|
39
|
-
attrs: tmpAttrs
|
|
40
|
-
};
|
|
41
|
-
if (info.title.length > 0) {
|
|
42
|
-
var style = (env.showCodeTitleByDefault === true)
|
|
43
|
-
? ""
|
|
44
|
-
: " style=\"visibility:hidden;\"";
|
|
45
|
-
return "<pre><code".concat(slf.renderAttrs(tmpToken), ">").concat(highlighted, "</code><span class=\"title\"").concat(style, ">").concat(info.title, "</span></pre>\n");
|
|
46
|
-
}
|
|
47
|
-
return "<pre><code".concat(slf.renderAttrs(tmpToken), ">").concat(highlighted, "</code></pre>\n");
|
|
48
|
-
}
|
|
49
|
-
return "<pre><code".concat(slf.renderAttrs(token), ">").concat(highlighted, "</code></pre>\n");
|
|
47
|
+
return `<pre><code${slf.renderAttrs(tmpToken)}>${highlighted}</code></pre>\n`;
|
|
48
|
+
}
|
|
49
|
+
return `<pre><code${slf.renderAttrs(token)}>${highlighted}</code></pre>\n`;
|
|
50
50
|
}
|
|
51
51
|
//# sourceMappingURL=fence-custom.js.map
|
package/dist/code/highlight.js
CHANGED
|
@@ -5,21 +5,17 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import hljs from "highlight.js";
|
|
7
7
|
import { InfoString } from "./info-string.js";
|
|
8
|
-
function _debuglog() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
_args[_i] = arguments[_i];
|
|
12
|
-
}
|
|
13
|
-
// if (_debuglog.caller.name !== "") return;
|
|
14
|
-
// console.log(...args);
|
|
8
|
+
function _debuglog(..._args) {
|
|
9
|
+
// if (_debuglog.caller.name !== "") return;
|
|
10
|
+
// console.log(...args);
|
|
15
11
|
}
|
|
16
12
|
/** Get digits of the number. e.g. 1000 => 4 */
|
|
17
13
|
function numDigits(n) {
|
|
18
|
-
|
|
14
|
+
return Math.floor(n).toString().length;
|
|
19
15
|
}
|
|
20
16
|
/** Print a decimal nicely */
|
|
21
17
|
function niceDec(n) {
|
|
22
|
-
|
|
18
|
+
return n.toFixed(3);
|
|
23
19
|
}
|
|
24
20
|
/**
|
|
25
21
|
* Highlight function with line number support
|
|
@@ -30,12 +26,12 @@ function niceDec(n) {
|
|
|
30
26
|
* @returns
|
|
31
27
|
*/
|
|
32
28
|
export function highlightWithLineNumber(code, lang, linestart) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
try {
|
|
30
|
+
/** convert if lang is specified + supported by highlight.js */
|
|
31
|
+
if (lang && hljs.getLanguage(lang)) {
|
|
32
|
+
/** do conversion */
|
|
33
|
+
let htmlLines = hljs.highlight(code, { language: lang }).value;
|
|
34
|
+
/**
|
|
39
35
|
* Attach the line number if specified.
|
|
40
36
|
*
|
|
41
37
|
* The given code is rendered in <pre><code>, so each line is terminated by '\n'.
|
|
@@ -50,33 +46,33 @@ export function highlightWithLineNumber(code, lang, linestart) {
|
|
|
50
46
|
* - user-select: none
|
|
51
47
|
* - width: ${numDigits}em
|
|
52
48
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
if (linestart !== undefined) {
|
|
50
|
+
const lines = htmlLines.split("\n");
|
|
51
|
+
const elWidth = numDigits(linestart + lines.length) * 0.8;
|
|
52
|
+
const elStyle = "display:inline-block;" +
|
|
57
53
|
"user-select:none;" +
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
`width: ${niceDec(elWidth)}em;`;
|
|
55
|
+
lines.forEach((line, i, lines) => {
|
|
56
|
+
lines[i] =
|
|
61
57
|
"<div class=\"line\">" +
|
|
62
|
-
|
|
58
|
+
`<span class="line-no" style="${elStyle}">${linestart + i}</span>${line}` +
|
|
63
59
|
"</div>";
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
// no language , no highlighting.
|
|
72
|
-
// If you want line numbers without highlighting, set language to
|
|
73
|
-
// "nohighlight" or "text"
|
|
74
|
-
return "";
|
|
75
|
-
}
|
|
60
|
+
});
|
|
61
|
+
_debuglog(lines);
|
|
62
|
+
htmlLines = lines.join("");
|
|
63
|
+
}
|
|
64
|
+
return htmlLines;
|
|
76
65
|
}
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
else {
|
|
67
|
+
// no language , no highlighting.
|
|
68
|
+
// If you want line numbers without highlighting, set language to
|
|
69
|
+
// "nohighlight" or "text"
|
|
70
|
+
return "";
|
|
79
71
|
}
|
|
72
|
+
}
|
|
73
|
+
catch (_) {
|
|
74
|
+
return "";
|
|
75
|
+
}
|
|
80
76
|
}
|
|
81
77
|
/**
|
|
82
78
|
* Exported function for markdown-it
|
|
@@ -87,9 +83,9 @@ export function highlightWithLineNumber(code, lang, linestart) {
|
|
|
87
83
|
* @returns
|
|
88
84
|
*/
|
|
89
85
|
export function highlighterForMarkdownIt(str, lang, attrs) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
_debuglog(lang ? lang : "(lang is empty or undefined)");
|
|
87
|
+
const info = new InfoString(lang + " " + attrs);
|
|
88
|
+
_debuglog(info);
|
|
89
|
+
return highlightWithLineNumber(str, info.lang, info.linestart);
|
|
94
90
|
}
|
|
95
91
|
//# sourceMappingURL=highlight.js.map
|
|
@@ -2,25 +2,25 @@
|
|
|
2
2
|
* InfoString parses info_string from fenced code block.
|
|
3
3
|
*/
|
|
4
4
|
export declare class InfoString {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
5
|
+
private readonly _lang;
|
|
6
|
+
private readonly _attrs;
|
|
7
|
+
private readonly _title;
|
|
8
|
+
private readonly _linestart;
|
|
9
|
+
constructor(info: string);
|
|
10
|
+
get lang(): string;
|
|
11
|
+
get attrs(): string[];
|
|
12
|
+
get title(): string;
|
|
13
|
+
get linestart(): number | undefined;
|
|
14
|
+
get hasLang(): boolean;
|
|
15
|
+
/** Parse info_string into an array of strings. All quotes are removed*/
|
|
16
|
+
static parseInfoString(info: string): string[];
|
|
17
|
+
/** Parse metadata notation "{filename:line, ...}"" */
|
|
18
|
+
static parseMetaNotation(text: string): {
|
|
19
|
+
filename: string;
|
|
20
|
+
line: number;
|
|
21
|
+
} | undefined;
|
|
22
|
+
/** From attributes list, return title metadata */
|
|
23
|
+
static getTitle(attr: string[]): string;
|
|
24
|
+
/** From attributes list, return line number if defined */
|
|
25
|
+
static getLineStart(attr: string[]): number | undefined;
|
|
26
26
|
}
|
package/dist/code/info-string.js
CHANGED
|
@@ -1,149 +1,129 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* InfoString parses info_string from fenced code block.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this._title = "";
|
|
17
|
-
this._linestart = undefined;
|
|
18
|
-
}
|
|
4
|
+
export class InfoString {
|
|
5
|
+
_lang;
|
|
6
|
+
_attrs;
|
|
7
|
+
_title;
|
|
8
|
+
_linestart;
|
|
9
|
+
constructor(info) {
|
|
10
|
+
if (info.length > 0) {
|
|
11
|
+
const arr = InfoString.parseInfoString(info);
|
|
12
|
+
this._lang = arr[0];
|
|
13
|
+
this._attrs = arr.slice(1);
|
|
14
|
+
this._title = InfoString.getTitle(this._attrs);
|
|
15
|
+
this._linestart = InfoString.getLineStart(this._attrs);
|
|
19
16
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
return undefined;
|
|
101
|
-
};
|
|
102
|
-
/** From attributes list, return title metadata */
|
|
103
|
-
InfoString.getTitle = function (attr) {
|
|
104
|
-
var _a;
|
|
105
|
-
var titleAttr = (_a = attr.find(function (x) { return x.startsWith("title="); })) !== null && _a !== void 0 ? _a : "";
|
|
106
|
-
if (titleAttr.length > 0) {
|
|
107
|
-
var match = titleAttr.match(/^title=(.*)$/);
|
|
108
|
-
if (match) {
|
|
109
|
-
var value = match[1].trim();
|
|
110
|
-
if (value.startsWith("\"") && value.endsWith("\"")) {
|
|
111
|
-
value = value.slice(1, -1);
|
|
112
|
-
value = unescape(value).trim();
|
|
113
|
-
}
|
|
114
|
-
return value;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
throw new Error("Must not fail. Check impl.");
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (attr.length > 0) {
|
|
121
|
-
var meta = InfoString.parseMetaNotation(attr[0]);
|
|
122
|
-
if (meta && meta.filename.length > 0) {
|
|
123
|
-
return meta.filename;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return "";
|
|
127
|
-
};
|
|
128
|
-
/** From attributes list, return line number if defined */
|
|
129
|
-
InfoString.getLineStart = function (attr) {
|
|
130
|
-
var _a;
|
|
131
|
-
var lineAttr = (_a = attr.find(function (x) { return x.startsWith("linestart="); })) !== null && _a !== void 0 ? _a : "";
|
|
132
|
-
if (lineAttr.length > 0) {
|
|
133
|
-
return parseInt(lineAttr.split("=")[1].trim());
|
|
134
|
-
}
|
|
135
|
-
if (attr.length > 0) {
|
|
136
|
-
var meta = InfoString.parseMetaNotation(attr[0]);
|
|
137
|
-
if (meta && meta.line > 0) {
|
|
138
|
-
return meta.line;
|
|
139
|
-
}
|
|
17
|
+
else {
|
|
18
|
+
this._lang = "";
|
|
19
|
+
this._attrs = [];
|
|
20
|
+
this._title = "";
|
|
21
|
+
this._linestart = undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
get lang() {
|
|
25
|
+
return this._lang;
|
|
26
|
+
}
|
|
27
|
+
get attrs() {
|
|
28
|
+
return this._attrs;
|
|
29
|
+
}
|
|
30
|
+
get title() {
|
|
31
|
+
return this._title;
|
|
32
|
+
}
|
|
33
|
+
get linestart() {
|
|
34
|
+
return this._linestart;
|
|
35
|
+
}
|
|
36
|
+
get hasLang() {
|
|
37
|
+
return this._lang.length > 0;
|
|
38
|
+
}
|
|
39
|
+
/** Parse info_string into an array of strings. All quotes are removed*/
|
|
40
|
+
static parseInfoString(info) {
|
|
41
|
+
// There are 4 possible tokens, but it can be reduced to 2 patterns.
|
|
42
|
+
// arg, "arg quoted", key=value, key="value quoted"
|
|
43
|
+
//
|
|
44
|
+
// This function returns a quote-removed string.
|
|
45
|
+
//
|
|
46
|
+
// const regex = /([^\s]+=)?(?:"([^"]*)"|'([^']*)'|([^\s]+))/g;
|
|
47
|
+
// ~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
48
|
+
// key= "value" 'value' value
|
|
49
|
+
//
|
|
50
|
+
// The regex above does not support escape letters. The next regex
|
|
51
|
+
// is escape char aware.
|
|
52
|
+
//
|
|
53
|
+
// NOTE: This class is designed to handle escape letters. However, tools
|
|
54
|
+
// might decide to unescape info_string before used (e.g. markdown-it).
|
|
55
|
+
// In such case, you might need to use double-escaped quotes.
|
|
56
|
+
//
|
|
57
|
+
const dq = "[^\"\\\\]*(?:\\\\.|[^\"\\\\]*)*"; // [^"]*
|
|
58
|
+
const sq = "[^\'\\\\]*(?:\\\\.|[^\'\\\\]*)*"; // [^']*
|
|
59
|
+
// ~~~~~~~~~~ ~~~~~ ~~~~~~~~~~
|
|
60
|
+
// char seq ( escape char seq )*
|
|
61
|
+
//
|
|
62
|
+
const ptn = `([^\\s]+=)?(?:"(${dq})"|'(${sq})'|([^\\s]+))`;
|
|
63
|
+
// ~~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~
|
|
64
|
+
// key= "value" 'value' value
|
|
65
|
+
const regex = new RegExp(ptn, "g");
|
|
66
|
+
const result = [];
|
|
67
|
+
let match;
|
|
68
|
+
while ((match = regex.exec(info)) !== null) {
|
|
69
|
+
let text = (match[1] || "") + (match[2] || match[3] || match[4] || "");
|
|
70
|
+
text = unescape(text).trim();
|
|
71
|
+
result.push(text);
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
/** Parse metadata notation "{filename:line, ...}"" */
|
|
76
|
+
static parseMetaNotation(text) {
|
|
77
|
+
const match = text.match(/^\{\s*([^:]+):(\d+)\s*\}$/);
|
|
78
|
+
if (match) {
|
|
79
|
+
return {
|
|
80
|
+
filename: match[1],
|
|
81
|
+
line: parseInt(match[2], 10),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
/** From attributes list, return title metadata */
|
|
87
|
+
static getTitle(attr) {
|
|
88
|
+
const titleAttr = attr.find(x => x.startsWith("title=")) ?? "";
|
|
89
|
+
if (titleAttr.length > 0) {
|
|
90
|
+
const match = titleAttr.match(/^title=(.*)$/);
|
|
91
|
+
if (match) {
|
|
92
|
+
let value = match[1].trim();
|
|
93
|
+
if (value.startsWith("\"") && value.endsWith("\"")) {
|
|
94
|
+
value = value.slice(1, -1);
|
|
95
|
+
value = unescape(value).trim();
|
|
140
96
|
}
|
|
141
|
-
return
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
throw new Error("Must not fail. Check impl.");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (attr.length > 0) {
|
|
104
|
+
const meta = InfoString.parseMetaNotation(attr[0]);
|
|
105
|
+
if (meta && meta.filename.length > 0) {
|
|
106
|
+
return meta.filename;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
/** From attributes list, return line number if defined */
|
|
112
|
+
static getLineStart(attr) {
|
|
113
|
+
const lineAttr = attr.find(x => x.startsWith("linestart=")) ?? "";
|
|
114
|
+
if (lineAttr.length > 0) {
|
|
115
|
+
return parseInt(lineAttr.split("=")[1].trim());
|
|
116
|
+
}
|
|
117
|
+
if (attr.length > 0) {
|
|
118
|
+
const meta = InfoString.parseMetaNotation(attr[0]);
|
|
119
|
+
if (meta && meta.line > 0) {
|
|
120
|
+
return meta.line;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
146
126
|
function unescape(text) {
|
|
147
|
-
|
|
127
|
+
return text.replaceAll(/\\\"/g, "\"").replaceAll(/\\\'/g, "'");
|
|
148
128
|
}
|
|
149
129
|
//# sourceMappingURL=info-string.js.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import markdownIt, { Options as MarkdownOptions } from "markdown-it";
|
|
2
|
+
import { Options as MathOptions } from "./math/mathjax.js";
|
|
3
|
+
export interface Config {
|
|
2
4
|
/**
|
|
3
5
|
* Set "true" to display the title (if specified) of the fenced code block.
|
|
4
6
|
* The title is hidden by default, and user must explicitly override the style.
|
|
5
7
|
*/
|
|
6
8
|
showCodeTitleByDefault: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* MarkdownIt options
|
|
11
|
+
*/
|
|
12
|
+
markdown: Partial<MarkdownOptions>;
|
|
13
|
+
/**
|
|
14
|
+
* MathJax options
|
|
15
|
+
*/
|
|
16
|
+
math: Partial<MathOptions>;
|
|
7
17
|
}
|
|
8
|
-
export type Options = Partial<
|
|
9
|
-
export declare class
|
|
18
|
+
export type Options = Partial<Config>;
|
|
19
|
+
export declare class CMarkdown {
|
|
10
20
|
private readonly _config;
|
|
11
21
|
private readonly _mj;
|
|
12
22
|
private readonly _md;
|
|
13
23
|
constructor(option?: Options);
|
|
24
|
+
/**
|
|
25
|
+
* Install plugins and renderers to the markdown-it instance.
|
|
26
|
+
*
|
|
27
|
+
* @param md The instance
|
|
28
|
+
*/
|
|
29
|
+
setup(md: markdownIt): void;
|
|
30
|
+
/**
|
|
31
|
+
* Render html from markdown.
|
|
32
|
+
*
|
|
33
|
+
* @param text markdown text
|
|
34
|
+
* @returns html text
|
|
35
|
+
*/
|
|
14
36
|
render(text: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Returns the MathJax CSS.
|
|
39
|
+
* @returns
|
|
40
|
+
*/
|
|
15
41
|
mathcss(): string;
|
|
16
42
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
var __assign = (this && this.__assign) || function () {
|
|
2
|
-
__assign = Object.assign || function(t) {
|
|
3
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
-
s = arguments[i];
|
|
5
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
-
t[p] = s[p];
|
|
7
|
-
}
|
|
8
|
-
return t;
|
|
9
|
-
};
|
|
10
|
-
return __assign.apply(this, arguments);
|
|
11
|
-
};
|
|
12
1
|
import markdownIt from "markdown-it";
|
|
13
2
|
import { highlighterForMarkdownIt } from "./code/highlight.js";
|
|
14
3
|
import anchor from "markdown-it-anchor";
|
|
@@ -23,45 +12,66 @@ import footnote from "markdown-it-footnote";
|
|
|
23
12
|
import { MathjaxEngine } from "./math/mathjax.js";
|
|
24
13
|
import { mdmath } from "./math/mdmath.js";
|
|
25
14
|
import { fence_custom } from "./code/fence-custom.js";
|
|
26
|
-
|
|
15
|
+
const defaultOptions = {
|
|
27
16
|
showCodeTitleByDefault: false,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
17
|
+
markdown: {
|
|
18
|
+
html: true,
|
|
19
|
+
linkify: true,
|
|
20
|
+
highlight: highlighterForMarkdownIt,
|
|
21
|
+
},
|
|
22
|
+
math: {
|
|
23
|
+
tex: {
|
|
24
|
+
macros: {
|
|
25
|
+
bm: ["\\boldsymbol{#1}", 1],
|
|
37
26
|
},
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export class CMarkdown {
|
|
31
|
+
_config;
|
|
32
|
+
_mj;
|
|
33
|
+
_md;
|
|
34
|
+
constructor(option) {
|
|
35
|
+
const config = { ...defaultOptions, ...option };
|
|
36
|
+
const mj = new MathjaxEngine(config.math);
|
|
37
|
+
const md = markdownIt(config.markdown);
|
|
38
|
+
this._config = config;
|
|
39
|
+
this._mj = mj;
|
|
40
|
+
this._md = md;
|
|
41
|
+
this.setup(md);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Install plugins and renderers to the markdown-it instance.
|
|
45
|
+
*
|
|
46
|
+
* @param md The instance
|
|
47
|
+
*/
|
|
48
|
+
setup(md) {
|
|
44
49
|
md.renderer.rules.fence = fence_custom;
|
|
45
50
|
md.use(anchor)
|
|
46
51
|
.use(cjkbreaks)
|
|
47
52
|
.use(footnote)
|
|
48
53
|
.use(deflist)
|
|
49
|
-
.use(mdmath(
|
|
54
|
+
.use(mdmath(this._mj))
|
|
50
55
|
.use(toc, {
|
|
51
56
|
includeLevel: [2, 3],
|
|
52
57
|
});
|
|
53
|
-
this._config = config;
|
|
54
|
-
this._mj = mj;
|
|
55
|
-
this._md = md;
|
|
56
58
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Render html from markdown.
|
|
61
|
+
*
|
|
62
|
+
* @param text markdown text
|
|
63
|
+
* @returns html text
|
|
64
|
+
*/
|
|
65
|
+
render(text) {
|
|
66
|
+
const env = { ...this._config }; // env object must s
|
|
59
67
|
return this._md.render(text, env);
|
|
60
|
-
}
|
|
61
|
-
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns the MathJax CSS.
|
|
71
|
+
* @returns
|
|
72
|
+
*/
|
|
73
|
+
mathcss() {
|
|
62
74
|
return this._mj.stylesheet();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
}());
|
|
66
|
-
export { MarkdownConverter };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
67
77
|
//# sourceMappingURL=index.js.map
|
package/dist/math/mathjax.d.ts
CHANGED
package/dist/math/mathjax.js
CHANGED
|
@@ -15,8 +15,8 @@ import { mathjax } from "mathjax-full/js/mathjax.js";
|
|
|
15
15
|
import { CHTML } from "mathjax-full/js/output/chtml.js";
|
|
16
16
|
import { AllPackages } from "mathjax-full/js/input/tex/AllPackages.js";
|
|
17
17
|
import { merge } from "lodash-es";
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const MATHJAX_DEFAULT_FONT_URL = "https://cdn.jsdelivr.net/npm/mathjax-full@3/es5/output/chtml/fonts/woff-v2";
|
|
19
|
+
const defaultOption = {
|
|
20
20
|
inline: false,
|
|
21
21
|
em: 16,
|
|
22
22
|
ex: 8,
|
|
@@ -39,18 +39,22 @@ var defaultOption = {
|
|
|
39
39
|
* The other returns a stylesheet document. The stylesheet must be included
|
|
40
40
|
* in your HTML document to render the equation properly.
|
|
41
41
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
export class MathjaxEngine {
|
|
43
|
+
option;
|
|
44
|
+
adaptor;
|
|
45
|
+
tex;
|
|
46
|
+
chtml;
|
|
47
|
+
html;
|
|
48
|
+
constructor(option) {
|
|
45
49
|
this.option = merge({}, defaultOption, option);
|
|
46
|
-
if (typeof
|
|
50
|
+
if (typeof this.option.tex?.packages === "string") {
|
|
47
51
|
this.option.tex.packages = this.option.tex.packages.split(/\s*,\s*/);
|
|
48
52
|
}
|
|
49
53
|
this.adaptor = liteAdaptor();
|
|
50
54
|
RegisterHTMLHandler(this.adaptor);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
55
|
+
const tex = new TeX(this.option.tex);
|
|
56
|
+
const chtml = new CHTML(this.option.chtml);
|
|
57
|
+
const html = mathjax.document("", {
|
|
54
58
|
InputJax: tex,
|
|
55
59
|
OutputJax: chtml,
|
|
56
60
|
});
|
|
@@ -60,12 +64,13 @@ var MathjaxEngine = /** @class */ (function () {
|
|
|
60
64
|
this.html = html;
|
|
61
65
|
function renderDoc(_doc) { }
|
|
62
66
|
function renderMath(math, doc) {
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
const adaptor = doc.adaptor;
|
|
68
|
+
const text = adaptor.node("mjx-copytext", { "aria-hidden": true }, [
|
|
65
69
|
adaptor.text(math.math),
|
|
66
70
|
]);
|
|
67
71
|
adaptor.setStyle(text, "position", "absolute");
|
|
68
|
-
adaptor.setStyle(text, "
|
|
72
|
+
adaptor.setStyle(text, "display", "none");
|
|
73
|
+
adaptor.setStyle(text, "width", "0");
|
|
69
74
|
adaptor.setStyle(math.typesetRoot, "position", "relative");
|
|
70
75
|
adaptor.append(math.typesetRoot, text);
|
|
71
76
|
}
|
|
@@ -77,13 +82,12 @@ var MathjaxEngine = /** @class */ (function () {
|
|
|
77
82
|
* @param override parameter to override the defaults, if you wish to
|
|
78
83
|
* @returns
|
|
79
84
|
*/
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
containerWidth: (_d = override === null || override === void 0 ? void 0 : override.width) !== null && _d !== void 0 ? _d : this.option.width,
|
|
85
|
+
convert(tex, override) {
|
|
86
|
+
const node = this.html.convert(tex, {
|
|
87
|
+
display: !(override?.inline ?? this.option.inline),
|
|
88
|
+
em: override?.em ?? this.option.em,
|
|
89
|
+
ex: override?.ex ?? this.option.ex,
|
|
90
|
+
containerWidth: override?.width ?? this.option.width,
|
|
87
91
|
scale: 1.0,
|
|
88
92
|
});
|
|
89
93
|
if (node instanceof LiteElement) {
|
|
@@ -92,17 +96,15 @@ var MathjaxEngine = /** @class */ (function () {
|
|
|
92
96
|
else {
|
|
93
97
|
return "ERROR";
|
|
94
98
|
}
|
|
95
|
-
}
|
|
99
|
+
}
|
|
96
100
|
/**
|
|
97
101
|
* returns adaptive css (stylesheet for the processed equations only),
|
|
98
102
|
* or the full mathjax css (if configured)
|
|
99
103
|
*
|
|
100
104
|
* @returns css content
|
|
101
105
|
*/
|
|
102
|
-
|
|
106
|
+
stylesheet() {
|
|
103
107
|
return this.adaptor.textContent(this.chtml.styleSheet(this.html));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
}());
|
|
107
|
-
export { MathjaxEngine };
|
|
108
|
+
}
|
|
109
|
+
}
|
|
108
110
|
//# sourceMappingURL=mathjax.js.map
|
package/dist/math/mdmath.js
CHANGED
|
@@ -16,7 +16,7 @@ function getRenderers(mathjax) {
|
|
|
16
16
|
function renderInlineMath(tex) {
|
|
17
17
|
return katex.renderToString(tex, {
|
|
18
18
|
throwOnError: false,
|
|
19
|
-
strict:
|
|
19
|
+
strict: (code, _msg, _token) => {
|
|
20
20
|
switch (code) {
|
|
21
21
|
case "unicodeTextInMathMode":
|
|
22
22
|
return "ignore";
|
|
@@ -28,7 +28,7 @@ function getRenderers(mathjax) {
|
|
|
28
28
|
}
|
|
29
29
|
function renderBlockMath(tex) {
|
|
30
30
|
try {
|
|
31
|
-
|
|
31
|
+
const math = mathjax.convert(tex);
|
|
32
32
|
return "<p>" + math + "</p>";
|
|
33
33
|
}
|
|
34
34
|
catch (err) {
|
|
@@ -43,8 +43,8 @@ function getRenderers(mathjax) {
|
|
|
43
43
|
return renderBlockMath(tokens[index].content + "\n");
|
|
44
44
|
}
|
|
45
45
|
return {
|
|
46
|
-
inlineRenderer
|
|
47
|
-
blockRenderer
|
|
46
|
+
inlineRenderer,
|
|
47
|
+
blockRenderer,
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
@@ -54,8 +54,8 @@ function getRenderers(mathjax) {
|
|
|
54
54
|
* @returns
|
|
55
55
|
*/
|
|
56
56
|
export function mdmath(math) {
|
|
57
|
-
|
|
58
|
-
return
|
|
57
|
+
const renderer = getRenderers(math);
|
|
58
|
+
return (md) => {
|
|
59
59
|
md.inline.ruler.after("escape", "math_inline", math_inline);
|
|
60
60
|
md.block.ruler.after("blockquote", "math_block", math_block, {
|
|
61
61
|
alt: ["paragraph", "reference", "blockquote", "list"],
|
package/dist/math/mdparser.js
CHANGED
|
@@ -8,141 +8,141 @@
|
|
|
8
8
|
* Assumes that there is a "$" at state.src[pos]
|
|
9
9
|
*/
|
|
10
10
|
function isValidDelim(state, pos) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
const max = state.posMax;
|
|
12
|
+
let can_open = true;
|
|
13
|
+
let can_close = true;
|
|
14
|
+
const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1;
|
|
15
|
+
const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1;
|
|
16
|
+
// Check non-whitespace conditions for opening and closing, and
|
|
17
|
+
// check that closing delimeter isn't followed by a number
|
|
18
|
+
if (prevChar === 0x20 /* " " */ ||
|
|
19
19
|
prevChar === 0x09 /* \t */ ||
|
|
20
20
|
(nextChar >= 0x30 /* "0" */ && nextChar <= 0x39) /* "9" */) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
can_close = false;
|
|
22
|
+
}
|
|
23
|
+
if (nextChar === 0x20 /* " " */ || nextChar === 0x09 /* \t */) {
|
|
24
|
+
can_open = false;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
can_open: can_open,
|
|
28
|
+
can_close: can_close,
|
|
29
|
+
};
|
|
30
30
|
}
|
|
31
31
|
export function math_inline(state, silent) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
state.pos += 1;
|
|
42
|
-
return true;
|
|
32
|
+
let match, token, res, pos;
|
|
33
|
+
if (state.src[state.pos] !== "$") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
res = isValidDelim(state, state.pos);
|
|
37
|
+
if (!res.can_open) {
|
|
38
|
+
if (!silent) {
|
|
39
|
+
state.pending += "$";
|
|
43
40
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
match += 1;
|
|
41
|
+
state.pos += 1;
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
// First check for and bypass all properly escaped delimieters
|
|
45
|
+
// This loop will assume that the first leading backtick can not
|
|
46
|
+
// be the first character in state.src, which is known since
|
|
47
|
+
// we have found an opening delimieter already.
|
|
48
|
+
const start = state.pos + 1;
|
|
49
|
+
match = start;
|
|
50
|
+
while ((match = state.src.indexOf("$", match)) !== -1) {
|
|
51
|
+
// Found potential $, look for escapes, pos will point to
|
|
52
|
+
// first non escape when complete
|
|
53
|
+
pos = match - 1;
|
|
54
|
+
while (state.src[pos] === "\\") {
|
|
55
|
+
pos -= 1;
|
|
62
56
|
}
|
|
63
|
-
//
|
|
64
|
-
if (match
|
|
65
|
-
|
|
66
|
-
state.pending += "$";
|
|
67
|
-
}
|
|
68
|
-
state.pos = start;
|
|
69
|
-
return true;
|
|
57
|
+
// Even number of escapes, potential closing delimiter found
|
|
58
|
+
if ((match - pos) % 2 == 1) {
|
|
59
|
+
break;
|
|
70
60
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
return true;
|
|
61
|
+
match += 1;
|
|
62
|
+
}
|
|
63
|
+
// No closing delimter found. Consume $ and continue.
|
|
64
|
+
if (match === -1) {
|
|
65
|
+
if (!silent) {
|
|
66
|
+
state.pending += "$";
|
|
78
67
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return true;
|
|
68
|
+
state.pos = start;
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
// Check if we have empty content, ie: $$. Do not parse.
|
|
72
|
+
if (match - start === 0) {
|
|
73
|
+
if (!silent) {
|
|
74
|
+
state.pending += "$$";
|
|
87
75
|
}
|
|
76
|
+
state.pos = start + 1;
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
// Check for valid closing delimiter
|
|
80
|
+
res = isValidDelim(state, match);
|
|
81
|
+
if (!res.can_close) {
|
|
88
82
|
if (!silent) {
|
|
89
|
-
|
|
90
|
-
token.markup = "$";
|
|
91
|
-
token.content = state.src.slice(start, match);
|
|
83
|
+
state.pending += "$";
|
|
92
84
|
}
|
|
93
|
-
state.pos =
|
|
85
|
+
state.pos = start;
|
|
94
86
|
return true;
|
|
87
|
+
}
|
|
88
|
+
if (!silent) {
|
|
89
|
+
token = state.push("math_inline", "math", 0);
|
|
90
|
+
token.markup = "$";
|
|
91
|
+
token.content = state.src.slice(start, match);
|
|
92
|
+
}
|
|
93
|
+
state.pos = match + 1;
|
|
94
|
+
return true;
|
|
95
95
|
}
|
|
96
96
|
export function math_block(state, start, end, silent) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
let firstLine;
|
|
98
|
+
let lastLine;
|
|
99
|
+
let next;
|
|
100
|
+
let lastPos;
|
|
101
|
+
let found = false;
|
|
102
|
+
let pos = state.bMarks[start] + state.tShift[start];
|
|
103
|
+
let max = state.eMarks[start];
|
|
104
|
+
if (pos + 2 > max) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if (state.src.slice(pos, pos + 2) !== "$$") {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
pos += 2;
|
|
111
|
+
firstLine = state.src.slice(pos, max);
|
|
112
|
+
if (silent) {
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
if (firstLine.trim().slice(-2) === "$$") {
|
|
116
|
+
// Single line expression
|
|
117
|
+
firstLine = firstLine.trim().slice(0, -2);
|
|
118
|
+
found = true;
|
|
119
|
+
}
|
|
120
|
+
for (next = start; !found;) {
|
|
121
|
+
next++;
|
|
122
|
+
if (next >= end) {
|
|
123
|
+
break;
|
|
114
124
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
pos = state.bMarks[next] + state.tShift[next];
|
|
126
|
+
max = state.eMarks[next];
|
|
127
|
+
if (pos < max && state.tShift[next] < state.blkIndent) {
|
|
128
|
+
// non-empty line with negative indent should stop the list:
|
|
129
|
+
break;
|
|
119
130
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
pos = state.bMarks[next] + state.tShift[next];
|
|
126
|
-
max = state.eMarks[next];
|
|
127
|
-
if (pos < max && state.tShift[next] < state.blkIndent) {
|
|
128
|
-
// non-empty line with negative indent should stop the list:
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
|
|
132
|
-
lastPos = state.src.slice(0, max).lastIndexOf("$$");
|
|
133
|
-
lastLine = state.src.slice(pos, lastPos);
|
|
134
|
-
found = true;
|
|
135
|
-
}
|
|
131
|
+
if (state.src.slice(pos, max).trim().slice(-2) === "$$") {
|
|
132
|
+
lastPos = state.src.slice(0, max).lastIndexOf("$$");
|
|
133
|
+
lastLine = state.src.slice(pos, lastPos);
|
|
134
|
+
found = true;
|
|
136
135
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
}
|
|
137
|
+
state.line = next + 1;
|
|
138
|
+
const token = state.push("math_block", "math", 0);
|
|
139
|
+
token.block = true;
|
|
140
|
+
token.content =
|
|
141
141
|
(firstLine && firstLine.trim() ? firstLine + "\n" : "") +
|
|
142
142
|
state.getLines(start + 1, next, state.tShift[start], true) +
|
|
143
143
|
(lastLine && lastLine.trim() ? lastLine : "");
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
token.map = [start, state.line];
|
|
145
|
+
token.markup = "$$";
|
|
146
|
+
return true;
|
|
147
147
|
}
|
|
148
148
|
//# sourceMappingURL=mdparser.js.map
|
package/package.json
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobapen/markdown",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A markdown converter for cobapen website",
|
|
5
|
+
"keywords": ["markdown"],
|
|
5
6
|
"license": "MIT",
|
|
6
7
|
"author": "yamavol",
|
|
7
8
|
"type": "module",
|
|
8
9
|
"main": "dist/index.js",
|
|
9
10
|
"types": "dist/index.d.ts",
|
|
10
|
-
"directories": {
|
|
11
|
-
"doc": "docs",
|
|
12
|
-
"test": "tests"
|
|
13
|
-
},
|
|
14
|
-
"keywords": [
|
|
15
|
-
"markdown"
|
|
16
|
-
],
|
|
17
11
|
"homepage": "https://github.com/cobapen/markdown#readme",
|
|
18
12
|
"bugs": {
|
|
19
13
|
"url": "https://github.com/cobapen/markdown/issues"
|
|
@@ -30,7 +24,10 @@
|
|
|
30
24
|
"build": "tsc",
|
|
31
25
|
"build:doc": "tsc && node docs/build.js",
|
|
32
26
|
"test": "vitest",
|
|
33
|
-
"coverage": "vitest run --coverage"
|
|
27
|
+
"coverage": "vitest run --coverage",
|
|
28
|
+
"lint": "eslint src",
|
|
29
|
+
"lint:fix": "eslint src --fix",
|
|
30
|
+
"lint:dist": "eslint dist --fix"
|
|
34
31
|
},
|
|
35
32
|
"dependencies": {
|
|
36
33
|
"highlight.js": "^11.11.1",
|