@jianwen-lang/parser 0.1.1 → 0.1.2
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 +16 -1
- package/dist/core/block/rules/attribute-line.d.ts +13 -0
- package/dist/core/block/rules/attribute-line.js +227 -0
- package/dist/core/block/rules/code-block.d.ts +2 -0
- package/dist/core/block/rules/code-block.js +73 -0
- package/dist/core/block/rules/code-fence.d.ts +15 -0
- package/dist/core/block/rules/code-fence.js +37 -0
- package/dist/core/block/rules/content-title.d.ts +12 -0
- package/dist/core/block/rules/content-title.js +70 -0
- package/dist/core/block/rules/footnotes.d.ts +9 -0
- package/dist/core/block/rules/footnotes.js +105 -0
- package/dist/core/block/rules/html.d.ts +7 -0
- package/dist/core/block/rules/html.js +48 -0
- package/dist/core/block/rules/image.d.ts +9 -0
- package/dist/core/block/rules/image.js +78 -0
- package/dist/core/block/rules/list.d.ts +3 -0
- package/dist/core/block/rules/list.js +275 -0
- package/dist/core/block/rules/paragraph.d.ts +6 -0
- package/dist/core/block/rules/paragraph.js +55 -0
- package/dist/core/block/rules/quote.d.ts +13 -0
- package/dist/core/block/rules/quote.js +104 -0
- package/dist/core/block/rules/table.d.ts +2 -0
- package/dist/core/block/rules/table.js +199 -0
- package/dist/core/block/runtime.d.ts +25 -0
- package/dist/core/block/runtime.js +116 -0
- package/dist/core/block-parser.js +183 -1322
- package/dist/html/convert.d.ts +8 -0
- package/dist/html/convert.js +22 -0
- package/dist/html/render/blocks.d.ts +15 -0
- package/dist/html/render/blocks.js +50 -6
- package/dist/html/render/html.d.ts +16 -0
- package/dist/html/render/html.js +48 -14
- package/dist/html/render/utils.d.ts +1 -0
- package/package.json +5 -1
package/dist/html/convert.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ParseOptions } from '../core/parser';
|
|
2
2
|
import { JianwenDocument } from '../core/ast';
|
|
3
3
|
import { ParseError } from '../core/errors';
|
|
4
|
+
import { RenderedBlockGroup } from './render/html';
|
|
4
5
|
import { RenderHtmlOptions } from './render/utils';
|
|
5
6
|
export declare const DEFAULT_RUNTIME_SRC = "dist/html/theme/runtime.js";
|
|
6
7
|
export interface HtmlDocumentOptions {
|
|
@@ -25,5 +26,12 @@ export interface RenderJianwenToHtmlDocumentResult {
|
|
|
25
26
|
ast: JianwenDocument;
|
|
26
27
|
errors: ParseError[];
|
|
27
28
|
}
|
|
29
|
+
export interface RenderJianwenToHtmlDocumentWithBlockMapResult {
|
|
30
|
+
html: string;
|
|
31
|
+
ast: JianwenDocument;
|
|
32
|
+
errors: ParseError[];
|
|
33
|
+
groups: RenderedBlockGroup[];
|
|
34
|
+
}
|
|
28
35
|
export declare function buildHtmlDocument(bodyHtml: string, options?: HtmlDocumentOptions): string;
|
|
29
36
|
export declare function renderJianwenToHtmlDocument(source: string, options?: RenderJianwenToHtmlDocumentOptions): RenderJianwenToHtmlDocumentResult;
|
|
37
|
+
export declare function renderJianwenToHtmlDocumentWithBlockMap(source: string, options?: RenderJianwenToHtmlDocumentOptions): RenderJianwenToHtmlDocumentWithBlockMapResult;
|
package/dist/html/convert.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DEFAULT_RUNTIME_SRC = void 0;
|
|
4
4
|
exports.buildHtmlDocument = buildHtmlDocument;
|
|
5
5
|
exports.renderJianwenToHtmlDocument = renderJianwenToHtmlDocument;
|
|
6
|
+
exports.renderJianwenToHtmlDocumentWithBlockMap = renderJianwenToHtmlDocumentWithBlockMap;
|
|
6
7
|
const parser_1 = require("../core/parser");
|
|
7
8
|
const format_1 = require("./format");
|
|
8
9
|
const html_1 = require("./render/html");
|
|
@@ -59,3 +60,24 @@ function renderJianwenToHtmlDocument(source, options = {}) {
|
|
|
59
60
|
});
|
|
60
61
|
return { html, ast: parseResult.ast, errors: parseResult.errors };
|
|
61
62
|
}
|
|
63
|
+
function renderJianwenToHtmlDocumentWithBlockMap(source, options = {}) {
|
|
64
|
+
const parseResult = (0, parser_1.parseJianwenWithErrors)(source, options.parse);
|
|
65
|
+
const renderOptions = {
|
|
66
|
+
includeMeta: true,
|
|
67
|
+
includeComments: false,
|
|
68
|
+
emitBlockMeta: true,
|
|
69
|
+
...options.render,
|
|
70
|
+
};
|
|
71
|
+
const rendered = (0, html_1.renderDocumentToHtmlWithBlockMap)(parseResult.ast, renderOptions);
|
|
72
|
+
const title = options.document?.title ?? parseResult.ast.meta?.title;
|
|
73
|
+
const html = buildHtmlDocument(rendered.html, {
|
|
74
|
+
...options.document,
|
|
75
|
+
title,
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
html,
|
|
79
|
+
ast: parseResult.ast,
|
|
80
|
+
errors: parseResult.errors,
|
|
81
|
+
groups: rendered.groups,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -1,4 +1,19 @@
|
|
|
1
1
|
import { BlockNode } from '../../core/ast';
|
|
2
2
|
import { RenderHtmlOptions } from './utils';
|
|
3
|
+
export type RenderBlockGroupKind = 'single' | 'sameLine' | 'foldable';
|
|
4
|
+
export interface RenderBlockGroupDraft {
|
|
5
|
+
id: string;
|
|
6
|
+
kind: RenderBlockGroupKind;
|
|
7
|
+
startBlockIndex: number;
|
|
8
|
+
endBlockIndex: number;
|
|
9
|
+
startLine?: number;
|
|
10
|
+
origin?: string;
|
|
11
|
+
readOnly: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface RenderBlocksResult {
|
|
14
|
+
html: string;
|
|
15
|
+
groups: RenderBlockGroupDraft[];
|
|
16
|
+
}
|
|
3
17
|
export declare function renderBlocksToHtml(blocks: BlockNode[], options?: RenderHtmlOptions): string;
|
|
18
|
+
export declare function renderBlocksToHtmlWithGroups(blocks: BlockNode[], options?: RenderHtmlOptions): RenderBlocksResult;
|
|
4
19
|
export declare function renderBlockToHtml(block: BlockNode, options: RenderHtmlOptions): string;
|
|
@@ -1,18 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.renderBlocksToHtml = renderBlocksToHtml;
|
|
4
|
+
exports.renderBlocksToHtmlWithGroups = renderBlocksToHtmlWithGroups;
|
|
4
5
|
exports.renderBlockToHtml = renderBlockToHtml;
|
|
5
6
|
const utils_1 = require("./utils");
|
|
6
7
|
const inlines_1 = require("./inlines");
|
|
8
|
+
const location_1 = require("../../core/location");
|
|
7
9
|
function renderBlocksToHtml(blocks, options = {}) {
|
|
10
|
+
return renderBlocksToHtmlWithGroups(blocks, options).html;
|
|
11
|
+
}
|
|
12
|
+
function renderBlocksToHtmlWithGroups(blocks, options = {}) {
|
|
8
13
|
const result = [];
|
|
14
|
+
const groups = [];
|
|
9
15
|
let i = 0;
|
|
10
|
-
function
|
|
16
|
+
function buildGroupDraft(kind, blockList, startBlockIndex) {
|
|
17
|
+
const endBlockIndex = startBlockIndex + blockList.length - 1;
|
|
18
|
+
let startLine;
|
|
19
|
+
const origins = new Set();
|
|
20
|
+
for (const block of blockList) {
|
|
21
|
+
const location = (0, location_1.getNodeLocation)(block);
|
|
22
|
+
if (location && (startLine === undefined || location.line < startLine)) {
|
|
23
|
+
startLine = location.line;
|
|
24
|
+
}
|
|
25
|
+
const origin = (0, location_1.getNodeOrigin)(block);
|
|
26
|
+
if (origin) {
|
|
27
|
+
origins.add(origin);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const origin = origins.size === 1 ? Array.from(origins)[0] : undefined;
|
|
31
|
+
const hasIncludeBlock = blockList.some((block) => block.type === 'include');
|
|
32
|
+
const readOnly = origins.size > 0 || hasIncludeBlock;
|
|
33
|
+
return {
|
|
34
|
+
id: `g-${groups.length}`,
|
|
35
|
+
kind,
|
|
36
|
+
startBlockIndex,
|
|
37
|
+
endBlockIndex,
|
|
38
|
+
startLine,
|
|
39
|
+
origin,
|
|
40
|
+
readOnly,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function wrapBlock(html, group) {
|
|
11
44
|
if (!html || !html.trim())
|
|
12
45
|
return '';
|
|
13
46
|
if (options.suppressBlockWrapper)
|
|
14
47
|
return html;
|
|
15
|
-
|
|
48
|
+
const dataAttr = options.emitBlockMeta && group ? ` data-jw-group-id="${(0, utils_1.escapeAttr)(group.id)}"` : '';
|
|
49
|
+
return `<div class="jw-block"${dataAttr}>${html}</div>`;
|
|
16
50
|
}
|
|
17
51
|
while (i < blocks.length) {
|
|
18
52
|
const block = blocks[i];
|
|
@@ -41,13 +75,18 @@ function renderBlocksToHtml(blocks, options = {}) {
|
|
|
41
75
|
}
|
|
42
76
|
const detailsContent = foldedBlocks.join('');
|
|
43
77
|
const detailsHtml = `<details class="jw-foldable-section">${headingHtml}${detailsContent}</details>`;
|
|
44
|
-
|
|
78
|
+
const groupBlocks = blocks.slice(i, j).filter((item) => Boolean(item));
|
|
79
|
+
const group = buildGroupDraft('foldable', groupBlocks, i);
|
|
80
|
+
groups.push(group);
|
|
81
|
+
result.push(wrapBlock(detailsHtml, group));
|
|
45
82
|
i = j;
|
|
46
83
|
continue;
|
|
47
84
|
}
|
|
48
85
|
const blockAttrs = 'blockAttrs' in block ? block.blockAttrs : undefined;
|
|
49
86
|
if (!blockAttrs?.sameLine) {
|
|
50
|
-
|
|
87
|
+
const group = buildGroupDraft('single', [block], i);
|
|
88
|
+
groups.push(group);
|
|
89
|
+
result.push(wrapBlock(renderBlockToHtml(block, options), group));
|
|
51
90
|
i++;
|
|
52
91
|
continue;
|
|
53
92
|
}
|
|
@@ -81,10 +120,15 @@ function renderBlocksToHtml(blocks, options = {}) {
|
|
|
81
120
|
}
|
|
82
121
|
}
|
|
83
122
|
const rowHtml = rowBlocks.map((b) => renderBlockToHtml(b, options)).join('');
|
|
84
|
-
|
|
123
|
+
const group = buildGroupDraft('sameLine', rowBlocks, rowStartIndex);
|
|
124
|
+
groups.push(group);
|
|
125
|
+
result.push(wrapBlock(`<div class="jw-same-line-row">${rowHtml}</div>`, group));
|
|
85
126
|
i = rowStartIndex + rowBlocks.length;
|
|
86
127
|
}
|
|
87
|
-
return
|
|
128
|
+
return {
|
|
129
|
+
html: result.join(''),
|
|
130
|
+
groups,
|
|
131
|
+
};
|
|
88
132
|
}
|
|
89
133
|
function renderBlockToHtml(block, options) {
|
|
90
134
|
switch (block.type) {
|
|
@@ -3,6 +3,22 @@ import { RenderHtmlOptions } from './utils';
|
|
|
3
3
|
export { RenderHtmlOptions } from './utils';
|
|
4
4
|
export { DocumentTheme } from '../theme/theme';
|
|
5
5
|
export { renderBlocksToHtml } from './blocks';
|
|
6
|
+
export { renderBlocksToHtmlWithGroups } from './blocks';
|
|
6
7
|
export { renderInlinesToHtml } from './inlines';
|
|
8
|
+
export interface RenderedBlockGroup {
|
|
9
|
+
id: string;
|
|
10
|
+
kind: 'single' | 'sameLine' | 'foldable';
|
|
11
|
+
startBlockIndex: number;
|
|
12
|
+
endBlockIndex: number;
|
|
13
|
+
startLine?: number;
|
|
14
|
+
endLine?: number;
|
|
15
|
+
origin?: string;
|
|
16
|
+
readOnly: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface RenderDocumentWithBlockMapResult {
|
|
19
|
+
html: string;
|
|
20
|
+
groups: RenderedBlockGroup[];
|
|
21
|
+
}
|
|
7
22
|
export declare function createDefaultAssetPathResolver(sourceFilePath: string, outputFilePath: string): (assetPath: string) => string | undefined;
|
|
8
23
|
export declare function renderDocumentToHtml(doc: JianwenDocument, options?: RenderHtmlOptions): string;
|
|
24
|
+
export declare function renderDocumentToHtmlWithBlockMap(doc: JianwenDocument, options?: RenderHtmlOptions): RenderDocumentWithBlockMapResult;
|
package/dist/html/render/html.js
CHANGED
|
@@ -33,9 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.renderInlinesToHtml = exports.renderBlocksToHtml = void 0;
|
|
36
|
+
exports.renderInlinesToHtml = exports.renderBlocksToHtmlWithGroups = exports.renderBlocksToHtml = void 0;
|
|
37
37
|
exports.createDefaultAssetPathResolver = createDefaultAssetPathResolver;
|
|
38
38
|
exports.renderDocumentToHtml = renderDocumentToHtml;
|
|
39
|
+
exports.renderDocumentToHtmlWithBlockMap = renderDocumentToHtmlWithBlockMap;
|
|
39
40
|
const path = __importStar(require("path"));
|
|
40
41
|
const format_1 = require("../format");
|
|
41
42
|
const utils_1 = require("./utils");
|
|
@@ -43,6 +44,8 @@ const meta_1 = require("./meta");
|
|
|
43
44
|
const blocks_1 = require("./blocks");
|
|
44
45
|
var blocks_2 = require("./blocks");
|
|
45
46
|
Object.defineProperty(exports, "renderBlocksToHtml", { enumerable: true, get: function () { return blocks_2.renderBlocksToHtml; } });
|
|
47
|
+
var blocks_3 = require("./blocks");
|
|
48
|
+
Object.defineProperty(exports, "renderBlocksToHtmlWithGroups", { enumerable: true, get: function () { return blocks_3.renderBlocksToHtmlWithGroups; } });
|
|
46
49
|
var inlines_1 = require("./inlines");
|
|
47
50
|
Object.defineProperty(exports, "renderInlinesToHtml", { enumerable: true, get: function () { return inlines_1.renderInlinesToHtml; } });
|
|
48
51
|
function createDefaultAssetPathResolver(sourceFilePath, outputFilePath) {
|
|
@@ -58,6 +61,25 @@ function createDefaultAssetPathResolver(sourceFilePath, outputFilePath) {
|
|
|
58
61
|
};
|
|
59
62
|
}
|
|
60
63
|
function renderDocumentToHtml(doc, options = {}) {
|
|
64
|
+
return renderDocumentToHtmlWithBlockMap(doc, {
|
|
65
|
+
...options,
|
|
66
|
+
emitBlockMeta: options.emitBlockMeta ?? false,
|
|
67
|
+
}).html;
|
|
68
|
+
}
|
|
69
|
+
function finalizeGroups(groups, sourceLineCount) {
|
|
70
|
+
return groups.map((group, index) => {
|
|
71
|
+
const next = groups[index + 1];
|
|
72
|
+
let endLine = sourceLineCount;
|
|
73
|
+
if (next?.startLine !== undefined) {
|
|
74
|
+
endLine = Math.max(1, next.startLine - 1);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
...group,
|
|
78
|
+
endLine: group.startLine !== undefined ? endLine : undefined,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function renderDocumentToHtmlWithBlockMap(doc, options = {}) {
|
|
61
83
|
const wrapperTag = options.documentWrapperTag === undefined ? 'article' : options.documentWrapperTag;
|
|
62
84
|
const finalOptions = { ...options };
|
|
63
85
|
if (options.sourceFilePath && options.outputFilePath && !options.resolveAssetPath) {
|
|
@@ -68,22 +90,34 @@ function renderDocumentToHtml(doc, options = {}) {
|
|
|
68
90
|
innerParts.push((0, meta_1.renderMetaToHtml)(doc.meta));
|
|
69
91
|
}
|
|
70
92
|
if (!wrapperTag) {
|
|
71
|
-
|
|
93
|
+
const rendered = (0, blocks_1.renderBlocksToHtmlWithGroups)(doc.children, {
|
|
72
94
|
...finalOptions,
|
|
73
95
|
suppressBlockWrapper: true,
|
|
74
|
-
|
|
96
|
+
emitBlockMeta: finalOptions.emitBlockMeta ?? true,
|
|
97
|
+
});
|
|
98
|
+
const lineCount = doc.source ? doc.source.split('\n').length : undefined;
|
|
99
|
+
innerParts.push(rendered.html);
|
|
100
|
+
return {
|
|
101
|
+
html: innerParts.join(''),
|
|
102
|
+
groups: finalizeGroups(rendered.groups, lineCount),
|
|
103
|
+
};
|
|
75
104
|
}
|
|
76
105
|
else {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
106
|
+
const rendered = (0, blocks_1.renderBlocksToHtmlWithGroups)(doc.children, {
|
|
107
|
+
...finalOptions,
|
|
108
|
+
emitBlockMeta: finalOptions.emitBlockMeta ?? true,
|
|
109
|
+
});
|
|
110
|
+
innerParts.push(rendered.html);
|
|
111
|
+
const innerHtml = innerParts.join('');
|
|
112
|
+
const wrapperAttrs = (0, meta_1.buildDocumentWrapperAttributes)(doc.meta);
|
|
113
|
+
const themeAttr = finalOptions.documentTheme
|
|
114
|
+
? ` data-jw-theme="${(0, utils_1.escapeAttr)(finalOptions.documentTheme)}"`
|
|
115
|
+
: '';
|
|
116
|
+
const html = `<${wrapperTag} class="jw-root"${wrapperAttrs}${themeAttr}>${innerHtml}</${wrapperTag}>`;
|
|
117
|
+
const lineCount = doc.source ? doc.source.split('\n').length : undefined;
|
|
118
|
+
return {
|
|
119
|
+
html: finalOptions.format ? (0, format_1.formatHtml)(html) : html,
|
|
120
|
+
groups: finalizeGroups(rendered.groups, lineCount),
|
|
121
|
+
};
|
|
82
122
|
}
|
|
83
|
-
const wrapperAttrs = (0, meta_1.buildDocumentWrapperAttributes)(doc.meta);
|
|
84
|
-
const themeAttr = finalOptions.documentTheme
|
|
85
|
-
? ` data-jw-theme="${(0, utils_1.escapeAttr)(finalOptions.documentTheme)}"`
|
|
86
|
-
: '';
|
|
87
|
-
const html = `<${wrapperTag} class="jw-root"${wrapperAttrs}${themeAttr}>${innerHtml}</${wrapperTag}>`;
|
|
88
|
-
return finalOptions.format ? (0, format_1.formatHtml)(html) : html;
|
|
89
123
|
}
|
|
@@ -3,6 +3,7 @@ import { DocumentTheme } from '../theme/theme';
|
|
|
3
3
|
export interface RenderHtmlOptions {
|
|
4
4
|
includeMeta?: boolean;
|
|
5
5
|
includeComments?: boolean;
|
|
6
|
+
emitBlockMeta?: boolean;
|
|
6
7
|
resolveHtmlSource?: (source: string) => string | undefined;
|
|
7
8
|
resolveInclude?: (mode: 'file' | 'tag', target: string) => string | undefined;
|
|
8
9
|
resolveAssetPath?: (assetPath: string) => string | undefined;
|
package/package.json
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jianwen-lang/parser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "JianWen language parser implemented in TypeScript",
|
|
5
5
|
"main": "dist/parser.js",
|
|
6
6
|
"types": "dist/parser.d.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Jianwen-lang/parser.git"
|
|
10
|
+
},
|
|
7
11
|
"publishConfig": {
|
|
8
12
|
"access": "public"
|
|
9
13
|
},
|