@yozora/tokenizer-inline-math 2.0.4 → 2.0.5-alpha.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.
@@ -150,20 +150,20 @@ const parse = function (api) {
150
150
  const uniqueName = '@yozora/tokenizer-inline-math';
151
151
 
152
152
  class InlineMathTokenizer extends coreTokenizer.BaseInlineTokenizer {
153
+ backtickRequired;
153
154
  constructor(props = {}) {
154
- var _a, _b, _c;
155
155
  super({
156
- name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
157
- priority: (_b = props.priority) !== null && _b !== void 0 ? _b : coreTokenizer.TokenizerPriority.ATOMIC,
156
+ name: props.name ?? uniqueName,
157
+ priority: props.priority ?? coreTokenizer.TokenizerPriority.ATOMIC,
158
158
  });
159
- this.match = match;
160
- this.parse = parse;
161
- this.backtickRequired = (_c = props.backtickRequired) !== null && _c !== void 0 ? _c : true;
159
+ this.backtickRequired = props.backtickRequired ?? true;
162
160
  }
161
+ match = match;
162
+ parse = parse;
163
163
  }
164
164
 
165
165
  exports.InlineMathTokenizer = InlineMathTokenizer;
166
166
  exports.InlineMathTokenizerName = uniqueName;
167
- exports["default"] = InlineMathTokenizer;
167
+ exports.default = InlineMathTokenizer;
168
168
  exports.inlineMathMatch = match;
169
169
  exports.inlineMathParse = parse;
@@ -146,16 +146,16 @@ const parse = function (api) {
146
146
  const uniqueName = '@yozora/tokenizer-inline-math';
147
147
 
148
148
  class InlineMathTokenizer extends BaseInlineTokenizer {
149
+ backtickRequired;
149
150
  constructor(props = {}) {
150
- var _a, _b, _c;
151
151
  super({
152
- name: (_a = props.name) !== null && _a !== void 0 ? _a : uniqueName,
153
- priority: (_b = props.priority) !== null && _b !== void 0 ? _b : TokenizerPriority.ATOMIC,
152
+ name: props.name ?? uniqueName,
153
+ priority: props.priority ?? TokenizerPriority.ATOMIC,
154
154
  });
155
- this.match = match;
156
- this.parse = parse;
157
- this.backtickRequired = (_c = props.backtickRequired) !== null && _c !== void 0 ? _c : true;
155
+ this.backtickRequired = props.backtickRequired ?? true;
158
156
  }
157
+ match = match;
158
+ parse = parse;
159
159
  }
160
160
 
161
161
  export { InlineMathTokenizer, uniqueName as InlineMathTokenizerName, InlineMathTokenizer as default, match as inlineMathMatch, parse as inlineMathParse };
@@ -1,8 +1,8 @@
1
1
  import { IPartialYastInlineToken, ITokenizer, IBaseInlineTokenizerProps, IYastTokenDelimiter, IMatchInlineHookCreator, IParseInlineHookCreator, BaseInlineTokenizer, IInlineTokenizer } from '@yozora/core-tokenizer';
2
2
  import { InlineMathType, InlineMath } from '@yozora/ast';
3
3
 
4
- declare type T = InlineMathType;
5
- declare type INode = InlineMath;
4
+ type T = InlineMathType;
5
+ type INode = InlineMath;
6
6
  declare const uniqueName = "@yozora/tokenizer-inline-math";
7
7
  interface IToken extends IPartialYastInlineToken<T> {
8
8
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yozora/tokenizer-inline-math",
3
- "version": "2.0.4",
3
+ "version": "2.0.5-alpha.0",
4
4
  "description": "Tokenizer for processing inline math (formulas)",
5
5
  "author": {
6
6
  "name": "guanghechen",
@@ -21,36 +21,40 @@
21
21
  "inline formula",
22
22
  "inline math"
23
23
  ],
24
- "main": "lib/cjs/index.js",
25
- "module": "lib/esm/index.js",
26
- "types": "lib/types/index.d.ts",
27
- "source": "src/index.ts",
24
+ "type": "module",
25
+ "exports": {
26
+ "types": "./lib/types/index.d.ts",
27
+ "import": "./lib/esm/index.mjs",
28
+ "require": "./lib/cjs/index.cjs"
29
+ },
30
+ "source": "./src/index.ts",
31
+ "types": "./lib/types/index.d.ts",
32
+ "main": "./lib/cjs/index.cjs",
33
+ "module": "./lib/esm/index.mjs",
28
34
  "license": "MIT",
29
35
  "engines": {
30
36
  "node": ">= 16.0.0"
31
37
  },
32
38
  "files": [
33
39
  "lib/",
34
- "!lib/**/*.js.map",
35
- "!lib/**/*.d.ts.map",
40
+ "src/",
36
41
  "package.json",
37
42
  "CHANGELOG.md",
38
43
  "LICENSE",
39
44
  "README.md"
40
45
  ],
41
46
  "scripts": {
42
- "build": "cross-env NODE_ENV=production rollup -c ../../rollup.config.js",
43
- "prebuild": "rimraf lib/",
47
+ "build": "rimraf lib/ && cross-env NODE_ENV=production rollup -c ../../rollup.config.mjs",
44
48
  "prepublishOnly": "cross-env ROLLUP_SHOULD_SOURCEMAP=false yarn build",
45
- "test": "cross-env TS_NODE_FILES=true jest --config ../../jest.config.js --rootDir ."
49
+ "test": "cross-env TS_NODE_FILES=true NODE_OPTIONS=--experimental-vm-modules jest --config ../../jest.config.mjs --rootDir ."
46
50
  },
47
51
  "dependencies": {
48
- "@yozora/ast": "^2.0.4",
49
- "@yozora/character": "^2.0.4",
50
- "@yozora/core-tokenizer": "^2.0.4"
52
+ "@yozora/ast": "^2.0.5-alpha.0",
53
+ "@yozora/character": "^2.0.5-alpha.0",
54
+ "@yozora/core-tokenizer": "^2.0.5-alpha.0"
51
55
  },
52
56
  "devDependencies": {
53
- "@yozora/tokenizer-inline-code": "^2.0.4"
57
+ "@yozora/tokenizer-inline-code": "^2.0.5-alpha.0"
54
58
  },
55
- "gitHead": "c980b95254394dcacba0cbb4bea251350b09397c"
59
+ "gitHead": "8bf941fe4ef82947165b0f3cc123cd493665e13b"
56
60
  }
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
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 ADDED
@@ -0,0 +1,172 @@
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
+ IYastTokenDelimiter,
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: IYastTokenDelimiter[] = []
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: IYastTokenDelimiter = {
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: IYastTokenDelimiter = {
92
+ type: 'both',
93
+ startIndex: _startIndex,
94
+ endIndex: i,
95
+ }
96
+ potentialDelimiters.push(delimiter)
97
+ break
98
+ }
99
+
100
+ const delimiter: IYastTokenDelimiter = {
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 ADDED
@@ -0,0 +1,53 @@
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
+ }
@@ -0,0 +1,33 @@
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 ADDED
@@ -0,0 +1,44 @@
1
+ import type { InlineMath, InlineMathType } from '@yozora/ast'
2
+ import type {
3
+ IBaseInlineTokenizerProps,
4
+ IPartialYastInlineToken,
5
+ ITokenizer,
6
+ IYastTokenDelimiter,
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 IPartialYastInlineToken<T> {
14
+ /**
15
+ * Thickness of the InlineMathDelimiter
16
+ */
17
+ thickness: number
18
+ }
19
+
20
+ /**
21
+ * IDelimiter of InlineMathToken.
22
+ */
23
+ export interface IDelimiter extends IYastTokenDelimiter {
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
+ }