@yozora/tokenizer-thematic-break 2.0.4 → 2.0.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/lib/cjs/{index.js → index.cjs} +5 -6
- package/lib/esm/{index.js → index.mjs} +4 -5
- package/lib/types/index.d.ts +4 -4
- package/package.json +18 -14
- package/src/index.ts +9 -0
- package/src/match.ts +127 -0
- package/src/parse.ts +15 -0
- package/src/tokenizer.ts +31 -0
- package/src/types.ts +25 -0
|
@@ -89,18 +89,17 @@ const uniqueName = '@yozora/tokenizer-thematic-break';
|
|
|
89
89
|
|
|
90
90
|
class ThematicBreakTokenizer extends coreTokenizer.BaseBlockTokenizer {
|
|
91
91
|
constructor(props = {}) {
|
|
92
|
-
var _a, _b;
|
|
93
92
|
super({
|
|
94
|
-
name:
|
|
95
|
-
priority:
|
|
93
|
+
name: props.name ?? uniqueName,
|
|
94
|
+
priority: props.priority ?? coreTokenizer.TokenizerPriority.ATOMIC,
|
|
96
95
|
});
|
|
97
|
-
this.match = match;
|
|
98
|
-
this.parse = parse;
|
|
99
96
|
}
|
|
97
|
+
match = match;
|
|
98
|
+
parse = parse;
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
exports.ThematicBreakTokenizer = ThematicBreakTokenizer;
|
|
103
102
|
exports.ThematicBreakTokenizerName = uniqueName;
|
|
104
|
-
exports
|
|
103
|
+
exports.default = ThematicBreakTokenizer;
|
|
105
104
|
exports.thematicBreakMatch = match;
|
|
106
105
|
exports.thematicBreakParse = parse;
|
|
@@ -85,14 +85,13 @@ const uniqueName = '@yozora/tokenizer-thematic-break';
|
|
|
85
85
|
|
|
86
86
|
class ThematicBreakTokenizer extends BaseBlockTokenizer {
|
|
87
87
|
constructor(props = {}) {
|
|
88
|
-
var _a, _b;
|
|
89
88
|
super({
|
|
90
|
-
name:
|
|
91
|
-
priority:
|
|
89
|
+
name: props.name ?? uniqueName,
|
|
90
|
+
priority: props.priority ?? TokenizerPriority.ATOMIC,
|
|
92
91
|
});
|
|
93
|
-
this.match = match;
|
|
94
|
-
this.parse = parse;
|
|
95
92
|
}
|
|
93
|
+
match = match;
|
|
94
|
+
parse = parse;
|
|
96
95
|
}
|
|
97
96
|
|
|
98
97
|
export { ThematicBreakTokenizer, uniqueName as ThematicBreakTokenizerName, ThematicBreakTokenizer as default, match as thematicBreakMatch, parse as thematicBreakParse };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { IPartialYastBlockToken, ITokenizer, IBaseBlockTokenizerProps, IMatchBlockHookCreator, IParseBlockHookCreator, BaseBlockTokenizer, IBlockTokenizer } from '@yozora/core-tokenizer';
|
|
2
2
|
import { ThematicBreakType, ThematicBreak } from '@yozora/ast';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type T = ThematicBreakType;
|
|
5
|
+
type INode = ThematicBreak;
|
|
6
6
|
declare const uniqueName = "@yozora/tokenizer-thematic-break";
|
|
7
7
|
interface IToken extends IPartialYastBlockToken<T> {
|
|
8
8
|
/**
|
|
@@ -14,8 +14,8 @@ interface IToken extends IPartialYastBlockToken<T> {
|
|
|
14
14
|
*/
|
|
15
15
|
continuous: boolean;
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
type IThis = ITokenizer;
|
|
18
|
+
type ITokenizerProps = Partial<IBaseBlockTokenizerProps>;
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* A line consisting of 0-3 spaces of indentation, followed by a sequence of
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-thematic-break",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.5",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "guanghechen",
|
|
6
6
|
"url": "https://github.com/guanghechen/"
|
|
@@ -11,33 +11,37 @@
|
|
|
11
11
|
"directory": "tokenizers/thematic-break"
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/yozorajs/yozora/tree/release-2.x.x/tokenizers/thematic-break",
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
"types": "./lib/types/index.d.ts",
|
|
17
|
+
"import": "./lib/esm/index.mjs",
|
|
18
|
+
"require": "./lib/cjs/index.cjs"
|
|
19
|
+
},
|
|
20
|
+
"source": "./src/index.ts",
|
|
21
|
+
"types": "./lib/types/index.d.ts",
|
|
22
|
+
"main": "./lib/cjs/index.cjs",
|
|
23
|
+
"module": "./lib/esm/index.mjs",
|
|
18
24
|
"license": "MIT",
|
|
19
25
|
"engines": {
|
|
20
26
|
"node": ">= 16.0.0"
|
|
21
27
|
},
|
|
22
28
|
"files": [
|
|
23
29
|
"lib/",
|
|
24
|
-
"
|
|
25
|
-
"!lib/**/*.d.ts.map",
|
|
30
|
+
"src/",
|
|
26
31
|
"package.json",
|
|
27
32
|
"CHANGELOG.md",
|
|
28
33
|
"LICENSE",
|
|
29
34
|
"README.md"
|
|
30
35
|
],
|
|
31
36
|
"scripts": {
|
|
32
|
-
"build": "cross-env NODE_ENV=production rollup -c ../../rollup.config.
|
|
33
|
-
"prebuild": "rimraf lib/",
|
|
37
|
+
"build": "rimraf lib/ && cross-env NODE_ENV=production rollup -c ../../rollup.config.mjs",
|
|
34
38
|
"prepublishOnly": "cross-env ROLLUP_SHOULD_SOURCEMAP=false yarn build",
|
|
35
|
-
"test": "cross-env TS_NODE_FILES=true jest --config ../../jest.config.
|
|
39
|
+
"test": "cross-env TS_NODE_FILES=true NODE_OPTIONS=--experimental-vm-modules jest --config ../../jest.config.mjs --rootDir ."
|
|
36
40
|
},
|
|
37
41
|
"dependencies": {
|
|
38
|
-
"@yozora/ast": "^2.0.
|
|
39
|
-
"@yozora/character": "^2.0.
|
|
40
|
-
"@yozora/core-tokenizer": "^2.0.
|
|
42
|
+
"@yozora/ast": "^2.0.5",
|
|
43
|
+
"@yozora/character": "^2.0.5",
|
|
44
|
+
"@yozora/core-tokenizer": "^2.0.5"
|
|
41
45
|
},
|
|
42
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "7ba3bab49fe65cf2f57082c0503af73da9356cf0"
|
|
43
47
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { match as thematicBreakMatch } from './match'
|
|
2
|
+
export { parse as thematicBreakParse } from './parse'
|
|
3
|
+
export { ThematicBreakTokenizer, ThematicBreakTokenizer as default } from './tokenizer'
|
|
4
|
+
export { uniqueName as ThematicBreakTokenizerName } from './types'
|
|
5
|
+
export type {
|
|
6
|
+
IThis as IThematicBreakHookContext,
|
|
7
|
+
IToken as IThematicBreakToken,
|
|
8
|
+
ITokenizerProps as IThematicBreakTokenizerProps,
|
|
9
|
+
} from './types'
|
package/src/match.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { ThematicBreakType } from '@yozora/ast'
|
|
2
|
+
import { AsciiCodePoint, isUnicodeWhitespaceCharacter } from '@yozora/character'
|
|
3
|
+
import type {
|
|
4
|
+
IMatchBlockHookCreator,
|
|
5
|
+
IPhrasingContentLine,
|
|
6
|
+
IResultOfEatAndInterruptPreviousSibling,
|
|
7
|
+
IResultOfEatOpener,
|
|
8
|
+
IYastBlockToken,
|
|
9
|
+
} from '@yozora/core-tokenizer'
|
|
10
|
+
import { calcEndPoint, calcStartPoint } from '@yozora/core-tokenizer'
|
|
11
|
+
import type { IThis, IToken, T } from './types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* A line consisting of 0-3 spaces of indentation, followed by a sequence of
|
|
15
|
+
* three or more matching -, _, or * characters, each followed optionally by
|
|
16
|
+
* any number of spaces or tabs, forms a thematic break.
|
|
17
|
+
*
|
|
18
|
+
* @see https://github.github.com/gfm/#thematic-break
|
|
19
|
+
*/
|
|
20
|
+
export const match: IMatchBlockHookCreator<T, IToken, IThis> = function () {
|
|
21
|
+
return {
|
|
22
|
+
isContainingBlock: false,
|
|
23
|
+
eatOpener,
|
|
24
|
+
eatAndInterruptPreviousSibling,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function eatOpener(line: Readonly<IPhrasingContentLine>): IResultOfEatOpener<T, IToken> {
|
|
28
|
+
/**
|
|
29
|
+
* Four spaces is too much
|
|
30
|
+
* @see https://github.github.com/gfm/#example-19
|
|
31
|
+
*/
|
|
32
|
+
if (line.countOfPrecedeSpaces >= 4) return null
|
|
33
|
+
|
|
34
|
+
const { nodePoints, startIndex, endIndex, firstNonWhitespaceIndex } = line
|
|
35
|
+
if (firstNonWhitespaceIndex + 2 >= endIndex) return null
|
|
36
|
+
|
|
37
|
+
let marker: number
|
|
38
|
+
let count = 0
|
|
39
|
+
let continuous = true
|
|
40
|
+
let hasPotentialInternalSpace = false
|
|
41
|
+
for (let i = firstNonWhitespaceIndex; i < endIndex; ++i) {
|
|
42
|
+
const c = nodePoints[i]
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Spaces are allowed between the characters
|
|
46
|
+
* Spaces are allowed at the end
|
|
47
|
+
* @see https://github.github.com/gfm/#example-21
|
|
48
|
+
* @see https://github.github.com/gfm/#example-22
|
|
49
|
+
* @see https://github.github.com/gfm/#example-23
|
|
50
|
+
* @see https://github.github.com/gfm/#example-24
|
|
51
|
+
*/
|
|
52
|
+
if (isUnicodeWhitespaceCharacter(c.codePoint)) {
|
|
53
|
+
hasPotentialInternalSpace = true
|
|
54
|
+
continue
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* As it is traversed from a non-empty character, if a blank character
|
|
59
|
+
* has been encountered before, it means that there is an internal space
|
|
60
|
+
*/
|
|
61
|
+
if (hasPotentialInternalSpace) {
|
|
62
|
+
continuous = false
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
switch (c.codePoint) {
|
|
66
|
+
/**
|
|
67
|
+
* A line consisting of 0-3 spaces of indentation, followed by a
|
|
68
|
+
* sequence of three or more matching '-', '_', or '*' characters,
|
|
69
|
+
* each followed optionally by any number of spaces or tabs, forms
|
|
70
|
+
* a thematic break
|
|
71
|
+
*/
|
|
72
|
+
case AsciiCodePoint.MINUS_SIGN:
|
|
73
|
+
case AsciiCodePoint.UNDERSCORE:
|
|
74
|
+
case AsciiCodePoint.ASTERISK: {
|
|
75
|
+
if (count <= 0) {
|
|
76
|
+
marker = c.codePoint
|
|
77
|
+
count += 1
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* It is required that all of the non-whitespace characters be the same
|
|
82
|
+
* @see https://github.github.com/gfm/#example-26
|
|
83
|
+
*/
|
|
84
|
+
if (c.codePoint !== marker!) return null
|
|
85
|
+
count += 1
|
|
86
|
+
break
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* No other characters may occur in the line
|
|
90
|
+
* @see https://github.github.com/gfm/#example-25
|
|
91
|
+
*/
|
|
92
|
+
default:
|
|
93
|
+
return null
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Not enough characters
|
|
99
|
+
* @see https://github.github.com/gfm/#example-16
|
|
100
|
+
*/
|
|
101
|
+
if (count < 3) return null
|
|
102
|
+
|
|
103
|
+
const token: IToken = {
|
|
104
|
+
nodeType: ThematicBreakType,
|
|
105
|
+
position: {
|
|
106
|
+
start: calcStartPoint(nodePoints, startIndex),
|
|
107
|
+
end: calcEndPoint(nodePoints, endIndex - 1),
|
|
108
|
+
},
|
|
109
|
+
marker: marker!,
|
|
110
|
+
continuous,
|
|
111
|
+
}
|
|
112
|
+
return { token, nextIndex: endIndex, saturated: true }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function eatAndInterruptPreviousSibling(
|
|
116
|
+
line: Readonly<IPhrasingContentLine>,
|
|
117
|
+
prevSiblingToken: Readonly<IYastBlockToken>,
|
|
118
|
+
): IResultOfEatAndInterruptPreviousSibling<T, IToken> {
|
|
119
|
+
const result = eatOpener(line)
|
|
120
|
+
if (result == null) return null
|
|
121
|
+
return {
|
|
122
|
+
token: result.token,
|
|
123
|
+
nextIndex: result.nextIndex,
|
|
124
|
+
remainingSibling: prevSiblingToken,
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/parse.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ThematicBreakType } from '@yozora/ast'
|
|
2
|
+
import type { IParseBlockHookCreator } from '@yozora/core-tokenizer'
|
|
3
|
+
import type { INode, IThis, IToken, T } from './types'
|
|
4
|
+
|
|
5
|
+
export const parse: IParseBlockHookCreator<T, IToken, INode, IThis> = function (api) {
|
|
6
|
+
return {
|
|
7
|
+
parse: tokens =>
|
|
8
|
+
tokens.map(token => {
|
|
9
|
+
const node: INode = api.shouldReservePosition
|
|
10
|
+
? { type: ThematicBreakType, position: token.position }
|
|
11
|
+
: { type: ThematicBreakType }
|
|
12
|
+
return node
|
|
13
|
+
}),
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/tokenizer.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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 ThematicBreak.
|
|
14
|
+
* @see https://github.github.com/gfm/#thematic-break
|
|
15
|
+
*/
|
|
16
|
+
export class ThematicBreakTokenizer
|
|
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
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ThematicBreak, ThematicBreakType } from '@yozora/ast'
|
|
2
|
+
import type {
|
|
3
|
+
IBaseBlockTokenizerProps,
|
|
4
|
+
IPartialYastBlockToken,
|
|
5
|
+
ITokenizer,
|
|
6
|
+
} from '@yozora/core-tokenizer'
|
|
7
|
+
|
|
8
|
+
export type T = ThematicBreakType
|
|
9
|
+
export type INode = ThematicBreak
|
|
10
|
+
export const uniqueName = '@yozora/tokenizer-thematic-break'
|
|
11
|
+
|
|
12
|
+
export interface IToken extends IPartialYastBlockToken<T> {
|
|
13
|
+
/**
|
|
14
|
+
* CodePoint of '-' / '_' / '*'
|
|
15
|
+
*/
|
|
16
|
+
marker: number
|
|
17
|
+
/**
|
|
18
|
+
* Whether there are no internal spaces between marker characters
|
|
19
|
+
*/
|
|
20
|
+
continuous: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type IThis = ITokenizer
|
|
24
|
+
|
|
25
|
+
export type ITokenizerProps = Partial<IBaseBlockTokenizerProps>
|