amateras 0.7.4 → 0.10.1
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 +76 -85
- package/package.json +29 -33
- package/tsconfig.json +4 -3
- package/packages/core/package.json +0 -32
- package/packages/core/src/env.browser.ts +0 -21
- package/packages/core/src/env.node.ts +0 -21
- package/packages/core/src/global.ts +0 -18
- package/packages/core/src/index.ts +0 -96
- package/packages/core/src/lib/assignNodeProperties.ts +0 -11
- package/packages/core/src/lib/assignProperties.ts +0 -57
- package/packages/core/src/lib/chain.ts +0 -17
- package/packages/core/src/lib/dom.ts +0 -20
- package/packages/core/src/main.ts +0 -4
- package/packages/core/src/node/$Element.ts +0 -366
- package/packages/core/src/node/$EventTarget.ts +0 -48
- package/packages/core/src/node/$HTMLElement.ts +0 -99
- package/packages/core/src/node/$Node.ts +0 -201
- package/packages/core/src/node/$Virtual.ts +0 -65
- package/packages/css/README.md +0 -128
- package/packages/css/package.json +0 -17
- package/packages/css/src/ext/colors/amber.ts +0 -25
- package/packages/css/src/ext/colors/blackwhite.ts +0 -13
- package/packages/css/src/ext/colors/blue.ts +0 -25
- package/packages/css/src/ext/colors/cyan.ts +0 -25
- package/packages/css/src/ext/colors/emerald.ts +0 -25
- package/packages/css/src/ext/colors/fuchsia.ts +0 -25
- package/packages/css/src/ext/colors/gray.ts +0 -25
- package/packages/css/src/ext/colors/green.ts +0 -25
- package/packages/css/src/ext/colors/indigo.ts +0 -25
- package/packages/css/src/ext/colors/lime.ts +0 -25
- package/packages/css/src/ext/colors/neutral.ts +0 -25
- package/packages/css/src/ext/colors/orange.ts +0 -25
- package/packages/css/src/ext/colors/pink.ts +0 -25
- package/packages/css/src/ext/colors/purple.ts +0 -25
- package/packages/css/src/ext/colors/red.ts +0 -25
- package/packages/css/src/ext/colors/rose.ts +0 -25
- package/packages/css/src/ext/colors/sky.ts +0 -25
- package/packages/css/src/ext/colors/slate.ts +0 -25
- package/packages/css/src/ext/colors/stone.ts +0 -25
- package/packages/css/src/ext/colors/teal.ts +0 -25
- package/packages/css/src/ext/colors/violet.ts +0 -25
- package/packages/css/src/ext/colors/yellow.ts +0 -25
- package/packages/css/src/ext/colors/zinc.ts +0 -25
- package/packages/css/src/ext/colors.ts +0 -23
- package/packages/css/src/ext/container.ts +0 -32
- package/packages/css/src/ext/keyframes.ts +0 -54
- package/packages/css/src/ext/media.ts +0 -32
- package/packages/css/src/ext/property.ts +0 -48
- package/packages/css/src/ext/variable.ts +0 -51
- package/packages/css/src/index.ts +0 -436
- package/packages/css/src/lib/colorAssign.ts +0 -6
- package/packages/css/src/lib/utils.ts +0 -11
- package/packages/css/src/structure/$CSSContainerRule.ts +0 -13
- package/packages/css/src/structure/$CSSDeclaration.ts +0 -16
- package/packages/css/src/structure/$CSSKeyframesRule.ts +0 -13
- package/packages/css/src/structure/$CSSMediaRule.ts +0 -10
- package/packages/css/src/structure/$CSSProperty.ts +0 -19
- package/packages/css/src/structure/$CSSRule.ts +0 -13
- package/packages/css/src/structure/$CSSStyleRule.ts +0 -14
- package/packages/css/src/structure/$CSSVariable.ts +0 -30
- package/packages/dom/package.json +0 -20
- package/packages/dom/src/lib/HTMLElementMap.ts +0 -213
- package/packages/dom/src/lib/assignAttributes.ts +0 -16
- package/packages/dom/src/structure/CSS.ts +0 -7
- package/packages/dom/src/structure/CSSStyleSheet.ts +0 -10
- package/packages/dom/src/structure/DOMTokenList.ts +0 -19
- package/packages/dom/src/structure/Document.ts +0 -36
- package/packages/dom/src/structure/Element.ts +0 -106
- package/packages/dom/src/structure/HTMLElement.ts +0 -34
- package/packages/dom/src/structure/History.ts +0 -11
- package/packages/dom/src/structure/Location.ts +0 -9
- package/packages/dom/src/structure/Node.ts +0 -51
- package/packages/dom/src/structure/NodeList.ts +0 -10
- package/packages/dom/src/structure/Storage.ts +0 -8
- package/packages/dom/src/structure/Text.ts +0 -20
- package/packages/dom/src/structure/Window.ts +0 -14
- package/packages/dom/src/structure/html/HTMLAbbrElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLAddressElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLAnchorElement.ts +0 -25
- package/packages/dom/src/structure/html/HTMLAreaElement.ts +0 -26
- package/packages/dom/src/structure/html/HTMLArticleElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLAsideElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLAudioElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLBDIElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLBDOElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLBElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLBRElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLBaseElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLBodyElement.ts +0 -22
- package/packages/dom/src/structure/html/HTMLButtonElement.ts +0 -26
- package/packages/dom/src/structure/html/HTMLCanvasElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLCiteElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLCodeElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLDDElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLDFNElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLDListElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLDTElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLDataElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLDataListElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLDetailsElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLDialogElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLDivElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLEMElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLEmbedElement.ts +0 -20
- package/packages/dom/src/structure/html/HTMLFieldSetElement.ts +0 -19
- package/packages/dom/src/structure/html/HTMLFigCaptionElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLFigureElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLFooterElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLFormElement.ts +0 -24
- package/packages/dom/src/structure/html/HTMLHGroupElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLHRElement.ts +0 -21
- package/packages/dom/src/structure/html/HTMLHeadElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLHeaderElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLHeadingElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLHtmlElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLIElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLIFrameElement.ts +0 -31
- package/packages/dom/src/structure/html/HTMLImageElement.ts +0 -38
- package/packages/dom/src/structure/html/HTMLInputElement.ts +0 -55
- package/packages/dom/src/structure/html/HTMLKBDElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLLIElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLLabelElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLLegendElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLLinkElement.ts +0 -31
- package/packages/dom/src/structure/html/HTMLMainElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLMapElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLMarkElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLMediaElement.ts +0 -48
- package/packages/dom/src/structure/html/HTMLMenuElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLMetaElement.ts +0 -22
- package/packages/dom/src/structure/html/HTMLMeterElement.ts +0 -23
- package/packages/dom/src/structure/html/HTMLModElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLNavElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLNoscriptElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLOListElement.ts +0 -20
- package/packages/dom/src/structure/html/HTMLObjectElement.ts +0 -34
- package/packages/dom/src/structure/html/HTMLOptGroupElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLOptionElement.ts +0 -20
- package/packages/dom/src/structure/html/HTMLOutputElement.ts +0 -20
- package/packages/dom/src/structure/html/HTMLParagraphElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLPictureElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLPreElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLProgressElement.ts +0 -19
- package/packages/dom/src/structure/html/HTMLQuoteElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLRPElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLRTElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLRubyElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSampElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLScriptElement.ts +0 -27
- package/packages/dom/src/structure/html/HTMLSectionElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSelectElement.ts +0 -27
- package/packages/dom/src/structure/html/HTMLSlotElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLSmallElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSourceElement.ts +0 -21
- package/packages/dom/src/structure/html/HTMLSpanElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLStrongElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLStyleElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLSubElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSummaryElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLSupElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLTableCaptionElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLTableCellElement.ts +0 -31
- package/packages/dom/src/structure/html/HTMLTableColElement.ts +0 -23
- package/packages/dom/src/structure/html/HTMLTableElement.ts +0 -26
- package/packages/dom/src/structure/html/HTMLTableRowElement.ts +0 -23
- package/packages/dom/src/structure/html/HTMLTableSectionElement.ts +0 -20
- package/packages/dom/src/structure/html/HTMLTemplateElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLTextAreaElement.ts +0 -33
- package/packages/dom/src/structure/html/HTMLTimeElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLTitleElement.ts +0 -17
- package/packages/dom/src/structure/html/HTMLTrackElement.ts +0 -21
- package/packages/dom/src/structure/html/HTMLUElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLUListElement.ts +0 -18
- package/packages/dom/src/structure/html/HTMLVarElement.ts +0 -16
- package/packages/dom/src/structure/html/HTMLVideoElement.ts +0 -22
- package/packages/dom/src/structure/html/HTMLWBRElement.ts +0 -16
- package/packages/html/package.json +0 -18
- package/packages/html/src/index.ts +0 -13
- package/packages/html/src/node/$Anchor.ts +0 -49
- package/packages/html/src/node/$Canvas.ts +0 -38
- package/packages/html/src/node/$Dialog.ts +0 -16
- package/packages/html/src/node/$Form.ts +0 -16
- package/packages/html/src/node/$Image.ts +0 -72
- package/packages/html/src/node/$Input.ts +0 -193
- package/packages/html/src/node/$Label.ts +0 -25
- package/packages/html/src/node/$Media.ts +0 -16
- package/packages/html/src/node/$OptGroup.ts +0 -23
- package/packages/html/src/node/$Option.ts +0 -40
- package/packages/html/src/node/$Select.ts +0 -76
- package/packages/html/src/node/$TextArea.ts +0 -16
- package/packages/i18n/README.md +0 -73
- package/packages/i18n/package.json +0 -19
- package/packages/i18n/src/index.ts +0 -140
- package/packages/i18n/src/structure/I18n.ts +0 -44
- package/packages/i18n/src/structure/I18nDictionary.ts +0 -31
- package/packages/i18n/src/structure/I18nTranslation.ts +0 -41
- package/packages/idb/README.md +0 -127
- package/packages/idb/package.json +0 -19
- package/packages/idb/src/core.ts +0 -6
- package/packages/idb/src/index.ts +0 -17
- package/packages/idb/src/lib/$IDBRequest.ts +0 -8
- package/packages/idb/src/structure/$IDB.ts +0 -63
- package/packages/idb/src/structure/$IDBCursor.ts +0 -34
- package/packages/idb/src/structure/$IDBIndex.ts +0 -48
- package/packages/idb/src/structure/$IDBStore.ts +0 -103
- package/packages/idb/src/structure/$IDBStoreBase.ts +0 -30
- package/packages/idb/src/structure/$IDBTransaction.ts +0 -38
- package/packages/idb/src/structure/builder/$IDBBuilder.ts +0 -229
- package/packages/idb/src/structure/builder/$IDBStoreBuilder.ts +0 -100
- package/packages/markdown/README.md +0 -53
- package/packages/markdown/package.json +0 -19
- package/packages/markdown/src/index.ts +0 -3
- package/packages/markdown/src/lib/type.ts +0 -26
- package/packages/markdown/src/lib/util.ts +0 -21
- package/packages/markdown/src/structure/Markdown.ts +0 -54
- package/packages/markdown/src/structure/MarkdownLexer.ts +0 -111
- package/packages/markdown/src/structure/MarkdownParser.ts +0 -34
- package/packages/markdown/src/syntax/alert.ts +0 -46
- package/packages/markdown/src/syntax/blockquote.ts +0 -35
- package/packages/markdown/src/syntax/bold.ts +0 -11
- package/packages/markdown/src/syntax/code.ts +0 -11
- package/packages/markdown/src/syntax/codeblock.ts +0 -44
- package/packages/markdown/src/syntax/heading.ts +0 -14
- package/packages/markdown/src/syntax/horizontalRule.ts +0 -11
- package/packages/markdown/src/syntax/image.ts +0 -23
- package/packages/markdown/src/syntax/italic.ts +0 -11
- package/packages/markdown/src/syntax/link.ts +0 -46
- package/packages/markdown/src/syntax/list.ts +0 -121
- package/packages/markdown/src/syntax/table.ts +0 -67
- package/packages/markdown/src/syntax/text.ts +0 -19
- package/packages/router/README.md +0 -175
- package/packages/router/package.json +0 -19
- package/packages/router/src/index.ts +0 -68
- package/packages/router/src/node/Page.ts +0 -38
- package/packages/router/src/node/Router.ts +0 -212
- package/packages/router/src/node/RouterAnchor.ts +0 -24
- package/packages/router/src/structure/PageBuilder.ts +0 -24
- package/packages/router/src/structure/Route.ts +0 -105
- package/packages/signal/README.md +0 -93
- package/packages/signal/package.json +0 -18
- package/packages/signal/src/index.ts +0 -221
- package/packages/signal/src/structure/Signal.ts +0 -38
- package/packages/ui/lib/VirtualScroll.ts +0 -25
- package/packages/ui/node/Accordian.ts +0 -97
- package/packages/ui/node/Carousel.ts +0 -20
- package/packages/ui/node/Form.ts +0 -54
- package/packages/ui/node/Grid.ts +0 -0
- package/packages/ui/node/Modal.ts +0 -45
- package/packages/ui/node/Table.ts +0 -43
- package/packages/ui/node/Tabs.ts +0 -129
- package/packages/ui/node/Toast.ts +0 -16
- package/packages/ui/node/Waterfall.ts +0 -94
- package/packages/ui/package.json +0 -21
- package/packages/utils/package.json +0 -17
- package/packages/utils/src/global.ts +0 -25
- package/packages/utils/src/index.ts +0 -90
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { alertProcessor, alertTokenizer } from "../syntax/alert";
|
|
2
|
-
import { blockquoteProcessor, blockquoteTokenizer } from "../syntax/blockquote";
|
|
3
|
-
import { boldProcessor, boldTokenizer } from "../syntax/bold";
|
|
4
|
-
import { codeProcessor, codeTokenizer } from "../syntax/code";
|
|
5
|
-
import { codeblockProcessor, codeblockTokenizer } from "../syntax/codeblock";
|
|
6
|
-
import { headingProcessor, headingTokenizer } from "../syntax/heading";
|
|
7
|
-
import { horizontalRuleProcessor, horizontalRuleTokenizer } from "../syntax/horizontalRule";
|
|
8
|
-
import { imageProcessor, imageTokenizer } from "../syntax/image";
|
|
9
|
-
import { italicProcessor, italicTokenizer } from "../syntax/italic";
|
|
10
|
-
import { linkProcessor, linkTokenizer } from "../syntax/link";
|
|
11
|
-
import { listProcessor, listTokenizer } from "../syntax/list";
|
|
12
|
-
import { textLineProcessor, textProcessor } from "../syntax/text";
|
|
13
|
-
import { MarkdownLexer } from "./MarkdownLexer";
|
|
14
|
-
import { MarkdownParser } from "./MarkdownParser";
|
|
15
|
-
|
|
16
|
-
export class Markdown {
|
|
17
|
-
lexer = new MarkdownLexer();
|
|
18
|
-
parser = new MarkdownParser();
|
|
19
|
-
constructor() {
|
|
20
|
-
this.lexer.use(
|
|
21
|
-
headingTokenizer,
|
|
22
|
-
codeblockTokenizer,
|
|
23
|
-
listTokenizer,
|
|
24
|
-
alertTokenizer,
|
|
25
|
-
blockquoteTokenizer,
|
|
26
|
-
horizontalRuleTokenizer,
|
|
27
|
-
imageTokenizer, // image tokenizer must before link
|
|
28
|
-
linkTokenizer, // link tokenizer must before bold and italic and code
|
|
29
|
-
codeTokenizer,
|
|
30
|
-
boldTokenizer,
|
|
31
|
-
italicTokenizer,
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
this.parser.use(
|
|
35
|
-
textProcessor,
|
|
36
|
-
imageProcessor,
|
|
37
|
-
linkProcessor,
|
|
38
|
-
codeProcessor,
|
|
39
|
-
italicProcessor,
|
|
40
|
-
boldProcessor,
|
|
41
|
-
textLineProcessor,
|
|
42
|
-
headingProcessor,
|
|
43
|
-
codeblockProcessor,
|
|
44
|
-
listProcessor,
|
|
45
|
-
alertProcessor,
|
|
46
|
-
blockquoteProcessor,
|
|
47
|
-
horizontalRuleProcessor
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
parseHTML(str: string) {
|
|
52
|
-
return this.parser.parse(this.lexer.blockTokenize(str));
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { BLOCK, EMPTY_LINE, INLINE_CONTENT, INLINE_TEXT, TEXT_LINE } from "#lib/type";
|
|
2
|
-
import { forEach, isString } from "@amateras/utils";
|
|
3
|
-
|
|
4
|
-
export class MarkdownLexer {
|
|
5
|
-
blockTokenizers = new Map<string, BlockTokenizer>();
|
|
6
|
-
inlineTokenizers = new Map<string, InlineTokenizer>();
|
|
7
|
-
|
|
8
|
-
blockTokenize(str: string) {
|
|
9
|
-
const lines = str?.split(/\r?\n/) ?? [];
|
|
10
|
-
const tokens: BlockToken[] = [];
|
|
11
|
-
let lineIndex = 0;
|
|
12
|
-
lineLoop: while (lineIndex < lines.length) {
|
|
13
|
-
let line = lines[lineIndex];
|
|
14
|
-
if (line === undefined) throw 'LINE ERROR';
|
|
15
|
-
let token: BlockToken | undefined;
|
|
16
|
-
for (const [type, tokenizer] of this.blockTokenizers) {
|
|
17
|
-
const matched = line.match(tokenizer.regex);
|
|
18
|
-
if (matched) {
|
|
19
|
-
const {content, multiLine, data} = tokenizer.handle(matched, lineIndex, lines);
|
|
20
|
-
token = { layout: BLOCK, type, content, data }
|
|
21
|
-
if (multiLine) {
|
|
22
|
-
tokens.push(token);
|
|
23
|
-
tokens.push(...multiLine.tokens)
|
|
24
|
-
lineIndex = multiLine.skip;
|
|
25
|
-
continue lineLoop;
|
|
26
|
-
}
|
|
27
|
-
break;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (!token) token = {
|
|
31
|
-
layout: BLOCK,
|
|
32
|
-
...(
|
|
33
|
-
line.length
|
|
34
|
-
? { type: TEXT_LINE, content: this.inlineTokenize(line) }
|
|
35
|
-
: { type: EMPTY_LINE, content: [] }
|
|
36
|
-
)
|
|
37
|
-
};
|
|
38
|
-
tokens.push(token);
|
|
39
|
-
lineIndex++;
|
|
40
|
-
}
|
|
41
|
-
return tokens;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
inlineTokenize(str: string): InlineToken[] {
|
|
45
|
-
const tokens: InlineToken[] = [];
|
|
46
|
-
let remainStr = str;
|
|
47
|
-
while (remainStr.length) {
|
|
48
|
-
let token: InlineToken | undefined;
|
|
49
|
-
for (const [type, tokenizer] of this.inlineTokenizers) {
|
|
50
|
-
const matched = remainStr.match(tokenizer.regex);
|
|
51
|
-
if (matched) {
|
|
52
|
-
const {index, 0: matchStr} = matched;
|
|
53
|
-
// handle before matched string
|
|
54
|
-
if (index != 0) tokens.push(...this.inlineTokenize(remainStr.substring(0, index)));
|
|
55
|
-
// handle matched string
|
|
56
|
-
const {content, data} = tokenizer.handle(matched);
|
|
57
|
-
token = { type, ...(isString(content) ? { layout: INLINE_TEXT, text: content } : { layout: INLINE_CONTENT, content })};
|
|
58
|
-
if (data) token.data = data;
|
|
59
|
-
remainStr = remainStr.substring(index! + matchStr.length);
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
if (!token) {
|
|
64
|
-
token = { type: 'TEXT', layout: INLINE_TEXT, text: remainStr };
|
|
65
|
-
remainStr = '';
|
|
66
|
-
}
|
|
67
|
-
tokens.push(token);
|
|
68
|
-
}
|
|
69
|
-
return tokens;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
use(...handle: ((parser: this) => void)[]) {
|
|
73
|
-
forEach(handle, fn => fn(this));
|
|
74
|
-
return this;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export type BlockTokenizer = {
|
|
79
|
-
regex: RegExp;
|
|
80
|
-
handle: (matches: RegExpMatchArray, position: number, lines: string[]) => { content: (InlineToken | BlockToken)[], multiLine?: BlockTokenizerMultiLine, data?: {[key: string]: any} };
|
|
81
|
-
}
|
|
82
|
-
export type BlockTokenizerMultiLine = {
|
|
83
|
-
skip: number;
|
|
84
|
-
tokens: BlockToken[];
|
|
85
|
-
}
|
|
86
|
-
export type InlineTokenizer = {
|
|
87
|
-
regex: RegExp;
|
|
88
|
-
handle: (matches: RegExpMatchArray) => { content: InlineToken[] | string, data?: {[key: string]: any} }
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface TokenBase {
|
|
92
|
-
type: string;
|
|
93
|
-
layout: 'BLOCK' | 'INLINE_CONTENT' | 'INLINE_TEXT';
|
|
94
|
-
content?: Token[];
|
|
95
|
-
text?: string;
|
|
96
|
-
data?: {[key: string]: any};
|
|
97
|
-
}
|
|
98
|
-
export interface BlockToken extends TokenBase {
|
|
99
|
-
layout: 'BLOCK'
|
|
100
|
-
content: Token[];
|
|
101
|
-
}
|
|
102
|
-
export interface InlineTextToken extends TokenBase {
|
|
103
|
-
layout: 'INLINE_TEXT'
|
|
104
|
-
text: string;
|
|
105
|
-
}
|
|
106
|
-
export interface InlineContentToken extends TokenBase {
|
|
107
|
-
layout: 'INLINE_CONTENT'
|
|
108
|
-
content: (InlineToken)[];
|
|
109
|
-
}
|
|
110
|
-
export type InlineToken = InlineTextToken | InlineContentToken;
|
|
111
|
-
export type Token = BlockToken | InlineToken;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { forEach, isString } from "@amateras/utils";
|
|
2
|
-
import { type Token } from "./MarkdownLexer";
|
|
3
|
-
|
|
4
|
-
export class MarkdownParser {
|
|
5
|
-
processors = new Map<string, MarkdownParseProcessor>();
|
|
6
|
-
|
|
7
|
-
parse(tokens: (Token)[]) {
|
|
8
|
-
let html = '';
|
|
9
|
-
let i = 0;
|
|
10
|
-
if (!tokens) return html;
|
|
11
|
-
while (i < tokens.length) {
|
|
12
|
-
const token = tokens[i]!;
|
|
13
|
-
const processor = this.processors.get(token.type);
|
|
14
|
-
if (processor) {
|
|
15
|
-
const result = processor(token, tokens.slice(i));
|
|
16
|
-
if (isString(result)) {
|
|
17
|
-
html += result;
|
|
18
|
-
} else {
|
|
19
|
-
html += result.html;
|
|
20
|
-
i += result.skipTokens;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
i++;
|
|
24
|
-
}
|
|
25
|
-
return html;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
use(...handle: ((parser: this) => void)[]) {
|
|
29
|
-
forEach(handle, fn => fn(this));
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type MarkdownParseProcessor = (token: Token, tokens: Token[]) => (string | { html: string, skipTokens: number })
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { ALERT, ALERT_LINE, BLOCK } from "#lib/type";
|
|
2
|
-
import { setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { BlockToken, MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
import { uppercase } from "@amateras/utils";
|
|
6
|
-
|
|
7
|
-
export const alertProcessor = (parser: MarkdownParser) => setProcessor(parser, ALERT, (token, tokens) => {
|
|
8
|
-
let html = '';
|
|
9
|
-
let i = 1;
|
|
10
|
-
while (i < tokens.length) {
|
|
11
|
-
const token = tokens[i]!;
|
|
12
|
-
if (token.type !== ALERT_LINE) break;
|
|
13
|
-
html += parser.parse(token.content![0]!.content!);
|
|
14
|
-
i++;
|
|
15
|
-
}
|
|
16
|
-
const alertType = token.data?.alertType as string;
|
|
17
|
-
return {
|
|
18
|
-
html: `<blockquote class="alert alert-${alertType}"><p class="alert-title">${uppercase(alertType, 0, 1)}</p>${html}</blockquote>`,
|
|
19
|
-
skipTokens: i
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
export const alertTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, ALERT, {
|
|
24
|
-
regex: /^> ?\[!(?:(?:NOTE)|(?:TIP)|(?:IMPORTANT)|(?:WARNING)|(?:CAUTION))\]/,
|
|
25
|
-
handle(_, position, lines) {
|
|
26
|
-
const tokens: BlockToken[] = [];
|
|
27
|
-
const match = lines[position]!.match(/> ?\[!(.+?)\]/);
|
|
28
|
-
const alertType = match?.[1]?.toLowerCase();
|
|
29
|
-
position++
|
|
30
|
-
while (position < lines.length) {
|
|
31
|
-
const line = lines[position]!;
|
|
32
|
-
const match = line.match(/^> ?(.+)/);
|
|
33
|
-
if (match) tokens.push({ layout: BLOCK, type: ALERT_LINE, content: lexer.blockTokenize(match[1]!) });
|
|
34
|
-
else break;
|
|
35
|
-
position++;
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
content: [],
|
|
39
|
-
data: { alertType },
|
|
40
|
-
multiLine: {
|
|
41
|
-
skip: position,
|
|
42
|
-
tokens
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
})
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { BLOCKQUOTE } from "#lib/type";
|
|
2
|
-
import { htmltag, setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const blockquoteProcessor = (parser: MarkdownParser) => setProcessor(parser, BLOCKQUOTE, (token, tokens) => {
|
|
7
|
-
let i = 0;
|
|
8
|
-
const blockquote = (deep: number) => {
|
|
9
|
-
let html = '';
|
|
10
|
-
while (i < tokens.length) {
|
|
11
|
-
const {type, content, data} = tokens[i]!;
|
|
12
|
-
if (type !== BLOCKQUOTE) break;
|
|
13
|
-
if (data!.deep > deep) html += blockquote(data!.deep);
|
|
14
|
-
else if (data!.deep < deep) break;
|
|
15
|
-
else { html += parser.parse(content!); i++ }
|
|
16
|
-
}
|
|
17
|
-
return htmltag('blockquote', html)
|
|
18
|
-
}
|
|
19
|
-
return {
|
|
20
|
-
html: blockquote(token.data!.deep),
|
|
21
|
-
skipTokens: i
|
|
22
|
-
}
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
export const blockquoteTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, BLOCKQUOTE, {
|
|
26
|
-
regex: /^(>+) ?(.+)?/,
|
|
27
|
-
handle(matches) {
|
|
28
|
-
return {
|
|
29
|
-
content: lexer.blockTokenize(matches[2] ?? ''),
|
|
30
|
-
data: {
|
|
31
|
-
deep: (matches[1]!.length - 1)
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { BOLD } from "#lib/type";
|
|
2
|
-
import { htmltag, setInlineTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const boldProcessor = (parser: MarkdownParser) => setProcessor(parser, BOLD, token => htmltag('b', parser.parse(token.content!)))
|
|
7
|
-
|
|
8
|
-
export const boldTokenizer = (lexer: MarkdownLexer) => setInlineTokenizer(lexer, BOLD, {
|
|
9
|
-
regex: /\*\*(.+?\*?)\*\*/,
|
|
10
|
-
handle: matches => ({ content: lexer.inlineTokenize(matches[1]!) })
|
|
11
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { CODE } from "#lib/type";
|
|
2
|
-
import { htmlEscapeChar, htmltag, setInlineTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const codeProcessor = (parser: MarkdownParser) => setProcessor(parser, CODE, token => htmltag('code', htmlEscapeChar(token.text!)))
|
|
7
|
-
|
|
8
|
-
export const codeTokenizer = (lexer: MarkdownLexer) => setInlineTokenizer(lexer, CODE, {
|
|
9
|
-
regex: /`(.+?)`/,
|
|
10
|
-
handle: matches => ({ content: matches[1]! })
|
|
11
|
-
})
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { BLOCK, CODE_END, CODE_LINE, CODE_START } from "#lib/type";
|
|
2
|
-
import { htmlEscapeChar, setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { BlockToken, MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const codeblockProcessor = (parser: MarkdownParser) => setProcessor(parser, CODE_START, (token, tokens) => {
|
|
7
|
-
let html = '';
|
|
8
|
-
let i = 1;
|
|
9
|
-
while (i < tokens.length) {
|
|
10
|
-
const token = tokens[i]!;
|
|
11
|
-
if (token.type === CODE_END) break;
|
|
12
|
-
html += token.content![0]!.text;
|
|
13
|
-
i++;
|
|
14
|
-
}
|
|
15
|
-
return {
|
|
16
|
-
html: `<pre><code${token.data?.lang ? ` lang="${token.data.lang}"` : ''}>${htmlEscapeChar(html)}</code></pre>`,
|
|
17
|
-
skipTokens: i
|
|
18
|
-
}
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
export const codeblockTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, CODE_START, {
|
|
22
|
-
regex: /^```(\w+)?/,
|
|
23
|
-
handle: (matches, position, lines) => {
|
|
24
|
-
const tokens: BlockToken[] = [];
|
|
25
|
-
position++;
|
|
26
|
-
while (position < lines.length) {
|
|
27
|
-
const line = lines[position]!;
|
|
28
|
-
position++;
|
|
29
|
-
if (line.includes('```')) {
|
|
30
|
-
tokens.push({ layout: BLOCK, type: CODE_END, content: [] })
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
33
|
-
tokens.push({ layout: BLOCK, type: CODE_LINE, content: [{ layout: "INLINE_TEXT", type: 'CODE_TEXT', text: `${line}\n` }] });
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
content: [],
|
|
37
|
-
data: { lang: matches[1] },
|
|
38
|
-
multiLine: {
|
|
39
|
-
skip: position,
|
|
40
|
-
tokens
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
})
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { HEADING } from "#lib/type";
|
|
2
|
-
import { htmltag, setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const headingProcessor = (parser: MarkdownParser) => setProcessor(parser, HEADING, token => {
|
|
7
|
-
const tagname = `h${token.data!.level}`;
|
|
8
|
-
return htmltag(tagname, parser.parse(token.content!))
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
export const headingTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, HEADING, {
|
|
12
|
-
regex: /^(#+) (.+)/,
|
|
13
|
-
handle: matches => ({ content: lexer.inlineTokenize(matches[2]!), data: { level: matches[1]!.length } })
|
|
14
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { HORIZONTAL_RULE } from "#lib/type";
|
|
2
|
-
import { setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const horizontalRuleProcessor = (parser: MarkdownParser) => setProcessor(parser, HORIZONTAL_RULE, _ => `<hr>`)
|
|
7
|
-
|
|
8
|
-
export const horizontalRuleTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, HORIZONTAL_RULE, {
|
|
9
|
-
regex: /^---/,
|
|
10
|
-
handle: _ => ({ content: [] })
|
|
11
|
-
})
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { IMAGE } from "#lib/type";
|
|
2
|
-
import { setInlineTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const imageProcessor = (parser: MarkdownParser) => setProcessor(parser, IMAGE, token => {
|
|
7
|
-
const { url, title } = token.data!;
|
|
8
|
-
return `<img alt="${parser.parse(token.content!)}" src="${url}"${title ? ` title="${title}"` : ''}>`
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
export const imageTokenizer = (lexer: MarkdownLexer) => setInlineTokenizer(lexer, IMAGE, {
|
|
12
|
-
regex: /^!\[(.+?)\]\((.+?)\)/,
|
|
13
|
-
handle: matches => {
|
|
14
|
-
const [_, alt, detail] = matches as [string, string, string];
|
|
15
|
-
const [__, url, title] = detail.match(/(\w\w+?:\/\/[^\s]+)(?: "(.+?)")?/) as [string, string, string];
|
|
16
|
-
return {
|
|
17
|
-
content: lexer.inlineTokenize(alt),
|
|
18
|
-
data: {
|
|
19
|
-
url, title
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
})
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { ITALIC } from "#lib/type";
|
|
2
|
-
import { setInlineTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
|
|
6
|
-
export const italicProcessor = (parser: MarkdownParser) => setProcessor(parser, ITALIC, token => `<i>${parser.parse(token.content!)}</i>`)
|
|
7
|
-
|
|
8
|
-
export const italicTokenizer = (lexer: MarkdownLexer) => setInlineTokenizer(lexer, ITALIC, {
|
|
9
|
-
regex: /\*(.+?)\*/,
|
|
10
|
-
handle: matches => ({ content: lexer.inlineTokenize(matches[1]!) })
|
|
11
|
-
})
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { LINK, QUICK_LINK } from "#lib/type";
|
|
2
|
-
import { setInlineTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer, Token } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
import { isUndefined } from "@amateras/utils";
|
|
6
|
-
|
|
7
|
-
export const linkProcessor = (parser: MarkdownParser) => {
|
|
8
|
-
const linkProcessor = (token: Token) => {
|
|
9
|
-
const {href, email, title} = token.data!;
|
|
10
|
-
return `<a href="${isUndefined(href) ? `mailto:${email}` : href}"${title ? ` title="${title}"` : ''}>${token.text ?? parser.parse(token.content!)}</a>`
|
|
11
|
-
}
|
|
12
|
-
setProcessor(parser, QUICK_LINK, linkProcessor)
|
|
13
|
-
setProcessor(parser, LINK, linkProcessor)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const linkTokenizer = (lexer: MarkdownLexer) => {
|
|
17
|
-
|
|
18
|
-
setInlineTokenizer(lexer, LINK, {
|
|
19
|
-
regex: /\[(.+?)\]\(((?:\w+?@(?:\w|\.\w)+)|(?:\w\w+?:[^\s)]+))(?: "(.+)?")?\)/,
|
|
20
|
-
handle: matches => {
|
|
21
|
-
const [_, alt, detail, title] = matches as [string, string, string, string];
|
|
22
|
-
const match = detail.match(/(?:\w+?@(?:\w|\.\w)+)|(?:\w\w+?:\/\/[^\s]+)/);
|
|
23
|
-
const [resolver] = match!;
|
|
24
|
-
const email_or_href = resolver.includes('@') ? { email: resolver }: { href: resolver };
|
|
25
|
-
return {
|
|
26
|
-
content: lexer.inlineTokenize(alt),
|
|
27
|
-
data: {
|
|
28
|
-
title, ...email_or_href
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
})
|
|
33
|
-
setInlineTokenizer(lexer, QUICK_LINK, {
|
|
34
|
-
regex: /<((?:\w+?@(?:\w|\.\w)+)|(?:\w\w+?:[^\s>]+))>/,
|
|
35
|
-
handle: matches => {
|
|
36
|
-
const [_, detail] = matches as [string, string];
|
|
37
|
-
const match = detail.match(/(?:\w+?@(?:\w|\.\w)+)|(?:\w\w+?:\/\/[^\s]+)/);
|
|
38
|
-
const [resolver] = match!;
|
|
39
|
-
const email_or_href = resolver.includes('@') ? { email: resolver }: { href: resolver };
|
|
40
|
-
return {
|
|
41
|
-
content: resolver,
|
|
42
|
-
data: email_or_href
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { EMPTY_LINE, ORDERED_LIST_ITEM, TEXT_LINE, UNORDERED_LIST_ITEM } from "#lib/type";
|
|
2
|
-
import { htmltag, setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { MarkdownLexer, Token } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
import { equal, isString } from "@amateras/utils";
|
|
6
|
-
|
|
7
|
-
export const listProcessor = (parser: MarkdownParser) => {
|
|
8
|
-
const listType = (type: string) => type === ORDERED_LIST_ITEM ? 'ol' : 'ul'
|
|
9
|
-
const listProcessor = (token: Token, tokens: Token[]) => {
|
|
10
|
-
let i = 0;
|
|
11
|
-
// cache the list by deep number
|
|
12
|
-
const deepListMap = new Map<number, List>();
|
|
13
|
-
|
|
14
|
-
const listGenerator = (type: string, deep: number) => {
|
|
15
|
-
const getList = deepListMap.get(deep)
|
|
16
|
-
const list = getList && listType(type) === getList.tagname ? getList : List(listType(type), []);
|
|
17
|
-
deepListMap.set(deep, list);
|
|
18
|
-
|
|
19
|
-
while (i < tokens.length) {
|
|
20
|
-
const token = tokens[i]!;
|
|
21
|
-
const tokenType = token.type;
|
|
22
|
-
// if token type not equal list item / empty line / text line, then finish loop
|
|
23
|
-
if (!equal(tokenType, ORDERED_LIST_ITEM, UNORDERED_LIST_ITEM, EMPTY_LINE, TEXT_LINE)) { i--; break};
|
|
24
|
-
// if token type equal text line
|
|
25
|
-
if (tokenType === TEXT_LINE) {
|
|
26
|
-
const text = token.content![0]?.text;
|
|
27
|
-
// if text start with double space
|
|
28
|
-
if (text?.match(/^\s\s/)) {
|
|
29
|
-
const match = text.match(/^(\s+)(.+)?/)!;
|
|
30
|
-
// if no content, then next token
|
|
31
|
-
if (!match[2]) { i++; continue }
|
|
32
|
-
token.data = { deep: Math.trunc(match[1]!.length / 2) - 1 }
|
|
33
|
-
}
|
|
34
|
-
// if text start with tab
|
|
35
|
-
else if (text?.match(/^\t/)) {
|
|
36
|
-
const match = text.match(/^(\t+)(.+)?/)!;
|
|
37
|
-
// if no content, then next token
|
|
38
|
-
if (!match[2]) { i++; continue }
|
|
39
|
-
token.data = { deep: match[1]!.length - 1 }
|
|
40
|
-
}
|
|
41
|
-
// else break
|
|
42
|
-
else {i--; break};
|
|
43
|
-
}
|
|
44
|
-
// if token type equal empty line, jump to next token
|
|
45
|
-
if (tokenType === EMPTY_LINE) i++;
|
|
46
|
-
// if token deep number not equal latest deep of list
|
|
47
|
-
else if (token.data!.deep !== deep) {
|
|
48
|
-
// if bigger, push deeper list into current list item
|
|
49
|
-
if (token.data!.deep > deep) deepListMap.get(deep)?.items.at(-1)?.content.push(listGenerator(tokenType, token.data!.deep))
|
|
50
|
-
// else delete current deep cache and return to upper list
|
|
51
|
-
else { deepListMap.delete(deep); break; }
|
|
52
|
-
}
|
|
53
|
-
// if token type equal text line, convert this list to paragraph mode
|
|
54
|
-
else if (tokenType === TEXT_LINE) {
|
|
55
|
-
list.paragraph = true;
|
|
56
|
-
list.items.at(-1)?.content.push(parser.parse(token.content!))
|
|
57
|
-
i++
|
|
58
|
-
}
|
|
59
|
-
// if list type not equal, then finish loop
|
|
60
|
-
else if (tokenType !== type) {
|
|
61
|
-
deepListMap.delete(deep);
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
// push list item
|
|
65
|
-
else {
|
|
66
|
-
list.items.push(ListItem([parser.parse(token.content!)]));
|
|
67
|
-
i++
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return list;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
html: `${listGenerator(token.type, token.data!.deep)}`,
|
|
75
|
-
skipTokens: i
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
interface ListItem { content: (string | List)[], toString(): string }
|
|
80
|
-
const ListItem = (content: (string | List)[]): ListItem => ({
|
|
81
|
-
content: content,
|
|
82
|
-
toString() { return htmltag('li', this.content.join('')) }
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
interface List { tagname: string, items: ListItem[], paragraph: boolean, toString(): string }
|
|
86
|
-
const List = (tagname: 'ul' | 'ol', items: ListItem[]): List => ({
|
|
87
|
-
tagname: tagname,
|
|
88
|
-
items: items,
|
|
89
|
-
paragraph: false,
|
|
90
|
-
toString() {
|
|
91
|
-
if (this.paragraph) this.items.forEach(item => item.content.forEach((text, i) => isString(text) && (item.content[i] = htmltag('p', text))))
|
|
92
|
-
return htmltag(this.tagname, this.items.join(''))
|
|
93
|
-
}
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
setProcessor(parser, UNORDERED_LIST_ITEM, listProcessor);
|
|
97
|
-
setProcessor(parser, ORDERED_LIST_ITEM, listProcessor);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export const listTokenizer = (lexer: MarkdownLexer) => {
|
|
101
|
-
const listHandle = (matches: RegExpMatchArray) => {
|
|
102
|
-
const prefix = matches[0].split(/[-*]/)[0]!;
|
|
103
|
-
const spaces = prefix.match(/\s/)?.length ?? 0;
|
|
104
|
-
const tabs = prefix.match(/\t/)?.length ?? 0;
|
|
105
|
-
return ({
|
|
106
|
-
content: lexer.inlineTokenize(matches[1]!),
|
|
107
|
-
data: {
|
|
108
|
-
deep: Math.trunc(tabs + spaces / 2)
|
|
109
|
-
}
|
|
110
|
-
})
|
|
111
|
-
}
|
|
112
|
-
setBlockTokenizer(lexer, UNORDERED_LIST_ITEM, {
|
|
113
|
-
regex: /^(?:[\s\t]+)?[-*] (.+)/,
|
|
114
|
-
handle: listHandle
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
setBlockTokenizer(lexer, ORDERED_LIST_ITEM, {
|
|
118
|
-
regex: /^(?:[\s\t]+)?\d+\. (.+)/,
|
|
119
|
-
handle: listHandle
|
|
120
|
-
})
|
|
121
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { BLOCK, TABLE, TABLE_COLUMN, TABLE_ROW } from "#lib/type";
|
|
2
|
-
import { htmltag, setBlockTokenizer, setProcessor } from "#lib/util";
|
|
3
|
-
import type { BlockToken, MarkdownLexer } from "#structure/MarkdownLexer";
|
|
4
|
-
import type { MarkdownParser } from "#structure/MarkdownParser";
|
|
5
|
-
import { _Array_from } from "@amateras/utils";
|
|
6
|
-
|
|
7
|
-
export const tableProcessor = (parser: MarkdownParser) => setProcessor(parser, TABLE, (token) => {
|
|
8
|
-
let thead = '';
|
|
9
|
-
let tbody = '';
|
|
10
|
-
let rowIndex = 0;
|
|
11
|
-
for (const row of token.content!) {
|
|
12
|
-
let rowHTML = '';
|
|
13
|
-
for (let i = 0; i < row.content!.length; i++) {
|
|
14
|
-
const col = row.content![i]!;
|
|
15
|
-
const align = token.data!.align[i];
|
|
16
|
-
const tagname = rowIndex === 0 ? 'th' : 'td';
|
|
17
|
-
rowHTML += `<${tagname} align="${align ?? 'left'}">${parser.parse(col.content!)}</${tagname}>`
|
|
18
|
-
}
|
|
19
|
-
if (rowIndex === 0) thead += htmltag('thead', htmltag('tr', rowHTML));
|
|
20
|
-
else tbody += htmltag('tr', rowHTML);
|
|
21
|
-
rowIndex++
|
|
22
|
-
}
|
|
23
|
-
tbody = htmltag('tbody', tbody);
|
|
24
|
-
return htmltag('table', thead + tbody)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
export const tableTokenizer = (lexer: MarkdownLexer) => setBlockTokenizer(lexer, TABLE, {
|
|
28
|
-
regex: /\|(?:.+\|)+/,
|
|
29
|
-
handle(_, position, lines) {
|
|
30
|
-
const tokens: BlockToken[] = [];
|
|
31
|
-
const align = []
|
|
32
|
-
while (position < lines.length) {
|
|
33
|
-
const row: BlockToken = {
|
|
34
|
-
type: TABLE_ROW,
|
|
35
|
-
layout: BLOCK,
|
|
36
|
-
content: []
|
|
37
|
-
}
|
|
38
|
-
const line = lines[position]!;
|
|
39
|
-
const matches = _Array_from(line.matchAll(/\| ([^|]+)/g));
|
|
40
|
-
if (!matches.length) break;
|
|
41
|
-
for (const match of matches) {
|
|
42
|
-
const text = match[1]!;
|
|
43
|
-
const separator = text.match(/(:)?---+(:)?/);
|
|
44
|
-
if (separator) {
|
|
45
|
-
const [_, LEFT, RIGHT] = separator;
|
|
46
|
-
align.push(RIGHT ? LEFT ? 'center' : 'right' : 'left');
|
|
47
|
-
continue;
|
|
48
|
-
}
|
|
49
|
-
row.content.push({
|
|
50
|
-
type: TABLE_COLUMN,
|
|
51
|
-
content: lexer.inlineTokenize(text.trim()),
|
|
52
|
-
layout: BLOCK
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
if (row.content.length) tokens.push(row);
|
|
56
|
-
position++
|
|
57
|
-
}
|
|
58
|
-
return {
|
|
59
|
-
content: tokens,
|
|
60
|
-
data: { align },
|
|
61
|
-
multiLine: {
|
|
62
|
-
skip: position,
|
|
63
|
-
tokens: []
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
})
|