simple-customize-markdown-converter 1.0.2 → 1.0.3
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 +12 -5
- package/dist/lexer.d.ts +10 -0
- package/dist/lexer.js +109 -2
- package/dist/parser.d.ts +4 -0
- package/dist/parser.js +89 -1
- package/dist/renderer.js +13 -3
- package/dist/types/node.d.ts +22 -0
- package/dist/types/token.d.ts +25 -4
- package/package.json +40 -40
package/README.md
CHANGED
|
@@ -3,12 +3,19 @@ This simple library help you convert Markdown to HTML and customize it.
|
|
|
3
3
|
|
|
4
4
|
## Feature
|
|
5
5
|
Currently, this lib only supports:
|
|
6
|
-
- Headings (
|
|
6
|
+
- Headings (`#, ##, …`)
|
|
7
7
|
- Paragraphs
|
|
8
|
-
- Bold (
|
|
9
|
-
- Italic (
|
|
10
|
-
-
|
|
11
|
-
-
|
|
8
|
+
- Bold (`\*\*text\*\*`)
|
|
9
|
+
- Italic (`\*text\* or \_text\_`)
|
|
10
|
+
- Strikethrough (`\~\~text\~\~`)
|
|
11
|
+
- Inline code (`\`code\``)
|
|
12
|
+
- Code blocks (`\`\`\`lang ... \`\`\``)
|
|
13
|
+
- Quote (`> text`)
|
|
14
|
+
- List (`- Item 1,...`)
|
|
15
|
+
- Tasklist (`- [ ], - \[x\]`)
|
|
16
|
+
- Link (`\[link\]\(url\)`)
|
|
17
|
+
- Image (`\[alt\]\(url\)`)
|
|
18
|
+
- Horizontal line (`---` or `***` or `___`)
|
|
12
19
|
|
|
13
20
|
And customizable renderer for all elements
|
|
14
21
|
|
package/dist/lexer.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export default class Lexer {
|
|
|
3
3
|
input: string;
|
|
4
4
|
pos: number;
|
|
5
5
|
listToken: Token[];
|
|
6
|
+
listLevelFlag: number;
|
|
6
7
|
constructor(input: string);
|
|
7
8
|
/**
|
|
8
9
|
* Tokenize the markdown into a list of tokens.
|
|
@@ -19,9 +20,18 @@ export default class Lexer {
|
|
|
19
20
|
private handleTextBlock;
|
|
20
21
|
private handleItalic;
|
|
21
22
|
private handleBold;
|
|
23
|
+
private handleStrikethrough;
|
|
22
24
|
private handleInlineBlock;
|
|
23
25
|
private handleQuoteBlock;
|
|
26
|
+
private handleList;
|
|
27
|
+
private handleStartList;
|
|
28
|
+
private handleListItem;
|
|
29
|
+
private handleTaskItem;
|
|
30
|
+
private handleEndList;
|
|
24
31
|
private handleLink;
|
|
25
32
|
private handleImage;
|
|
33
|
+
private handleHorizontalLine;
|
|
26
34
|
private readUntil;
|
|
35
|
+
private peekUntil;
|
|
36
|
+
private isStartOfLine;
|
|
27
37
|
}
|
package/dist/lexer.js
CHANGED
|
@@ -4,6 +4,8 @@ class Lexer {
|
|
|
4
4
|
constructor(input) {
|
|
5
5
|
this.pos = 0;
|
|
6
6
|
this.listToken = [];
|
|
7
|
+
// Flag for handle special syntax
|
|
8
|
+
this.listLevelFlag = 0;
|
|
7
9
|
this.input = input;
|
|
8
10
|
}
|
|
9
11
|
/**
|
|
@@ -12,8 +14,46 @@ class Lexer {
|
|
|
12
14
|
*/
|
|
13
15
|
tokenize() {
|
|
14
16
|
const TOKEN_HANDLER = [
|
|
17
|
+
//Handle escape character first
|
|
18
|
+
{
|
|
19
|
+
match: (lex) => lex.peek() === "\\" && lex.peek(1) !== undefined,
|
|
20
|
+
emit: (lex) => {
|
|
21
|
+
lex.next(1);
|
|
22
|
+
lex.handleTextBlock();
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
//Regex: if line started with at least 3 characters: -, *, _
|
|
27
|
+
match: (lex) => /^([-*_])\1{2,}$/.test(lex.peekUntil("\n").trim()) && this.getLastToken()?.type === "NewLine",
|
|
28
|
+
emit: (lex) => lex.handleHorizontalLine()
|
|
29
|
+
},
|
|
15
30
|
{ match: (lex) => lex.startsWith("```"), emit: (lex) => lex.handleCodeBlock() },
|
|
16
31
|
{ match: (lex) => lex.startsWith("**"), emit: (lex) => lex.handleBold() },
|
|
32
|
+
{ match: (lex) => lex.startsWith("~~"), emit: (lex) => lex.handleStrikethrough() },
|
|
33
|
+
//For List
|
|
34
|
+
{
|
|
35
|
+
match: (lex) => lex.isStartOfLine() && /^(\s*)([-*+]) \[( |x|X)\] /.test(lex.peekUntil("\n")),
|
|
36
|
+
emit: (lex) => lex.handleList(false, true)
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
//Regex: if line started with zero or more spaces, then have - or + or * + 1 space
|
|
40
|
+
match: (lex) => lex.isStartOfLine() && /^(\s*)([-*+]) /.test(lex.peekUntil("\n")),
|
|
41
|
+
emit: (lex) => lex.handleList(false, false)
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
//Regex: if line started with zero or more spaces, then have number. character + 1 space
|
|
45
|
+
match: (lex) => lex.isStartOfLine() && /^(\s*)(\d+)\. /.test(lex.peekUntil("\n")),
|
|
46
|
+
emit: (lex) => lex.handleList(true, false)
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
match: (lex) => lex.listLevelFlag > 0 && lex.isStartOfLine() && !/^(\s*)([-+*]|\d+\.) /.test(lex.peekUntil("\n")),
|
|
50
|
+
emit: (lex) => {
|
|
51
|
+
while (lex.listLevelFlag > 0) {
|
|
52
|
+
lex.handleEndList();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
//For common syntax
|
|
17
57
|
{ match: (lex) => lex.peek() === "`", emit: (lex) => lex.handleInlineBlock() },
|
|
18
58
|
{ match: (lex) => lex.peek() === "#", emit: (lex) => lex.handleHeader() },
|
|
19
59
|
{ match: (lex) => lex.peek() === "*" || lex.peek() === "_", emit: (lex) => lex.handleItalic() },
|
|
@@ -36,6 +76,9 @@ class Lexer {
|
|
|
36
76
|
}
|
|
37
77
|
this.next();
|
|
38
78
|
}
|
|
79
|
+
while (this.listLevelFlag > 0) {
|
|
80
|
+
this.handleEndList();
|
|
81
|
+
}
|
|
39
82
|
this.listToken.push({ type: "EOF" });
|
|
40
83
|
return this.listToken;
|
|
41
84
|
}
|
|
@@ -101,7 +144,11 @@ class Lexer {
|
|
|
101
144
|
}
|
|
102
145
|
handleBold() {
|
|
103
146
|
this.listToken.push({ type: "Bold" });
|
|
104
|
-
this.next(); //Skip *
|
|
147
|
+
this.next(); //Skip remain *
|
|
148
|
+
}
|
|
149
|
+
handleStrikethrough() {
|
|
150
|
+
this.listToken.push({ type: "Strikethrough" });
|
|
151
|
+
this.next(); //Skip remain ~
|
|
105
152
|
}
|
|
106
153
|
handleInlineBlock() {
|
|
107
154
|
let content = "";
|
|
@@ -110,12 +157,51 @@ class Lexer {
|
|
|
110
157
|
content += this.peek();
|
|
111
158
|
this.next();
|
|
112
159
|
}
|
|
113
|
-
// this.next() //Skip close block
|
|
114
160
|
this.listToken.push({ "type": "InlineCode", content: content });
|
|
115
161
|
}
|
|
116
162
|
handleQuoteBlock() {
|
|
117
163
|
this.listToken.push({ type: "Quote" });
|
|
118
164
|
}
|
|
165
|
+
handleList(isOrdered, isTask) {
|
|
166
|
+
const line = this.peekUntil("\n");
|
|
167
|
+
if (isTask) {
|
|
168
|
+
const m = line.match(/^(\s*)([-*+]) \[( |x|X)\] (.*)$/);
|
|
169
|
+
const indent = Math.floor(m[1].length / 2) + 1;
|
|
170
|
+
while (this.listLevelFlag < indent)
|
|
171
|
+
this.handleStartList(false);
|
|
172
|
+
while (this.listLevelFlag > indent)
|
|
173
|
+
this.handleEndList();
|
|
174
|
+
this.next(m[1].length + 4);
|
|
175
|
+
this.handleTaskItem(m[3].toLowerCase() === "x");
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
//Regex: line started with: Group 1: zero or more spaces, group 2: (- or + or * + 1 space) or (number with . character), group 3: everything else in line
|
|
179
|
+
const m = isOrdered ? line.match(/^(\s*)(\d+)\. (.*)$/) : line.match(/^(\s*)([-*+]) (.*)$/);
|
|
180
|
+
const indent = Math.floor(m[1].length / 2) + 1; //m[1] to get the spaces in group 1
|
|
181
|
+
while (this.listLevelFlag < indent)
|
|
182
|
+
this.handleStartList(isOrdered);
|
|
183
|
+
while (this.listLevelFlag > indent)
|
|
184
|
+
this.handleEndList();
|
|
185
|
+
this.next(m[1].length + (isOrdered ? 1 : 0)); //+1 due to marker have 2 characters (e.g: 1.) instead 1 like unordered list
|
|
186
|
+
this.handleListItem();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
handleStartList(isOrder) {
|
|
190
|
+
this.listLevelFlag++;
|
|
191
|
+
this.listToken.push({ type: "ListStart", level: this.listLevelFlag, ordered: isOrder });
|
|
192
|
+
}
|
|
193
|
+
handleListItem() {
|
|
194
|
+
this.next(); // Skip space between - and text
|
|
195
|
+
this.listToken.push({ type: "ListItem" });
|
|
196
|
+
}
|
|
197
|
+
handleTaskItem(isChecked) {
|
|
198
|
+
this.next(); // Skip space between last ] and text
|
|
199
|
+
this.listToken.push({ type: "TaskItem", checked: isChecked });
|
|
200
|
+
}
|
|
201
|
+
handleEndList() {
|
|
202
|
+
this.listLevelFlag === 0 ? 0 : this.listLevelFlag--;
|
|
203
|
+
this.listToken.push({ type: "ListEnd" });
|
|
204
|
+
}
|
|
119
205
|
handleLink() {
|
|
120
206
|
this.next(); //Skip [
|
|
121
207
|
const text = this.readUntil("]");
|
|
@@ -145,6 +231,11 @@ class Lexer {
|
|
|
145
231
|
else
|
|
146
232
|
this.listToken.push({ type: "Text", value: `![${alt}]` });
|
|
147
233
|
}
|
|
234
|
+
handleHorizontalLine() {
|
|
235
|
+
this.next(2); //Skip two first characters, remain will be skiped after loop
|
|
236
|
+
this.listToken.push({ type: "HorizontalLine" });
|
|
237
|
+
}
|
|
238
|
+
//Utilities function
|
|
148
239
|
readUntil(char) {
|
|
149
240
|
let result = "";
|
|
150
241
|
while (this.peek() !== char) {
|
|
@@ -153,5 +244,21 @@ class Lexer {
|
|
|
153
244
|
}
|
|
154
245
|
return result;
|
|
155
246
|
}
|
|
247
|
+
peekUntil(char) {
|
|
248
|
+
let result = "";
|
|
249
|
+
let i = 0;
|
|
250
|
+
while (true) {
|
|
251
|
+
const current = this.peek(i++);
|
|
252
|
+
if (current == null)
|
|
253
|
+
break;
|
|
254
|
+
if (current == char)
|
|
255
|
+
break;
|
|
256
|
+
result += current;
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
isStartOfLine() {
|
|
261
|
+
return this.pos === 0 || this.peek(-1) === "\n";
|
|
262
|
+
}
|
|
156
263
|
}
|
|
157
264
|
exports.default = Lexer;
|
package/dist/parser.d.ts
CHANGED
|
@@ -18,9 +18,13 @@ export declare class Parser {
|
|
|
18
18
|
private parseHeader;
|
|
19
19
|
private parseBold;
|
|
20
20
|
private parseItalic;
|
|
21
|
+
private parseStrikethrough;
|
|
21
22
|
private parseInlineCode;
|
|
22
23
|
private parseQuote;
|
|
24
|
+
private parseList;
|
|
25
|
+
private parseListItem;
|
|
23
26
|
private parseLink;
|
|
24
27
|
private parseImage;
|
|
28
|
+
private parseHorizontalLine;
|
|
25
29
|
private parseInlineUntil;
|
|
26
30
|
}
|
package/dist/parser.js
CHANGED
|
@@ -49,6 +49,14 @@ class Parser {
|
|
|
49
49
|
listNode.push(this.parseImage());
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
52
|
+
case "HorizontalLine": {
|
|
53
|
+
listNode.push(this.parseHorizontalLine());
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "ListStart": {
|
|
57
|
+
listNode.push(this.parseList());
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
52
60
|
case "NewLine": {
|
|
53
61
|
this.next(); // skip
|
|
54
62
|
break;
|
|
@@ -90,6 +98,10 @@ class Parser {
|
|
|
90
98
|
this.next(); // skip marker
|
|
91
99
|
return { type: "Italic", children: this.parseInlineUntil("Italic") };
|
|
92
100
|
}
|
|
101
|
+
parseStrikethrough() {
|
|
102
|
+
this.next(); // skip marker
|
|
103
|
+
return { type: "Strikethrough", children: this.parseInlineUntil("Strikethrough") };
|
|
104
|
+
}
|
|
93
105
|
parseInlineCode() {
|
|
94
106
|
const tok = this.peek();
|
|
95
107
|
this.next();
|
|
@@ -102,6 +114,70 @@ class Parser {
|
|
|
102
114
|
this.next(); //skip marker
|
|
103
115
|
return { type: "Quote", children: [{ type: "Paragraph", children: this.parseInlineUntil("NewLine") }] };
|
|
104
116
|
}
|
|
117
|
+
parseList() {
|
|
118
|
+
const tok = this.peek();
|
|
119
|
+
if (tok?.type === "ListStart") {
|
|
120
|
+
this.next(); //skip marker
|
|
121
|
+
const result = {
|
|
122
|
+
type: "List",
|
|
123
|
+
level: tok.level,
|
|
124
|
+
ordered: tok.ordered,
|
|
125
|
+
children: [],
|
|
126
|
+
};
|
|
127
|
+
let nextToken = this.peek();
|
|
128
|
+
while (!this.isEnd()) {
|
|
129
|
+
if (nextToken?.type === "ListItem" || nextToken?.type === "TaskItem") {
|
|
130
|
+
result.children.push(this.parseListItem());
|
|
131
|
+
nextToken = this.peek();
|
|
132
|
+
}
|
|
133
|
+
else if (nextToken?.type === "ListEnd") {
|
|
134
|
+
this.next();
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
else
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
//Temp return
|
|
143
|
+
return {
|
|
144
|
+
type: "Text",
|
|
145
|
+
value: ""
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
parseListItem() {
|
|
149
|
+
const currentToken = this.peek();
|
|
150
|
+
this.next(); // skip marker
|
|
151
|
+
const children = [];
|
|
152
|
+
while (!this.isEnd()) {
|
|
153
|
+
const tok = this.peek();
|
|
154
|
+
if (!tok)
|
|
155
|
+
break;
|
|
156
|
+
if (tok.type === "NewLine") {
|
|
157
|
+
this.next();
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (tok.type === "ListStart") {
|
|
161
|
+
children.push(this.parseList());
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (["ListItem", "TaskItem", "ListEnd"].includes(tok.type)) {
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
children.push({
|
|
168
|
+
type: "Paragraph",
|
|
169
|
+
children: this.parseInlineUntil("NewLine")
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
return currentToken?.type === "TaskItem" ? {
|
|
173
|
+
type: "TaskItem",
|
|
174
|
+
checked: currentToken.type === "TaskItem" ? currentToken.checked : false,
|
|
175
|
+
children: children
|
|
176
|
+
} : {
|
|
177
|
+
type: "ListItem",
|
|
178
|
+
children: children
|
|
179
|
+
};
|
|
180
|
+
}
|
|
105
181
|
parseLink() {
|
|
106
182
|
const tok = this.peek();
|
|
107
183
|
this.next();
|
|
@@ -127,12 +203,20 @@ class Parser {
|
|
|
127
203
|
else
|
|
128
204
|
return { type: "Image", src: "", alt: "" };
|
|
129
205
|
}
|
|
206
|
+
parseHorizontalLine() {
|
|
207
|
+
const tok = this.peek();
|
|
208
|
+
this.next(); // skip marker
|
|
209
|
+
return { type: "HorizontalLine" };
|
|
210
|
+
}
|
|
130
211
|
parseInlineUntil(stopType) {
|
|
212
|
+
const stop = Array.isArray(stopType) ? stopType : [stopType];
|
|
131
213
|
const listNode = [];
|
|
132
|
-
while (!this.isEnd()
|
|
214
|
+
while (!this.isEnd()) {
|
|
133
215
|
const currentNode = this.peek();
|
|
134
216
|
if (!currentNode)
|
|
135
217
|
break;
|
|
218
|
+
if (stop.includes(currentNode.type))
|
|
219
|
+
break;
|
|
136
220
|
switch (currentNode.type) {
|
|
137
221
|
case "Bold": {
|
|
138
222
|
listNode.push(this.parseBold());
|
|
@@ -142,6 +226,10 @@ class Parser {
|
|
|
142
226
|
listNode.push(this.parseItalic());
|
|
143
227
|
break;
|
|
144
228
|
}
|
|
229
|
+
case "Strikethrough": {
|
|
230
|
+
listNode.push(this.parseStrikethrough());
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
145
233
|
case "InlineCode": {
|
|
146
234
|
listNode.push(this.parseInlineCode());
|
|
147
235
|
break;
|
package/dist/renderer.js
CHANGED
|
@@ -19,16 +19,26 @@ class Renderer {
|
|
|
19
19
|
}
|
|
20
20
|
handleRender(type) {
|
|
21
21
|
const defaultRender = {
|
|
22
|
+
//Base structural nodes
|
|
22
23
|
Document: (_node, children) => children.join(""),
|
|
23
24
|
Paragraph: (_node, children) => `<p>${children.join("")}</p>`,
|
|
24
|
-
|
|
25
|
-
InlineCode: (node) => `<code>${this.escapeHtml(node.content)}</code>`,
|
|
25
|
+
//Container nodes
|
|
26
26
|
CodeBlock: (node) => `<pre><code class="lang-${node.lang}">${this.escapeHtml(node.content)}</code></pre>`,
|
|
27
|
+
Header: (node, children) => `<h${node.level}${node.level <= 2 ? ' style="border-bottom: 1px solid #d1d9e0b3"' : ''}>${children.join("")}</h${node.level}>`,
|
|
28
|
+
Quote: (_node, children) => `<blockquote>${children.join("")}</blockquote>`,
|
|
29
|
+
List: (node, children) => node.ordered ? `<ol>${children.join("")}</ol>` : `<ul>${children.join("")}</ul>`,
|
|
30
|
+
ListItem: (_node, children) => `<li>${children.join("")}</li>`,
|
|
31
|
+
TaskItem: (node, children) => `<li><input type="checkbox" disabled ${node.checked ? "checked" : ""}>${children.join("")}</li>`,
|
|
32
|
+
//Styling nodes
|
|
27
33
|
Bold: (_node, children) => `<strong>${children.join("")}</strong>`,
|
|
28
34
|
Italic: (_node, children) => `<em>${children.join("")}</em>`,
|
|
29
|
-
|
|
35
|
+
Strikethrough: (_node, children) => `<s>${children.join("")}</s>`,
|
|
36
|
+
InlineCode: (node) => `<code>${this.escapeHtml(node.content)}</code>`,
|
|
37
|
+
//Media nodes
|
|
30
38
|
Link: (node) => `<a href="${node.href}">${node.text}</a>`,
|
|
31
39
|
Image: (node) => `<img src="${node.src}" alt="${node.alt}"/>`,
|
|
40
|
+
//Leaf nodes
|
|
41
|
+
HorizontalLine: (_node) => `<hr>`,
|
|
32
42
|
Text: (node) => node.value,
|
|
33
43
|
};
|
|
34
44
|
return this.option.elements?.[type] ?? defaultRender[type];
|
package/dist/types/node.d.ts
CHANGED
|
@@ -10,11 +10,16 @@
|
|
|
10
10
|
* - Header: A header with given `level` (1-6)
|
|
11
11
|
* - Bold: Bold text
|
|
12
12
|
* - Italic: Italic text
|
|
13
|
+
* - Strikethrough: Strilethrough text
|
|
13
14
|
* - InlineCode: Inline code snippet, with it's `content`
|
|
14
15
|
* - Quote: A quote block
|
|
15
16
|
* - CodeBlock: A code block, with it's `lang` and `content`
|
|
17
|
+
* - List: A list, with it's level and children
|
|
18
|
+
* - ListItem: An item of a list, with it's children
|
|
19
|
+
* - TaskItem: An item for tasklist, with it's checked state
|
|
16
20
|
* - Link: A link, with it's `text` and `href`
|
|
17
21
|
* - Image: An image, with it's `src` and `alt`
|
|
22
|
+
* - HorizontalLine: A horizontal line
|
|
18
23
|
* - Text: Raw text content.
|
|
19
24
|
*/
|
|
20
25
|
export type Node = {
|
|
@@ -33,6 +38,9 @@ export type Node = {
|
|
|
33
38
|
} | {
|
|
34
39
|
type: "Italic";
|
|
35
40
|
children: Node[];
|
|
41
|
+
} | {
|
|
42
|
+
type: "Strikethrough";
|
|
43
|
+
children: Node[];
|
|
36
44
|
} | {
|
|
37
45
|
type: "InlineCode";
|
|
38
46
|
content: string;
|
|
@@ -43,6 +51,18 @@ export type Node = {
|
|
|
43
51
|
} | {
|
|
44
52
|
type: "Quote";
|
|
45
53
|
children: Node[];
|
|
54
|
+
} | {
|
|
55
|
+
type: "List";
|
|
56
|
+
ordered: boolean;
|
|
57
|
+
level: number;
|
|
58
|
+
children: Node[];
|
|
59
|
+
} | {
|
|
60
|
+
type: "ListItem";
|
|
61
|
+
children: Node[];
|
|
62
|
+
} | {
|
|
63
|
+
type: "TaskItem";
|
|
64
|
+
checked: boolean;
|
|
65
|
+
children: Node[];
|
|
46
66
|
} | {
|
|
47
67
|
type: "Link";
|
|
48
68
|
href: string;
|
|
@@ -51,6 +71,8 @@ export type Node = {
|
|
|
51
71
|
type: "Image";
|
|
52
72
|
src: string;
|
|
53
73
|
alt: string;
|
|
74
|
+
} | {
|
|
75
|
+
type: "HorizontalLine";
|
|
54
76
|
} | {
|
|
55
77
|
type: "Text";
|
|
56
78
|
value: string;
|
package/dist/types/token.d.ts
CHANGED
|
@@ -8,13 +8,19 @@
|
|
|
8
8
|
* - Header: Markdown header (`#`), with a `level` (1–6).
|
|
9
9
|
* - CodeBlock: Fenced code block (` ``` `), with optional `lang` and its `content`.
|
|
10
10
|
* - NewLine: Line break (`\n`).
|
|
11
|
-
* - Text: Plain text content.
|
|
12
11
|
* - Bold: Bold marker (`**`).
|
|
13
12
|
* - Italic: Italic marker (`*` or `_`).
|
|
13
|
+
* - Strikethrough: Strikethrough marker (`~~`)
|
|
14
14
|
* - InlineCode: Inline code snippet (`` ` ``), with its `content`.
|
|
15
15
|
* - Quote: A quote block (`>`).
|
|
16
|
+
* - ListStart: Start a list
|
|
17
|
+
* - ListItem: A list's item (`* ` or `+ ` or `- ` or `number with dot`)
|
|
18
|
+
* - TaskItem: A task item in a list (`- [ ]` or `- [x]`)
|
|
19
|
+
* - ListEnd: End a list
|
|
16
20
|
* - Link: A link (`[text](url)`)
|
|
17
21
|
* - Image: An image (``)
|
|
22
|
+
* - HorizontalLine: A horizontal line (`---` or `___` or `***`)
|
|
23
|
+
* - Text: Plain text content.
|
|
18
24
|
* - EOF: A special token, this is the end of input.
|
|
19
25
|
*/
|
|
20
26
|
export type Token = {
|
|
@@ -26,18 +32,28 @@ export type Token = {
|
|
|
26
32
|
content: string;
|
|
27
33
|
} | {
|
|
28
34
|
type: "NewLine";
|
|
29
|
-
} | {
|
|
30
|
-
type: "Text";
|
|
31
|
-
value: string;
|
|
32
35
|
} | {
|
|
33
36
|
type: "Bold";
|
|
34
37
|
} | {
|
|
35
38
|
type: "Italic";
|
|
39
|
+
} | {
|
|
40
|
+
type: "Strikethrough";
|
|
36
41
|
} | {
|
|
37
42
|
type: "InlineCode";
|
|
38
43
|
content: string;
|
|
39
44
|
} | {
|
|
40
45
|
type: "Quote";
|
|
46
|
+
} | {
|
|
47
|
+
type: "ListStart";
|
|
48
|
+
ordered: boolean;
|
|
49
|
+
level: number;
|
|
50
|
+
} | {
|
|
51
|
+
type: "ListItem";
|
|
52
|
+
} | {
|
|
53
|
+
type: "TaskItem";
|
|
54
|
+
checked: boolean;
|
|
55
|
+
} | {
|
|
56
|
+
type: "ListEnd";
|
|
41
57
|
} | {
|
|
42
58
|
type: "Link";
|
|
43
59
|
text: string;
|
|
@@ -46,6 +62,11 @@ export type Token = {
|
|
|
46
62
|
type: "Image";
|
|
47
63
|
src: string;
|
|
48
64
|
alt: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "HorizontalLine";
|
|
67
|
+
} | {
|
|
68
|
+
type: "Text";
|
|
69
|
+
value: string;
|
|
49
70
|
} | {
|
|
50
71
|
type: "EOF";
|
|
51
72
|
};
|
package/package.json
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "simple-customize-markdown-converter",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Convert Markdown to your customize HTML",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"markdown",
|
|
7
|
-
"html",
|
|
8
|
-
"converter"
|
|
9
|
-
],
|
|
10
|
-
"author": "Regiko04",
|
|
11
|
-
"license": "MIT",
|
|
12
|
-
"main": "dist/index.js",
|
|
13
|
-
"module": "dist/index.js",
|
|
14
|
-
"types": "dist/index.d.ts",
|
|
15
|
-
"files": [
|
|
16
|
-
"dist",
|
|
17
|
-
"LICENSE",
|
|
18
|
-
"README.md"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"test": "jest",
|
|
22
|
-
"build": "tsc",
|
|
23
|
-
"start": "ts-node src/index.ts"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@types/jest": "^30.0.0",
|
|
27
|
-
"@types/node": "^24.3.3",
|
|
28
|
-
"jest": "^30.1.3",
|
|
29
|
-
"ts-jest": "^29.4.1",
|
|
30
|
-
"ts-node": "^10.9.2",
|
|
31
|
-
"typescript": "^5.9.2"
|
|
32
|
-
},
|
|
33
|
-
"repository": {
|
|
34
|
-
"type": "git",
|
|
35
|
-
"url": "git+https://github.com/Riiichan04/simple-custom-markdown-converter.git"
|
|
36
|
-
},
|
|
37
|
-
"bugs": {
|
|
38
|
-
"url": "https://github.com/Riiichan04/simple-custom-markdown-converter/issues"
|
|
39
|
-
},
|
|
40
|
-
"homepage": "https://github.com/Riiichan04/simple-custom-markdown-converter#readme"
|
|
1
|
+
{
|
|
2
|
+
"name": "simple-customize-markdown-converter",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Convert Markdown to your customize HTML",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"markdown",
|
|
7
|
+
"html",
|
|
8
|
+
"converter"
|
|
9
|
+
],
|
|
10
|
+
"author": "Regiko04",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"module": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"LICENSE",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"test": "jest",
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"start": "ts-node src/index.ts"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/jest": "^30.0.0",
|
|
27
|
+
"@types/node": "^24.3.3",
|
|
28
|
+
"jest": "^30.1.3",
|
|
29
|
+
"ts-jest": "^29.4.1",
|
|
30
|
+
"ts-node": "^10.9.2",
|
|
31
|
+
"typescript": "^5.9.2"
|
|
32
|
+
},
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/Riiichan04/simple-custom-markdown-converter.git"
|
|
36
|
+
},
|
|
37
|
+
"bugs": {
|
|
38
|
+
"url": "https://github.com/Riiichan04/simple-custom-markdown-converter/issues"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/Riiichan04/simple-custom-markdown-converter#readme"
|
|
41
41
|
}
|