@yozora/tokenizer-html-inline 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yozora/tokenizer-html-inline",
3
- "version": "2.1.2",
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
- "src/",
30
+ "lib/**/*.map",
31
31
  "package.json",
32
32
  "CHANGELOG.md",
33
33
  "LICENSE",
@@ -39,10 +39,10 @@
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.2",
43
- "@yozora/character": "^2.1.2",
44
- "@yozora/core-tokenizer": "^2.1.2",
45
- "@yozora/tokenizer-html-block": "^2.1.2"
42
+ "@yozora/ast": "^2.1.4",
43
+ "@yozora/character": "^2.1.4",
44
+ "@yozora/core-tokenizer": "^2.1.4",
45
+ "@yozora/tokenizer-html-block": "^2.1.4"
46
46
  },
47
- "gitHead": "992bacafd173e7788e99fed34ce8b45f6ed24cfe"
47
+ "gitHead": "aa464ed1e3cd84892773a833910cfc53a556bf5f"
48
48
  }
package/src/index.ts DELETED
@@ -1,15 +0,0 @@
1
- export * from './util/cdata'
2
- export * from './util/closing'
3
- export * from './util/comment'
4
- export * from './util/declaration'
5
- export * from './util/instruction'
6
- export * from './util/open'
7
- export { match as htmlInlineMatch } from './match'
8
- export { parse as htmlInlineParse } from './parse'
9
- export { HtmlInlineTokenizer, HtmlInlineTokenizer as default } from './tokenizer'
10
- export { uniqueName as HtmlInlineTokenizerName } from './types'
11
- export type {
12
- IThis as IHtmlInlineHookContext,
13
- IToken as IHtmlInlineToken,
14
- ITokenizerProps as IHtmlInlineTokenizerProps,
15
- } from './types'
package/src/match.ts DELETED
@@ -1,101 +0,0 @@
1
- import { HtmlType } from '@yozora/ast'
2
- import type { INodePoint } from '@yozora/character'
3
- import { AsciiCodePoint } from '@yozora/character'
4
- import type {
5
- IMatchInlineHookCreator,
6
- IResultOfProcessSingleDelimiter,
7
- } from '@yozora/core-tokenizer'
8
- import { eatOptionalWhitespaces, genFindDelimiter } from '@yozora/core-tokenizer'
9
- import type { IDelimiter, IThis, IToken, T } from './types'
10
- import { eatHtmlInlineCDataDelimiter } from './util/cdata'
11
- import { eatHtmlInlineClosingDelimiter } from './util/closing'
12
- import { eatHtmlInlineCommentDelimiter } from './util/comment'
13
- import { eatHtmlInlineDeclarationDelimiter } from './util/declaration'
14
- import { eatHtmlInlineInstructionDelimiter } from './util/instruction'
15
- import { eatHtmlInlineTokenOpenDelimiter } from './util/open'
16
-
17
- /**
18
- * Text between '<' and '>' that looks like an HTML tag is parsed as a raw HTML
19
- * tag and will be rendered in HTML without escaping. Tag and attribute names
20
- * are not limited to current HTML tags, so custom tags (and even, say, DocBook
21
- * tags) may be used.
22
- *
23
- * @see https://github.github.com/gfm/#raw-html
24
- */
25
- export const match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis> = function (api) {
26
- return {
27
- findDelimiter: () => genFindDelimiter<IDelimiter>(_findDelimiter),
28
- processSingleDelimiter,
29
- }
30
-
31
- function _findDelimiter(startIndex: number, endIndex: number): IDelimiter | null {
32
- const nodePoints: ReadonlyArray<INodePoint> = api.getNodePoints()
33
-
34
- for (let i = startIndex; i < endIndex; ++i) {
35
- i = eatOptionalWhitespaces(nodePoints, i, endIndex)
36
- if (i >= endIndex) break
37
-
38
- const c = nodePoints[i].codePoint
39
- switch (c) {
40
- case AsciiCodePoint.BACKSLASH:
41
- i += 1
42
- break
43
- case AsciiCodePoint.OPEN_ANGLE: {
44
- const delimiter: IDelimiter | null = tryToEatDelimiter(nodePoints, i, endIndex)
45
- if (delimiter != null) return delimiter
46
- break
47
- }
48
- }
49
- }
50
- return null
51
- }
52
-
53
- function processSingleDelimiter(
54
- delimiter: IDelimiter,
55
- ): IResultOfProcessSingleDelimiter<T, IToken> {
56
- const token: IToken = {
57
- ...delimiter,
58
- nodeType: HtmlType,
59
- }
60
- return [token]
61
- }
62
- }
63
-
64
- /**
65
- * Try to eat a delimiter
66
- *
67
- * @param nodePoints
68
- * @param startIndex
69
- * @param endIndex
70
- */
71
- function tryToEatDelimiter(
72
- nodePoints: ReadonlyArray<INodePoint>,
73
- startIndex: number,
74
- endIndex: number,
75
- ): IDelimiter | null {
76
- let delimiter: IDelimiter | null = null
77
-
78
- // Try open tag.
79
- delimiter = eatHtmlInlineTokenOpenDelimiter(nodePoints, startIndex, endIndex)
80
- if (delimiter != null) return delimiter
81
-
82
- // Try closing tag.
83
- delimiter = eatHtmlInlineClosingDelimiter(nodePoints, startIndex, endIndex)
84
- if (delimiter != null) return delimiter
85
-
86
- // Try html comment.
87
- delimiter = eatHtmlInlineCommentDelimiter(nodePoints, startIndex, endIndex)
88
- if (delimiter != null) return delimiter
89
-
90
- // Try processing instruction.
91
- delimiter = eatHtmlInlineInstructionDelimiter(nodePoints, startIndex, endIndex)
92
- if (delimiter != null) return delimiter
93
-
94
- // Try declaration.
95
- delimiter = eatHtmlInlineDeclarationDelimiter(nodePoints, startIndex, endIndex)
96
- if (delimiter != null) return delimiter
97
-
98
- // Try CDATA section.
99
- delimiter = eatHtmlInlineCDataDelimiter(nodePoints, startIndex, endIndex)
100
- return delimiter
101
- }
package/src/parse.ts DELETED
@@ -1,20 +0,0 @@
1
- import { HtmlType } from '@yozora/ast'
2
- import type { INodePoint } from '@yozora/character'
3
- import { calcStringFromNodePoints } 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 { startIndex, endIndex } = token
12
- const nodePoints: ReadonlyArray<INodePoint> = api.getNodePoints()
13
- const value = calcStringFromNodePoints(nodePoints, startIndex, endIndex)
14
- const node: INode = api.shouldReservePosition
15
- ? { type: HtmlType, position: api.calcPosition(token), value }
16
- : { type: HtmlType, value }
17
- return node
18
- }),
19
- }
20
- }
package/src/tokenizer.ts DELETED
@@ -1,37 +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 HtmlInline.
14
- *
15
- * Text between '<' and '>' that looks like an HTML tag is parsed as a raw HTML
16
- * tag and will be rendered in HTML without escaping. Tag and attribute names
17
- * are not limited to current HTML tags, so custom tags (and even, say, DocBook
18
- * tags) may be used.
19
- *
20
- * @see https://github.github.com/gfm/#raw-html
21
- */
22
- export class HtmlInlineTokenizer
23
- extends BaseInlineTokenizer<T, IDelimiter, IToken, INode, IThis>
24
- implements IInlineTokenizer<T, IDelimiter, IToken, INode, IThis>
25
- {
26
- /* istanbul ignore next */
27
- constructor(props: ITokenizerProps = {}) {
28
- super({
29
- name: props.name ?? uniqueName,
30
- priority: props.priority ?? TokenizerPriority.ATOMIC,
31
- })
32
- }
33
-
34
- public override readonly match: IMatchInlineHookCreator<T, IDelimiter, IToken, IThis> = match
35
-
36
- public override readonly parse: IParseInlineHookCreator<T, IToken, INode, IThis> = parse
37
- }
package/src/types.ts DELETED
@@ -1,52 +0,0 @@
1
- import type { Html, HtmlType } from '@yozora/ast'
2
- import type {
3
- IBaseInlineTokenizerProps,
4
- IPartialInlineToken,
5
- ITokenizer,
6
- } from '@yozora/core-tokenizer'
7
- import type { IHtmlInlineCDataDelimiter, IHtmlInlineCDataTokenData } from './util/cdata'
8
- import type { IHtmlInlineClosingDelimiter, IHtmlInlineClosingTokenData } from './util/closing'
9
- import type { IHtmlInlineCommentDelimiter, IHtmlInlineCommentTokenData } from './util/comment'
10
- import type {
11
- IHtmlInlineDeclarationDelimiter,
12
- IHtmlInlineDeclarationTokenData,
13
- } from './util/declaration'
14
- import type {
15
- IHtmlInlineInstructionDelimiter,
16
- IHtmlInlineInstructionTokenData,
17
- } from './util/instruction'
18
- import type { IHtmlInlineOpenDelimiter, IHtmlInlineOpenTokenData } from './util/open'
19
-
20
- export type T = HtmlType
21
- export type INode = Html
22
- export const uniqueName = '@yozora/tokenizer-html-inline'
23
-
24
- /**
25
- * Text between '<' and '>' that looks like an HTML tag is parsed as a raw
26
- * HTML tag and will be rendered in HTML without escaping. Tag and attribute
27
- * names are not limited to current HTML tags, so custom tags (and even, say,
28
- * DocBook tags) may be used.
29
- *
30
- * @see https://github.github.com/gfm/#raw-html
31
- */
32
- export type IToken = IPartialInlineToken<T> &
33
- (
34
- | IHtmlInlineOpenTokenData
35
- | IHtmlInlineClosingTokenData
36
- | IHtmlInlineCommentTokenData
37
- | IHtmlInlineInstructionTokenData
38
- | IHtmlInlineDeclarationTokenData
39
- | IHtmlInlineCDataTokenData
40
- )
41
-
42
- export type IDelimiter =
43
- | IHtmlInlineOpenDelimiter
44
- | IHtmlInlineClosingDelimiter
45
- | IHtmlInlineCommentDelimiter
46
- | IHtmlInlineInstructionDelimiter
47
- | IHtmlInlineDeclarationDelimiter
48
- | IHtmlInlineCDataDelimiter
49
-
50
- export type IThis = ITokenizer
51
-
52
- export type ITokenizerProps = Partial<IBaseInlineTokenizerProps>
package/src/util/cdata.ts DELETED
@@ -1,64 +0,0 @@
1
- import type { INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
-
5
- export interface IHtmlInlineCDataData {
6
- htmlType: 'cdata'
7
- }
8
-
9
- export interface IHtmlInlineCDataTokenData {
10
- htmlType: 'cdata'
11
- }
12
-
13
- export interface IHtmlInlineCDataDelimiter extends ITokenDelimiter, IHtmlInlineCDataTokenData {
14
- type: 'full'
15
- }
16
-
17
- /**
18
- * A CDATA section consists of the string `<![CDATA[`, a string of characters
19
- * not including the string `]]>`, and the string `]]>`.
20
- *
21
- * @param nodePoints
22
- * @param startIndex
23
- * @param endIndex
24
- * @see https://github.github.com/gfm/#cdata-section
25
- */
26
- export function eatHtmlInlineCDataDelimiter(
27
- nodePoints: ReadonlyArray<INodePoint>,
28
- startIndex: number,
29
- endIndex: number,
30
- ): IHtmlInlineCDataDelimiter | null {
31
- let i = startIndex
32
- if (
33
- i + 11 >= endIndex ||
34
- nodePoints[i + 1].codePoint !== AsciiCodePoint.EXCLAMATION_MARK ||
35
- nodePoints[i + 2].codePoint !== AsciiCodePoint.OPEN_BRACKET ||
36
- nodePoints[i + 3].codePoint !== AsciiCodePoint.UPPERCASE_C ||
37
- nodePoints[i + 4].codePoint !== AsciiCodePoint.UPPERCASE_D ||
38
- nodePoints[i + 5].codePoint !== AsciiCodePoint.UPPERCASE_A ||
39
- nodePoints[i + 6].codePoint !== AsciiCodePoint.UPPERCASE_T ||
40
- nodePoints[i + 7].codePoint !== AsciiCodePoint.UPPERCASE_A ||
41
- nodePoints[i + 8].codePoint !== AsciiCodePoint.OPEN_BRACKET
42
- )
43
- return null
44
-
45
- const si = i + 9
46
- for (i = si; i < endIndex; ++i) {
47
- const p = nodePoints[i]
48
- if (p.codePoint !== AsciiCodePoint.CLOSE_BRACKET) continue
49
- if (i + 2 >= endIndex) return null
50
- if (
51
- nodePoints[i + 1].codePoint === AsciiCodePoint.CLOSE_BRACKET &&
52
- nodePoints[i + 2].codePoint === AsciiCodePoint.CLOSE_ANGLE
53
- ) {
54
- const delimiter: IHtmlInlineCDataDelimiter = {
55
- type: 'full',
56
- startIndex,
57
- endIndex: i + 3,
58
- htmlType: 'cdata',
59
- }
60
- return delimiter
61
- }
62
- }
63
- return null
64
- }
@@ -1,56 +0,0 @@
1
- import type { INodeInterval, INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
- import { eatOptionalWhitespaces } from '@yozora/core-tokenizer'
5
- import { eatHTMLTagName } from '@yozora/tokenizer-html-block'
6
-
7
- export interface IHtmlInlineClosingTagData {
8
- htmlType: 'closing'
9
- tagName: string
10
- }
11
-
12
- export interface IHtmlInlineClosingTokenData {
13
- htmlType: 'closing'
14
- tagName: INodeInterval
15
- }
16
-
17
- export interface IHtmlInlineClosingDelimiter extends ITokenDelimiter, IHtmlInlineClosingTokenData {
18
- type: 'full'
19
- }
20
-
21
- /**
22
- * A closing tag consists of the string '</', a tag name, optional whitespace,
23
- * and the character '>'.
24
- *
25
- * @param nodePoints
26
- * @param startIndex
27
- * @param endIndex
28
- * @see https://github.github.com/gfm/#closing-tag
29
- */
30
- export function eatHtmlInlineClosingDelimiter(
31
- nodePoints: ReadonlyArray<INodePoint>,
32
- startIndex: number,
33
- endIndex: number,
34
- ): IHtmlInlineClosingDelimiter | null {
35
- let i = startIndex
36
- if (i + 3 >= endIndex || nodePoints[i + 1].codePoint !== AsciiCodePoint.SLASH) return null
37
-
38
- const tagNameStartIndex = i + 2
39
- const tagNameEndIndex = eatHTMLTagName(nodePoints, tagNameStartIndex, endIndex)
40
- if (tagNameEndIndex == null) return null
41
-
42
- i = eatOptionalWhitespaces(nodePoints, tagNameEndIndex, endIndex)
43
- if (i >= endIndex || nodePoints[i].codePoint !== AsciiCodePoint.CLOSE_ANGLE) return null
44
-
45
- const delimiter: IHtmlInlineClosingDelimiter = {
46
- type: 'full',
47
- startIndex,
48
- endIndex: i + 1,
49
- htmlType: 'closing',
50
- tagName: {
51
- startIndex: tagNameStartIndex,
52
- endIndex: tagNameEndIndex,
53
- },
54
- }
55
- return delimiter
56
- }
@@ -1,87 +0,0 @@
1
- import type { INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
-
5
- export interface IHtmlInlineCommentData {
6
- htmlType: 'comment'
7
- }
8
-
9
- export interface IHtmlInlineCommentTokenData {
10
- htmlType: 'comment'
11
- }
12
-
13
- export interface IHtmlInlineCommentDelimiter extends ITokenDelimiter, IHtmlInlineCommentTokenData {
14
- type: 'full'
15
- }
16
-
17
- /**
18
- * An HTML comment consists of `<!--` + text + `-->`, where text does not start
19
- * with `>` or `->`, does not end with `-`, and does not contain `--`.
20
- *
21
- * @param nodePoints
22
- * @param startIndex
23
- * @param endIndex
24
- * @see https://github.github.com/gfm/#html-comment
25
- */
26
- export function eatHtmlInlineCommentDelimiter(
27
- nodePoints: ReadonlyArray<INodePoint>,
28
- startIndex: number,
29
- endIndex: number,
30
- ): IHtmlInlineCommentDelimiter | null {
31
- let i = startIndex
32
- if (
33
- i + 6 >= endIndex ||
34
- nodePoints[i + 1].codePoint !== AsciiCodePoint.EXCLAMATION_MARK ||
35
- nodePoints[i + 2].codePoint !== AsciiCodePoint.MINUS_SIGN ||
36
- nodePoints[i + 3].codePoint !== AsciiCodePoint.MINUS_SIGN
37
- )
38
- return null
39
-
40
- // text dose not start with '>'
41
- if (nodePoints[i + 4].codePoint === AsciiCodePoint.CLOSE_ANGLE) return null
42
-
43
- // text dose not start with '->', and does not end with -
44
- if (
45
- nodePoints[i + 4].codePoint === AsciiCodePoint.MINUS_SIGN &&
46
- nodePoints[i + 5].codePoint === AsciiCodePoint.CLOSE_ANGLE
47
- )
48
- return null
49
-
50
- const si = i + 4
51
- for (i = si; i < endIndex; ++i) {
52
- const p = nodePoints[i]
53
- if (p.codePoint !== AsciiCodePoint.MINUS_SIGN) continue
54
-
55
- let hyphenCount = 1
56
- for (; i + hyphenCount < endIndex; hyphenCount += 1) {
57
- const q = nodePoints[i + hyphenCount]
58
- if (q.codePoint !== AsciiCodePoint.MINUS_SIGN) break
59
- }
60
-
61
- /**
62
- * Single hyphen is allowed.
63
- * @see https://github.github.com/gfm/#example-644
64
- */
65
- if (hyphenCount < 2) continue
66
-
67
- /**
68
- * text does not contain '--' and does not end with -
69
- * @see https://github.github.com/gfm/#example-645
70
- */
71
- if (
72
- hyphenCount > 2 ||
73
- i + 2 >= endIndex ||
74
- nodePoints[i + 2].codePoint !== AsciiCodePoint.CLOSE_ANGLE
75
- )
76
- return null
77
-
78
- const delimiter: IHtmlInlineCommentDelimiter = {
79
- type: 'full',
80
- startIndex,
81
- endIndex: i + 3,
82
- htmlType: 'comment',
83
- }
84
- return delimiter
85
- }
86
- return null
87
- }
@@ -1,77 +0,0 @@
1
- import type { INodeInterval, INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint, isAsciiUpperLetter, isWhitespaceCharacter } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
-
5
- export interface IHtmlInlineDeclarationData {
6
- htmlType: 'declaration'
7
- }
8
-
9
- export interface IHtmlInlineDeclarationTokenData {
10
- htmlType: 'declaration'
11
- tagName: INodeInterval
12
- }
13
-
14
- export interface IHtmlInlineDeclarationDelimiter
15
- extends ITokenDelimiter,
16
- IHtmlInlineDeclarationTokenData {
17
- type: 'full'
18
- }
19
-
20
- /**
21
- * A declaration consists of the string `<!`, a name consisting of one or more
22
- * uppercase ASCII letters, whitespace, a string of characters not including
23
- * the character `>`, and the character `>`.
24
- *
25
- * @param nodePoints
26
- * @param startIndex
27
- * @param endIndex
28
- * @see https://github.github.com/gfm/#declaration
29
- */
30
- export function eatHtmlInlineDeclarationDelimiter(
31
- nodePoints: ReadonlyArray<INodePoint>,
32
- startIndex: number,
33
- endIndex: number,
34
- ): IHtmlInlineDeclarationDelimiter | null {
35
- let i = startIndex
36
- if (i + 4 >= endIndex || nodePoints[i + 1].codePoint !== AsciiCodePoint.EXCLAMATION_MARK)
37
- return null
38
-
39
- const tagNameStartIndex = i + 2
40
-
41
- // Try to eating a declaration name.
42
- for (i = tagNameStartIndex; i < endIndex; ++i) {
43
- const p = nodePoints[i]
44
- if (!isAsciiUpperLetter(p.codePoint)) break
45
- }
46
-
47
- /**
48
- * If no uppercase name or a following whitespace exists,
49
- * then it's not a valid declaration.
50
- */
51
- if (
52
- i - tagNameStartIndex <= 0 ||
53
- i + 1 >= endIndex ||
54
- !isWhitespaceCharacter(nodePoints[i].codePoint)
55
- )
56
- return null
57
-
58
- const tagNameEndIndex = i,
59
- si = i + 1
60
- for (i = si; i < endIndex; ++i) {
61
- const p = nodePoints[i]
62
- if (p.codePoint === AsciiCodePoint.CLOSE_ANGLE) {
63
- const delimiter: IHtmlInlineDeclarationDelimiter = {
64
- type: 'full',
65
- startIndex,
66
- endIndex: i + 1,
67
- htmlType: 'declaration',
68
- tagName: {
69
- startIndex: tagNameStartIndex,
70
- endIndex: tagNameEndIndex,
71
- },
72
- }
73
- return delimiter
74
- }
75
- }
76
- return null
77
- }
@@ -1,56 +0,0 @@
1
- import type { INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
-
5
- /**
6
- *
7
- * @see https://github.github.com/gfm/#processing-instruction
8
- */
9
- export interface IHtmlInlineInstructionData {
10
- htmlType: 'instruction'
11
- }
12
-
13
- export interface IHtmlInlineInstructionTokenData {
14
- htmlType: 'instruction'
15
- }
16
-
17
- export interface IHtmlInlineInstructionDelimiter
18
- extends ITokenDelimiter,
19
- IHtmlInlineInstructionTokenData {
20
- type: 'full'
21
- }
22
-
23
- /**
24
- * A processing instruction consists of the string `<?`, a string of characters
25
- * not including the string `?>`, and the string `?>`.
26
- *
27
- * @param nodePoints
28
- * @param startIndex
29
- * @param endIndex
30
- * @see https://github.github.com/gfm/#processing-instruction
31
- */
32
- export function eatHtmlInlineInstructionDelimiter(
33
- nodePoints: ReadonlyArray<INodePoint>,
34
- startIndex: number,
35
- endIndex: number,
36
- ): IHtmlInlineInstructionDelimiter | null {
37
- let i = startIndex
38
- if (i + 3 >= endIndex || nodePoints[i + 1].codePoint !== AsciiCodePoint.QUESTION_MARK) return null
39
-
40
- const si = i + 2
41
- for (i = si; i < endIndex; ++i) {
42
- const p = nodePoints[i]
43
- if (p.codePoint !== AsciiCodePoint.QUESTION_MARK) continue
44
- if (i + 1 >= endIndex) return null
45
- if (nodePoints[i + 1].codePoint === AsciiCodePoint.CLOSE_ANGLE) {
46
- const delimiter: IHtmlInlineInstructionDelimiter = {
47
- type: 'full',
48
- startIndex,
49
- endIndex: i + 2,
50
- htmlType: 'instruction',
51
- }
52
- return delimiter
53
- }
54
- }
55
- return null
56
- }
package/src/util/open.ts DELETED
@@ -1,88 +0,0 @@
1
- import type { INodeInterval, INodePoint } from '@yozora/character'
2
- import { AsciiCodePoint } from '@yozora/character'
3
- import type { ITokenDelimiter } from '@yozora/core-tokenizer'
4
- import { eatOptionalWhitespaces } from '@yozora/core-tokenizer'
5
- import type { RawHTMLAttribute } from '@yozora/tokenizer-html-block'
6
- import { eatHTMLAttribute, eatHTMLTagName } from '@yozora/tokenizer-html-block'
7
-
8
- export interface IHtmlInlineOpenTagData {
9
- htmlType: 'open'
10
- /**
11
- * HTML tag name.
12
- */
13
- tagName: string
14
- /**
15
- * HTML attributes.
16
- */
17
- attributes: Array<{ name: string; value?: string }>
18
- /**
19
- * Whether if a html tag is self closed.
20
- */
21
- selfClosed: boolean
22
- }
23
-
24
- export interface IHtmlInlineOpenTokenData {
25
- htmlType: 'open'
26
- tagName: INodeInterval
27
- attributes: RawHTMLAttribute[]
28
- selfClosed: boolean
29
- }
30
-
31
- export interface IHtmlInlineOpenDelimiter extends ITokenDelimiter, IHtmlInlineOpenTokenData {
32
- type: 'full'
33
- }
34
-
35
- /**
36
- * An open tag consists of a '<' character, a tag name, zero or more attributes,
37
- * optional whitespace, an optional '/' character, and a '>' character.
38
- *
39
- * @param nodePoints
40
- * @param startIndex
41
- * @param endIndex
42
- * @see https://github.github.com/gfm/#open-tag
43
- */
44
- export function eatHtmlInlineTokenOpenDelimiter(
45
- nodePoints: ReadonlyArray<INodePoint>,
46
- startIndex: number,
47
- endIndex: number,
48
- ): IHtmlInlineOpenDelimiter | null {
49
- let i = startIndex
50
- if (i + 2 >= endIndex) return null
51
-
52
- const tagNameStartIndex = i + 1
53
- const tagNameEndIndex = eatHTMLTagName(nodePoints, tagNameStartIndex, endIndex)
54
- if (tagNameEndIndex == null) return null
55
-
56
- const attributes: RawHTMLAttribute[] = []
57
- for (i = tagNameEndIndex; i < endIndex; ) {
58
- const result = eatHTMLAttribute(nodePoints, i, endIndex)
59
- if (result == null) break
60
- attributes.push(result.attribute)
61
- i = result.nextIndex
62
- }
63
-
64
- i = eatOptionalWhitespaces(nodePoints, i, endIndex)
65
- if (i >= endIndex) return null
66
-
67
- let selfClosed = false
68
- if (nodePoints[i].codePoint === AsciiCodePoint.SLASH) {
69
- i += 1
70
- selfClosed = true
71
- }
72
-
73
- if (i >= endIndex || nodePoints[i].codePoint !== AsciiCodePoint.CLOSE_ANGLE) return null
74
-
75
- const delimiter: IHtmlInlineOpenDelimiter = {
76
- type: 'full',
77
- startIndex,
78
- endIndex: i + 1,
79
- htmlType: 'open',
80
- tagName: {
81
- startIndex: tagNameStartIndex,
82
- endIndex: tagNameEndIndex,
83
- },
84
- attributes,
85
- selfClosed,
86
- }
87
- return delimiter
88
- }