@yozora/tokenizer-emphasis 2.0.0-alpha.0 → 2.0.0
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/README.md +4 -6
- package/lib/cjs/index.js +150 -142
- package/lib/esm/index.js +150 -144
- package/lib/types/index.d.ts +3 -1
- package/lib/types/match.d.ts +7 -0
- package/lib/types/parse.d.ts +3 -0
- package/lib/types/tokenizer.d.ts +4 -5
- package/lib/types/types.d.ts +4 -3
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -84,14 +84,14 @@ so you can use `YozoraParser` / `GfmExParser` / `GfmParser` directly.
|
|
|
84
84
|
registered in *YastParser* as a plugin-in before it can be used.
|
|
85
85
|
|
|
86
86
|
```typescript {4,9}
|
|
87
|
-
import {
|
|
87
|
+
import { DefaultParser } from '@yozora/core-parser'
|
|
88
88
|
import ParagraphTokenizer from '@yozora/tokenizer-paragraph'
|
|
89
89
|
import TextTokenizer from '@yozora/tokenizer-text'
|
|
90
90
|
import EmphasisTokenizer from '@yozora/tokenizer-emphasis'
|
|
91
91
|
|
|
92
|
-
const parser = new
|
|
93
|
-
.
|
|
94
|
-
.
|
|
92
|
+
const parser = new DefaultParser()
|
|
93
|
+
.useFallbackTokenizer(new ParagraphTokenizer())
|
|
94
|
+
.useFallbackTokenizer(new TextTokenizer())
|
|
95
95
|
.useTokenizer(new EmphasisTokenizer())
|
|
96
96
|
|
|
97
97
|
// parse source markdown content
|
|
@@ -265,7 +265,6 @@ Name | Type | Required | Default
|
|
|
265
265
|
[@yozora/tokenizer-link]: https://github.com/yozorajs/yozora/tree/main/tokenizers/link#readme
|
|
266
266
|
[@yozora/tokenizer-link-reference]: https://github.com/yozorajs/yozora/tree/main/tokenizers/link-reference#readme
|
|
267
267
|
[@yozora/tokenizer-list]: https://github.com/yozorajs/yozora/tree/main/tokenizers/list#readme
|
|
268
|
-
[@yozora/tokenizer-list-item]: https://github.com/yozorajs/yozora/tree/main/tokenizers/list-item#readme
|
|
269
268
|
[@yozora/tokenizer-math]: https://github.com/yozorajs/yozora/tree/main/tokenizers/math#readme
|
|
270
269
|
[@yozora/tokenizer-paragraph]: https://github.com/yozorajs/yozora/tree/main/tokenizers/paragraph#readme
|
|
271
270
|
[@yozora/tokenizer-setext-heading]: https://github.com/yozorajs/yozora/tree/main/tokenizers/setext-heading#readme
|
|
@@ -325,7 +324,6 @@ Name | Type | Required | Default
|
|
|
325
324
|
[doc-@yozora/tokenizer-definition]: https://yozora.guanghechen.com/docs/package/tokenizer-definition
|
|
326
325
|
[doc-@yozora/tokenizer-link-reference]: https://yozora.guanghechen.com/docs/package/tokenizer-link-reference
|
|
327
326
|
[doc-@yozora/tokenizer-list]: https://yozora.guanghechen.com/docs/package/tokenizer-list
|
|
328
|
-
[doc-@yozora/tokenizer-list-item]: https://yozora.guanghechen.com/docs/package/tokenizer-list-item
|
|
329
327
|
[doc-@yozora/tokenizer-math]: https://yozora.guanghechen.com/docs/package/tokenizer-math
|
|
330
328
|
[doc-@yozora/tokenizer-paragraph]: https://yozora.guanghechen.com/docs/package/tokenizer-paragraph
|
|
331
329
|
[doc-@yozora/tokenizer-setext-heading]: https://yozora.guanghechen.com/docs/package/tokenizer-setext-heading
|
package/lib/cjs/index.js
CHANGED
|
@@ -6,160 +6,168 @@ var ast = require('@yozora/ast');
|
|
|
6
6
|
var character = require('@yozora/character');
|
|
7
7
|
var coreTokenizer = require('@yozora/core-tokenizer');
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (c === character.AsciiCodePoint.UNDERSCORE) {
|
|
76
|
-
if (isLeftFlankingDelimiterRun && isRightFlankingDelimiterRun) {
|
|
77
|
-
if (_startIndex > startIndex &&
|
|
78
|
-
!character.isPunctuationCharacter(nodePoints[_startIndex - 1].codePoint)) {
|
|
79
|
-
isOpener = false;
|
|
80
|
-
}
|
|
81
|
-
const nextCodePosition = nodePoints[_endIndex];
|
|
82
|
-
if (!character.isPunctuationCharacter(nextCodePosition.codePoint)) {
|
|
83
|
-
isCloser = false;
|
|
84
|
-
}
|
|
85
|
-
}
|
|
9
|
+
const match = function (api) {
|
|
10
|
+
return {
|
|
11
|
+
findDelimiter: () => coreTokenizer.genFindDelimiter(_findDelimiter),
|
|
12
|
+
isDelimiterPair,
|
|
13
|
+
processDelimiterPair,
|
|
14
|
+
};
|
|
15
|
+
function _findDelimiter(startIndex, endIndex) {
|
|
16
|
+
const nodePoints = api.getNodePoints();
|
|
17
|
+
const blockStartIndex = api.getBlockStartIndex();
|
|
18
|
+
const blockEndIndex = api.getBlockEndIndex();
|
|
19
|
+
const isOpenerDelimiter = (delimiterStartIndex, delimiterEndIndex) => {
|
|
20
|
+
if (delimiterEndIndex === blockEndIndex)
|
|
21
|
+
return false;
|
|
22
|
+
if (delimiterEndIndex === endIndex)
|
|
23
|
+
return true;
|
|
24
|
+
const nextCodePosition = nodePoints[delimiterEndIndex];
|
|
25
|
+
if (character.isUnicodeWhitespaceCharacter(nextCodePosition.codePoint))
|
|
26
|
+
return false;
|
|
27
|
+
if (!character.isPunctuationCharacter(nextCodePosition.codePoint))
|
|
28
|
+
return true;
|
|
29
|
+
if (delimiterStartIndex <= startIndex)
|
|
30
|
+
return true;
|
|
31
|
+
const prevCodePosition = nodePoints[delimiterStartIndex - 1];
|
|
32
|
+
return (character.isUnicodeWhitespaceCharacter(prevCodePosition.codePoint) ||
|
|
33
|
+
character.isPunctuationCharacter(prevCodePosition.codePoint));
|
|
34
|
+
};
|
|
35
|
+
const isCloserDelimiter = (delimiterStartIndex, delimiterEndIndex) => {
|
|
36
|
+
if (delimiterStartIndex === blockStartIndex)
|
|
37
|
+
return false;
|
|
38
|
+
if (delimiterStartIndex === startIndex)
|
|
39
|
+
return true;
|
|
40
|
+
const prevCodePosition = nodePoints[delimiterStartIndex - 1];
|
|
41
|
+
if (character.isUnicodeWhitespaceCharacter(prevCodePosition.codePoint))
|
|
42
|
+
return false;
|
|
43
|
+
if (!character.isPunctuationCharacter(prevCodePosition.codePoint))
|
|
44
|
+
return true;
|
|
45
|
+
if (delimiterEndIndex >= endIndex)
|
|
46
|
+
return true;
|
|
47
|
+
const nextCodePosition = nodePoints[delimiterEndIndex];
|
|
48
|
+
return (character.isUnicodeWhitespaceCharacter(nextCodePosition.codePoint) ||
|
|
49
|
+
character.isPunctuationCharacter(nextCodePosition.codePoint));
|
|
50
|
+
};
|
|
51
|
+
for (let i = startIndex; i < endIndex; ++i) {
|
|
52
|
+
const c = nodePoints[i].codePoint;
|
|
53
|
+
switch (c) {
|
|
54
|
+
case character.AsciiCodePoint.BACKSLASH:
|
|
55
|
+
i += 1;
|
|
56
|
+
break;
|
|
57
|
+
case character.AsciiCodePoint.ASTERISK:
|
|
58
|
+
case character.AsciiCodePoint.UNDERSCORE: {
|
|
59
|
+
const _startIndex = i;
|
|
60
|
+
i = coreTokenizer.eatOptionalCharacters(nodePoints, i + 1, endIndex, c) - 1;
|
|
61
|
+
const _endIndex = i + 1;
|
|
62
|
+
const isLeftFlankingDelimiterRun = isOpenerDelimiter(_startIndex, _endIndex);
|
|
63
|
+
const isRightFlankingDelimiterRun = isCloserDelimiter(_startIndex, _endIndex);
|
|
64
|
+
let isOpener = isLeftFlankingDelimiterRun;
|
|
65
|
+
let isCloser = isRightFlankingDelimiterRun;
|
|
66
|
+
if (c === character.AsciiCodePoint.UNDERSCORE) {
|
|
67
|
+
if (isLeftFlankingDelimiterRun && isRightFlankingDelimiterRun) {
|
|
68
|
+
if (_startIndex > startIndex &&
|
|
69
|
+
!character.isPunctuationCharacter(nodePoints[_startIndex - 1].codePoint)) {
|
|
70
|
+
isOpener = false;
|
|
71
|
+
}
|
|
72
|
+
const nextCodePosition = nodePoints[_endIndex];
|
|
73
|
+
if (!character.isPunctuationCharacter(nextCodePosition.codePoint)) {
|
|
74
|
+
isCloser = false;
|
|
86
75
|
}
|
|
87
|
-
if (!isOpener && !isCloser)
|
|
88
|
-
break;
|
|
89
|
-
const thickness = _endIndex - _startIndex;
|
|
90
|
-
return {
|
|
91
|
-
type: isOpener ? (isCloser ? 'both' : 'opener') : 'closer',
|
|
92
|
-
startIndex: _startIndex,
|
|
93
|
-
endIndex: _endIndex,
|
|
94
|
-
thickness,
|
|
95
|
-
originalThickness: thickness,
|
|
96
|
-
};
|
|
97
76
|
}
|
|
98
77
|
}
|
|
78
|
+
if (!isOpener && !isCloser)
|
|
79
|
+
break;
|
|
80
|
+
const thickness = _endIndex - _startIndex;
|
|
81
|
+
return {
|
|
82
|
+
type: isOpener ? (isCloser ? 'both' : 'opener') : 'closer',
|
|
83
|
+
startIndex: _startIndex,
|
|
84
|
+
endIndex: _endIndex,
|
|
85
|
+
thickness,
|
|
86
|
+
originalThickness: thickness,
|
|
87
|
+
};
|
|
99
88
|
}
|
|
100
|
-
return null;
|
|
101
89
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
function isDelimiterPair(openerDelimiter, closerDelimiter) {
|
|
94
|
+
const nodePoints = api.getNodePoints();
|
|
95
|
+
if (nodePoints[openerDelimiter.startIndex].codePoint !==
|
|
96
|
+
nodePoints[closerDelimiter.startIndex].codePoint ||
|
|
97
|
+
((openerDelimiter.type === 'both' || closerDelimiter.type === 'both') &&
|
|
98
|
+
(openerDelimiter.originalThickness + closerDelimiter.originalThickness) % 3 === 0 &&
|
|
99
|
+
openerDelimiter.originalThickness % 3 !== 0)) {
|
|
100
|
+
return { paired: false, opener: true, closer: true };
|
|
101
|
+
}
|
|
102
|
+
return { paired: true };
|
|
103
|
+
}
|
|
104
|
+
function processDelimiterPair(openerDelimiter, closerDelimiter, internalTokens) {
|
|
105
|
+
let thickness = 1;
|
|
106
|
+
if (openerDelimiter.thickness > 1 && closerDelimiter.thickness > 1) {
|
|
107
|
+
thickness = 2;
|
|
108
|
+
}
|
|
109
|
+
internalTokens = api.resolveInternalTokens(internalTokens, openerDelimiter.endIndex, closerDelimiter.startIndex);
|
|
110
|
+
const token = {
|
|
111
|
+
nodeType: thickness === 1 ? ast.EmphasisType : ast.StrongType,
|
|
112
|
+
startIndex: openerDelimiter.endIndex - thickness,
|
|
113
|
+
endIndex: closerDelimiter.startIndex + thickness,
|
|
114
|
+
thickness,
|
|
115
|
+
children: internalTokens,
|
|
116
|
+
};
|
|
117
|
+
const remainOpenerDelimiter = openerDelimiter.thickness > thickness
|
|
118
|
+
? {
|
|
119
|
+
type: openerDelimiter.type,
|
|
120
|
+
startIndex: openerDelimiter.startIndex,
|
|
121
|
+
endIndex: openerDelimiter.endIndex - thickness,
|
|
122
|
+
thickness: openerDelimiter.thickness - thickness,
|
|
123
|
+
originalThickness: openerDelimiter.originalThickness,
|
|
112
124
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
startIndex: openerDelimiter.endIndex - thickness,
|
|
122
|
-
endIndex: closerDelimiter.startIndex + thickness,
|
|
123
|
-
thickness,
|
|
124
|
-
children: internalTokens,
|
|
125
|
-
};
|
|
126
|
-
const remainOpenerDelimiter = openerDelimiter.thickness > thickness
|
|
127
|
-
? {
|
|
128
|
-
type: openerDelimiter.type,
|
|
129
|
-
startIndex: openerDelimiter.startIndex,
|
|
130
|
-
endIndex: openerDelimiter.endIndex - thickness,
|
|
131
|
-
thickness: openerDelimiter.thickness - thickness,
|
|
132
|
-
originalThickness: openerDelimiter.originalThickness,
|
|
133
|
-
}
|
|
134
|
-
: undefined;
|
|
135
|
-
const remainCloserDelimiter = closerDelimiter.thickness > thickness
|
|
136
|
-
? {
|
|
137
|
-
type: closerDelimiter.type,
|
|
138
|
-
startIndex: closerDelimiter.startIndex + thickness,
|
|
139
|
-
endIndex: closerDelimiter.endIndex,
|
|
140
|
-
thickness: closerDelimiter.thickness - thickness,
|
|
141
|
-
originalThickness: closerDelimiter.originalThickness,
|
|
142
|
-
}
|
|
143
|
-
: undefined;
|
|
144
|
-
return {
|
|
145
|
-
tokens: [token],
|
|
146
|
-
remainOpenerDelimiter,
|
|
147
|
-
remainCloserDelimiter,
|
|
148
|
-
};
|
|
125
|
+
: undefined;
|
|
126
|
+
const remainCloserDelimiter = closerDelimiter.thickness > thickness
|
|
127
|
+
? {
|
|
128
|
+
type: closerDelimiter.type,
|
|
129
|
+
startIndex: closerDelimiter.startIndex + thickness,
|
|
130
|
+
endIndex: closerDelimiter.endIndex,
|
|
131
|
+
thickness: closerDelimiter.thickness - thickness,
|
|
132
|
+
originalThickness: closerDelimiter.originalThickness,
|
|
149
133
|
}
|
|
134
|
+
: undefined;
|
|
135
|
+
return {
|
|
136
|
+
tokens: [token],
|
|
137
|
+
remainOpenerDelimiter,
|
|
138
|
+
remainCloserDelimiter,
|
|
150
139
|
};
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const parse = function (api) {
|
|
144
|
+
return {
|
|
145
|
+
parse: tokens => tokens.map(token => {
|
|
146
|
+
const children = api.parseInlineTokens(token.children);
|
|
147
|
+
const node = api.shouldReservePosition
|
|
148
|
+
? { type: token.nodeType, position: api.calcPosition(token), children }
|
|
149
|
+
: { type: token.nodeType, children };
|
|
150
|
+
return node;
|
|
151
|
+
}),
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const uniqueName = '@yozora/tokenizer-emphasis';
|
|
156
|
+
|
|
157
|
+
class EmphasisTokenizer extends coreTokenizer.BaseInlineTokenizer {
|
|
158
|
+
constructor(props = {}) {
|
|
159
|
+
var _a, _b;
|
|
160
|
+
super({
|
|
161
|
+
name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
|
|
162
|
+
priority: (_b = props.priority) !== null && _b !== void 0 ? _b : coreTokenizer.TokenizerPriority.CONTAINING_INLINE,
|
|
159
163
|
});
|
|
164
|
+
this.match = match;
|
|
165
|
+
this.parse = parse;
|
|
160
166
|
}
|
|
161
167
|
}
|
|
162
168
|
|
|
163
169
|
exports.EmphasisTokenizer = EmphasisTokenizer;
|
|
164
170
|
exports.EmphasisTokenizerName = uniqueName;
|
|
165
171
|
exports["default"] = EmphasisTokenizer;
|
|
172
|
+
exports.emphasisMatch = match;
|
|
173
|
+
exports.emphasisParse = parse;
|
package/lib/esm/index.js
CHANGED
|
@@ -1,159 +1,165 @@
|
|
|
1
1
|
import { EmphasisType, StrongType } from '@yozora/ast';
|
|
2
2
|
import { AsciiCodePoint, isPunctuationCharacter, isUnicodeWhitespaceCharacter } from '@yozora/character';
|
|
3
|
-
import {
|
|
3
|
+
import { genFindDelimiter, eatOptionalCharacters, BaseInlineTokenizer, TokenizerPriority } from '@yozora/core-tokenizer';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (c === AsciiCodePoint.UNDERSCORE) {
|
|
72
|
-
if (isLeftFlankingDelimiterRun && isRightFlankingDelimiterRun) {
|
|
73
|
-
if (_startIndex > startIndex &&
|
|
74
|
-
!isPunctuationCharacter(nodePoints[_startIndex - 1].codePoint)) {
|
|
75
|
-
isOpener = false;
|
|
76
|
-
}
|
|
77
|
-
const nextCodePosition = nodePoints[_endIndex];
|
|
78
|
-
if (!isPunctuationCharacter(nextCodePosition.codePoint)) {
|
|
79
|
-
isCloser = false;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
5
|
+
const match = function (api) {
|
|
6
|
+
return {
|
|
7
|
+
findDelimiter: () => genFindDelimiter(_findDelimiter),
|
|
8
|
+
isDelimiterPair,
|
|
9
|
+
processDelimiterPair,
|
|
10
|
+
};
|
|
11
|
+
function _findDelimiter(startIndex, endIndex) {
|
|
12
|
+
const nodePoints = api.getNodePoints();
|
|
13
|
+
const blockStartIndex = api.getBlockStartIndex();
|
|
14
|
+
const blockEndIndex = api.getBlockEndIndex();
|
|
15
|
+
const isOpenerDelimiter = (delimiterStartIndex, delimiterEndIndex) => {
|
|
16
|
+
if (delimiterEndIndex === blockEndIndex)
|
|
17
|
+
return false;
|
|
18
|
+
if (delimiterEndIndex === endIndex)
|
|
19
|
+
return true;
|
|
20
|
+
const nextCodePosition = nodePoints[delimiterEndIndex];
|
|
21
|
+
if (isUnicodeWhitespaceCharacter(nextCodePosition.codePoint))
|
|
22
|
+
return false;
|
|
23
|
+
if (!isPunctuationCharacter(nextCodePosition.codePoint))
|
|
24
|
+
return true;
|
|
25
|
+
if (delimiterStartIndex <= startIndex)
|
|
26
|
+
return true;
|
|
27
|
+
const prevCodePosition = nodePoints[delimiterStartIndex - 1];
|
|
28
|
+
return (isUnicodeWhitespaceCharacter(prevCodePosition.codePoint) ||
|
|
29
|
+
isPunctuationCharacter(prevCodePosition.codePoint));
|
|
30
|
+
};
|
|
31
|
+
const isCloserDelimiter = (delimiterStartIndex, delimiterEndIndex) => {
|
|
32
|
+
if (delimiterStartIndex === blockStartIndex)
|
|
33
|
+
return false;
|
|
34
|
+
if (delimiterStartIndex === startIndex)
|
|
35
|
+
return true;
|
|
36
|
+
const prevCodePosition = nodePoints[delimiterStartIndex - 1];
|
|
37
|
+
if (isUnicodeWhitespaceCharacter(prevCodePosition.codePoint))
|
|
38
|
+
return false;
|
|
39
|
+
if (!isPunctuationCharacter(prevCodePosition.codePoint))
|
|
40
|
+
return true;
|
|
41
|
+
if (delimiterEndIndex >= endIndex)
|
|
42
|
+
return true;
|
|
43
|
+
const nextCodePosition = nodePoints[delimiterEndIndex];
|
|
44
|
+
return (isUnicodeWhitespaceCharacter(nextCodePosition.codePoint) ||
|
|
45
|
+
isPunctuationCharacter(nextCodePosition.codePoint));
|
|
46
|
+
};
|
|
47
|
+
for (let i = startIndex; i < endIndex; ++i) {
|
|
48
|
+
const c = nodePoints[i].codePoint;
|
|
49
|
+
switch (c) {
|
|
50
|
+
case AsciiCodePoint.BACKSLASH:
|
|
51
|
+
i += 1;
|
|
52
|
+
break;
|
|
53
|
+
case AsciiCodePoint.ASTERISK:
|
|
54
|
+
case AsciiCodePoint.UNDERSCORE: {
|
|
55
|
+
const _startIndex = i;
|
|
56
|
+
i = eatOptionalCharacters(nodePoints, i + 1, endIndex, c) - 1;
|
|
57
|
+
const _endIndex = i + 1;
|
|
58
|
+
const isLeftFlankingDelimiterRun = isOpenerDelimiter(_startIndex, _endIndex);
|
|
59
|
+
const isRightFlankingDelimiterRun = isCloserDelimiter(_startIndex, _endIndex);
|
|
60
|
+
let isOpener = isLeftFlankingDelimiterRun;
|
|
61
|
+
let isCloser = isRightFlankingDelimiterRun;
|
|
62
|
+
if (c === AsciiCodePoint.UNDERSCORE) {
|
|
63
|
+
if (isLeftFlankingDelimiterRun && isRightFlankingDelimiterRun) {
|
|
64
|
+
if (_startIndex > startIndex &&
|
|
65
|
+
!isPunctuationCharacter(nodePoints[_startIndex - 1].codePoint)) {
|
|
66
|
+
isOpener = false;
|
|
67
|
+
}
|
|
68
|
+
const nextCodePosition = nodePoints[_endIndex];
|
|
69
|
+
if (!isPunctuationCharacter(nextCodePosition.codePoint)) {
|
|
70
|
+
isCloser = false;
|
|
82
71
|
}
|
|
83
|
-
if (!isOpener && !isCloser)
|
|
84
|
-
break;
|
|
85
|
-
const thickness = _endIndex - _startIndex;
|
|
86
|
-
return {
|
|
87
|
-
type: isOpener ? (isCloser ? 'both' : 'opener') : 'closer',
|
|
88
|
-
startIndex: _startIndex,
|
|
89
|
-
endIndex: _endIndex,
|
|
90
|
-
thickness,
|
|
91
|
-
originalThickness: thickness,
|
|
92
|
-
};
|
|
93
72
|
}
|
|
94
73
|
}
|
|
74
|
+
if (!isOpener && !isCloser)
|
|
75
|
+
break;
|
|
76
|
+
const thickness = _endIndex - _startIndex;
|
|
77
|
+
return {
|
|
78
|
+
type: isOpener ? (isCloser ? 'both' : 'opener') : 'closer',
|
|
79
|
+
startIndex: _startIndex,
|
|
80
|
+
endIndex: _endIndex,
|
|
81
|
+
thickness,
|
|
82
|
+
originalThickness: thickness,
|
|
83
|
+
};
|
|
95
84
|
}
|
|
96
|
-
return null;
|
|
97
85
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
function isDelimiterPair(openerDelimiter, closerDelimiter) {
|
|
90
|
+
const nodePoints = api.getNodePoints();
|
|
91
|
+
if (nodePoints[openerDelimiter.startIndex].codePoint !==
|
|
92
|
+
nodePoints[closerDelimiter.startIndex].codePoint ||
|
|
93
|
+
((openerDelimiter.type === 'both' || closerDelimiter.type === 'both') &&
|
|
94
|
+
(openerDelimiter.originalThickness + closerDelimiter.originalThickness) % 3 === 0 &&
|
|
95
|
+
openerDelimiter.originalThickness % 3 !== 0)) {
|
|
96
|
+
return { paired: false, opener: true, closer: true };
|
|
97
|
+
}
|
|
98
|
+
return { paired: true };
|
|
99
|
+
}
|
|
100
|
+
function processDelimiterPair(openerDelimiter, closerDelimiter, internalTokens) {
|
|
101
|
+
let thickness = 1;
|
|
102
|
+
if (openerDelimiter.thickness > 1 && closerDelimiter.thickness > 1) {
|
|
103
|
+
thickness = 2;
|
|
104
|
+
}
|
|
105
|
+
internalTokens = api.resolveInternalTokens(internalTokens, openerDelimiter.endIndex, closerDelimiter.startIndex);
|
|
106
|
+
const token = {
|
|
107
|
+
nodeType: thickness === 1 ? EmphasisType : StrongType,
|
|
108
|
+
startIndex: openerDelimiter.endIndex - thickness,
|
|
109
|
+
endIndex: closerDelimiter.startIndex + thickness,
|
|
110
|
+
thickness,
|
|
111
|
+
children: internalTokens,
|
|
112
|
+
};
|
|
113
|
+
const remainOpenerDelimiter = openerDelimiter.thickness > thickness
|
|
114
|
+
? {
|
|
115
|
+
type: openerDelimiter.type,
|
|
116
|
+
startIndex: openerDelimiter.startIndex,
|
|
117
|
+
endIndex: openerDelimiter.endIndex - thickness,
|
|
118
|
+
thickness: openerDelimiter.thickness - thickness,
|
|
119
|
+
originalThickness: openerDelimiter.originalThickness,
|
|
108
120
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
startIndex: openerDelimiter.endIndex - thickness,
|
|
118
|
-
endIndex: closerDelimiter.startIndex + thickness,
|
|
119
|
-
thickness,
|
|
120
|
-
children: internalTokens,
|
|
121
|
-
};
|
|
122
|
-
const remainOpenerDelimiter = openerDelimiter.thickness > thickness
|
|
123
|
-
? {
|
|
124
|
-
type: openerDelimiter.type,
|
|
125
|
-
startIndex: openerDelimiter.startIndex,
|
|
126
|
-
endIndex: openerDelimiter.endIndex - thickness,
|
|
127
|
-
thickness: openerDelimiter.thickness - thickness,
|
|
128
|
-
originalThickness: openerDelimiter.originalThickness,
|
|
129
|
-
}
|
|
130
|
-
: undefined;
|
|
131
|
-
const remainCloserDelimiter = closerDelimiter.thickness > thickness
|
|
132
|
-
? {
|
|
133
|
-
type: closerDelimiter.type,
|
|
134
|
-
startIndex: closerDelimiter.startIndex + thickness,
|
|
135
|
-
endIndex: closerDelimiter.endIndex,
|
|
136
|
-
thickness: closerDelimiter.thickness - thickness,
|
|
137
|
-
originalThickness: closerDelimiter.originalThickness,
|
|
138
|
-
}
|
|
139
|
-
: undefined;
|
|
140
|
-
return {
|
|
141
|
-
tokens: [token],
|
|
142
|
-
remainOpenerDelimiter,
|
|
143
|
-
remainCloserDelimiter,
|
|
144
|
-
};
|
|
121
|
+
: undefined;
|
|
122
|
+
const remainCloserDelimiter = closerDelimiter.thickness > thickness
|
|
123
|
+
? {
|
|
124
|
+
type: closerDelimiter.type,
|
|
125
|
+
startIndex: closerDelimiter.startIndex + thickness,
|
|
126
|
+
endIndex: closerDelimiter.endIndex,
|
|
127
|
+
thickness: closerDelimiter.thickness - thickness,
|
|
128
|
+
originalThickness: closerDelimiter.originalThickness,
|
|
145
129
|
}
|
|
130
|
+
: undefined;
|
|
131
|
+
return {
|
|
132
|
+
tokens: [token],
|
|
133
|
+
remainOpenerDelimiter,
|
|
134
|
+
remainCloserDelimiter,
|
|
146
135
|
};
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const parse = function (api) {
|
|
140
|
+
return {
|
|
141
|
+
parse: tokens => tokens.map(token => {
|
|
142
|
+
const children = api.parseInlineTokens(token.children);
|
|
143
|
+
const node = api.shouldReservePosition
|
|
144
|
+
? { type: token.nodeType, position: api.calcPosition(token), children }
|
|
145
|
+
: { type: token.nodeType, children };
|
|
146
|
+
return node;
|
|
147
|
+
}),
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const uniqueName = '@yozora/tokenizer-emphasis';
|
|
152
|
+
|
|
153
|
+
class EmphasisTokenizer extends BaseInlineTokenizer {
|
|
154
|
+
constructor(props = {}) {
|
|
155
|
+
var _a, _b;
|
|
156
|
+
super({
|
|
157
|
+
name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
|
|
158
|
+
priority: (_b = props.priority) !== null && _b !== void 0 ? _b : TokenizerPriority.CONTAINING_INLINE,
|
|
155
159
|
});
|
|
160
|
+
this.match = match;
|
|
161
|
+
this.parse = parse;
|
|
156
162
|
}
|
|
157
163
|
}
|
|
158
164
|
|
|
159
|
-
export { EmphasisTokenizer, uniqueName as EmphasisTokenizerName, EmphasisTokenizer as default };
|
|
165
|
+
export { EmphasisTokenizer, uniqueName as EmphasisTokenizerName, EmphasisTokenizer as default, match as emphasisMatch, parse as emphasisParse };
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { match as emphasisMatch } from './match';
|
|
2
|
+
export { parse as emphasisParse } from './parse';
|
|
1
3
|
export { EmphasisTokenizer, EmphasisTokenizer as default } from './tokenizer';
|
|
2
4
|
export { uniqueName as EmphasisTokenizerName } from './types';
|
|
3
|
-
export type { IToken as IEmphasisToken, ITokenizerProps as IEmphasisTokenizerProps } from './types';
|
|
5
|
+
export type { IThis as IEmphasisHookContext, IToken as IEmphasisToken, ITokenizerProps as IEmphasisTokenizerProps, } from './types';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { IMatchInlineHookCreator } from '@yozora/core-tokenizer';
|
|
2
|
+
import type { IDelimiter, IThis, IToken, T } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* @see https://github.com/syntax-tree/mdast#strong
|
|
5
|
+
* @see https://github.github.com/gfm/#emphasis-and-strong-emphasis
|
|
6
|
+
*/
|
|
7
|
+
export declare const match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis>;
|
package/lib/types/tokenizer.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import type { IInlineTokenizer, IMatchInlineHookCreator, IParseInlineHookCreator } from '@yozora/core-tokenizer';
|
|
2
2
|
import { BaseInlineTokenizer } from '@yozora/core-tokenizer';
|
|
3
|
-
import type { IDelimiter, INode, IToken, ITokenizerProps, T } from './types';
|
|
3
|
+
import type { IDelimiter, INode, IThis, IToken, ITokenizerProps, T } from './types';
|
|
4
4
|
/**
|
|
5
5
|
* Lexical Analyzer for Emphasis and Strong Emphasis.
|
|
6
|
-
*
|
|
7
6
|
* @see https://github.com/syntax-tree/mdast#strong
|
|
8
7
|
* @see https://github.github.com/gfm/#emphasis-and-strong-emphasis
|
|
9
8
|
*/
|
|
10
|
-
export declare class EmphasisTokenizer extends BaseInlineTokenizer<T, IDelimiter, IToken, INode> implements IInlineTokenizer<T, IDelimiter, IToken, INode> {
|
|
9
|
+
export declare class EmphasisTokenizer extends BaseInlineTokenizer<T, IDelimiter, IToken, INode, IThis> implements IInlineTokenizer<T, IDelimiter, IToken, INode, IThis> {
|
|
11
10
|
constructor(props?: ITokenizerProps);
|
|
12
|
-
readonly match: IMatchInlineHookCreator<T, IDelimiter, IToken>;
|
|
13
|
-
readonly parse: IParseInlineHookCreator<T, IToken, INode>;
|
|
11
|
+
readonly match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis>;
|
|
12
|
+
readonly parse: IParseInlineHookCreator<T, IToken, INode, IThis>;
|
|
14
13
|
}
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { IBaseInlineTokenizerProps, IPartialYastInlineToken, IYastTokenDelimiter } from '@yozora/core-tokenizer';
|
|
1
|
+
import type { Emphasis, EmphasisType, Strong, StrongType } from '@yozora/ast';
|
|
2
|
+
import type { IBaseInlineTokenizerProps, IPartialYastInlineToken, ITokenizer, IYastTokenDelimiter } from '@yozora/core-tokenizer';
|
|
3
3
|
export declare type T = EmphasisType | StrongType;
|
|
4
|
-
export declare type INode =
|
|
4
|
+
export declare type INode = Emphasis | Strong;
|
|
5
5
|
export declare const uniqueName = "@yozora/tokenizer-emphasis";
|
|
6
6
|
export interface IToken extends IPartialYastInlineToken<T> {
|
|
7
7
|
/**
|
|
@@ -19,4 +19,5 @@ export interface IDelimiter extends IYastTokenDelimiter {
|
|
|
19
19
|
*/
|
|
20
20
|
originalThickness: number;
|
|
21
21
|
}
|
|
22
|
+
export declare type IThis = ITokenizer;
|
|
22
23
|
export declare type ITokenizerProps = Partial<IBaseInlineTokenizerProps>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-emphasis",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "guanghechen",
|
|
6
6
|
"url": "https://github.com/guanghechen/"
|
|
@@ -35,9 +35,9 @@
|
|
|
35
35
|
"test": "cross-env TS_NODE_FILES=true jest --config ../../jest.config.js --rootDir ."
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@yozora/ast": "^2.0.0
|
|
39
|
-
"@yozora/character": "^2.0.0
|
|
40
|
-
"@yozora/core-tokenizer": "^2.0.0
|
|
38
|
+
"@yozora/ast": "^2.0.0",
|
|
39
|
+
"@yozora/character": "^2.0.0",
|
|
40
|
+
"@yozora/core-tokenizer": "^2.0.0"
|
|
41
41
|
},
|
|
42
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "65e99d1709fdd1c918465dce6b1e91de96bdab5e"
|
|
43
43
|
}
|