@yozora/tokenizer-footnote-definition 2.1.2 → 2.1.4
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/package.json +6 -6
- package/src/index.ts +0 -10
- package/src/match.ts +0 -115
- package/src/parse.ts +0 -31
- package/src/tokenizer.ts +0 -37
- package/src/types.ts +0 -37
- package/src/util.ts +0 -58
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-footnote-definition",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
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.4",
|
|
43
|
+
"@yozora/character": "^2.1.4",
|
|
44
|
+
"@yozora/core-tokenizer": "^2.1.4"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "aa464ed1e3cd84892773a833910cfc53a556bf5f"
|
|
47
47
|
}
|
package/src/index.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export * from './util'
|
|
2
|
-
export { match as footnoteDefinitionMatch } from './match'
|
|
3
|
-
export { parse as footnoteDefinitionParse } from './parse'
|
|
4
|
-
export { FootnoteDefinitionTokenizer, FootnoteDefinitionTokenizer as default } from './tokenizer'
|
|
5
|
-
export { uniqueName as FootnoteDefinitionTokenizerName } from './types'
|
|
6
|
-
export type {
|
|
7
|
-
IThis as IFootnoteDefinitionHookContext,
|
|
8
|
-
IToken as IFootnoteDefinitionToken,
|
|
9
|
-
ITokenizerProps as IFootnoteDefinitionTokenizerProps,
|
|
10
|
-
} from './types'
|
package/src/match.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { FootnoteDefinitionType } from '@yozora/ast'
|
|
2
|
-
import { AsciiCodePoint, calcStringFromNodePoints } from '@yozora/character'
|
|
3
|
-
import type {
|
|
4
|
-
IMatchBlockHookCreator,
|
|
5
|
-
IPhrasingContentLine,
|
|
6
|
-
IResultOfEatContinuationText,
|
|
7
|
-
IResultOfEatOpener,
|
|
8
|
-
IResultOfOnClose,
|
|
9
|
-
} from '@yozora/core-tokenizer'
|
|
10
|
-
import { calcEndPoint, calcStartPoint, resolveLabelToIdentifier } from '@yozora/core-tokenizer'
|
|
11
|
-
import type { IThis, IToken, T } from './types'
|
|
12
|
-
import { eatFootnoteLabel } from './util'
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* A footnote reference definition consists of a footnote label, indented up
|
|
16
|
-
* to three spaces, followed by a colon (:), optional whitespace (including up
|
|
17
|
-
* to one line ending), a footnote contents consisted by paragraph-like strings.
|
|
18
|
-
*
|
|
19
|
-
* Unlike the link label, the footnote label should be on the same line and it
|
|
20
|
-
* begins with a left bracket ([) followed by a caret (^), and ends with the
|
|
21
|
-
* first right bracket (]) that is not backslash-escaped. Between the caret of
|
|
22
|
-
* right bracket, there must be at least one non-whitespace character.
|
|
23
|
-
* Unescaped square bracket characters are not allowed inside the opening creat
|
|
24
|
-
* and closing square bracket of footnote labels. A footnote label can have at
|
|
25
|
-
* most 999 characters inside the caret and right bracket.
|
|
26
|
-
*
|
|
27
|
-
* @see https://github.github.com/gfm/#link-label
|
|
28
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
29
|
-
* @see https://github.com/syntax-tree/mdast-util-footnote
|
|
30
|
-
* @see https://github.com/remarkjs/remark-footnotes
|
|
31
|
-
* @see https://www.markdownguide.org/extended-syntax/#footnotes
|
|
32
|
-
*/
|
|
33
|
-
export const match: IMatchBlockHookCreator<T, IToken, IThis> = function (api) {
|
|
34
|
-
const { indent } = this
|
|
35
|
-
return {
|
|
36
|
-
isContainingBlock: true,
|
|
37
|
-
eatOpener,
|
|
38
|
-
eatContinuationText,
|
|
39
|
-
onClose,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function eatOpener(line: Readonly<IPhrasingContentLine>): IResultOfEatOpener<T, IToken> {
|
|
43
|
-
if (line.countOfPrecedeSpaces >= 4) return null
|
|
44
|
-
|
|
45
|
-
const { nodePoints, startIndex, firstNonWhitespaceIndex, endIndex } = line
|
|
46
|
-
const nextIndex = eatFootnoteLabel(nodePoints, firstNonWhitespaceIndex, endIndex)
|
|
47
|
-
|
|
48
|
-
// Try to match the following colon (:).
|
|
49
|
-
if (
|
|
50
|
-
nextIndex < 0 ||
|
|
51
|
-
nextIndex >= endIndex ||
|
|
52
|
-
nodePoints[nextIndex].codePoint !== AsciiCodePoint.COLON
|
|
53
|
-
) {
|
|
54
|
-
return null
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const token: IToken = {
|
|
58
|
-
nodeType: FootnoteDefinitionType,
|
|
59
|
-
position: {
|
|
60
|
-
start: calcStartPoint(nodePoints, startIndex),
|
|
61
|
-
end: calcEndPoint(nodePoints, nextIndex),
|
|
62
|
-
},
|
|
63
|
-
label: {
|
|
64
|
-
nodePoints,
|
|
65
|
-
startIndex: firstNonWhitespaceIndex,
|
|
66
|
-
endIndex: nextIndex,
|
|
67
|
-
},
|
|
68
|
-
children: [],
|
|
69
|
-
}
|
|
70
|
-
return { token, nextIndex: nextIndex + 1 }
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function eatContinuationText(line: Readonly<IPhrasingContentLine>): IResultOfEatContinuationText {
|
|
74
|
-
const { startIndex, endIndex, firstNonWhitespaceIndex, countOfPrecedeSpaces } = line
|
|
75
|
-
|
|
76
|
-
// Blank line is allowed
|
|
77
|
-
if (firstNonWhitespaceIndex >= endIndex) {
|
|
78
|
-
return {
|
|
79
|
-
status: 'opening',
|
|
80
|
-
nextIndex: Math.min(endIndex - 1, startIndex + indent),
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Indent of a non-blank line is required.
|
|
85
|
-
if (countOfPrecedeSpaces >= indent) {
|
|
86
|
-
return { status: 'opening', nextIndex: startIndex + indent }
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return { status: 'notMatched' }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function onClose(token: IToken): IResultOfOnClose {
|
|
93
|
-
/**
|
|
94
|
-
* Labels are trimmed and case-insensitive
|
|
95
|
-
* @see https://github.github.com/gfm/#example-174
|
|
96
|
-
* @see https://github.github.com/gfm/#example-175
|
|
97
|
-
*/
|
|
98
|
-
const label = calcStringFromNodePoints(
|
|
99
|
-
token.label.nodePoints,
|
|
100
|
-
token.label.startIndex + 2,
|
|
101
|
-
token.label.endIndex - 1,
|
|
102
|
-
)
|
|
103
|
-
const identifier = resolveLabelToIdentifier(label)
|
|
104
|
-
|
|
105
|
-
// Register definition identifier.
|
|
106
|
-
api.registerFootnoteDefinitionIdentifier(identifier)
|
|
107
|
-
|
|
108
|
-
// Cache label and identifier for performance.
|
|
109
|
-
|
|
110
|
-
// eslint-disable-next-line no-param-reassign
|
|
111
|
-
token._label = label
|
|
112
|
-
// eslint-disable-next-line no-param-reassign
|
|
113
|
-
token._identifier = identifier
|
|
114
|
-
}
|
|
115
|
-
}
|
package/src/parse.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { Node } from '@yozora/ast'
|
|
2
|
-
import { FootnoteDefinitionType } from '@yozora/ast'
|
|
3
|
-
import type { IParseBlockHookCreator } from '@yozora/core-tokenizer'
|
|
4
|
-
import type { INode, IThis, IToken, T } from './types'
|
|
5
|
-
|
|
6
|
-
export const parse: IParseBlockHookCreator<T, IToken, INode, IThis> = function (api) {
|
|
7
|
-
return {
|
|
8
|
-
parse: tokens =>
|
|
9
|
-
tokens.map(token => {
|
|
10
|
-
const label: string = token._label!
|
|
11
|
-
const identifier: string = token._identifier!
|
|
12
|
-
|
|
13
|
-
const children: Node[] = api.parseBlockTokens(token.children)
|
|
14
|
-
const node: INode = api.shouldReservePosition
|
|
15
|
-
? {
|
|
16
|
-
type: FootnoteDefinitionType,
|
|
17
|
-
position: token.position,
|
|
18
|
-
identifier,
|
|
19
|
-
label,
|
|
20
|
-
children,
|
|
21
|
-
}
|
|
22
|
-
: {
|
|
23
|
-
type: FootnoteDefinitionType,
|
|
24
|
-
identifier,
|
|
25
|
-
label,
|
|
26
|
-
children,
|
|
27
|
-
}
|
|
28
|
-
return node
|
|
29
|
-
}),
|
|
30
|
-
}
|
|
31
|
-
}
|
package/src/tokenizer.ts
DELETED
|
@@ -1,37 +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 type { INode, IThis, IToken, ITokenizerProps, T } from './types'
|
|
10
|
-
import { uniqueName } from './types'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Lexical Analyzer for FootnoteDefinition.
|
|
14
|
-
* @see https://github.github.com/gfm/#link-label
|
|
15
|
-
* @see https://github.github.com/gfm/#link-reference-definition
|
|
16
|
-
* @see https://github.com/syntax-tree/mdast-util-footnote
|
|
17
|
-
* @see https://github.com/remarkjs/remark-footnotes
|
|
18
|
-
* @see https://www.markdownguide.org/extended-syntax/#footnotes
|
|
19
|
-
*/
|
|
20
|
-
export class FootnoteDefinitionTokenizer
|
|
21
|
-
extends BaseBlockTokenizer<T, IToken, INode, IThis>
|
|
22
|
-
implements IBlockTokenizer<T, IToken, INode, IThis>
|
|
23
|
-
{
|
|
24
|
-
/* istanbul ignore next */
|
|
25
|
-
constructor(props: ITokenizerProps = {}) {
|
|
26
|
-
super({
|
|
27
|
-
name: props.name ?? uniqueName,
|
|
28
|
-
priority: props.priority ?? TokenizerPriority.CONTAINING_BLOCK,
|
|
29
|
-
})
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public readonly indent = 4
|
|
33
|
-
|
|
34
|
-
public override readonly match: IMatchBlockHookCreator<T, IToken, IThis> = match
|
|
35
|
-
|
|
36
|
-
public override readonly parse: IParseBlockHookCreator<T, IToken, INode, IThis> = parse
|
|
37
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import type { FootnoteDefinition, FootnoteDefinitionType } from '@yozora/ast'
|
|
2
|
-
import type { INodeInterval, INodePoint } from '@yozora/character'
|
|
3
|
-
import type {
|
|
4
|
-
IBaseBlockTokenizerProps,
|
|
5
|
-
IBlockToken,
|
|
6
|
-
IPartialBlockToken,
|
|
7
|
-
ITokenizer,
|
|
8
|
-
} from '@yozora/core-tokenizer'
|
|
9
|
-
|
|
10
|
-
export type T = FootnoteDefinitionType
|
|
11
|
-
export type INode = FootnoteDefinition
|
|
12
|
-
export const uniqueName = '@yozora/tokenizer-footnote-definition'
|
|
13
|
-
|
|
14
|
-
export interface IToken extends IPartialBlockToken<T> {
|
|
15
|
-
/**
|
|
16
|
-
* Footnote label
|
|
17
|
-
*/
|
|
18
|
-
label: INodeInterval & { nodePoints: ReadonlyArray<INodePoint> }
|
|
19
|
-
/**
|
|
20
|
-
*
|
|
21
|
-
*/
|
|
22
|
-
children: IBlockToken[]
|
|
23
|
-
/**
|
|
24
|
-
* Resolved definition label.
|
|
25
|
-
*/
|
|
26
|
-
_label?: string
|
|
27
|
-
/**
|
|
28
|
-
* Resolved definition identifier.
|
|
29
|
-
*/
|
|
30
|
-
_identifier?: string
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface IThis extends ITokenizer {
|
|
34
|
-
indent: number
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type ITokenizerProps = Partial<IBaseBlockTokenizerProps>
|
package/src/util.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { INodePoint } from '@yozora/character'
|
|
2
|
-
import { AsciiCodePoint, VirtualCodePoint, isWhitespaceCharacter } from '@yozora/character'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Try to match a footnote label.
|
|
6
|
-
*
|
|
7
|
-
* Unlike the link label, the footnote label should be on the same line and it
|
|
8
|
-
* begins with a left bracket ([) followed by a caret (^), and ends with the
|
|
9
|
-
* first right bracket (]) that is not backslash-escaped. Between the caret of
|
|
10
|
-
* right bracket, there must be at least one non-whitespace character.
|
|
11
|
-
* Unescaped square bracket characters are not allowed inside the opening creat
|
|
12
|
-
* and closing square bracket of footnote labels. A footnote label can have at
|
|
13
|
-
* most 999 characters inside the caret and right bracket.
|
|
14
|
-
*
|
|
15
|
-
* @param nodePoints
|
|
16
|
-
* @param firstNonWhitespaceIndex
|
|
17
|
-
* @param endIndex
|
|
18
|
-
* @see https://github.github.com/gfm/#link-label
|
|
19
|
-
*/
|
|
20
|
-
export function eatFootnoteLabel(
|
|
21
|
-
nodePoints: ReadonlyArray<INodePoint>,
|
|
22
|
-
firstNonWhitespaceIndex: number,
|
|
23
|
-
endIndex: number,
|
|
24
|
-
): number {
|
|
25
|
-
let i = firstNonWhitespaceIndex
|
|
26
|
-
|
|
27
|
-
// Try to match an opening delimiter of a footnote label.
|
|
28
|
-
if (
|
|
29
|
-
i + 1 >= endIndex ||
|
|
30
|
-
nodePoints[i].codePoint !== AsciiCodePoint.OPEN_BRACKET ||
|
|
31
|
-
nodePoints[i + 1].codePoint !== AsciiCodePoint.CARET
|
|
32
|
-
) {
|
|
33
|
-
return -1
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
let isEmpty = true
|
|
37
|
-
const lastIndex = Math.min(endIndex, i + 1 + 1000)
|
|
38
|
-
for (i += 2; i < lastIndex; ++i) {
|
|
39
|
-
const c = nodePoints[i].codePoint
|
|
40
|
-
switch (c) {
|
|
41
|
-
case AsciiCodePoint.BACKSLASH:
|
|
42
|
-
i += 1
|
|
43
|
-
break
|
|
44
|
-
case AsciiCodePoint.OPEN_BRACKET:
|
|
45
|
-
return -1
|
|
46
|
-
case AsciiCodePoint.CLOSE_BRACKET:
|
|
47
|
-
return isEmpty ? -1 : i + 1
|
|
48
|
-
case VirtualCodePoint.LINE_END:
|
|
49
|
-
return -1
|
|
50
|
-
default:
|
|
51
|
-
if (isEmpty && !isWhitespaceCharacter(c)) {
|
|
52
|
-
isEmpty = false
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return -1
|
|
58
|
-
}
|