@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 +7 -7
- package/src/index.ts +0 -15
- package/src/match.ts +0 -101
- package/src/parse.ts +0 -20
- package/src/tokenizer.ts +0 -37
- package/src/types.ts +0 -52
- package/src/util/cdata.ts +0 -64
- package/src/util/closing.ts +0 -56
- package/src/util/comment.ts +0 -87
- package/src/util/declaration.ts +0 -77
- package/src/util/instruction.ts +0 -56
- package/src/util/open.ts +0 -88
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yozora/tokenizer-html-inline",
|
|
3
|
-
"version": "2.1.
|
|
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
|
-
"
|
|
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.
|
|
43
|
-
"@yozora/character": "^2.1.
|
|
44
|
-
"@yozora/core-tokenizer": "^2.1.
|
|
45
|
-
"@yozora/tokenizer-html-block": "^2.1.
|
|
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": "
|
|
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
|
-
}
|
package/src/util/closing.ts
DELETED
|
@@ -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
|
-
}
|
package/src/util/comment.ts
DELETED
|
@@ -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
|
-
}
|
package/src/util/declaration.ts
DELETED
|
@@ -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
|
-
}
|
package/src/util/instruction.ts
DELETED
|
@@ -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
|
-
}
|