@jianwen-lang/parser 0.1.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.
Files changed (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/dist/cli/render.d.ts +1 -0
  4. package/dist/cli/render.js +300 -0
  5. package/dist/core/ast.d.ts +286 -0
  6. package/dist/core/ast.js +2 -0
  7. package/dist/core/block/rules/heading.d.ts +9 -0
  8. package/dist/core/block/rules/heading.js +75 -0
  9. package/dist/core/block/rules/horizontal-rule.d.ts +9 -0
  10. package/dist/core/block/rules/horizontal-rule.js +87 -0
  11. package/dist/core/block/rules/include.d.ts +9 -0
  12. package/dist/core/block/rules/include.js +64 -0
  13. package/dist/core/block/rules/index.d.ts +2 -0
  14. package/dist/core/block/rules/index.js +16 -0
  15. package/dist/core/block/rules/types.d.ts +21 -0
  16. package/dist/core/block/rules/types.js +2 -0
  17. package/dist/core/block/types.d.ts +10 -0
  18. package/dist/core/block/types.js +2 -0
  19. package/dist/core/block-parser.d.ts +3 -0
  20. package/dist/core/block-parser.js +1385 -0
  21. package/dist/core/clone.d.ts +9 -0
  22. package/dist/core/clone.js +32 -0
  23. package/dist/core/diagnostics.d.ts +12 -0
  24. package/dist/core/diagnostics.js +24 -0
  25. package/dist/core/errors.d.ts +12 -0
  26. package/dist/core/errors.js +2 -0
  27. package/dist/core/inline/rules/backtick.d.ts +4 -0
  28. package/dist/core/inline/rules/backtick.js +90 -0
  29. package/dist/core/inline/rules/bracket.d.ts +4 -0
  30. package/dist/core/inline/rules/bracket.js +721 -0
  31. package/dist/core/inline/rules/disabled.d.ts +2 -0
  32. package/dist/core/inline/rules/disabled.js +34 -0
  33. package/dist/core/inline/rules/escape.d.ts +2 -0
  34. package/dist/core/inline/rules/escape.js +11 -0
  35. package/dist/core/inline/rules/index.d.ts +2 -0
  36. package/dist/core/inline/rules/index.js +25 -0
  37. package/dist/core/inline/rules/marker-highlight.d.ts +4 -0
  38. package/dist/core/inline/rules/marker-highlight.js +56 -0
  39. package/dist/core/inline/rules/style.d.ts +4 -0
  40. package/dist/core/inline/rules/style.js +120 -0
  41. package/dist/core/inline/rules/types.d.ts +22 -0
  42. package/dist/core/inline/rules/types.js +2 -0
  43. package/dist/core/inline/types.d.ts +1 -0
  44. package/dist/core/inline/types.js +2 -0
  45. package/dist/core/inline-parser.d.ts +3 -0
  46. package/dist/core/inline-parser.js +52 -0
  47. package/dist/core/location.d.ts +9 -0
  48. package/dist/core/location.js +30 -0
  49. package/dist/core/parser.d.ts +9 -0
  50. package/dist/core/parser.js +423 -0
  51. package/dist/core/traverse.d.ts +7 -0
  52. package/dist/core/traverse.js +71 -0
  53. package/dist/html/convert.d.ts +29 -0
  54. package/dist/html/convert.js +61 -0
  55. package/dist/html/format.d.ts +1 -0
  56. package/dist/html/format.js +17 -0
  57. package/dist/html/render/blocks.d.ts +4 -0
  58. package/dist/html/render/blocks.js +433 -0
  59. package/dist/html/render/html.d.ts +8 -0
  60. package/dist/html/render/html.js +89 -0
  61. package/dist/html/render/inlines.d.ts +4 -0
  62. package/dist/html/render/inlines.js +110 -0
  63. package/dist/html/render/meta.d.ts +3 -0
  64. package/dist/html/render/meta.js +51 -0
  65. package/dist/html/render/utils.d.ts +31 -0
  66. package/dist/html/render/utils.js +213 -0
  67. package/dist/html/theme/base/css.d.ts +2 -0
  68. package/dist/html/theme/base/css.js +383 -0
  69. package/dist/html/theme/dark/css.d.ts +2 -0
  70. package/dist/html/theme/dark/css.js +108 -0
  71. package/dist/html/theme/default/colors.d.ts +13 -0
  72. package/dist/html/theme/default/colors.js +2 -0
  73. package/dist/html/theme/default/css.d.ts +2 -0
  74. package/dist/html/theme/default/css.js +6 -0
  75. package/dist/html/theme/default/runtime.d.ts +0 -0
  76. package/dist/html/theme/default/runtime.js +31 -0
  77. package/dist/html/theme/light/css.d.ts +2 -0
  78. package/dist/html/theme/light/css.js +55 -0
  79. package/dist/html/theme/preset/colors.d.ts +10 -0
  80. package/dist/html/theme/preset/colors.js +14 -0
  81. package/dist/html/theme/runtime.d.ts +0 -0
  82. package/dist/html/theme/runtime.js +31 -0
  83. package/dist/html/theme/theme.d.ts +9 -0
  84. package/dist/html/theme/theme.js +21 -0
  85. package/dist/lexer/lexer.d.ts +17 -0
  86. package/dist/lexer/lexer.js +47 -0
  87. package/dist/parser.d.ts +6 -0
  88. package/dist/parser.js +22 -0
  89. package/package.json +50 -0
@@ -0,0 +1,2 @@
1
+ import { InlineRule } from './types';
2
+ export declare const disabledRule: InlineRule;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.disabledRule = void 0;
4
+ const diagnostics_1 = require("../../diagnostics");
5
+ exports.disabledRule = {
6
+ flushTextBefore: false,
7
+ parse(scanner, ctx) {
8
+ const startLine = scanner.line;
9
+ const startColumn = scanner.column;
10
+ const open = scanner.next();
11
+ if (open !== '{') {
12
+ return { kind: 'append', text: '' };
13
+ }
14
+ let content = '';
15
+ while (!scanner.eof()) {
16
+ const ch = scanner.peek();
17
+ if (ch === undefined) {
18
+ break;
19
+ }
20
+ if (ch === '}') {
21
+ scanner.next();
22
+ return { kind: 'append', text: content };
23
+ }
24
+ scanner.next();
25
+ content += ch;
26
+ }
27
+ (0, diagnostics_1.reportParseWarning)(ctx.errors, {
28
+ message: 'Missing closing } for disabled inline segment',
29
+ line: startLine,
30
+ column: startColumn,
31
+ });
32
+ return { kind: 'append', text: `{${content}` };
33
+ },
34
+ };
@@ -0,0 +1,2 @@
1
+ import { InlineRule } from './types';
2
+ export declare const escapeRule: InlineRule;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.escapeRule = void 0;
4
+ exports.escapeRule = {
5
+ flushTextBefore: false,
6
+ parse(scanner) {
7
+ scanner.next();
8
+ const escaped = scanner.next();
9
+ return { kind: 'append', text: escaped ?? '' };
10
+ },
11
+ };
@@ -0,0 +1,2 @@
1
+ import { InlineRule } from './types';
2
+ export declare function getInlineRuleForChar(ch: string): InlineRule | undefined;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getInlineRuleForChar = getInlineRuleForChar;
4
+ const backtick_1 = require("./backtick");
5
+ const bracket_1 = require("./bracket");
6
+ const disabled_1 = require("./disabled");
7
+ const escape_1 = require("./escape");
8
+ const marker_highlight_1 = require("./marker-highlight");
9
+ const style_1 = require("./style");
10
+ const INLINE_RULES_BY_FIRST_CHAR = {
11
+ '\\': escape_1.escapeRule,
12
+ '{': disabled_1.disabledRule,
13
+ '`': backtick_1.backtickRule,
14
+ '=': marker_highlight_1.markerHighlightRule,
15
+ '*': style_1.styleRule,
16
+ '/': style_1.styleRule,
17
+ _: style_1.styleRule,
18
+ '-': style_1.styleRule,
19
+ '~': style_1.styleRule,
20
+ '^': style_1.styleRule,
21
+ '[': bracket_1.bracketRule,
22
+ };
23
+ function getInlineRuleForChar(ch) {
24
+ return INLINE_RULES_BY_FIRST_CHAR[ch];
25
+ }
@@ -0,0 +1,4 @@
1
+ import { InlineNode } from '../../ast';
2
+ import { InlineRule, InlineRuleContext, InlineScanner } from './types';
3
+ export declare function readMarkerHighlight(scanner: InlineScanner, ctx: InlineRuleContext): InlineNode | undefined;
4
+ export declare const markerHighlightRule: InlineRule;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.markerHighlightRule = void 0;
4
+ exports.readMarkerHighlight = readMarkerHighlight;
5
+ const diagnostics_1 = require("../../diagnostics");
6
+ function readMarkerHighlight(scanner, ctx) {
7
+ const startLine = scanner.line;
8
+ const startColumn = scanner.column;
9
+ const first = scanner.next();
10
+ if (first !== '=') {
11
+ return undefined;
12
+ }
13
+ const remaining = scanner.text.slice(scanner.index);
14
+ if (!remaining.includes('=')) {
15
+ return { type: 'text', value: '=' };
16
+ }
17
+ let content = '';
18
+ while (!scanner.eof()) {
19
+ const ch = scanner.peek();
20
+ if (ch === undefined) {
21
+ break;
22
+ }
23
+ if (ch === '=') {
24
+ scanner.next();
25
+ if (content.length === 0) {
26
+ return { type: 'text', value: '==' };
27
+ }
28
+ const children = ctx.parseNested(content, startLine);
29
+ const node = {
30
+ type: 'highlight',
31
+ mode: 'marker',
32
+ children,
33
+ };
34
+ return node;
35
+ }
36
+ scanner.next();
37
+ content += ch;
38
+ }
39
+ (0, diagnostics_1.reportParseWarning)(ctx.errors, {
40
+ message: 'Missing closing = for marker highlight',
41
+ line: startLine,
42
+ column: startColumn,
43
+ });
44
+ return { type: 'text', value: `=${content}` };
45
+ }
46
+ exports.markerHighlightRule = {
47
+ flushTextBefore: true,
48
+ parse(scanner, ctx) {
49
+ const node = readMarkerHighlight(scanner, ctx);
50
+ if (node) {
51
+ return { kind: 'emit', node };
52
+ }
53
+ const consumed = scanner.next();
54
+ return { kind: 'append', text: consumed ?? '' };
55
+ },
56
+ };
@@ -0,0 +1,4 @@
1
+ import { InlineNode } from '../../ast';
2
+ import { InlineRule, InlineRuleContext, InlineScanner } from './types';
3
+ export declare function readStyledSegment(scanner: InlineScanner, ctx: InlineRuleContext): InlineNode | undefined;
4
+ export declare const styleRule: InlineRule;
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.styleRule = void 0;
4
+ exports.readStyledSegment = readStyledSegment;
5
+ const diagnostics_1 = require("../../diagnostics");
6
+ function isAsciiWordChar(ch) {
7
+ if (!ch) {
8
+ return false;
9
+ }
10
+ return /[A-Za-z0-9]/.test(ch);
11
+ }
12
+ function shouldTreatMarkerAsLiteralWordSeparator(scanner, marker, markerStartIndex) {
13
+ if (marker !== '-' && marker !== '/' && marker !== '_' && marker !== '^') {
14
+ return false;
15
+ }
16
+ const prev = markerStartIndex > 0 ? scanner.text[markerStartIndex - 1] : undefined;
17
+ const next = markerStartIndex + 1 < scanner.length ? scanner.text[markerStartIndex + 1] : undefined;
18
+ return isAsciiWordChar(prev) && isAsciiWordChar(next);
19
+ }
20
+ function hasClosingDelimiterAhead(scanner, marker, expectDoubleCaret) {
21
+ const remaining = scanner.text.slice(scanner.index);
22
+ if (marker === '^' && expectDoubleCaret) {
23
+ return remaining.includes('^^');
24
+ }
25
+ return remaining.includes(marker);
26
+ }
27
+ function readStyledSegment(scanner, ctx) {
28
+ const startLine = scanner.line;
29
+ const startColumn = scanner.column;
30
+ const markerStartIndex = scanner.index;
31
+ const marker = scanner.next();
32
+ if (!marker) {
33
+ return undefined;
34
+ }
35
+ let styleType;
36
+ let expectDoubleCaret = false;
37
+ if (marker === '*') {
38
+ styleType = 'strong';
39
+ }
40
+ else if (marker === '/') {
41
+ styleType = 'em';
42
+ }
43
+ else if (marker === '_') {
44
+ styleType = 'underline';
45
+ }
46
+ else if (marker === '-') {
47
+ styleType = 'strike';
48
+ }
49
+ else if (marker === '~') {
50
+ styleType = 'wave';
51
+ }
52
+ else if (marker === '^') {
53
+ if (!scanner.eof() && scanner.peek() === '^') {
54
+ scanner.next();
55
+ styleType = 'sub';
56
+ expectDoubleCaret = true;
57
+ }
58
+ else {
59
+ styleType = 'sup';
60
+ }
61
+ }
62
+ if (!styleType) {
63
+ return undefined;
64
+ }
65
+ const openingToken = marker === '^' && expectDoubleCaret ? '^^' : marker;
66
+ if (shouldTreatMarkerAsLiteralWordSeparator(scanner, marker, markerStartIndex)) {
67
+ return { type: 'text', value: openingToken };
68
+ }
69
+ if (!hasClosingDelimiterAhead(scanner, marker, expectDoubleCaret)) {
70
+ if (marker === '-' || marker === '/' || marker === '_' || marker === '^') {
71
+ return { type: 'text', value: openingToken };
72
+ }
73
+ }
74
+ let content = '';
75
+ while (!scanner.eof()) {
76
+ const ch = scanner.peek();
77
+ if (ch === undefined) {
78
+ break;
79
+ }
80
+ if (ch === marker || (marker === '^' && ch === '^')) {
81
+ if (marker === '^' && expectDoubleCaret) {
82
+ const saveIndex = scanner.index;
83
+ const firstCaret = scanner.next();
84
+ const secondCaret = scanner.peek();
85
+ if (firstCaret === '^' && secondCaret === '^') {
86
+ scanner.next();
87
+ const children = ctx.parseNested(content, startLine);
88
+ const node = { type: styleType, children };
89
+ return node;
90
+ }
91
+ scanner.index = saveIndex;
92
+ }
93
+ else {
94
+ scanner.next();
95
+ const children = ctx.parseNested(content, startLine);
96
+ const node = { type: styleType, children };
97
+ return node;
98
+ }
99
+ }
100
+ scanner.next();
101
+ content += ch;
102
+ }
103
+ (0, diagnostics_1.reportParseWarning)(ctx.errors, {
104
+ message: 'Missing closing style delimiter',
105
+ line: startLine,
106
+ column: startColumn,
107
+ });
108
+ return { type: 'text', value: `${marker}${content}` };
109
+ }
110
+ exports.styleRule = {
111
+ flushTextBefore: true,
112
+ parse(scanner, ctx) {
113
+ const node = readStyledSegment(scanner, ctx);
114
+ if (node) {
115
+ return { kind: 'emit', node };
116
+ }
117
+ const consumed = scanner.next();
118
+ return { kind: 'append', text: consumed ?? '' };
119
+ },
120
+ };
@@ -0,0 +1,22 @@
1
+ import { InlineNode } from '../../ast';
2
+ import { ParseError } from '../../errors';
3
+ import { CharScanner } from '../../../lexer/lexer';
4
+ export type InlineScanner = CharScanner;
5
+ export interface InlineRuleContext {
6
+ errors: ParseError[];
7
+ parseNested: (text: string, baseLine: number) => InlineNode[];
8
+ }
9
+ export type InlineRuleResult = {
10
+ kind: 'append';
11
+ text: string;
12
+ } | {
13
+ kind: 'emit';
14
+ node: InlineNode;
15
+ } | {
16
+ kind: 'emitText';
17
+ text: string;
18
+ };
19
+ export interface InlineRule {
20
+ flushTextBefore: boolean;
21
+ parse: (scanner: InlineScanner, ctx: InlineRuleContext) => InlineRuleResult;
22
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type InlineFontStyleKey = 'italic' | 'bold' | 'heavy' | 'slim' | 'serif' | 'mono';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import { InlineNode } from './ast';
2
+ import { ParseError } from './errors';
3
+ export declare function parseInlines(text: string, errors: ParseError[], baseLine: number, baseColumn?: number): InlineNode[];
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseInlines = parseInlines;
4
+ const lexer_1 = require("../lexer/lexer");
5
+ const rules_1 = require("./inline/rules");
6
+ function parseInlines(text, errors, baseLine, baseColumn = 1) {
7
+ const scanner = createScanner(text, baseLine, baseColumn);
8
+ const nodes = [];
9
+ let buffer = '';
10
+ const ctx = {
11
+ errors,
12
+ parseNested: (nestedText, nestedBaseLine) => parseInlines(nestedText, errors, nestedBaseLine),
13
+ };
14
+ function flushText() {
15
+ if (buffer.length === 0) {
16
+ return;
17
+ }
18
+ const node = { type: 'text', value: buffer };
19
+ nodes.push(node);
20
+ buffer = '';
21
+ }
22
+ while (!scanner.eof()) {
23
+ const ch = scanner.peek();
24
+ if (ch === undefined) {
25
+ break;
26
+ }
27
+ const rule = (0, rules_1.getInlineRuleForChar)(ch);
28
+ if (rule) {
29
+ if (rule.flushTextBefore) {
30
+ flushText();
31
+ }
32
+ const result = rule.parse(scanner, ctx);
33
+ if (result.kind === 'append') {
34
+ buffer += result.text;
35
+ }
36
+ else if (result.kind === 'emit') {
37
+ nodes.push(result.node);
38
+ }
39
+ else {
40
+ nodes.push({ type: 'text', value: result.text });
41
+ }
42
+ continue;
43
+ }
44
+ scanner.next();
45
+ buffer += ch;
46
+ }
47
+ flushText();
48
+ return nodes;
49
+ }
50
+ function createScanner(text, baseLine, baseColumn) {
51
+ return (0, lexer_1.createCharScanner)(text, baseLine, baseColumn);
52
+ }
@@ -0,0 +1,9 @@
1
+ export interface SourceLocation {
2
+ line: number;
3
+ column: number;
4
+ }
5
+ export type NodeOrigin = string;
6
+ export declare function setNodeLocation(node: object, location: SourceLocation): void;
7
+ export declare function getNodeLocation(node: object): SourceLocation | undefined;
8
+ export declare function setNodeOrigin(node: object, origin: NodeOrigin): void;
9
+ export declare function getNodeOrigin(node: object): NodeOrigin | undefined;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setNodeLocation = setNodeLocation;
4
+ exports.getNodeLocation = getNodeLocation;
5
+ exports.setNodeOrigin = setNodeOrigin;
6
+ exports.getNodeOrigin = getNodeOrigin;
7
+ const NODE_LOCATION = Symbol('jianwen.node.location');
8
+ const NODE_ORIGIN = Symbol('jianwen.node.origin');
9
+ function setNodeLocation(node, location) {
10
+ Object.defineProperty(node, NODE_LOCATION, {
11
+ value: location,
12
+ enumerable: false,
13
+ configurable: false,
14
+ writable: false,
15
+ });
16
+ }
17
+ function getNodeLocation(node) {
18
+ return node[NODE_LOCATION];
19
+ }
20
+ function setNodeOrigin(node, origin) {
21
+ Object.defineProperty(node, NODE_ORIGIN, {
22
+ value: origin,
23
+ enumerable: false,
24
+ configurable: false,
25
+ writable: false,
26
+ });
27
+ }
28
+ function getNodeOrigin(node) {
29
+ return node[NODE_ORIGIN];
30
+ }
@@ -0,0 +1,9 @@
1
+ import { JianwenDocument } from './ast';
2
+ import { ParseResult } from './errors';
3
+ export interface ParseOptions {
4
+ expandInclude?: boolean;
5
+ includeMaxDepth?: number;
6
+ loadFile?: (path: string, fromStack: string[]) => string | undefined;
7
+ }
8
+ export declare function parseJianwen(source: string, options?: ParseOptions): JianwenDocument;
9
+ export declare function parseJianwenWithErrors(source: string, options?: ParseOptions): ParseResult;