@yozora/tokenizer-inline-math 2.1.3 → 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 +7 -7
- package/src/index.ts +0 -9
- package/src/match.ts +0 -172
- package/src/parse.ts +0 -53
- package/src/tokenizer.ts +0 -33
- package/src/types.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-inline-math",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "Tokenizer for processing inline math (formulas)",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "guanghechen",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"files": [
|
|
39
39
|
"lib/",
|
|
40
|
-
"
|
|
40
|
+
"lib/**/*.map",
|
|
41
41
|
"package.json",
|
|
42
42
|
"CHANGELOG.md",
|
|
43
43
|
"LICENSE",
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"test": "cross-env TS_NODE_FILES=true NODE_OPTIONS=--experimental-vm-modules jest --config ../../jest.config.mjs --rootDir ."
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@yozora/ast": "^2.1.
|
|
53
|
-
"@yozora/character": "^2.1.
|
|
54
|
-
"@yozora/core-tokenizer": "^2.1.
|
|
52
|
+
"@yozora/ast": "^2.1.4",
|
|
53
|
+
"@yozora/character": "^2.1.4",
|
|
54
|
+
"@yozora/core-tokenizer": "^2.1.4"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@yozora/tokenizer-inline-code": "^2.1.
|
|
57
|
+
"@yozora/tokenizer-inline-code": "^2.1.4"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "aa464ed1e3cd84892773a833910cfc53a556bf5f"
|
|
60
60
|
}
|
package/src/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { match as inlineMathMatch } from './match'
|
|
2
|
-
export { parse as inlineMathParse } from './parse'
|
|
3
|
-
export { InlineMathTokenizer, InlineMathTokenizer as default } from './tokenizer'
|
|
4
|
-
export { uniqueName as InlineMathTokenizerName } from './types'
|
|
5
|
-
export type {
|
|
6
|
-
IThis as IInlineMathHookContext,
|
|
7
|
-
IToken as IInlineMathToken,
|
|
8
|
-
ITokenizerProps as IInlineMathTokenizerProps,
|
|
9
|
-
} from './types'
|
package/src/match.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import { InlineMathType } from '@yozora/ast'
|
|
2
|
-
import type { INodeInterval, INodePoint } from '@yozora/character'
|
|
3
|
-
import { AsciiCodePoint } from '@yozora/character'
|
|
4
|
-
import type {
|
|
5
|
-
IMatchInlineHookCreator,
|
|
6
|
-
IResultOfFindDelimiters,
|
|
7
|
-
IResultOfProcessSingleDelimiter,
|
|
8
|
-
ITokenDelimiter,
|
|
9
|
-
} from '@yozora/core-tokenizer'
|
|
10
|
-
import { eatOptionalCharacters } from '@yozora/core-tokenizer'
|
|
11
|
-
import type { IDelimiter, IThis, IToken, T } from './types'
|
|
12
|
-
|
|
13
|
-
export const match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis> = function (api) {
|
|
14
|
-
const { backtickRequired } = this
|
|
15
|
-
return { findDelimiter, processSingleDelimiter }
|
|
16
|
-
|
|
17
|
-
function* findDelimiter(): IResultOfFindDelimiters<IDelimiter> {
|
|
18
|
-
const nodePoints: ReadonlyArray<INodePoint> = api.getNodePoints()
|
|
19
|
-
const blockStartIndex: number = api.getBlockStartIndex()
|
|
20
|
-
const blockEndIndex: number = api.getBlockEndIndex()
|
|
21
|
-
|
|
22
|
-
const potentialDelimiters: ITokenDelimiter[] = []
|
|
23
|
-
for (let i = blockStartIndex; i < blockEndIndex; ++i) {
|
|
24
|
-
const c = nodePoints[i].codePoint
|
|
25
|
-
switch (c) {
|
|
26
|
-
case AsciiCodePoint.BACKSLASH:
|
|
27
|
-
/**
|
|
28
|
-
* Note that unlink code spans, backslash escapes works in inline-math.
|
|
29
|
-
* @see https://github.github.com/gfm/#example-348
|
|
30
|
-
*/
|
|
31
|
-
i += 1
|
|
32
|
-
break
|
|
33
|
-
/**
|
|
34
|
-
* A backtick string is a string of one or more backtick characters '`'
|
|
35
|
-
* that is neither preceded nor followed by a backtick.
|
|
36
|
-
* A code span begins with a backtick string and ends with a
|
|
37
|
-
* backtick string of equal length.
|
|
38
|
-
* @see https://github.github.com/gfm/#backtick-string
|
|
39
|
-
* @see https://github.github.com/gfm/#code-span
|
|
40
|
-
*
|
|
41
|
-
* the left flanking string pattern is: <BACKTICK STRING><DOLLAR_SIGN>.
|
|
42
|
-
* eg: `$, ``$
|
|
43
|
-
*
|
|
44
|
-
* A backtick string is a string of one or more backtick
|
|
45
|
-
* characters '`' that is neither preceded nor followed by a backtick.
|
|
46
|
-
* @see https://github.github.com/gfm/#backtick-string
|
|
47
|
-
*/
|
|
48
|
-
case AsciiCodePoint.BACKTICK: {
|
|
49
|
-
const _startIndex = i
|
|
50
|
-
|
|
51
|
-
// matched as many backtick as possible
|
|
52
|
-
i = eatOptionalCharacters(nodePoints, i + 1, blockEndIndex, AsciiCodePoint.BACKTICK)
|
|
53
|
-
|
|
54
|
-
// No dollar character found after backtick string
|
|
55
|
-
if (i >= blockEndIndex || nodePoints[i].codePoint !== AsciiCodePoint.DOLLAR_SIGN) {
|
|
56
|
-
break
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const delimiter: ITokenDelimiter = {
|
|
60
|
-
type: 'opener',
|
|
61
|
-
startIndex: _startIndex,
|
|
62
|
-
endIndex: i + 1,
|
|
63
|
-
}
|
|
64
|
-
potentialDelimiters.push(delimiter)
|
|
65
|
-
break
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* the right flanking string pattern is: <DOLLAR_SIGN><BACKTICK STRING>.
|
|
69
|
-
* eg: $`, $``
|
|
70
|
-
*
|
|
71
|
-
* A backtick string is a string of one or more backtick characters '`'
|
|
72
|
-
* that is neither preceded nor followed by a backtick.
|
|
73
|
-
* @see https://github.github.com/gfm/#backtick-string
|
|
74
|
-
*/
|
|
75
|
-
case AsciiCodePoint.DOLLAR_SIGN: {
|
|
76
|
-
// matched as many backtick as possible
|
|
77
|
-
const _startIndex = i
|
|
78
|
-
i = eatOptionalCharacters(nodePoints, i + 1, blockEndIndex, AsciiCodePoint.BACKTICK)
|
|
79
|
-
|
|
80
|
-
// A dollar sign followed by a dollar sign is not part of a valid
|
|
81
|
-
// inlineMath delimiter
|
|
82
|
-
if (i < blockEndIndex && nodePoints[i].codePoint === AsciiCodePoint.DOLLAR_SIGN) {
|
|
83
|
-
break
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const thickness: number = i - _startIndex
|
|
87
|
-
|
|
88
|
-
// No backtick character found after dollar
|
|
89
|
-
if (thickness <= 1) {
|
|
90
|
-
if (backtickRequired) break
|
|
91
|
-
const delimiter: ITokenDelimiter = {
|
|
92
|
-
type: 'both',
|
|
93
|
-
startIndex: _startIndex,
|
|
94
|
-
endIndex: i,
|
|
95
|
-
}
|
|
96
|
-
potentialDelimiters.push(delimiter)
|
|
97
|
-
break
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const delimiter: ITokenDelimiter = {
|
|
101
|
-
type: 'closer',
|
|
102
|
-
startIndex: _startIndex,
|
|
103
|
-
endIndex: i,
|
|
104
|
-
}
|
|
105
|
-
potentialDelimiters.push(delimiter)
|
|
106
|
-
i -= 1
|
|
107
|
-
break
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
let pIndex = 0
|
|
113
|
-
let lastEndIndex = -1
|
|
114
|
-
let delimiter: IDelimiter | null = null
|
|
115
|
-
while (pIndex < potentialDelimiters.length) {
|
|
116
|
-
const [startIndex, endIndex] = yield delimiter
|
|
117
|
-
|
|
118
|
-
// Read from cache.
|
|
119
|
-
if (lastEndIndex === endIndex) {
|
|
120
|
-
if (delimiter == null || delimiter.startIndex >= startIndex) continue
|
|
121
|
-
}
|
|
122
|
-
lastEndIndex = endIndex
|
|
123
|
-
|
|
124
|
-
let openerDelimiter: INodeInterval | null = null
|
|
125
|
-
let closerDelimiter: INodeInterval | null = null
|
|
126
|
-
for (; pIndex < potentialDelimiters.length; ++pIndex) {
|
|
127
|
-
for (; pIndex < potentialDelimiters.length; ++pIndex) {
|
|
128
|
-
const delimiter = potentialDelimiters[pIndex]
|
|
129
|
-
if (delimiter.startIndex >= startIndex && delimiter.type !== 'closer') break
|
|
130
|
-
}
|
|
131
|
-
if (pIndex + 1 >= potentialDelimiters.length) break
|
|
132
|
-
|
|
133
|
-
openerDelimiter = potentialDelimiters[pIndex]
|
|
134
|
-
const thickness = openerDelimiter.endIndex - openerDelimiter.startIndex
|
|
135
|
-
for (let i = pIndex + 1; i < potentialDelimiters.length; ++i) {
|
|
136
|
-
const delimiter = potentialDelimiters[i]
|
|
137
|
-
if (
|
|
138
|
-
delimiter.type !== 'opener' &&
|
|
139
|
-
delimiter.endIndex - delimiter.startIndex === thickness
|
|
140
|
-
) {
|
|
141
|
-
closerDelimiter = delimiter
|
|
142
|
-
break
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// No matched inlineCode closer marker found, try next one.
|
|
147
|
-
if (closerDelimiter != null) break
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (closerDelimiter == null) return
|
|
151
|
-
|
|
152
|
-
delimiter = {
|
|
153
|
-
type: 'full',
|
|
154
|
-
startIndex: openerDelimiter!.startIndex,
|
|
155
|
-
endIndex: closerDelimiter.endIndex,
|
|
156
|
-
thickness: closerDelimiter.endIndex - closerDelimiter.startIndex,
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function processSingleDelimiter(
|
|
162
|
-
delimiter: IDelimiter,
|
|
163
|
-
): IResultOfProcessSingleDelimiter<T, IToken> {
|
|
164
|
-
const token: IToken = {
|
|
165
|
-
nodeType: InlineMathType,
|
|
166
|
-
startIndex: delimiter.startIndex,
|
|
167
|
-
endIndex: delimiter.endIndex,
|
|
168
|
-
thickness: delimiter.thickness,
|
|
169
|
-
}
|
|
170
|
-
return [token]
|
|
171
|
-
}
|
|
172
|
-
}
|
package/src/parse.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { InlineMathType } from '@yozora/ast'
|
|
2
|
-
import type { INodePoint } from '@yozora/character'
|
|
3
|
-
import { calcStringFromNodePoints, isSpaceLike } from '@yozora/character'
|
|
4
|
-
import type { IParseInlineHookCreator } from '@yozora/core-tokenizer'
|
|
5
|
-
import type { INode, IThis, IToken, T } from './types'
|
|
6
|
-
|
|
7
|
-
export const parse: IParseInlineHookCreator<T, IToken, INode, IThis> = function (api) {
|
|
8
|
-
return {
|
|
9
|
-
parse: tokens =>
|
|
10
|
-
tokens.map(token => {
|
|
11
|
-
const nodePoints: ReadonlyArray<INodePoint> = api.getNodePoints()
|
|
12
|
-
let startIndex: number = token.startIndex + token.thickness
|
|
13
|
-
let endIndex: number = token.endIndex - token.thickness
|
|
14
|
-
|
|
15
|
-
let isAllSpace = true
|
|
16
|
-
for (let i = startIndex; i < endIndex; ++i) {
|
|
17
|
-
if (isSpaceLike(nodePoints[i].codePoint)) continue
|
|
18
|
-
isAllSpace = false
|
|
19
|
-
break
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* If the resulting string both begins and ends with a space character,
|
|
24
|
-
* but doesn't consist entirely of space characters, a single space
|
|
25
|
-
* character is removed from the front and back. This allows you to
|
|
26
|
-
* include code that begins or endsWith backtick characters, which must
|
|
27
|
-
* be separated by whitespace from the opening or closing backtick strings.
|
|
28
|
-
* @see https://github.github.com/gfm/#example-340
|
|
29
|
-
*
|
|
30
|
-
* Only spaces, and not unicode whitespace in general, are stripped
|
|
31
|
-
* in this way
|
|
32
|
-
* @see https://github.github.com/gfm/#example-343
|
|
33
|
-
*
|
|
34
|
-
* No stripping occurs if the code span contains only spaces
|
|
35
|
-
* @see https://github.github.com/gfm/#example-344
|
|
36
|
-
*/
|
|
37
|
-
if (!isAllSpace && startIndex + 2 < endIndex) {
|
|
38
|
-
const firstCharacter = nodePoints[startIndex].codePoint
|
|
39
|
-
const lastCharacter = nodePoints[endIndex - 1].codePoint
|
|
40
|
-
if (isSpaceLike(firstCharacter) && isSpaceLike(lastCharacter)) {
|
|
41
|
-
startIndex += 1
|
|
42
|
-
endIndex -= 1
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex).replace(/\n/g, ' ')
|
|
47
|
-
const node: INode = api.shouldReservePosition
|
|
48
|
-
? { type: InlineMathType, position: api.calcPosition(token), value }
|
|
49
|
-
: { type: InlineMathType, value }
|
|
50
|
-
return node
|
|
51
|
-
}),
|
|
52
|
-
}
|
|
53
|
-
}
|
package/src/tokenizer.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
IInlineTokenizer,
|
|
3
|
-
IMatchInlineHookCreator,
|
|
4
|
-
IParseInlineHookCreator,
|
|
5
|
-
} from '@yozora/core-tokenizer'
|
|
6
|
-
import { BaseInlineTokenizer, TokenizerPriority } from '@yozora/core-tokenizer'
|
|
7
|
-
import { match } from './match'
|
|
8
|
-
import { parse } from './parse'
|
|
9
|
-
import type { IDelimiter, INode, IThis, IToken, ITokenizerProps, T } from './types'
|
|
10
|
-
import { uniqueName } from './types'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Lexical Analyzer for inlineMath.
|
|
14
|
-
*/
|
|
15
|
-
export class InlineMathTokenizer
|
|
16
|
-
extends BaseInlineTokenizer<T, IDelimiter, IToken, INode, IThis>
|
|
17
|
-
implements IInlineTokenizer<T, IDelimiter, IToken, INode, IThis>
|
|
18
|
-
{
|
|
19
|
-
public readonly backtickRequired: boolean
|
|
20
|
-
|
|
21
|
-
/* istanbul ignore next */
|
|
22
|
-
constructor(props: ITokenizerProps = {}) {
|
|
23
|
-
super({
|
|
24
|
-
name: props.name ?? uniqueName,
|
|
25
|
-
priority: props.priority ?? TokenizerPriority.ATOMIC,
|
|
26
|
-
})
|
|
27
|
-
this.backtickRequired = props.backtickRequired ?? true
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public override readonly match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis> = match
|
|
31
|
-
|
|
32
|
-
public override readonly parse: IParseInlineHookCreator<T, IToken, INode, IThis> = parse
|
|
33
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { InlineMath, InlineMathType } from '@yozora/ast'
|
|
2
|
-
import type {
|
|
3
|
-
IBaseInlineTokenizerProps,
|
|
4
|
-
IPartialInlineToken,
|
|
5
|
-
ITokenDelimiter,
|
|
6
|
-
ITokenizer,
|
|
7
|
-
} from '@yozora/core-tokenizer'
|
|
8
|
-
|
|
9
|
-
export type T = InlineMathType
|
|
10
|
-
export type INode = InlineMath
|
|
11
|
-
export const uniqueName = '@yozora/tokenizer-inline-math'
|
|
12
|
-
|
|
13
|
-
export interface IToken extends IPartialInlineToken<T> {
|
|
14
|
-
/**
|
|
15
|
-
* Thickness of the InlineMathDelimiter
|
|
16
|
-
*/
|
|
17
|
-
thickness: number
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* IDelimiter of InlineMathToken.
|
|
22
|
-
*/
|
|
23
|
-
export interface IDelimiter extends ITokenDelimiter {
|
|
24
|
-
type: 'full'
|
|
25
|
-
/**
|
|
26
|
-
* Thickness of the InlineMathDelimiter
|
|
27
|
-
*/
|
|
28
|
-
thickness: number
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface IThis extends ITokenizer {
|
|
32
|
-
/**
|
|
33
|
-
* Whether if the backtick mark wrapping necessary.
|
|
34
|
-
*/
|
|
35
|
-
readonly backtickRequired: boolean
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface ITokenizerProps extends Partial<IBaseInlineTokenizerProps> {
|
|
39
|
-
/**
|
|
40
|
-
* Whether if the backtick mark wrapping necessary.
|
|
41
|
-
* @default true
|
|
42
|
-
*/
|
|
43
|
-
readonly backtickRequired?: boolean
|
|
44
|
-
}
|