@yozora/tokenizer-definition 2.1.3 → 2.1.5
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/CHANGELOG.md +598 -0
- package/README.md +42 -42
- package/package.json +6 -6
- package/src/index.ts +0 -12
- package/src/match.ts +0 -340
- package/src/parse.ts +0 -50
- package/src/tokenizer.ts +0 -31
- package/src/types.ts +0 -58
- package/src/util/link-destination.ts +0 -160
- package/src/util/link-label.ts +0 -116
- package/src/util/link-title.ts +0 -143
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<header>
|
|
4
4
|
<h1 align="center">
|
|
5
|
-
<a href="https://github.com/yozorajs/yozora/tree/
|
|
5
|
+
<a href="https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/definition#readme">@yozora/tokenizer-definition</a>
|
|
6
6
|
</h1>
|
|
7
7
|
<div align="center">
|
|
8
8
|
<a href="https://www.npmjs.com/package/@yozora/tokenizer-definition">
|
|
@@ -201,53 +201,53 @@ Name | Type | Required | Default
|
|
|
201
201
|
|
|
202
202
|
[live-examples]: https://yozora.guanghechen.com/docs/package/tokenizer-definition#live-examples
|
|
203
203
|
[docpage]: https://yozora.guanghechen.com/docs/package/tokenizer-definition
|
|
204
|
-
[homepage]: https://github.com/yozorajs/yozora/tree/
|
|
204
|
+
[homepage]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/definition#readme
|
|
205
205
|
[gfm-spec]: https://github.github.com/gfm
|
|
206
206
|
[mdast-homepage]: https://github.com/syntax-tree/mdast
|
|
207
207
|
|
|
208
|
-
[@yozora/ast]: https://github.com/yozorajs/yozora/tree/
|
|
209
|
-
[@yozora/ast-util]: https://github.com/yozorajs/yozora/tree/
|
|
210
|
-
[@yozora/character]: https://github.com/yozorajs/yozora/tree/
|
|
208
|
+
[@yozora/ast]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/ast#readme
|
|
209
|
+
[@yozora/ast-util]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/ast-util#readme
|
|
210
|
+
[@yozora/character]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/character#readme
|
|
211
211
|
[@yozora/eslint-config]: https://github.com/yozorajs/yozora/tree/release-2.x.x/packages/eslint-config#readme
|
|
212
|
-
[@yozora/core-parser]: https://github.com/yozorajs/yozora/tree/
|
|
213
|
-
[@yozora/core-tokenizer]: https://github.com/yozorajs/yozora/tree/
|
|
214
|
-
[@yozora/invariant]: https://github.com/yozorajs/yozora/tree/
|
|
212
|
+
[@yozora/core-parser]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/core-parser#readme
|
|
213
|
+
[@yozora/core-tokenizer]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/core-tokenizer#readme
|
|
214
|
+
[@yozora/invariant]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/invariant#readme
|
|
215
215
|
[@yozora/jest-for-tokenizer]: https://github.com/yozorajs/yozora/tree/release-2.x.x/packages/jest-for-tokenizer#readme
|
|
216
|
-
[@yozora/parser]: https://github.com/yozorajs/yozora/tree/
|
|
217
|
-
[@yozora/parser-gfm]: https://github.com/yozorajs/yozora/tree/
|
|
218
|
-
[@yozora/parser-gfm-ex]: https://github.com/yozorajs/yozora/tree/
|
|
216
|
+
[@yozora/parser]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/parser#readme
|
|
217
|
+
[@yozora/parser-gfm]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/parser-gfm#readme
|
|
218
|
+
[@yozora/parser-gfm-ex]: https://github.com/yozorajs/yozora/tree/v2.1.5/packages/parser-gfm-ex#readme
|
|
219
219
|
[@yozora/template-tokenizer]: https://github.com/yozorajs/yozora/tree/release-2.x.x/packages/template-tokenizer#readme
|
|
220
|
-
[@yozora/tokenizer-admonition]: https://github.com/yozorajs/yozora/tree/
|
|
221
|
-
[@yozora/tokenizer-autolink]: https://github.com/yozorajs/yozora/tree/
|
|
222
|
-
[@yozora/tokenizer-autolink-extension]: https://github.com/yozorajs/yozora/tree/
|
|
223
|
-
[@yozora/tokenizer-blockquote]: https://github.com/yozorajs/yozora/tree/
|
|
224
|
-
[@yozora/tokenizer-break]: https://github.com/yozorajs/yozora/tree/
|
|
225
|
-
[@yozora/tokenizer-definition]: https://github.com/yozorajs/yozora/tree/
|
|
226
|
-
[@yozora/tokenizer-delete]: https://github.com/yozorajs/yozora/tree/
|
|
227
|
-
[@yozora/tokenizer-ecma-import]: https://github.com/yozorajs/yozora/tree/
|
|
228
|
-
[@yozora/tokenizer-emphasis]: https://github.com/yozorajs/yozora/tree/
|
|
229
|
-
[@yozora/tokenizer-fenced-block]: https://github.com/yozorajs/yozora/tree/
|
|
230
|
-
[@yozora/tokenizer-fenced-code]: https://github.com/yozorajs/yozora/tree/
|
|
231
|
-
[@yozora/tokenizer-footnote]: https://github.com/yozorajs/yozora/tree/
|
|
232
|
-
[@yozora/tokenizer-footnote-definition]: https://github.com/yozorajs/yozora/tree/
|
|
233
|
-
[@yozora/tokenizer-footnote-reference]: https://github.com/yozorajs/yozora/tree/
|
|
234
|
-
[@yozora/tokenizer-heading]: https://github.com/yozorajs/yozora/tree/
|
|
235
|
-
[@yozora/tokenizer-html-block]: https://github.com/yozorajs/yozora/tree/
|
|
236
|
-
[@yozora/tokenizer-html-inline]: https://github.com/yozorajs/yozora/tree/
|
|
237
|
-
[@yozora/tokenizer-image]: https://github.com/yozorajs/yozora/tree/
|
|
238
|
-
[@yozora/tokenizer-image-reference]: https://github.com/yozorajs/yozora/tree/
|
|
239
|
-
[@yozora/tokenizer-indented-code]: https://github.com/yozorajs/yozora/tree/
|
|
240
|
-
[@yozora/tokenizer-inline-code]: https://github.com/yozorajs/yozora/tree/
|
|
241
|
-
[@yozora/tokenizer-inline-math]: https://github.com/yozorajs/yozora/tree/
|
|
242
|
-
[@yozora/tokenizer-link]: https://github.com/yozorajs/yozora/tree/
|
|
243
|
-
[@yozora/tokenizer-link-reference]: https://github.com/yozorajs/yozora/tree/
|
|
244
|
-
[@yozora/tokenizer-list]: https://github.com/yozorajs/yozora/tree/
|
|
245
|
-
[@yozora/tokenizer-math]: https://github.com/yozorajs/yozora/tree/
|
|
246
|
-
[@yozora/tokenizer-paragraph]: https://github.com/yozorajs/yozora/tree/
|
|
247
|
-
[@yozora/tokenizer-setext-heading]: https://github.com/yozorajs/yozora/tree/
|
|
248
|
-
[@yozora/tokenizer-table]: https://github.com/yozorajs/yozora/tree/
|
|
249
|
-
[@yozora/tokenizer-text]: https://github.com/yozorajs/yozora/tree/
|
|
250
|
-
[@yozora/tokenizer-thematic-break]: https://github.com/yozorajs/yozora/tree/
|
|
220
|
+
[@yozora/tokenizer-admonition]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/admonition#readme
|
|
221
|
+
[@yozora/tokenizer-autolink]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/autolink#readme
|
|
222
|
+
[@yozora/tokenizer-autolink-extension]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/autolink-extension#readme
|
|
223
|
+
[@yozora/tokenizer-blockquote]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/blockquote#readme
|
|
224
|
+
[@yozora/tokenizer-break]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/break#readme
|
|
225
|
+
[@yozora/tokenizer-definition]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/definition#readme
|
|
226
|
+
[@yozora/tokenizer-delete]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/delete#readme
|
|
227
|
+
[@yozora/tokenizer-ecma-import]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/ecma-import#readme
|
|
228
|
+
[@yozora/tokenizer-emphasis]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/emphasis#readme
|
|
229
|
+
[@yozora/tokenizer-fenced-block]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/fenced-block#readme
|
|
230
|
+
[@yozora/tokenizer-fenced-code]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/fenced-code#readme
|
|
231
|
+
[@yozora/tokenizer-footnote]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/footnote#readme
|
|
232
|
+
[@yozora/tokenizer-footnote-definition]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/footnote-definition#readme
|
|
233
|
+
[@yozora/tokenizer-footnote-reference]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/footnote-reference#readme
|
|
234
|
+
[@yozora/tokenizer-heading]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/heading#readme
|
|
235
|
+
[@yozora/tokenizer-html-block]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/html-block#readme
|
|
236
|
+
[@yozora/tokenizer-html-inline]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/html-inline#readme
|
|
237
|
+
[@yozora/tokenizer-image]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/image#readme
|
|
238
|
+
[@yozora/tokenizer-image-reference]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/image-reference#readme
|
|
239
|
+
[@yozora/tokenizer-indented-code]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/indented-code#readme
|
|
240
|
+
[@yozora/tokenizer-inline-code]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/inline-code#readme
|
|
241
|
+
[@yozora/tokenizer-inline-math]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/inline-math#readme
|
|
242
|
+
[@yozora/tokenizer-link]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/link#readme
|
|
243
|
+
[@yozora/tokenizer-link-reference]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/link-reference#readme
|
|
244
|
+
[@yozora/tokenizer-list]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/list#readme
|
|
245
|
+
[@yozora/tokenizer-math]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/math#readme
|
|
246
|
+
[@yozora/tokenizer-paragraph]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/paragraph#readme
|
|
247
|
+
[@yozora/tokenizer-setext-heading]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/setext-heading#readme
|
|
248
|
+
[@yozora/tokenizer-table]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/table#readme
|
|
249
|
+
[@yozora/tokenizer-text]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/text#readme
|
|
250
|
+
[@yozora/tokenizer-thematic-break]: https://github.com/yozorajs/yozora/tree/v2.1.5/tokenizers/thematic-break#readme
|
|
251
251
|
|
|
252
252
|
[@yozora/react-admonition]: https://github.com/yozorajs/yozora-react/tree/main/packages/admonition#readme
|
|
253
253
|
[@yozora/react-blockquote]: https://github.com/yozorajs/yozora-react/tree/main/packages/blockquote#readme
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-definition",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.5",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "guanghechen",
|
|
6
6
|
"url": "https://github.com/guanghechen/"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"lib/",
|
|
30
|
-
"
|
|
30
|
+
"!lib/**/*.map",
|
|
31
31
|
"package.json",
|
|
32
32
|
"CHANGELOG.md",
|
|
33
33
|
"LICENSE",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
"test": "cross-env TS_NODE_FILES=true NODE_OPTIONS=--experimental-vm-modules jest --config ../../jest.config.mjs --rootDir ."
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@yozora/ast": "^2.1.
|
|
43
|
-
"@yozora/character": "^2.1.
|
|
44
|
-
"@yozora/core-tokenizer": "^2.1.
|
|
42
|
+
"@yozora/ast": "^2.1.5",
|
|
43
|
+
"@yozora/character": "^2.1.5",
|
|
44
|
+
"@yozora/core-tokenizer": "^2.1.5"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "4f753bcf0fd921938464802462dc48c53bbd014d"
|
|
47
47
|
}
|
package/src/index.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export * from './util/link-destination'
|
|
2
|
-
export * from './util/link-label'
|
|
3
|
-
export * from './util/link-title'
|
|
4
|
-
export { match as definitionMatch } from './match'
|
|
5
|
-
export { parse as definitionParse } from './parse'
|
|
6
|
-
export { DefinitionTokenizer, DefinitionTokenizer as default } from './tokenizer'
|
|
7
|
-
export { uniqueName as DefinitionTokenizerName } from './types'
|
|
8
|
-
export type {
|
|
9
|
-
IThis as IDefinitionHookContext,
|
|
10
|
-
IToken as IDefinitionToken,
|
|
11
|
-
ITokenizerProps as IDefinitionTokenizerProps,
|
|
12
|
-
} from './types'
|
package/src/match.ts
DELETED
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
import { DefinitionType } from '@yozora/ast'
|
|
2
|
-
import type { INodePoint } from '@yozora/character'
|
|
3
|
-
import { AsciiCodePoint, calcStringFromNodePoints } from '@yozora/character'
|
|
4
|
-
import type {
|
|
5
|
-
IMatchBlockHookCreator,
|
|
6
|
-
IPhrasingContentLine,
|
|
7
|
-
IResultOfEatContinuationText,
|
|
8
|
-
IResultOfEatOpener,
|
|
9
|
-
IResultOfOnClose,
|
|
10
|
-
} from '@yozora/core-tokenizer'
|
|
11
|
-
import {
|
|
12
|
-
calcEndPoint,
|
|
13
|
-
calcStartPoint,
|
|
14
|
-
eatOptionalWhitespaces,
|
|
15
|
-
resolveLabelToIdentifier,
|
|
16
|
-
} from '@yozora/core-tokenizer'
|
|
17
|
-
import type { IThis, IToken, T } from './types'
|
|
18
|
-
import { eatAndCollectLinkDestination } from './util/link-destination'
|
|
19
|
-
import { eatAndCollectLinkLabel } from './util/link-label'
|
|
20
|
-
import { eatAndCollectLinkTitle } from './util/link-title'
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* A link reference definition consists of a link label, indented up to three
|
|
24
|
-
* spaces, followed by a colon (:), optional whitespace (including up to one
|
|
25
|
-
* line ending), a link destination, optional whitespace (including up to one
|
|
26
|
-
* line ending), and an optional link title, which if it is present must be
|
|
27
|
-
* separated from the link destination by whitespace. No further non-whitespace
|
|
28
|
-
* characters may occur on the line.
|
|
29
|
-
*
|
|
30
|
-
* A link reference definition does not correspond to a structural element of
|
|
31
|
-
* a document. Instead, it defines a label which can be used in reference
|
|
32
|
-
* links and reference-style images elsewhere in the document. Link reference
|
|
33
|
-
* definitions can come either before or after the links that use them.
|
|
34
|
-
*
|
|
35
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
36
|
-
*/
|
|
37
|
-
export const match: IMatchBlockHookCreator<T, IToken, IThis> = function (api) {
|
|
38
|
-
return {
|
|
39
|
-
isContainingBlock: false,
|
|
40
|
-
eatOpener,
|
|
41
|
-
eatContinuationText,
|
|
42
|
-
onClose,
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function eatOpener(line: Readonly<IPhrasingContentLine>): IResultOfEatOpener<T, IToken> {
|
|
46
|
-
/**
|
|
47
|
-
* Four spaces are too much
|
|
48
|
-
* @see https://github.github.com/gfm/#example-180
|
|
49
|
-
*/
|
|
50
|
-
if (line.countOfPrecedeSpaces >= 4) return null
|
|
51
|
-
|
|
52
|
-
const { nodePoints, startIndex, endIndex, firstNonWhitespaceIndex } = line
|
|
53
|
-
if (firstNonWhitespaceIndex >= endIndex) return null
|
|
54
|
-
|
|
55
|
-
// Try to match link label
|
|
56
|
-
let i = firstNonWhitespaceIndex
|
|
57
|
-
const { nextIndex: labelEndIndex, state: labelState } = eatAndCollectLinkLabel(
|
|
58
|
-
nodePoints,
|
|
59
|
-
i,
|
|
60
|
-
endIndex,
|
|
61
|
-
null,
|
|
62
|
-
)
|
|
63
|
-
if (labelEndIndex < 0) return null
|
|
64
|
-
|
|
65
|
-
const lineNo = nodePoints[startIndex].line
|
|
66
|
-
|
|
67
|
-
// Optimization: lazy calculation
|
|
68
|
-
const createInitState = (): IToken => {
|
|
69
|
-
const token: IToken = {
|
|
70
|
-
nodeType: DefinitionType,
|
|
71
|
-
position: {
|
|
72
|
-
start: calcStartPoint(nodePoints, startIndex),
|
|
73
|
-
end: calcEndPoint(nodePoints, endIndex - 1),
|
|
74
|
-
},
|
|
75
|
-
label: labelState,
|
|
76
|
-
destination: null,
|
|
77
|
-
title: null,
|
|
78
|
-
lineNoOfLabel: lineNo,
|
|
79
|
-
lineNoOfDestination: -1,
|
|
80
|
-
lineNoOfTitle: -1,
|
|
81
|
-
lines: [line],
|
|
82
|
-
}
|
|
83
|
-
return token
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (!labelState.saturated) {
|
|
87
|
-
const token = createInitState()
|
|
88
|
-
return { token, nextIndex: endIndex }
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Saturated but no following colon exists.
|
|
92
|
-
if (
|
|
93
|
-
labelEndIndex < 0 ||
|
|
94
|
-
labelEndIndex + 1 >= endIndex ||
|
|
95
|
-
nodePoints[labelEndIndex].codePoint !== AsciiCodePoint.COLON
|
|
96
|
-
)
|
|
97
|
-
return null
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* At most one line break can be used between link destination and link label
|
|
101
|
-
* @see https://github.github.com/gfm/#example-162
|
|
102
|
-
* @see https://github.github.com/gfm/#example-164
|
|
103
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
104
|
-
*/
|
|
105
|
-
i = eatOptionalWhitespaces(nodePoints, labelEndIndex + 1, endIndex)
|
|
106
|
-
if (i >= endIndex) {
|
|
107
|
-
const token = createInitState()
|
|
108
|
-
return { token, nextIndex: endIndex }
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Try to match link destination
|
|
112
|
-
const { nextIndex: destinationEndIndex, state: destinationState } =
|
|
113
|
-
eatAndCollectLinkDestination(nodePoints, i, endIndex, null)
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* The link destination may not be omitted
|
|
117
|
-
* @see https://github.github.com/gfm/#example-168
|
|
118
|
-
*/
|
|
119
|
-
if (destinationEndIndex < 0) return null
|
|
120
|
-
|
|
121
|
-
// Link destination not saturated
|
|
122
|
-
if (!destinationState.saturated && destinationEndIndex !== endIndex) return null
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* At most one line break can be used between link title and link destination
|
|
126
|
-
* @see https://github.github.com/gfm/#example-162
|
|
127
|
-
* @see https://github.github.com/gfm/#example-164
|
|
128
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
129
|
-
*/
|
|
130
|
-
i = eatOptionalWhitespaces(nodePoints, destinationEndIndex, endIndex)
|
|
131
|
-
if (i >= endIndex) {
|
|
132
|
-
const token = createInitState()
|
|
133
|
-
token.destination = destinationState
|
|
134
|
-
token.lineNoOfDestination = lineNo
|
|
135
|
-
return { token, nextIndex: endIndex }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* The title must be separated from the link destination by whitespace.
|
|
140
|
-
* @see https://github.github.com/gfm/#example-170
|
|
141
|
-
*/
|
|
142
|
-
if (i === destinationEndIndex) return null
|
|
143
|
-
|
|
144
|
-
// Try to match link-title
|
|
145
|
-
const { nextIndex: titleEndIndex, state: titleState } = eatAndCollectLinkTitle(
|
|
146
|
-
nodePoints,
|
|
147
|
-
i,
|
|
148
|
-
endIndex,
|
|
149
|
-
null,
|
|
150
|
-
)
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* non-whitespace characters after title is not allowed
|
|
154
|
-
* @see https://github.github.com/gfm/#example-178
|
|
155
|
-
*/
|
|
156
|
-
if (titleEndIndex >= 0) i = titleEndIndex
|
|
157
|
-
|
|
158
|
-
if (i < endIndex) {
|
|
159
|
-
const k = eatOptionalWhitespaces(nodePoints, i, endIndex)
|
|
160
|
-
if (k < endIndex) return null
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const token = createInitState()
|
|
164
|
-
token.destination = destinationState
|
|
165
|
-
token.title = titleState
|
|
166
|
-
token.lineNoOfDestination = lineNo
|
|
167
|
-
token.lineNoOfTitle = lineNo
|
|
168
|
-
return { token, nextIndex: endIndex }
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function eatContinuationText(
|
|
172
|
-
line: Readonly<IPhrasingContentLine>,
|
|
173
|
-
token: IToken,
|
|
174
|
-
): IResultOfEatContinuationText {
|
|
175
|
-
// All parts of Definition have been matched
|
|
176
|
-
if (token.title != null && token.title.saturated) return { status: 'notMatched' }
|
|
177
|
-
|
|
178
|
-
const { nodePoints, startIndex, firstNonWhitespaceIndex, endIndex } = line
|
|
179
|
-
const lineNo = nodePoints[startIndex].line
|
|
180
|
-
|
|
181
|
-
let i = firstNonWhitespaceIndex
|
|
182
|
-
if (!token.label.saturated) {
|
|
183
|
-
const { nextIndex: labelEndIndex, state: labelState } = eatAndCollectLinkLabel(
|
|
184
|
-
nodePoints,
|
|
185
|
-
i,
|
|
186
|
-
endIndex,
|
|
187
|
-
token.label,
|
|
188
|
-
)
|
|
189
|
-
if (labelEndIndex < 0) {
|
|
190
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (!labelState.saturated) {
|
|
194
|
-
token.lines.push(line)
|
|
195
|
-
return { status: 'opening', nextIndex: endIndex }
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Saturated but no following colon exists.
|
|
199
|
-
if (
|
|
200
|
-
labelEndIndex + 1 >= endIndex ||
|
|
201
|
-
nodePoints[labelEndIndex].codePoint !== AsciiCodePoint.COLON
|
|
202
|
-
) {
|
|
203
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
i = labelEndIndex + 1
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (token.destination == null) {
|
|
210
|
-
i = eatOptionalWhitespaces(nodePoints, i, endIndex)
|
|
211
|
-
if (i >= endIndex) {
|
|
212
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// Try to match link destination
|
|
216
|
-
const { nextIndex: destinationEndIndex, state: destinationState } =
|
|
217
|
-
eatAndCollectLinkDestination(nodePoints, i, endIndex, null)
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* At most one line break can be used between link destination and link label,
|
|
221
|
-
* therefore, this line must match a complete link destination
|
|
222
|
-
*/
|
|
223
|
-
if (destinationEndIndex < 0 || !destinationState.saturated) {
|
|
224
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* At most one line break can be used between link title and link destination
|
|
229
|
-
* @see https://github.github.com/gfm/#example-162
|
|
230
|
-
* @see https://github.github.com/gfm/#example-164
|
|
231
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
232
|
-
*/
|
|
233
|
-
i = eatOptionalWhitespaces(nodePoints, destinationEndIndex, endIndex)
|
|
234
|
-
if (i >= endIndex) {
|
|
235
|
-
// eslint-disable-next-line no-param-reassign
|
|
236
|
-
token.destination = destinationState
|
|
237
|
-
token.lines.push(line)
|
|
238
|
-
return { status: 'opening', nextIndex: endIndex }
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// eslint-disable-next-line no-param-reassign
|
|
242
|
-
token.lineNoOfDestination = lineNo
|
|
243
|
-
// eslint-disable-next-line no-param-reassign
|
|
244
|
-
token.lineNoOfTitle = lineNo
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (token.lineNoOfTitle < 0) {
|
|
248
|
-
// eslint-disable-next-line no-param-reassign
|
|
249
|
-
token.lineNoOfTitle = lineNo
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
const { nextIndex: titleEndIndex, state: titleState } = eatAndCollectLinkTitle(
|
|
253
|
-
nodePoints,
|
|
254
|
-
i,
|
|
255
|
-
endIndex,
|
|
256
|
-
token.title,
|
|
257
|
-
)
|
|
258
|
-
// eslint-disable-next-line no-param-reassign
|
|
259
|
-
token.title = titleState
|
|
260
|
-
|
|
261
|
-
if (
|
|
262
|
-
titleEndIndex < 0 ||
|
|
263
|
-
titleState.nodePoints.length <= 0 ||
|
|
264
|
-
(titleState.saturated &&
|
|
265
|
-
eatOptionalWhitespaces(nodePoints, titleEndIndex, endIndex) < endIndex)
|
|
266
|
-
) {
|
|
267
|
-
// check if there exists a valid title
|
|
268
|
-
if (token.lineNoOfDestination === token.lineNoOfTitle) {
|
|
269
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const lastLine = token.lines[token.lines.length - 1]
|
|
273
|
-
// eslint-disable-next-line no-param-reassign
|
|
274
|
-
token.title = null
|
|
275
|
-
// eslint-disable-next-line no-param-reassign
|
|
276
|
-
token.position.end = calcEndPoint(lastLine.nodePoints, lastLine.endIndex - 1)
|
|
277
|
-
return {
|
|
278
|
-
status: 'closingAndRollback',
|
|
279
|
-
lines: token.lines.slice(token.lineNoOfTitle - 1),
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
token.lines.push(line)
|
|
284
|
-
const saturated: boolean = token.title?.saturated
|
|
285
|
-
return { status: saturated ? 'closing' : 'opening', nextIndex: endIndex }
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
function onClose(token: IToken): IResultOfOnClose {
|
|
289
|
-
let result: IResultOfOnClose
|
|
290
|
-
|
|
291
|
-
// Not all parts of Definition have been matched.
|
|
292
|
-
if (token.title == null || !token.title.saturated) {
|
|
293
|
-
// No valid label matched.
|
|
294
|
-
if (!token.label.saturated) {
|
|
295
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// No valid destination matched.
|
|
299
|
-
if (token.destination == null || !token.destination.saturated) {
|
|
300
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// No valid title matched.
|
|
304
|
-
if (token.title != null && !token.title.saturated) {
|
|
305
|
-
if (token.lineNoOfDestination === token.lineNoOfTitle) {
|
|
306
|
-
return { status: 'failedAndRollback', lines: token.lines }
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
const lines = token.lines.splice(token.lineNoOfTitle - 1)
|
|
310
|
-
const lastLine = token.lines[token.lines.length - 1]
|
|
311
|
-
// eslint-disable-next-line no-param-reassign
|
|
312
|
-
token.title = null
|
|
313
|
-
// eslint-disable-next-line no-param-reassign
|
|
314
|
-
token.position.end = calcEndPoint(lastLine.nodePoints, lastLine.endIndex - 1)
|
|
315
|
-
|
|
316
|
-
result = { status: 'closingAndRollback', lines }
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Labels are trimmed and case-insensitive
|
|
322
|
-
* @see https://github.github.com/gfm/#example-174
|
|
323
|
-
* @see https://github.github.com/gfm/#example-175
|
|
324
|
-
*/
|
|
325
|
-
const labelPoints: INodePoint[] = token.label.nodePoints
|
|
326
|
-
const label = calcStringFromNodePoints(labelPoints, 1, labelPoints.length - 1)
|
|
327
|
-
const identifier = resolveLabelToIdentifier(label)
|
|
328
|
-
|
|
329
|
-
// Register definition identifier.
|
|
330
|
-
api.registerDefinitionIdentifier(identifier)
|
|
331
|
-
|
|
332
|
-
// Cache label and identifier for performance.
|
|
333
|
-
|
|
334
|
-
// eslint-disable-next-line no-param-reassign
|
|
335
|
-
token._label = label
|
|
336
|
-
// eslint-disable-next-line no-param-reassign
|
|
337
|
-
token._identifier = identifier
|
|
338
|
-
return result
|
|
339
|
-
}
|
|
340
|
-
}
|
package/src/parse.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { DefinitionType } from '@yozora/ast'
|
|
2
|
-
import type { INodePoint } from '@yozora/character'
|
|
3
|
-
import { AsciiCodePoint, calcEscapedStringFromNodePoints } from '@yozora/character'
|
|
4
|
-
import type { IParseBlockHookCreator } from '@yozora/core-tokenizer'
|
|
5
|
-
import { encodeLinkDestination } from '@yozora/core-tokenizer'
|
|
6
|
-
import type { INode, IThis, IToken, T } from './types'
|
|
7
|
-
|
|
8
|
-
export const parse: IParseBlockHookCreator<T, IToken, INode, IThis> = function (api) {
|
|
9
|
-
return {
|
|
10
|
-
parse: tokens =>
|
|
11
|
-
tokens.map(token => {
|
|
12
|
-
const label: string = token._label!
|
|
13
|
-
const identifier: string = token._identifier!
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Resolve link destination
|
|
17
|
-
* @see https://github.github.com/gfm/#link-destination
|
|
18
|
-
*/
|
|
19
|
-
const destinationPoints: INodePoint[] = token.destination!.nodePoints
|
|
20
|
-
const destination: string =
|
|
21
|
-
destinationPoints[0].codePoint === AsciiCodePoint.OPEN_ANGLE
|
|
22
|
-
? calcEscapedStringFromNodePoints(
|
|
23
|
-
destinationPoints,
|
|
24
|
-
1,
|
|
25
|
-
destinationPoints.length - 1,
|
|
26
|
-
true,
|
|
27
|
-
)
|
|
28
|
-
: calcEscapedStringFromNodePoints(destinationPoints, 0, destinationPoints.length, true)
|
|
29
|
-
const url = encodeLinkDestination(destination)
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Resolve link title
|
|
33
|
-
* @see https://github.github.com/gfm/#link-title
|
|
34
|
-
*/
|
|
35
|
-
const title: string | undefined =
|
|
36
|
-
token.title == null
|
|
37
|
-
? undefined
|
|
38
|
-
: calcEscapedStringFromNodePoints(
|
|
39
|
-
token.title.nodePoints,
|
|
40
|
-
1,
|
|
41
|
-
token.title.nodePoints.length - 1,
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
const node: INode = api.shouldReservePosition
|
|
45
|
-
? { type: DefinitionType, position: token.position, identifier, label, url, title }
|
|
46
|
-
: { type: DefinitionType, identifier, label, url, title }
|
|
47
|
-
return node
|
|
48
|
-
}),
|
|
49
|
-
}
|
|
50
|
-
}
|
package/src/tokenizer.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
IBlockTokenizer,
|
|
3
|
-
IMatchBlockHookCreator,
|
|
4
|
-
IParseBlockHookCreator,
|
|
5
|
-
} from '@yozora/core-tokenizer'
|
|
6
|
-
import { BaseBlockTokenizer, TokenizerPriority } from '@yozora/core-tokenizer'
|
|
7
|
-
import { match } from './match'
|
|
8
|
-
import { parse } from './parse'
|
|
9
|
-
import { uniqueName } from './types'
|
|
10
|
-
import type { INode, IThis, IToken, ITokenizerProps, T } from './types'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Lexical Analyzer for Definition.
|
|
14
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
15
|
-
*/
|
|
16
|
-
export class DefinitionTokenizer
|
|
17
|
-
extends BaseBlockTokenizer<T, IToken, INode, IThis>
|
|
18
|
-
implements IBlockTokenizer<T, IToken, INode, IThis>
|
|
19
|
-
{
|
|
20
|
-
/* istanbul ignore next */
|
|
21
|
-
constructor(props: ITokenizerProps = {}) {
|
|
22
|
-
super({
|
|
23
|
-
name: props.name ?? uniqueName,
|
|
24
|
-
priority: props.priority ?? TokenizerPriority.ATOMIC,
|
|
25
|
-
})
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
public override readonly match: IMatchBlockHookCreator<T, IToken, IThis> = match
|
|
29
|
-
|
|
30
|
-
public override readonly parse: IParseBlockHookCreator<T, IToken, INode, IThis> = parse
|
|
31
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { Definition, DefinitionType } from '@yozora/ast'
|
|
2
|
-
import type {
|
|
3
|
-
IBaseBlockTokenizerProps,
|
|
4
|
-
IPartialBlockToken,
|
|
5
|
-
IPhrasingContentLine,
|
|
6
|
-
ITokenizer,
|
|
7
|
-
} from '@yozora/core-tokenizer'
|
|
8
|
-
import type { ILinkDestinationCollectingState } from './util/link-destination'
|
|
9
|
-
import type { ILinkLabelCollectingState } from './util/link-label'
|
|
10
|
-
import type { ILinkTitleCollectingState } from './util/link-title'
|
|
11
|
-
|
|
12
|
-
export type T = DefinitionType
|
|
13
|
-
export type INode = Definition
|
|
14
|
-
export const uniqueName = '@yozora/tokenizer-definition'
|
|
15
|
-
|
|
16
|
-
export interface IToken extends IPartialBlockToken<T> {
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*/
|
|
20
|
-
lines: Array<Readonly<IPhrasingContentLine>>
|
|
21
|
-
/**
|
|
22
|
-
* Link label
|
|
23
|
-
* Trimmed, Case-Insensitive
|
|
24
|
-
*/
|
|
25
|
-
label: ILinkLabelCollectingState
|
|
26
|
-
/**
|
|
27
|
-
* Link destination
|
|
28
|
-
*/
|
|
29
|
-
destination: ILinkDestinationCollectingState | null
|
|
30
|
-
/**
|
|
31
|
-
* Link title
|
|
32
|
-
*/
|
|
33
|
-
title: ILinkTitleCollectingState | null
|
|
34
|
-
/**
|
|
35
|
-
* The line number of the first matched character of the link label
|
|
36
|
-
*/
|
|
37
|
-
lineNoOfLabel: number
|
|
38
|
-
/**
|
|
39
|
-
* The line number of the first matched character of the link destination
|
|
40
|
-
*/
|
|
41
|
-
lineNoOfDestination: number
|
|
42
|
-
/**
|
|
43
|
-
* The line number of the first matched character of the link title
|
|
44
|
-
*/
|
|
45
|
-
lineNoOfTitle: number
|
|
46
|
-
/**
|
|
47
|
-
* Resolved definition label.
|
|
48
|
-
*/
|
|
49
|
-
_label?: string
|
|
50
|
-
/**
|
|
51
|
-
* Resolved definition identifier.
|
|
52
|
-
*/
|
|
53
|
-
_identifier?: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export type IThis = ITokenizer
|
|
57
|
-
|
|
58
|
-
export type ITokenizerProps = Partial<IBaseBlockTokenizerProps>
|