@flex-development/docmark 1.0.0-dev.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/LICENSE.md +28 -0
- package/README.md +92 -0
- package/dist/index.d.mts +67 -0
- package/dist/index.mjs +1121 -0
- package/package.json +98 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024, Flex Development, LLC All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
+
are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
16
|
+
may be used to endorse or promote products derived from this software without
|
|
17
|
+
specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
20
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
21
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
23
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
24
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
25
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
26
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
28
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# docmark
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/@flex-development/docmark)
|
|
4
|
+
[](https://www.npmcharts.com/compare/@flex-development/docmark?interval=30)
|
|
5
|
+
[](https://packagephobia.now.sh/result?p=@flex-development/docmark)
|
|
6
|
+
[](https://github.com/voxpelli/badges-cjs-esm)
|
|
7
|
+
|
|
8
|
+
a comment parser with support for markdown.
|
|
9
|
+
|
|
10
|
+
> **Note**: This is the `docmark` package from the docmark monorepo.
|
|
11
|
+
> See the [monorepo readme][docmark] for more on the project.
|
|
12
|
+
> See this readme for how to use it.
|
|
13
|
+
|
|
14
|
+
## Contents
|
|
15
|
+
|
|
16
|
+
- [What is this?](#what-is-this)
|
|
17
|
+
- [When should I use this?](#when-should-i-use-this)
|
|
18
|
+
- [Install](#install)
|
|
19
|
+
- [Use](#use)
|
|
20
|
+
- [API](#api)
|
|
21
|
+
- [Types](#types)
|
|
22
|
+
- [Contribute](#contribute)
|
|
23
|
+
|
|
24
|
+
## What is this?
|
|
25
|
+
|
|
26
|
+
**TODO**: what is this?
|
|
27
|
+
|
|
28
|
+
## When should I use this?
|
|
29
|
+
|
|
30
|
+
docmark parses documentation comments, not just docblocks.
|
|
31
|
+
Extensions can register additional comment syntaxes — such as line comments, hash comments, or language-specific
|
|
32
|
+
documentation comments — without changing how the comment content itself is parsed.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
This package is [ESM only][esm].
|
|
37
|
+
|
|
38
|
+
In Node.js (version 20+) with [yarn][]:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
yarn add @flex-development/docmark
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
<blockquote>
|
|
45
|
+
<small>
|
|
46
|
+
See <a href='https://yarnpkg.com/protocol/git'>Git - Protocols | Yarn</a>
|
|
47
|
+
for details regarding installing from Git.
|
|
48
|
+
</small>
|
|
49
|
+
</blockquote>
|
|
50
|
+
|
|
51
|
+
In Deno with [`esm.sh`][esmsh]:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { docmark } from 'https://esm.sh/@flex-development/docmark'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
In browsers with [`esm.sh`][esmsh]:
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<script type="module">
|
|
61
|
+
import { docmark } from 'https://esm.sh/@flex-development/docmark'
|
|
62
|
+
</script>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Use
|
|
66
|
+
|
|
67
|
+
**TODO**: use
|
|
68
|
+
|
|
69
|
+
## API
|
|
70
|
+
|
|
71
|
+
**TODO**: api
|
|
72
|
+
|
|
73
|
+
## Types
|
|
74
|
+
|
|
75
|
+
This package is fully typed with [TypeScript][].
|
|
76
|
+
|
|
77
|
+
## Contribute
|
|
78
|
+
|
|
79
|
+
See [`CONTRIBUTING.md`](../../CONTRIBUTING.md).
|
|
80
|
+
|
|
81
|
+
This project has a [code of conduct](../../CODE_OF_CONDUCT.md).
|
|
82
|
+
By interacting with this repository, organization, or community you agree to abide by its terms.
|
|
83
|
+
|
|
84
|
+
[docmark]: ../../README.md
|
|
85
|
+
|
|
86
|
+
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
|
87
|
+
|
|
88
|
+
[esmsh]: https://esm.sh
|
|
89
|
+
|
|
90
|
+
[typescript]: https://www.typescriptlang.org
|
|
91
|
+
|
|
92
|
+
[yarn]: https://yarnpkg.com
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { ParseOptions, ParseContext, Event, PreprocessOptions, Preprocessor } from '@flex-development/docmark-util-types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file parse
|
|
5
|
+
* @module docmark/parse
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a parser.
|
|
10
|
+
*
|
|
11
|
+
* Tokenizers deal with one content type.
|
|
12
|
+
* The parser is the object dealing with it all.
|
|
13
|
+
*
|
|
14
|
+
* @see {@linkcode ParseContext}
|
|
15
|
+
* @see {@linkcode ParseOptions}
|
|
16
|
+
*
|
|
17
|
+
* @this {void}
|
|
18
|
+
*
|
|
19
|
+
* @param {ParseOptions | null | undefined} [options]
|
|
20
|
+
* Options for parsing
|
|
21
|
+
* @return {ParseContext}
|
|
22
|
+
* The parse context
|
|
23
|
+
*/
|
|
24
|
+
declare function parse(this: void, options?: ParseOptions | null | undefined): ParseContext;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @file postprocess
|
|
28
|
+
* @module docmark/postprocess
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Postprocess events.
|
|
33
|
+
*
|
|
34
|
+
* @todo resolve trailing whitespace
|
|
35
|
+
*
|
|
36
|
+
* @see {@linkcode Event}
|
|
37
|
+
*
|
|
38
|
+
* @this {void}
|
|
39
|
+
*
|
|
40
|
+
* @param {Event[]} events
|
|
41
|
+
* The current list of events
|
|
42
|
+
* @return {Event[]}
|
|
43
|
+
* The list of changed events
|
|
44
|
+
*/
|
|
45
|
+
declare function postprocess(this: void, events: Event[]): Event[];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @file preprocess
|
|
49
|
+
* @module docmark/preprocess
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Create a preprocessor to turn a value into chunks.
|
|
54
|
+
*
|
|
55
|
+
* @see {@linkcode Preprocessor}
|
|
56
|
+
* @see {@linkcode PreprocessOptions}
|
|
57
|
+
*
|
|
58
|
+
* @this {void}
|
|
59
|
+
*
|
|
60
|
+
* @param {PreprocessOptions | null | undefined} [options]
|
|
61
|
+
* The configuration options
|
|
62
|
+
* @return {Preprocessor}
|
|
63
|
+
* The preprocessor
|
|
64
|
+
*/
|
|
65
|
+
declare function preprocess(this: void, options?: PreprocessOptions | null | undefined): Preprocessor;
|
|
66
|
+
|
|
67
|
+
export { parse, postprocess, preprocess };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1121 @@
|
|
|
1
|
+
import { combineExtensions } from '@flex-development/docmark-util-combine-extensions';
|
|
2
|
+
import { ct, tt, codes, constants, ev } from '@flex-development/docmark-util-symbol';
|
|
3
|
+
import { createTokenizer } from '@flex-development/mark-parser';
|
|
4
|
+
import { eos, bos, eol, whitespace, htab } from '@flex-development/mark-util-character';
|
|
5
|
+
import { typeExpressionValue, summary, blankLine, region } from '@flex-development/docmark-grammar';
|
|
6
|
+
import * as commonmark from 'micromark-core-commonmark';
|
|
7
|
+
import { splice } from '@flex-development/mark-util-chunked';
|
|
8
|
+
import { ok } from 'devlop';
|
|
9
|
+
import { subtokenize } from '@flex-development/docmark-util-subtokenize';
|
|
10
|
+
import { factorySpace } from '@flex-development/docmark-factory-space';
|
|
11
|
+
import { subtokenize as subtokenize$1 } from 'micromark-util-subtokenize';
|
|
12
|
+
import { decode } from '@flex-development/mark-parser/utils';
|
|
13
|
+
|
|
14
|
+
const docmark = {
|
|
15
|
+
comment: { null: summary },
|
|
16
|
+
source: {},
|
|
17
|
+
type: { null: typeExpressionValue }
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const string = initializeFactory(ct.string);
|
|
21
|
+
const text = initializeFactory(ct.text);
|
|
22
|
+
function initializeFactory(contentType) {
|
|
23
|
+
const capt = `${contentType[0].toUpperCase()}${contentType.slice(1)}`;
|
|
24
|
+
const tokenizer = tokenize.name + capt;
|
|
25
|
+
return {
|
|
26
|
+
resolveAll: resolver(contentType === 'text' && resolveLineSuffixes),
|
|
27
|
+
tokenize: Object.defineProperties(tokenize, { name: { value: tokenizer } })
|
|
28
|
+
};
|
|
29
|
+
function tokenize(effects) {
|
|
30
|
+
const self = this;
|
|
31
|
+
const constructs = self.parser.constructs[contentType];
|
|
32
|
+
const state = effects.attempt(constructs, start, notText);
|
|
33
|
+
return start;
|
|
34
|
+
function start(code) {
|
|
35
|
+
return atBreak(code) ? state(code) : notText(code);
|
|
36
|
+
}
|
|
37
|
+
function notText(code) {
|
|
38
|
+
if (eos(code))
|
|
39
|
+
return void effects.consume(code);
|
|
40
|
+
return effects.enter(tt.data), effects.consume(code), data;
|
|
41
|
+
}
|
|
42
|
+
function data(code) {
|
|
43
|
+
if (atBreak(code))
|
|
44
|
+
return effects.exit(tt.data), state(code);
|
|
45
|
+
return effects.consume(code), data;
|
|
46
|
+
}
|
|
47
|
+
function atBreak(code) {
|
|
48
|
+
if (eos(code))
|
|
49
|
+
return true;
|
|
50
|
+
const pack = constructs[code];
|
|
51
|
+
if (pack) {
|
|
52
|
+
ok(Array.isArray(pack), 'expected list of constructs');
|
|
53
|
+
let index = -1;
|
|
54
|
+
while (++index < pack.length) {
|
|
55
|
+
ok(pack[index], 'expected `pack[index]`');
|
|
56
|
+
const item = pack[index];
|
|
57
|
+
if (!item.previous || item.previous.call(self, self.previous)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function resolver(extraResolver) {
|
|
66
|
+
const name = resolveAll.name + capt;
|
|
67
|
+
Object.defineProperties(resolveAll, { name: { value: name } });
|
|
68
|
+
return resolveAll;
|
|
69
|
+
function resolveAll(events, context) {
|
|
70
|
+
let index = -1;
|
|
71
|
+
let enter = undefined;
|
|
72
|
+
while (++index <= events.length) {
|
|
73
|
+
if (enter === undefined) {
|
|
74
|
+
if (events[index] && events[index][1].type === tt.data) {
|
|
75
|
+
enter = index;
|
|
76
|
+
index++;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (!events[index] || events[index][1].type !== tt.data) {
|
|
80
|
+
if (index !== enter + 2) {
|
|
81
|
+
events[enter][1].end = events[index - 1][1].end;
|
|
82
|
+
events.splice(enter + 2, index - enter - 2);
|
|
83
|
+
index = enter + 2;
|
|
84
|
+
}
|
|
85
|
+
enter = undefined;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return extraResolver ? extraResolver(events, context) : events;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function resolveLineSuffixes(events) {
|
|
93
|
+
let index = 0;
|
|
94
|
+
while (++index <= events.length) {
|
|
95
|
+
if (index === events.length || events[index][1].type === tt.lineEnding) {
|
|
96
|
+
if (events[index - 1][1].type === tt.data) {
|
|
97
|
+
const [, data, context] = events[index - 1];
|
|
98
|
+
const chunks = context.sliceStream(data);
|
|
99
|
+
let bufferIndex = -1;
|
|
100
|
+
let chunkIndex = chunks.length;
|
|
101
|
+
let size = 0;
|
|
102
|
+
let tabs = undefined;
|
|
103
|
+
while (chunkIndex--) {
|
|
104
|
+
const chunk = chunks[chunkIndex];
|
|
105
|
+
if (typeof chunk === 'string') {
|
|
106
|
+
bufferIndex = chunk.length;
|
|
107
|
+
while (chunk.codePointAt(bufferIndex - 1) === codes.space) {
|
|
108
|
+
size++;
|
|
109
|
+
bufferIndex--;
|
|
110
|
+
}
|
|
111
|
+
if (bufferIndex)
|
|
112
|
+
break;
|
|
113
|
+
bufferIndex = -1;
|
|
114
|
+
}
|
|
115
|
+
else if (chunk === codes.horizontalTab) {
|
|
116
|
+
tabs = true;
|
|
117
|
+
size++;
|
|
118
|
+
}
|
|
119
|
+
else if (chunk !== codes.virtualSpace) {
|
|
120
|
+
chunkIndex++;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (size) {
|
|
125
|
+
const _bufferIndex = chunkIndex
|
|
126
|
+
? bufferIndex
|
|
127
|
+
: data.start._bufferIndex + bufferIndex;
|
|
128
|
+
const lineSuffix = index === events.length ||
|
|
129
|
+
tabs ||
|
|
130
|
+
size < constants.hardBreakPrefixSizeMin;
|
|
131
|
+
const start = {
|
|
132
|
+
line: data.end.line,
|
|
133
|
+
column: data.end.column - size,
|
|
134
|
+
offset: data.end.offset - size,
|
|
135
|
+
_index: data.start._index + chunkIndex,
|
|
136
|
+
_bufferIndex
|
|
137
|
+
};
|
|
138
|
+
const type = lineSuffix
|
|
139
|
+
? tt.lineSuffix
|
|
140
|
+
: tt.hardBreakTrailing;
|
|
141
|
+
const token = context.token(type, {
|
|
142
|
+
end: structuredClone(data.end),
|
|
143
|
+
start: (data.end = structuredClone(start), start)
|
|
144
|
+
});
|
|
145
|
+
if (data.start.offset === data.end.offset) {
|
|
146
|
+
Object.assign(data, token);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const enter = [ev.enter, token, context];
|
|
150
|
+
const exit = [ev.exit, token, context];
|
|
151
|
+
splice(events, index, 0, [enter, exit]);
|
|
152
|
+
index += 2;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
index++;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return events;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const markdown = {
|
|
163
|
+
attentionMarkers: {
|
|
164
|
+
null: [codes.asterisk, codes.underscore]
|
|
165
|
+
},
|
|
166
|
+
contentInitial: {
|
|
167
|
+
[codes.leftSquareBracket]: commonmark.definition
|
|
168
|
+
},
|
|
169
|
+
disable: {
|
|
170
|
+
null: []
|
|
171
|
+
},
|
|
172
|
+
document: {
|
|
173
|
+
[codes.asterisk]: commonmark.list,
|
|
174
|
+
[codes.plusSign]: commonmark.list,
|
|
175
|
+
[codes.dash]: commonmark.list,
|
|
176
|
+
[codes.digit0]: commonmark.list,
|
|
177
|
+
[codes.digit1]: commonmark.list,
|
|
178
|
+
[codes.digit2]: commonmark.list,
|
|
179
|
+
[codes.digit3]: commonmark.list,
|
|
180
|
+
[codes.digit4]: commonmark.list,
|
|
181
|
+
[codes.digit5]: commonmark.list,
|
|
182
|
+
[codes.digit6]: commonmark.list,
|
|
183
|
+
[codes.digit7]: commonmark.list,
|
|
184
|
+
[codes.digit8]: commonmark.list,
|
|
185
|
+
[codes.digit9]: commonmark.list,
|
|
186
|
+
[codes.greaterThan]: commonmark.blockQuote
|
|
187
|
+
},
|
|
188
|
+
flow: {
|
|
189
|
+
[codes.numberSign]: commonmark.headingAtx,
|
|
190
|
+
[codes.asterisk]: commonmark.thematicBreak,
|
|
191
|
+
[codes.dash]: [commonmark.setextUnderline, commonmark.thematicBreak],
|
|
192
|
+
[codes.lessThan]: commonmark.htmlFlow,
|
|
193
|
+
[codes.equalsTo]: commonmark.setextUnderline,
|
|
194
|
+
[codes.underscore]: commonmark.thematicBreak,
|
|
195
|
+
[codes.graveAccent]: commonmark.codeFenced,
|
|
196
|
+
[codes.tilde]: commonmark.codeFenced
|
|
197
|
+
},
|
|
198
|
+
flowInitial: {
|
|
199
|
+
[codes.horizontalTab]: commonmark.codeIndented,
|
|
200
|
+
[codes.virtualSpace]: commonmark.codeIndented,
|
|
201
|
+
[codes.space]: commonmark.codeIndented
|
|
202
|
+
},
|
|
203
|
+
insideSpan: {
|
|
204
|
+
null: [
|
|
205
|
+
{ resolveAll: commonmark.attention.resolveAll },
|
|
206
|
+
{ resolveAll: string.resolveAll }
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
string: {
|
|
210
|
+
[codes.ampersand]: commonmark.characterReference,
|
|
211
|
+
[codes.backslash]: commonmark.characterEscape
|
|
212
|
+
},
|
|
213
|
+
text: {
|
|
214
|
+
[codes.carriageReturn]: commonmark.lineEnding,
|
|
215
|
+
[codes.lineFeed]: commonmark.lineEnding,
|
|
216
|
+
[codes.carriageReturnLineFeed]: commonmark.lineEnding,
|
|
217
|
+
[codes.exclamationMark]: commonmark.labelStartImage,
|
|
218
|
+
[codes.ampersand]: commonmark.characterReference,
|
|
219
|
+
[codes.asterisk]: commonmark.attention,
|
|
220
|
+
[codes.lessThan]: [commonmark.autolink, commonmark.htmlText],
|
|
221
|
+
[codes.leftSquareBracket]: commonmark.labelStartLink,
|
|
222
|
+
[codes.backslash]: [commonmark.hardBreakEscape, commonmark.characterEscape],
|
|
223
|
+
[codes.rightSquareBracket]: commonmark.labelEnd,
|
|
224
|
+
[codes.underscore]: commonmark.attention,
|
|
225
|
+
[codes.graveAccent]: commonmark.codeText
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
function resolveRegionExits(events) {
|
|
230
|
+
let index = -1;
|
|
231
|
+
let region;
|
|
232
|
+
while (++index < events.length) {
|
|
233
|
+
ok(events[index], 'expected `events[index]`');
|
|
234
|
+
const [event, token, self] = events[index];
|
|
235
|
+
if (token._region) {
|
|
236
|
+
if (event === ev.enter) {
|
|
237
|
+
region = token;
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
region = undefined;
|
|
241
|
+
const previousIndex = index - 1;
|
|
242
|
+
ok(events[previousIndex], 'expected `events[previousIndex]`');
|
|
243
|
+
const [previousEvent, previousToken] = events[previousIndex];
|
|
244
|
+
if (previousEvent === ev.exit &&
|
|
245
|
+
(previousToken.type === tt.hardBreakEscape ||
|
|
246
|
+
previousToken.type === tt.hardBreakTrailing ||
|
|
247
|
+
previousToken.type === tt.lineSuffix ||
|
|
248
|
+
previousToken._trailing)) {
|
|
249
|
+
token.end = structuredClone(previousToken.start);
|
|
250
|
+
splice(events, index, 1);
|
|
251
|
+
splice(events, previousIndex - 1, 0, [[event, token, self]]);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (region && event === ev.enter && token.type === tt.lineEnding) {
|
|
257
|
+
let position = index + 1;
|
|
258
|
+
while (++position < events.length) {
|
|
259
|
+
ok(events[position], 'expected `events[position]`');
|
|
260
|
+
ok(token !== events[position][1], 'did not expect `token` match');
|
|
261
|
+
const event = events[position];
|
|
262
|
+
if (region === event[1]) {
|
|
263
|
+
ok(event[0] === ev.exit, 'expected region `exit` event');
|
|
264
|
+
event[1].end = structuredClone(token.start);
|
|
265
|
+
splice(events, position, 1);
|
|
266
|
+
splice(events, index, 0, [event]);
|
|
267
|
+
index--;
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
if (event[0] === ev.enter) {
|
|
271
|
+
if (event[1].type === tt.linePrefix) {
|
|
272
|
+
const k = 2;
|
|
273
|
+
if (events[position + k]?.[1].type !== tt.lineEndingBlank) {
|
|
274
|
+
index++;
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
position += k;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else if (event[1].type !== token.type &&
|
|
282
|
+
event[1].type !== tt.lineEndingBlank) {
|
|
283
|
+
index++;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return events;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function postprocess$1(events) {
|
|
294
|
+
while (!subtokenize(events))
|
|
295
|
+
;
|
|
296
|
+
return resolveRegionExits(events);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const comment = {
|
|
300
|
+
resolve: resolveComment,
|
|
301
|
+
tokenize: tokenizeComment
|
|
302
|
+
};
|
|
303
|
+
function resolveComment(events) {
|
|
304
|
+
return postprocess$1(events);
|
|
305
|
+
}
|
|
306
|
+
function tokenizeComment(effects) {
|
|
307
|
+
const self = this;
|
|
308
|
+
const stack = [];
|
|
309
|
+
let continued = 0;
|
|
310
|
+
let markdown;
|
|
311
|
+
let md;
|
|
312
|
+
let then;
|
|
313
|
+
return start;
|
|
314
|
+
function start(code) {
|
|
315
|
+
ok(bos(self.previous) || eol(self.previous) || eos(code), 'expected beginning of stream, beginning of line, or end of stream');
|
|
316
|
+
restate();
|
|
317
|
+
if (!stack[0]) {
|
|
318
|
+
return effects.check(blankLine, beforeBlankLine, checkNewRegions)(code);
|
|
319
|
+
}
|
|
320
|
+
return effects.check(blankLine, continueAtBlankLine, continueAtNoBlankLine)(code);
|
|
321
|
+
}
|
|
322
|
+
function beforeBlankLine(code) {
|
|
323
|
+
self.parser.atBlankLine = true;
|
|
324
|
+
return beforeMarkdown(code);
|
|
325
|
+
}
|
|
326
|
+
function continueAtBlankLine(code) {
|
|
327
|
+
ok(stack.length, 'expected region on `stack`');
|
|
328
|
+
self.parser.atBlankLine = true;
|
|
329
|
+
return tryContinuation(code);
|
|
330
|
+
}
|
|
331
|
+
function continueAtNoBlankLine(code) {
|
|
332
|
+
ok(stack.length, 'expected region on `stack`');
|
|
333
|
+
self.parser.atBlankLine = false;
|
|
334
|
+
return checkNewRegions(code);
|
|
335
|
+
}
|
|
336
|
+
function checkNewRegions(code) {
|
|
337
|
+
ok(!self.parser.atBlankLine, 'expected no blank line');
|
|
338
|
+
self.interrupt = Boolean(markdown?.currentConstruct ?? markdown?.interrupt);
|
|
339
|
+
if (stack.length === 1) {
|
|
340
|
+
if (!markdown) {
|
|
341
|
+
return effects.check(region, aNewRegion, tryContinuation)(code);
|
|
342
|
+
}
|
|
343
|
+
if (markdown.concrete)
|
|
344
|
+
return tryContinuation(code);
|
|
345
|
+
return effects.check(region, aNewRegion, tryContinuation)(code);
|
|
346
|
+
}
|
|
347
|
+
ok(!stack.length, 'expected no region on `stack`');
|
|
348
|
+
return tryRegion(code);
|
|
349
|
+
}
|
|
350
|
+
function aNewRegion(code) {
|
|
351
|
+
ok(stack.length === 1, 'expected region on `stack`');
|
|
352
|
+
flush();
|
|
353
|
+
return tryRegion(code);
|
|
354
|
+
}
|
|
355
|
+
function tryRegion(code) {
|
|
356
|
+
restate();
|
|
357
|
+
continued = self.events.length;
|
|
358
|
+
return effects.attempt(region, addRegion, beforeMarkdown)(code);
|
|
359
|
+
}
|
|
360
|
+
function addRegion(code) {
|
|
361
|
+
ok(self.currentConstruct, 'expected a current construct');
|
|
362
|
+
ok(self.currentConstruct.continuation, 'expected continuable construct');
|
|
363
|
+
ok(self.containerState, 'expected `containerState` when adding region');
|
|
364
|
+
forward();
|
|
365
|
+
ok(stack.length === 0, 'expected empty region stack');
|
|
366
|
+
stack[0] = [self.currentConstruct, self.containerState];
|
|
367
|
+
self.parser.freshRegion = true;
|
|
368
|
+
self.parser.skipSummary = true;
|
|
369
|
+
if (self.containerState._closeFlow)
|
|
370
|
+
flush();
|
|
371
|
+
if (bos(self.previous) || eol(self.previous))
|
|
372
|
+
return start(code);
|
|
373
|
+
if (eol(code)) {
|
|
374
|
+
effects.enter(tt.lineEnding);
|
|
375
|
+
effects.consume(code);
|
|
376
|
+
effects.exit(tt.lineEnding);
|
|
377
|
+
return start;
|
|
378
|
+
}
|
|
379
|
+
ok(eos(code), 'expected end of stream');
|
|
380
|
+
return start(code);
|
|
381
|
+
}
|
|
382
|
+
function tryContinuation(code) {
|
|
383
|
+
ok(self.containerState, 'expected `containerState` when continuing');
|
|
384
|
+
ok(stack[0], 'expected region on `stack` when continuing');
|
|
385
|
+
const [construct, containerState] = stack[0];
|
|
386
|
+
self.containerState = containerState;
|
|
387
|
+
continued = self.events.length;
|
|
388
|
+
then = self.now();
|
|
389
|
+
self.interrupt = Boolean(markdown?.currentConstruct ?? markdown?.interrupt);
|
|
390
|
+
return effects.attempt(construct.continuation, afterContinuation, noContinuation)(code);
|
|
391
|
+
}
|
|
392
|
+
function afterContinuation(code) {
|
|
393
|
+
ok(self.containerState, 'expected `containerState` after continuing');
|
|
394
|
+
ok(stack.length === 1, 'expected region on `stack`');
|
|
395
|
+
ok(then, 'expected `then` after continuing');
|
|
396
|
+
forward();
|
|
397
|
+
if (self.containerState._closeFlow)
|
|
398
|
+
return noContinuation(code);
|
|
399
|
+
self.parser.freshRegion = false;
|
|
400
|
+
const now = self.now();
|
|
401
|
+
if (then.line === now.line &&
|
|
402
|
+
then.column === now.column &&
|
|
403
|
+
then.offset === now.offset &&
|
|
404
|
+
then._bufferIndex === now._bufferIndex &&
|
|
405
|
+
then._index === now._index) {
|
|
406
|
+
return beforeMarkdown(code);
|
|
407
|
+
}
|
|
408
|
+
if (!eol(self.previous))
|
|
409
|
+
return beforeMarkdown(code);
|
|
410
|
+
return start(code);
|
|
411
|
+
}
|
|
412
|
+
function noContinuation(code) {
|
|
413
|
+
flush();
|
|
414
|
+
if (self.parser.atBlankLine)
|
|
415
|
+
return beforeMarkdown(code);
|
|
416
|
+
return start(code);
|
|
417
|
+
}
|
|
418
|
+
function beforeMarkdown(code) {
|
|
419
|
+
if (eos(code))
|
|
420
|
+
return void end(code);
|
|
421
|
+
return markdownStart(code);
|
|
422
|
+
}
|
|
423
|
+
function markdownStart(code) {
|
|
424
|
+
ok(!eos(code), 'did not expect end of stream');
|
|
425
|
+
markdown ??= self.parser.document(self.now());
|
|
426
|
+
effects.enter(tt.chunkMarkdown, {
|
|
427
|
+
_tokenizer: markdown,
|
|
428
|
+
contentType: constants.contentTypeDocument,
|
|
429
|
+
previous: md
|
|
430
|
+
});
|
|
431
|
+
return markdownContinue(code);
|
|
432
|
+
}
|
|
433
|
+
function markdownContinue(code) {
|
|
434
|
+
ok(markdown, 'expected `markdown` when continuing markdown');
|
|
435
|
+
ok(self.containerState, 'expected `containerState` inside markdown');
|
|
436
|
+
if (eos(code)) {
|
|
437
|
+
write(effects.exit(tt.chunkMarkdown), true);
|
|
438
|
+
return void end(code);
|
|
439
|
+
}
|
|
440
|
+
if (eol(code)) {
|
|
441
|
+
effects.consume(code);
|
|
442
|
+
write(effects.exit(tt.chunkMarkdown));
|
|
443
|
+
return start;
|
|
444
|
+
}
|
|
445
|
+
effects.consume(code);
|
|
446
|
+
return markdownContinue;
|
|
447
|
+
}
|
|
448
|
+
function closeMarkdown() {
|
|
449
|
+
if (markdown && !eos(markdown.code))
|
|
450
|
+
markdown.write([codes.eos]);
|
|
451
|
+
markdown = undefined;
|
|
452
|
+
md = undefined;
|
|
453
|
+
return void markdown;
|
|
454
|
+
}
|
|
455
|
+
function end(code) {
|
|
456
|
+
ok(eos(code), 'expected end of stream');
|
|
457
|
+
flush();
|
|
458
|
+
self.parser.atBlankLine = undefined;
|
|
459
|
+
self.parser.freshRegion = undefined;
|
|
460
|
+
self.parser.previousBlankLine = undefined;
|
|
461
|
+
return void effects.consume(code);
|
|
462
|
+
}
|
|
463
|
+
function flush() {
|
|
464
|
+
ok(stack.length <= 1, 'expected no more than 1 region');
|
|
465
|
+
closeMarkdown();
|
|
466
|
+
while (stack.length) {
|
|
467
|
+
const [construct, containerState] = stack.pop();
|
|
468
|
+
self.containerState = containerState;
|
|
469
|
+
construct.exit.call(self, effects);
|
|
470
|
+
}
|
|
471
|
+
self.currentConstruct = undefined;
|
|
472
|
+
self.concrete = undefined;
|
|
473
|
+
return void restate();
|
|
474
|
+
}
|
|
475
|
+
function forward() {
|
|
476
|
+
while (continued < self.events.length) {
|
|
477
|
+
ok(self.events[continued], 'expected `self.events[continued]`');
|
|
478
|
+
const [event, token] = self.events[continued];
|
|
479
|
+
if (event === ev.exit &&
|
|
480
|
+
token.type === tt.chunkMarkdown &&
|
|
481
|
+
token.contentType === constants.contentTypeDocument) {
|
|
482
|
+
write(token);
|
|
483
|
+
}
|
|
484
|
+
continued++;
|
|
485
|
+
}
|
|
486
|
+
return void self.events;
|
|
487
|
+
}
|
|
488
|
+
function restate() {
|
|
489
|
+
const { comment } = self.containerState ?? {};
|
|
490
|
+
self.containerState = {};
|
|
491
|
+
self.containerState.comment = comment;
|
|
492
|
+
return void self.containerState;
|
|
493
|
+
}
|
|
494
|
+
function write(token, end) {
|
|
495
|
+
ok(self.containerState, 'expected `containerState` during write');
|
|
496
|
+
ok(token !== md, 'did not expect `token` to match previous token');
|
|
497
|
+
markdown ??= self.parser.document(token.start);
|
|
498
|
+
token._tokenizer ??= markdown;
|
|
499
|
+
const stream = self.sliceStream(token);
|
|
500
|
+
if (eol(stream.at(-1))) {
|
|
501
|
+
self.parser.previousBlankLine = self.parser.atBlankLine;
|
|
502
|
+
self.parser.atBlankLine = null;
|
|
503
|
+
}
|
|
504
|
+
if (end)
|
|
505
|
+
stream.push(codes.eos);
|
|
506
|
+
token.previous = md;
|
|
507
|
+
if (md)
|
|
508
|
+
md.next = token;
|
|
509
|
+
md = token;
|
|
510
|
+
if (token.previous)
|
|
511
|
+
markdown.defineSkip(token.start);
|
|
512
|
+
markdown.write(stream);
|
|
513
|
+
self.concrete = markdown.concrete;
|
|
514
|
+
return void markdown;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
const content = { tokenize: tokenizeContent };
|
|
519
|
+
function tokenizeContent(effects) {
|
|
520
|
+
const contentStart = effects.attempt(this.parser.constructs.contentInitial, afterContentStart, paragraphInitial);
|
|
521
|
+
let previous;
|
|
522
|
+
return contentStart;
|
|
523
|
+
function afterContentStart(code) {
|
|
524
|
+
if (eos(code))
|
|
525
|
+
return void effects.consume(code);
|
|
526
|
+
ok(eol(code), 'expected eol');
|
|
527
|
+
effects.enter(tt.lineEnding);
|
|
528
|
+
effects.consume(code);
|
|
529
|
+
effects.exit(tt.lineEnding);
|
|
530
|
+
return factorySpace(effects, contentStart, tt.linePrefix);
|
|
531
|
+
}
|
|
532
|
+
function paragraphInitial(code) {
|
|
533
|
+
ok(!eos(code) && !eol(code), 'expected anything other than a line ending or eof');
|
|
534
|
+
effects.enter(tt.paragraph);
|
|
535
|
+
return lineStart(code);
|
|
536
|
+
}
|
|
537
|
+
function lineStart(code) {
|
|
538
|
+
const token = effects.enter(tt.chunkText, {
|
|
539
|
+
contentType: ct.text,
|
|
540
|
+
previous
|
|
541
|
+
});
|
|
542
|
+
if (previous)
|
|
543
|
+
previous.next = token;
|
|
544
|
+
previous = token;
|
|
545
|
+
return data(code);
|
|
546
|
+
}
|
|
547
|
+
function data(code) {
|
|
548
|
+
if (eos(code)) {
|
|
549
|
+
effects.exit(tt.chunkText);
|
|
550
|
+
effects.exit(tt.paragraph);
|
|
551
|
+
return void effects.consume(code);
|
|
552
|
+
}
|
|
553
|
+
if (eol(code)) {
|
|
554
|
+
effects.consume(code);
|
|
555
|
+
effects.exit(tt.chunkText);
|
|
556
|
+
return lineStart;
|
|
557
|
+
}
|
|
558
|
+
effects.consume(code);
|
|
559
|
+
return data;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function postprocess(events) {
|
|
564
|
+
while (!subtokenize$1(events)) {
|
|
565
|
+
}
|
|
566
|
+
return events;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
function resolveMarkdown(events) {
|
|
570
|
+
return postprocess(events);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
const document = {
|
|
574
|
+
resolve: resolveMarkdown,
|
|
575
|
+
tokenize: tokenizeDocument
|
|
576
|
+
};
|
|
577
|
+
const container = { tokenize: tokenizeContainer };
|
|
578
|
+
function tokenizeDocument(effects) {
|
|
579
|
+
const self = this;
|
|
580
|
+
const stack = [];
|
|
581
|
+
let childFlow;
|
|
582
|
+
let childToken;
|
|
583
|
+
let continued = 0;
|
|
584
|
+
let lineStartOffset;
|
|
585
|
+
return start;
|
|
586
|
+
function start(code) {
|
|
587
|
+
if (continued < stack.length) {
|
|
588
|
+
const [construct, containerState] = stack[continued];
|
|
589
|
+
ok(construct.continuation, 'expected `continuation` on container construct');
|
|
590
|
+
self.containerState = containerState;
|
|
591
|
+
return effects.attempt(construct.continuation, documentContinue, checkNewContainers)(code);
|
|
592
|
+
}
|
|
593
|
+
return checkNewContainers(code);
|
|
594
|
+
}
|
|
595
|
+
function documentContinue(code) {
|
|
596
|
+
ok(self.containerState, 'expected `containerState` after continuation');
|
|
597
|
+
continued++;
|
|
598
|
+
if (self.containerState._closeFlow) {
|
|
599
|
+
self.containerState._closeFlow = undefined;
|
|
600
|
+
closeFlow();
|
|
601
|
+
const indexBeforeExits = self.events.length;
|
|
602
|
+
let flowExitIndex = indexBeforeExits;
|
|
603
|
+
let point = undefined;
|
|
604
|
+
while (flowExitIndex--) {
|
|
605
|
+
ok(self.events[flowExitIndex], 'expected `events[flowExitIndex]`');
|
|
606
|
+
const [event, token] = self.events[flowExitIndex];
|
|
607
|
+
if (event === ev.exit && token.type === tt.chunkFlow) {
|
|
608
|
+
point = token.end;
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
ok(point, 'could not find previous flow chunk');
|
|
613
|
+
exitContainers(continued);
|
|
614
|
+
let index = indexBeforeExits;
|
|
615
|
+
while (index < self.events.length) {
|
|
616
|
+
self.events[index][1].end = { ...point };
|
|
617
|
+
index++;
|
|
618
|
+
}
|
|
619
|
+
splice(self.events, flowExitIndex + 1, 0, self.events.slice(indexBeforeExits));
|
|
620
|
+
self.events.length = index;
|
|
621
|
+
return checkNewContainers(code);
|
|
622
|
+
}
|
|
623
|
+
return start(code);
|
|
624
|
+
}
|
|
625
|
+
function checkNewContainers(code) {
|
|
626
|
+
if (continued === stack.length) {
|
|
627
|
+
if (!childFlow)
|
|
628
|
+
return documentContinued(code);
|
|
629
|
+
if (childFlow.currentConstruct?.concrete)
|
|
630
|
+
return flowStart(code);
|
|
631
|
+
self.interrupt = Boolean(childFlow.currentConstruct && !childFlow._gfmTableDynamicInterruptHack);
|
|
632
|
+
}
|
|
633
|
+
self.containerState = {};
|
|
634
|
+
return effects.check(container, thereIsANewContainer, thereIsNoNewContainer)(code);
|
|
635
|
+
}
|
|
636
|
+
function thereIsANewContainer(code) {
|
|
637
|
+
closeFlow();
|
|
638
|
+
exitContainers(continued);
|
|
639
|
+
return documentContinued(code);
|
|
640
|
+
}
|
|
641
|
+
function thereIsNoNewContainer(code) {
|
|
642
|
+
self.parser.lazy[self.now().line] = continued !== stack.length;
|
|
643
|
+
lineStartOffset = self.now().offset;
|
|
644
|
+
return flowStart(code);
|
|
645
|
+
}
|
|
646
|
+
function documentContinued(code) {
|
|
647
|
+
self.containerState = {};
|
|
648
|
+
return effects.attempt(container, containerContinue, flowStart)(code);
|
|
649
|
+
}
|
|
650
|
+
function containerContinue(code) {
|
|
651
|
+
ok(self.containerState, 'expected `containerState`');
|
|
652
|
+
ok(self.currentConstruct, 'expected `currentConstruct`');
|
|
653
|
+
ok(self.currentConstruct.continuation, 'expected container construct');
|
|
654
|
+
continued++;
|
|
655
|
+
stack.push([self.currentConstruct, self.containerState]);
|
|
656
|
+
return documentContinued(code);
|
|
657
|
+
}
|
|
658
|
+
function flowStart(code) {
|
|
659
|
+
if (eos(code)) {
|
|
660
|
+
closeFlow();
|
|
661
|
+
exitContainers(0);
|
|
662
|
+
return void effects.consume(code);
|
|
663
|
+
}
|
|
664
|
+
childFlow ??= self.parser.flow(self.now());
|
|
665
|
+
effects.enter(tt.chunkFlow, {
|
|
666
|
+
_tokenizer: childFlow,
|
|
667
|
+
contentType: constants.contentTypeFlow,
|
|
668
|
+
previous: childToken
|
|
669
|
+
});
|
|
670
|
+
return flowContinue(code);
|
|
671
|
+
}
|
|
672
|
+
function flowContinue(code) {
|
|
673
|
+
if (eos(code)) {
|
|
674
|
+
writeToChild(effects.exit(tt.chunkFlow), true);
|
|
675
|
+
exitContainers(0);
|
|
676
|
+
return void effects.consume(code);
|
|
677
|
+
}
|
|
678
|
+
if (eol(code)) {
|
|
679
|
+
effects.consume(code);
|
|
680
|
+
writeToChild(effects.exit(tt.chunkFlow));
|
|
681
|
+
continued = 0;
|
|
682
|
+
self.interrupt = undefined;
|
|
683
|
+
return start;
|
|
684
|
+
}
|
|
685
|
+
effects.consume(code);
|
|
686
|
+
return flowContinue;
|
|
687
|
+
}
|
|
688
|
+
function exitContainers(size) {
|
|
689
|
+
let index = stack.length;
|
|
690
|
+
while (index-- > size) {
|
|
691
|
+
ok(stack[index], 'expected `stack[index]`');
|
|
692
|
+
const [construct, containerState] = stack[index];
|
|
693
|
+
self.containerState = containerState;
|
|
694
|
+
ok(construct.exit, 'expected `exit` on container construct');
|
|
695
|
+
construct.exit.call(self, effects);
|
|
696
|
+
}
|
|
697
|
+
stack.length = size;
|
|
698
|
+
if (!stack.length)
|
|
699
|
+
self.currentConstruct = undefined;
|
|
700
|
+
return void size;
|
|
701
|
+
}
|
|
702
|
+
function writeToChild(token, end) {
|
|
703
|
+
ok(childFlow, 'expected `childFlow` to be defined when continuing');
|
|
704
|
+
const stream = self.sliceStream(token);
|
|
705
|
+
if (end)
|
|
706
|
+
stream.push(codes.eos);
|
|
707
|
+
token.previous = childToken;
|
|
708
|
+
if (childToken)
|
|
709
|
+
childToken.next = token;
|
|
710
|
+
childToken = token;
|
|
711
|
+
childFlow.defineSkip(token.start);
|
|
712
|
+
childFlow.write(stream);
|
|
713
|
+
self.concrete = childFlow.currentConstruct?.concrete;
|
|
714
|
+
if (self.parser.lazy[token.start.line]) {
|
|
715
|
+
let index = childFlow.events.length;
|
|
716
|
+
while (index--) {
|
|
717
|
+
const [, eventToken] = childFlow.events[index];
|
|
718
|
+
if (
|
|
719
|
+
eventToken.start.offset < lineStartOffset && (
|
|
720
|
+
!eventToken.end ||
|
|
721
|
+
eventToken.end.offset > lineStartOffset
|
|
722
|
+
)) {
|
|
723
|
+
return void eventToken;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
const indexBeforeExits = self.events.length;
|
|
727
|
+
let flowExitIndex = indexBeforeExits;
|
|
728
|
+
let point = undefined;
|
|
729
|
+
let seen = undefined;
|
|
730
|
+
while (flowExitIndex--) {
|
|
731
|
+
ok(self.events[flowExitIndex], 'expected `events[flowExitIndex]`');
|
|
732
|
+
const [event, token] = self.events[flowExitIndex];
|
|
733
|
+
if (event === ev.exit && token.type === tt.chunkFlow) {
|
|
734
|
+
if (seen) {
|
|
735
|
+
point = token.end;
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
seen = true;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
ok(point, 'could not find previous flow chunk');
|
|
742
|
+
exitContainers(continued);
|
|
743
|
+
index = indexBeforeExits;
|
|
744
|
+
while (index < self.events.length) {
|
|
745
|
+
self.events[index][1].end = { ...point };
|
|
746
|
+
index++;
|
|
747
|
+
}
|
|
748
|
+
splice(self.events, flowExitIndex + 1, 0, self.events.slice(indexBeforeExits));
|
|
749
|
+
self.events.length = index;
|
|
750
|
+
}
|
|
751
|
+
return void token;
|
|
752
|
+
}
|
|
753
|
+
function closeFlow() {
|
|
754
|
+
ok(self.containerState, 'expected `containerState` when closing flow');
|
|
755
|
+
if (childFlow) {
|
|
756
|
+
childFlow.write([codes.eos]);
|
|
757
|
+
childFlow = undefined;
|
|
758
|
+
childToken = undefined;
|
|
759
|
+
self.containerState._closeFlow = undefined;
|
|
760
|
+
}
|
|
761
|
+
return void childFlow;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function tokenizeContainer(effects, ok$1, nok) {
|
|
765
|
+
ok(this.parser.constructs.disable.null, 'expected `disable.null`');
|
|
766
|
+
return factorySpace(effects, effects.attempt(this.parser.constructs.document, ok$1, nok), tt.linePrefix, this.parser.constructs.disable.null.includes('codeIndented')
|
|
767
|
+
? undefined
|
|
768
|
+
: constants.tabSize);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
const flow = { tokenize: tokenizeFlow };
|
|
772
|
+
function tokenizeFlow(effects) {
|
|
773
|
+
const self = this;
|
|
774
|
+
return initial;
|
|
775
|
+
function initial(code) {
|
|
776
|
+
return effects.attempt(blankLine,
|
|
777
|
+
atBlankEnding, noBlankLine)(code);
|
|
778
|
+
}
|
|
779
|
+
function noBlankLine(code) {
|
|
780
|
+
return effects.attempt(self.parser.constructs.flowInitial,
|
|
781
|
+
afterFlow, noFlowInitial)(code);
|
|
782
|
+
}
|
|
783
|
+
function noFlowInitial(code) {
|
|
784
|
+
return factorySpace(effects, effects.attempt(self.parser.constructs.flow, afterFlow, noFlow), tt.linePrefix)(code);
|
|
785
|
+
}
|
|
786
|
+
function noFlow(code) {
|
|
787
|
+
return effects.attempt(commonmark.content, afterFlow)(code);
|
|
788
|
+
}
|
|
789
|
+
function atBlankEnding(code) {
|
|
790
|
+
if (eos(code))
|
|
791
|
+
return void effects.consume(code);
|
|
792
|
+
ok(eol(code), 'expected eol');
|
|
793
|
+
effects.enter(tt.lineEndingBlank);
|
|
794
|
+
effects.consume(code);
|
|
795
|
+
effects.exit(tt.lineEndingBlank);
|
|
796
|
+
self.currentConstruct = undefined;
|
|
797
|
+
return initial;
|
|
798
|
+
}
|
|
799
|
+
function afterFlow(code) {
|
|
800
|
+
if (eos(code))
|
|
801
|
+
return void effects.consume(code);
|
|
802
|
+
ok(eol(code), 'expected eol');
|
|
803
|
+
effects.enter(tt.lineEnding);
|
|
804
|
+
effects.consume(code);
|
|
805
|
+
effects.exit(tt.lineEnding);
|
|
806
|
+
self.currentConstruct = undefined;
|
|
807
|
+
return initial;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const source = { tokenize: tokenizeSource };
|
|
812
|
+
const sourceComment = { tokenize: tokenizeSourceComment };
|
|
813
|
+
function tokenizeSource(effects) {
|
|
814
|
+
const self = this;
|
|
815
|
+
const stack = [];
|
|
816
|
+
let comment;
|
|
817
|
+
let content;
|
|
818
|
+
let continued = 0;
|
|
819
|
+
return start;
|
|
820
|
+
function start(code) {
|
|
821
|
+
ok(bos(self.previous) || eol(self.previous), 'expected beginning of stream or line');
|
|
822
|
+
self.containerState ??= {};
|
|
823
|
+
if (!stack[0])
|
|
824
|
+
return effects.attempt(blankLine, restart, tryComment)(code);
|
|
825
|
+
return tryContinuation(code);
|
|
826
|
+
}
|
|
827
|
+
function tryContinuation(code) {
|
|
828
|
+
ok(self.containerState, 'expected `containerState` when continuing');
|
|
829
|
+
ok(stack[0], 'expected comment on `stack` when continuing');
|
|
830
|
+
const [construct, containerState] = stack[0];
|
|
831
|
+
ok(self.containerState === containerState, 'expected `containerState` to match `stack[0][1]`');
|
|
832
|
+
continued = self.events.length;
|
|
833
|
+
self.interrupt = Boolean(comment?.currentConstruct ?? comment?.interrupt);
|
|
834
|
+
return effects.attempt(construct.continuation, afterContinuation, noContinuation)(code);
|
|
835
|
+
}
|
|
836
|
+
function afterContinuation(code) {
|
|
837
|
+
ok(stack.length === 1, 'expected comment on `stack`');
|
|
838
|
+
ok(self.containerState, 'expected `containerState` after continuing');
|
|
839
|
+
forward();
|
|
840
|
+
if (self.containerState._closeFlow)
|
|
841
|
+
return noContinuation(code);
|
|
842
|
+
self.parser.freshComment = false;
|
|
843
|
+
if (!eol(self.previous))
|
|
844
|
+
return beforeChunk(code);
|
|
845
|
+
return start(code);
|
|
846
|
+
}
|
|
847
|
+
function noContinuation(code) {
|
|
848
|
+
flush();
|
|
849
|
+
return tryComment(code);
|
|
850
|
+
}
|
|
851
|
+
function tryComment(code) {
|
|
852
|
+
self.containerState = {};
|
|
853
|
+
continued = self.events.length;
|
|
854
|
+
if (whitespace(code))
|
|
855
|
+
return factorySpace(effects, tryComment)(code);
|
|
856
|
+
return effects.attempt(sourceComment, takeComment, restart)(code);
|
|
857
|
+
}
|
|
858
|
+
function takeComment(code) {
|
|
859
|
+
ok(self.containerState, 'expected `containerState`');
|
|
860
|
+
ok(self.currentConstruct, 'expected `currentConstruct`');
|
|
861
|
+
ok(self.currentConstruct.continuation, 'expected continuable construct');
|
|
862
|
+
ok(self.events[continued], 'expected `self.events[continued]`');
|
|
863
|
+
ok(self.events[continued][0] === ev.enter, 'expected `enter` event');
|
|
864
|
+
self.containerState.comment ??= self.events[continued][1]._kind;
|
|
865
|
+
forward();
|
|
866
|
+
ok(stack.length === 0, 'expected empty comment stack');
|
|
867
|
+
stack[0] = [self.currentConstruct, self.containerState];
|
|
868
|
+
self.parser.freshComment = true;
|
|
869
|
+
if (self.containerState._closeFlow)
|
|
870
|
+
return noContinuation(code);
|
|
871
|
+
if (eol(self.previous))
|
|
872
|
+
return start(code);
|
|
873
|
+
return beforeChunk(code);
|
|
874
|
+
}
|
|
875
|
+
function restart(code) {
|
|
876
|
+
ok(!comment, 'did not expect comment content parser');
|
|
877
|
+
ok(stack.length === 0, 'expected empty comment stack');
|
|
878
|
+
if (eos(code))
|
|
879
|
+
return beforeChunk(code);
|
|
880
|
+
effects.consume(code);
|
|
881
|
+
if (eol(self.previous))
|
|
882
|
+
return start;
|
|
883
|
+
return tryComment;
|
|
884
|
+
}
|
|
885
|
+
function beforeChunk(code) {
|
|
886
|
+
if (eos(code))
|
|
887
|
+
return void end(code);
|
|
888
|
+
return chunkStart(code);
|
|
889
|
+
}
|
|
890
|
+
function chunkStart(code) {
|
|
891
|
+
ok(!eos(code), 'did not expect end of stream');
|
|
892
|
+
ok(self.containerState, 'expected `containerState` inside comment');
|
|
893
|
+
ok(self.containerState.comment, 'expected comment kind');
|
|
894
|
+
ok(stack.length === 1, 'expected comment on `stack`');
|
|
895
|
+
comment ??= self.parser.comment(self.now());
|
|
896
|
+
comment.containerState ??= {};
|
|
897
|
+
comment.containerState.comment = self.containerState.comment;
|
|
898
|
+
effects.enter(tt.chunkComment, {
|
|
899
|
+
_tokenizer: comment,
|
|
900
|
+
contentType: constants.contentTypeComment,
|
|
901
|
+
previous: content
|
|
902
|
+
});
|
|
903
|
+
return chunkContinue(code);
|
|
904
|
+
}
|
|
905
|
+
function chunkContinue(code) {
|
|
906
|
+
ok(comment, 'expected comment content parser');
|
|
907
|
+
if (eos(code)) {
|
|
908
|
+
write(effects.exit(tt.chunkComment), true);
|
|
909
|
+
return void end(code);
|
|
910
|
+
}
|
|
911
|
+
if (eol(code)) {
|
|
912
|
+
effects.consume(code);
|
|
913
|
+
write(effects.exit(tt.chunkComment));
|
|
914
|
+
self.interrupt = undefined;
|
|
915
|
+
return start;
|
|
916
|
+
}
|
|
917
|
+
effects.consume(code);
|
|
918
|
+
return chunkContinue;
|
|
919
|
+
}
|
|
920
|
+
function end(code) {
|
|
921
|
+
ok(eos(code), 'expected end of stream');
|
|
922
|
+
flush();
|
|
923
|
+
self.parser.freshComment = undefined;
|
|
924
|
+
effects.enter(tt.eoc);
|
|
925
|
+
effects.consume(code);
|
|
926
|
+
effects.exit(tt.eoc);
|
|
927
|
+
return void code;
|
|
928
|
+
}
|
|
929
|
+
function flush() {
|
|
930
|
+
ok(stack.length <= 1, 'expected no more than 1 comment');
|
|
931
|
+
if (comment && !eos(comment.code))
|
|
932
|
+
comment.write([codes.eos]);
|
|
933
|
+
comment = undefined;
|
|
934
|
+
content = undefined;
|
|
935
|
+
while (stack.length) {
|
|
936
|
+
const [construct, containerState] = stack.pop();
|
|
937
|
+
self.containerState = containerState;
|
|
938
|
+
construct.exit.call(self, effects);
|
|
939
|
+
}
|
|
940
|
+
self.currentConstruct = undefined;
|
|
941
|
+
self.containerState = {};
|
|
942
|
+
self.parser.skipSummary = undefined;
|
|
943
|
+
return void stack;
|
|
944
|
+
}
|
|
945
|
+
function forward() {
|
|
946
|
+
while (continued < self.events.length) {
|
|
947
|
+
ok(self.events[continued], 'expected `self.events[continued]`');
|
|
948
|
+
const [event, token] = self.events[continued];
|
|
949
|
+
if (event === ev.exit &&
|
|
950
|
+
token.type === tt.chunkComment &&
|
|
951
|
+
token.contentType === constants.contentTypeComment) {
|
|
952
|
+
write(token);
|
|
953
|
+
}
|
|
954
|
+
continued++;
|
|
955
|
+
}
|
|
956
|
+
return void self.events;
|
|
957
|
+
}
|
|
958
|
+
function write(token, end) {
|
|
959
|
+
ok(self.containerState, 'expected `containerState` during write');
|
|
960
|
+
ok(token !== content, 'did not expect `token` to match previous token');
|
|
961
|
+
comment ??= self.parser.comment(token.start);
|
|
962
|
+
token._tokenizer ??= comment;
|
|
963
|
+
const stream = self.sliceStream(token);
|
|
964
|
+
if (end)
|
|
965
|
+
stream.push(codes.eos);
|
|
966
|
+
token.previous = content;
|
|
967
|
+
if (content)
|
|
968
|
+
content.next = token;
|
|
969
|
+
content = token;
|
|
970
|
+
if (token.previous)
|
|
971
|
+
comment.defineSkip(token.start);
|
|
972
|
+
comment.write(stream);
|
|
973
|
+
self.concrete = comment.concrete;
|
|
974
|
+
return void token;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
function tokenizeSourceComment(effects, ok, nok) {
|
|
978
|
+
return effects.attempt(this.parser.constructs.source, ok, nok);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
const type = { tokenize: tokenizeType };
|
|
982
|
+
function tokenizeType(effects) {
|
|
983
|
+
const self = this;
|
|
984
|
+
return attempt;
|
|
985
|
+
function attempt(code) {
|
|
986
|
+
return effects.attempt(self.parser.constructs.type, attempt, eat)(code);
|
|
987
|
+
}
|
|
988
|
+
function eat(code) {
|
|
989
|
+
return effects.consume(code), attempt;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function parse(options) {
|
|
994
|
+
const context = createTokenizer({
|
|
995
|
+
debug: 'docmark',
|
|
996
|
+
eol,
|
|
997
|
+
extensions: extensions,
|
|
998
|
+
finalizeContext,
|
|
999
|
+
initialize: initialize
|
|
1000
|
+
});
|
|
1001
|
+
return context.parser;
|
|
1002
|
+
function extensions() {
|
|
1003
|
+
return combineExtensions(docmark, markdown, options?.extensions);
|
|
1004
|
+
}
|
|
1005
|
+
function finalizeContext(self) {
|
|
1006
|
+
if (typeof self.parser.defined === 'undefined')
|
|
1007
|
+
self.parser.defined = [];
|
|
1008
|
+
if (typeof self.parser.lazy === 'undefined')
|
|
1009
|
+
self.parser.lazy = {};
|
|
1010
|
+
switch (self.contentType) {
|
|
1011
|
+
case constants.contentTypeDocument:
|
|
1012
|
+
case constants.contentTypeFlow:
|
|
1013
|
+
case constants.contentTypeContent:
|
|
1014
|
+
case constants.contentTypeText:
|
|
1015
|
+
case constants.contentTypeString:
|
|
1016
|
+
self.code = codes.eos;
|
|
1017
|
+
self.previous = codes.eos;
|
|
1018
|
+
self.noEmptyTokens = true;
|
|
1019
|
+
self.noPrevious = true;
|
|
1020
|
+
break;
|
|
1021
|
+
case constants.contentTypeSource:
|
|
1022
|
+
case constants.contentTypeComment:
|
|
1023
|
+
case constants.contentTypeType:
|
|
1024
|
+
self.code = codes.bos;
|
|
1025
|
+
self.previous = codes.bos;
|
|
1026
|
+
break;
|
|
1027
|
+
}
|
|
1028
|
+
if (self.contentType) {
|
|
1029
|
+
options?.finalizeContext?.(self);
|
|
1030
|
+
}
|
|
1031
|
+
return void self;
|
|
1032
|
+
}
|
|
1033
|
+
function initialize() {
|
|
1034
|
+
return {
|
|
1035
|
+
[constants.contentTypeSource]: source,
|
|
1036
|
+
[constants.contentTypeComment]: comment,
|
|
1037
|
+
[constants.contentTypeType]: type,
|
|
1038
|
+
[constants.contentTypeDocument]: document,
|
|
1039
|
+
[constants.contentTypeFlow]: flow,
|
|
1040
|
+
[constants.contentTypeContent]: content,
|
|
1041
|
+
[constants.contentTypeText]: text,
|
|
1042
|
+
[constants.contentTypeString]: string,
|
|
1043
|
+
...options?.initializers
|
|
1044
|
+
};
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
function preprocess(options) {
|
|
1049
|
+
const tabSize = options?.tabSize ?? constants.tabSize;
|
|
1050
|
+
return preprocessor;
|
|
1051
|
+
function preprocessor(value, encoding, end) {
|
|
1052
|
+
const chunks = [];
|
|
1053
|
+
if (typeof value === 'number') {
|
|
1054
|
+
if (value !== codes.bos && value !== codes.empty)
|
|
1055
|
+
chunks.push(value);
|
|
1056
|
+
if (end)
|
|
1057
|
+
chunks.push(codes.eos);
|
|
1058
|
+
return chunks;
|
|
1059
|
+
}
|
|
1060
|
+
if (value !== codes.eos && value !== undefined) {
|
|
1061
|
+
let decoded = decode(value, encoding);
|
|
1062
|
+
if (typeof decoded === 'number') {
|
|
1063
|
+
if (end)
|
|
1064
|
+
chunks.push(codes.eos);
|
|
1065
|
+
return chunks;
|
|
1066
|
+
}
|
|
1067
|
+
value = decoded;
|
|
1068
|
+
let column = 1;
|
|
1069
|
+
let index = 0;
|
|
1070
|
+
let sliceIndex = 0;
|
|
1071
|
+
while (index < value.length) {
|
|
1072
|
+
const code = value.codePointAt(index);
|
|
1073
|
+
let k = code > 0xffff ? 2 : 1;
|
|
1074
|
+
if (code !== codes.nul && !eol(code) && !htab(code)) {
|
|
1075
|
+
index += k;
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
if (sliceIndex < index) {
|
|
1079
|
+
const chunk = value.slice(sliceIndex, index);
|
|
1080
|
+
chunks.push(chunk);
|
|
1081
|
+
column += [...chunk].length;
|
|
1082
|
+
}
|
|
1083
|
+
switch (code) {
|
|
1084
|
+
case codes.ht:
|
|
1085
|
+
const n = Math.ceil(column / tabSize) * tabSize;
|
|
1086
|
+
chunks.push(codes.horizontalTab);
|
|
1087
|
+
while (column++ < n)
|
|
1088
|
+
chunks.push(codes.virtualSpace);
|
|
1089
|
+
break;
|
|
1090
|
+
case codes.lf:
|
|
1091
|
+
chunks.push(codes.lineFeed);
|
|
1092
|
+
column = 1;
|
|
1093
|
+
break;
|
|
1094
|
+
case codes.nul:
|
|
1095
|
+
chunks.push(codes.nul);
|
|
1096
|
+
column = 1;
|
|
1097
|
+
break;
|
|
1098
|
+
default:
|
|
1099
|
+
const nextIndex = index + 1;
|
|
1100
|
+
const next = value.codePointAt(nextIndex);
|
|
1101
|
+
if (next === codes.lf) {
|
|
1102
|
+
chunks.push(codes.carriageReturnLineFeed);
|
|
1103
|
+
index = nextIndex;
|
|
1104
|
+
}
|
|
1105
|
+
else {
|
|
1106
|
+
chunks.push(codes.carriageReturn);
|
|
1107
|
+
}
|
|
1108
|
+
column = 1;
|
|
1109
|
+
break;
|
|
1110
|
+
}
|
|
1111
|
+
index += k;
|
|
1112
|
+
sliceIndex = index;
|
|
1113
|
+
}
|
|
1114
|
+
if (sliceIndex < value.length)
|
|
1115
|
+
chunks.push(value.slice(sliceIndex));
|
|
1116
|
+
}
|
|
1117
|
+
return end && chunks.push(codes.eos), chunks;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
export { parse, postprocess$1 as postprocess, preprocess };
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flex-development/docmark",
|
|
3
|
+
"description": "commonmark compliant documentation parser with positional info and concrete tokens",
|
|
4
|
+
"version": "1.0.0-dev.3",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"comment",
|
|
7
|
+
"commonmark",
|
|
8
|
+
"compiler",
|
|
9
|
+
"docblock",
|
|
10
|
+
"docdown",
|
|
11
|
+
"documentation",
|
|
12
|
+
"gfm",
|
|
13
|
+
"html",
|
|
14
|
+
"jsdoc",
|
|
15
|
+
"lexer",
|
|
16
|
+
"markdown",
|
|
17
|
+
"md",
|
|
18
|
+
"mdast",
|
|
19
|
+
"parse",
|
|
20
|
+
"parser",
|
|
21
|
+
"token",
|
|
22
|
+
"tokenize",
|
|
23
|
+
"tokenizer",
|
|
24
|
+
"tsdoc",
|
|
25
|
+
"typedoc",
|
|
26
|
+
"typescript",
|
|
27
|
+
"unified"
|
|
28
|
+
],
|
|
29
|
+
"license": "BSD-3-Clause",
|
|
30
|
+
"homepage": "https://github.com/flex-development/docmark",
|
|
31
|
+
"repository": {
|
|
32
|
+
"directory": "packages/docmark",
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/flex-development/docmark.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": "https://github.com/flex-development/docmark/issues",
|
|
37
|
+
"author": {
|
|
38
|
+
"name": "Lexus Drumgold",
|
|
39
|
+
"url": "https://github.com/unicornware"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public",
|
|
43
|
+
"diff-dst-prefix": "docmark",
|
|
44
|
+
"diff-src-prefix": "docmark",
|
|
45
|
+
"directory": "./",
|
|
46
|
+
"executableFiles": [],
|
|
47
|
+
"node-options": null,
|
|
48
|
+
"pack-destination": ".",
|
|
49
|
+
"parseable": true,
|
|
50
|
+
"prefer-dedupe": true,
|
|
51
|
+
"provenance": true,
|
|
52
|
+
"tag-version-prefix": "docmark"
|
|
53
|
+
},
|
|
54
|
+
"type": "module",
|
|
55
|
+
"files": [
|
|
56
|
+
"LICENSE.md",
|
|
57
|
+
"README.md",
|
|
58
|
+
"dist"
|
|
59
|
+
],
|
|
60
|
+
"exports": {
|
|
61
|
+
".": {
|
|
62
|
+
"docmark": "./src/index.mts",
|
|
63
|
+
"default": "./dist/index.mjs"
|
|
64
|
+
},
|
|
65
|
+
"./package.json": "./package.json"
|
|
66
|
+
},
|
|
67
|
+
"imports": {
|
|
68
|
+
"#fixtures/*": "./__fixtures__/*.mts",
|
|
69
|
+
"#lib/postprocess": {
|
|
70
|
+
"docmark": "./src/postprocess.mts",
|
|
71
|
+
"default": "./dist/postprocess.mjs"
|
|
72
|
+
},
|
|
73
|
+
"#tests/*": "./__tests__/*.mts"
|
|
74
|
+
},
|
|
75
|
+
"module": "./dist/index.mjs",
|
|
76
|
+
"types": "./dist/index.d.mts",
|
|
77
|
+
"scripts": {
|
|
78
|
+
"attw": "tsc --build tsconfig.build.json --clean --dry && tsc --build tsconfig.build.json --clean && tsc --build tsconfig.build.json --verbose"
|
|
79
|
+
},
|
|
80
|
+
"dependencies": {
|
|
81
|
+
"@flex-development/docmark-factory-space": "1.0.0-dev.3",
|
|
82
|
+
"@flex-development/docmark-grammar": "1.0.0-dev.3",
|
|
83
|
+
"@flex-development/docmark-util-combine-extensions": "1.0.0-dev.3",
|
|
84
|
+
"@flex-development/docmark-util-subtokenize": "1.0.0-dev.3",
|
|
85
|
+
"@flex-development/docmark-util-symbol": "1.0.0-dev.3",
|
|
86
|
+
"@flex-development/docmark-util-types": "1.0.0-dev.3",
|
|
87
|
+
"@flex-development/mark": "1.0.0-alpha.4",
|
|
88
|
+
"@flex-development/mark-parser": "1.0.0-alpha.19",
|
|
89
|
+
"@flex-development/mark-util-character": "1.1.0",
|
|
90
|
+
"@flex-development/mark-util-chunked": "1.0.0",
|
|
91
|
+
"devlop": "1.1.0",
|
|
92
|
+
"micromark-core-commonmark": "2.0.3",
|
|
93
|
+
"micromark-util-subtokenize": "2.1.0",
|
|
94
|
+
"micromark-util-types": "2.0.2"
|
|
95
|
+
},
|
|
96
|
+
"sideEffects": false,
|
|
97
|
+
"build": "575af951968e8cbab57769b5789f5542b71d62be"
|
|
98
|
+
}
|