sugar-high 1.3.0 → 2.0.1
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 +128 -43
- package/lib/core.d.ts +117 -0
- package/lib/core.js +202 -0
- package/lib/index.d.ts +39 -24
- package/lib/index.js +15 -1007
- package/lib/lang.d.ts +14 -0
- package/lib/lang.js +132 -0
- package/lib/presets/lang/cpp.js +22 -0
- package/lib/presets/lang/csharp.js +21 -0
- package/lib/presets/lang/css.js +86 -0
- package/lib/presets/lang/diff.js +12 -6
- package/lib/presets/lang/dockerfile.js +5 -0
- package/lib/presets/lang/graphql.js +5 -0
- package/lib/presets/lang/hash-comment-base.js +7 -0
- package/lib/presets/lang/hcl.js +4 -0
- package/lib/presets/lang/html.js +14 -0
- package/lib/presets/lang/javascript-runtime.js +781 -0
- package/lib/presets/lang/javascript.js +6 -0
- package/lib/presets/lang/json.js +4 -0
- package/lib/presets/lang/kotlin.js +5 -0
- package/lib/presets/lang/markdown.js +15 -0
- package/lib/presets/lang/php.js +5 -0
- package/lib/presets/lang/plain-base.js +4 -0
- package/lib/presets/lang/powershell.js +5 -0
- package/lib/presets/lang/shell.js +10 -0
- package/lib/presets/lang/sql.js +31 -0
- package/lib/presets/lang/swift.js +5 -0
- package/lib/presets/lang/toml.js +5 -0
- package/lib/presets/lang/typescript.js +7 -0
- package/lib/presets/lang/yaml.js +10 -0
- package/lib/shared.js +149 -0
- package/package.json +15 -10
- package/lib/presets/index.d.ts +0 -18
- package/lib/presets/index.js +0 -8
package/lib/lang.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LanguageName } from './index.js'
|
|
2
|
+
import type { ParseOptions } from './core.js'
|
|
3
|
+
|
|
4
|
+
export type Language = Readonly<{
|
|
5
|
+
id: LanguageName
|
|
6
|
+
/** Preferred file extension without a leading dot. */
|
|
7
|
+
extension: string
|
|
8
|
+
aliases: readonly string[]
|
|
9
|
+
config?: ParseOptions
|
|
10
|
+
}>
|
|
11
|
+
|
|
12
|
+
export const languages: readonly Language[]
|
|
13
|
+
/** Normalize a language name, fence alias, or extension to its canonical name. */
|
|
14
|
+
export function lang(name: string): LanguageName | undefined
|
package/lib/lang.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import * as c from './presets/lang/c.js'
|
|
4
|
+
import * as cpp from './presets/lang/cpp.js'
|
|
5
|
+
import * as csharp from './presets/lang/csharp.js'
|
|
6
|
+
import * as css from './presets/lang/css.js'
|
|
7
|
+
import * as diff from './presets/lang/diff.js'
|
|
8
|
+
import * as dockerfile from './presets/lang/dockerfile.js'
|
|
9
|
+
import * as go from './presets/lang/go.js'
|
|
10
|
+
import * as html from './presets/lang/html.js'
|
|
11
|
+
import * as graphql from './presets/lang/graphql.js'
|
|
12
|
+
import * as hcl from './presets/lang/hcl.js'
|
|
13
|
+
import * as java from './presets/lang/java.js'
|
|
14
|
+
import * as json from './presets/lang/json.js'
|
|
15
|
+
import * as javascript from './presets/lang/javascript.js'
|
|
16
|
+
import * as kotlin from './presets/lang/kotlin.js'
|
|
17
|
+
import * as markdown from './presets/lang/markdown.js'
|
|
18
|
+
import * as php from './presets/lang/php.js'
|
|
19
|
+
import * as powershell from './presets/lang/powershell.js'
|
|
20
|
+
import * as python from './presets/lang/python.js'
|
|
21
|
+
import * as rust from './presets/lang/rust.js'
|
|
22
|
+
import * as shell from './presets/lang/shell.js'
|
|
23
|
+
import * as sql from './presets/lang/sql.js'
|
|
24
|
+
import * as swift from './presets/lang/swift.js'
|
|
25
|
+
import * as toml from './presets/lang/toml.js'
|
|
26
|
+
import * as typescript from './presets/lang/typescript.js'
|
|
27
|
+
import * as yaml from './presets/lang/yaml.js'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {import('./core.js').ParseOptions} ParseOptions
|
|
31
|
+
* @typedef {{
|
|
32
|
+
* id: string
|
|
33
|
+
* extension: string
|
|
34
|
+
* aliases: readonly string[]
|
|
35
|
+
* config?: ParseOptions
|
|
36
|
+
* }} Language
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Disable JavaScript-only scanner modes for a non-JavaScript language.
|
|
41
|
+
* @param {ParseOptions} config
|
|
42
|
+
* @returns {ParseOptions}
|
|
43
|
+
*/
|
|
44
|
+
function nonJavaScript(config) {
|
|
45
|
+
return {
|
|
46
|
+
...config,
|
|
47
|
+
jsx: false,
|
|
48
|
+
regex: false,
|
|
49
|
+
templateStrings: false,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** @type {readonly Language[]} */
|
|
54
|
+
const languages = [
|
|
55
|
+
{ id: 'javascript', extension: 'js', aliases: ['js', 'jsx', 'node'], config: javascript },
|
|
56
|
+
{ id: 'typescript', extension: 'ts', aliases: ['ts', 'tsx'], config: typescript },
|
|
57
|
+
{ id: 'css', extension: 'css', aliases: ['scss'], config: nonJavaScript(css) },
|
|
58
|
+
{ id: 'python', extension: 'py', aliases: ['py', 'python3'], config: nonJavaScript(python) },
|
|
59
|
+
{ id: 'c', extension: 'c', aliases: [], config: nonJavaScript(c) },
|
|
60
|
+
{ id: 'go', extension: 'go', aliases: ['golang'], config: nonJavaScript(go) },
|
|
61
|
+
{ id: 'java', extension: 'java', aliases: [], config: nonJavaScript(java) },
|
|
62
|
+
{ id: 'rust', extension: 'rs', aliases: ['rs'], config: nonJavaScript(rust) },
|
|
63
|
+
{ id: 'json', extension: 'json', aliases: ['jsonc'], config: nonJavaScript(json) },
|
|
64
|
+
{ id: 'diff', extension: 'diff', aliases: ['patch'], config: nonJavaScript(diff) },
|
|
65
|
+
{ id: 'shell', extension: 'sh', aliases: ['sh', 'bash', 'zsh'], config: nonJavaScript(shell) },
|
|
66
|
+
{ id: 'cpp', extension: 'cpp', aliases: ['c++', 'cc', 'cxx'], config: nonJavaScript(cpp) },
|
|
67
|
+
{ id: 'csharp', extension: 'cs', aliases: ['c#', 'cs', 'dotnet'], config: nonJavaScript(csharp) },
|
|
68
|
+
{ id: 'sql', extension: 'sql', aliases: [], config: nonJavaScript(sql) },
|
|
69
|
+
{ id: 'html', extension: 'html', aliases: ['htm', 'xml'], config: html },
|
|
70
|
+
{ id: 'yaml', extension: 'yaml', aliases: ['yml'], config: nonJavaScript(yaml) },
|
|
71
|
+
{ id: 'markdown', extension: 'md', aliases: ['md', 'mdx'], config: nonJavaScript(markdown) },
|
|
72
|
+
{ id: 'kotlin', extension: 'kt', aliases: ['kts'], config: nonJavaScript(kotlin) },
|
|
73
|
+
{ id: 'swift', extension: 'swift', aliases: [], config: nonJavaScript(swift) },
|
|
74
|
+
{ id: 'php', extension: 'php', aliases: [], config: nonJavaScript(php) },
|
|
75
|
+
{ id: 'toml', extension: 'toml', aliases: [], config: nonJavaScript(toml) },
|
|
76
|
+
{ id: 'powershell', extension: 'ps1', aliases: ['pwsh'], config: nonJavaScript(powershell) },
|
|
77
|
+
{ id: 'dockerfile', extension: 'dockerfile', aliases: ['docker'], config: nonJavaScript(dockerfile) },
|
|
78
|
+
{ id: 'graphql', extension: 'graphql', aliases: ['gql'], config: nonJavaScript(graphql) },
|
|
79
|
+
{ id: 'hcl', extension: 'hcl', aliases: ['terraform', 'tf'], config: nonJavaScript(hcl) },
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
/** @param {string} value */
|
|
83
|
+
function normalizeLanguageName(value) {
|
|
84
|
+
return value.trim().toLowerCase().replace(/^\./, '')
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** @type {Map<string, Language>} */
|
|
88
|
+
const languageLookup = new Map()
|
|
89
|
+
|
|
90
|
+
for (const language of languages) {
|
|
91
|
+
const names = new Set([language.id, language.extension, ...language.aliases])
|
|
92
|
+
for (const name of names) {
|
|
93
|
+
const normalized = normalizeLanguageName(name)
|
|
94
|
+
const existing = languageLookup.get(normalized)
|
|
95
|
+
if (existing && existing !== language) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Language name "${normalized}" is shared by "${existing.id}" and "${language.id}"`
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
languageLookup.set(normalized, language)
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Find canonical language metadata using a name, alias, or preferred extension.
|
|
106
|
+
* @param {string} name
|
|
107
|
+
* @returns {Language | undefined}
|
|
108
|
+
*/
|
|
109
|
+
function findLanguage(name) {
|
|
110
|
+
if (typeof name !== 'string') return undefined
|
|
111
|
+
return languageLookup.get(normalizeLanguageName(name))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Find metadata only when the input is already a canonical language name.
|
|
116
|
+
* Direct highlighting uses this stricter lookup; integrations resolve aliases first.
|
|
117
|
+
* @param {string} name
|
|
118
|
+
* @returns {Language | undefined}
|
|
119
|
+
*/
|
|
120
|
+
/**
|
|
121
|
+
* Resolve a name, alias, or extension to its canonical language name.
|
|
122
|
+
* @param {string} name
|
|
123
|
+
* @returns {string | undefined}
|
|
124
|
+
*/
|
|
125
|
+
function lang(name) {
|
|
126
|
+
return findLanguage(name)?.id
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
lang,
|
|
131
|
+
languages,
|
|
132
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { onCommentEnd, onCommentStart } from './clike-base.js'
|
|
3
|
+
|
|
4
|
+
export const keywords = new Set([
|
|
5
|
+
'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'break',
|
|
6
|
+
'case', 'catch', 'class', 'compl', 'concept', 'const', 'consteval', 'constexpr',
|
|
7
|
+
'constinit', 'const_cast', 'continue', 'co_await', 'co_return', 'co_yield', 'decltype',
|
|
8
|
+
'default', 'delete', 'do', 'dynamic_cast', 'else', 'enum', 'explicit', 'export',
|
|
9
|
+
'extern', 'false', 'for', 'friend', 'goto', 'if', 'inline', 'mutable', 'namespace',
|
|
10
|
+
'new', 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'private',
|
|
11
|
+
'protected', 'public', 'register', 'reinterpret_cast', 'requires', 'return', 'sizeof',
|
|
12
|
+
'static', 'static_assert', 'static_cast', 'struct', 'switch', 'template', 'this',
|
|
13
|
+
'thread_local', 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', 'union',
|
|
14
|
+
'using', 'virtual', 'volatile', 'while', 'xor', 'xor_eq',
|
|
15
|
+
])
|
|
16
|
+
|
|
17
|
+
export const typeKeywords = new Set([
|
|
18
|
+
'bool', 'char', 'char8_t', 'char16_t', 'char32_t', 'double', 'float', 'int', 'long',
|
|
19
|
+
'short', 'signed', 'unsigned', 'void', 'wchar_t',
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
export { onCommentEnd, onCommentStart }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { onCommentEnd, onCommentStart } from './clike-base.js'
|
|
3
|
+
|
|
4
|
+
export const keywords = new Set([
|
|
5
|
+
'abstract', 'as', 'async', 'await', 'base', 'break', 'case', 'catch', 'checked',
|
|
6
|
+
'class', 'const', 'continue', 'default', 'delegate', 'do', 'else', 'enum', 'event',
|
|
7
|
+
'explicit', 'extern', 'false', 'finally', 'fixed', 'for', 'foreach', 'from', 'get',
|
|
8
|
+
'global', 'goto', 'if', 'implicit', 'in', 'init', 'interface', 'internal', 'into', 'is',
|
|
9
|
+
'join', 'let', 'lock', 'namespace', 'new', 'null', 'on', 'operator', 'orderby', 'out',
|
|
10
|
+
'override', 'params', 'partial', 'private', 'protected', 'public', 'readonly', 'record',
|
|
11
|
+
'ref', 'remove', 'required', 'return', 'sealed', 'select', 'set', 'sizeof', 'stackalloc',
|
|
12
|
+
'static', 'struct', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'unchecked',
|
|
13
|
+
'unsafe', 'using', 'value', 'virtual', 'volatile', 'when', 'where', 'while', 'with', 'yield',
|
|
14
|
+
])
|
|
15
|
+
|
|
16
|
+
export const typeKeywords = new Set([
|
|
17
|
+
'bool', 'byte', 'char', 'decimal', 'double', 'dynamic', 'float', 'int', 'long', 'nint',
|
|
18
|
+
'nuint', 'object', 'sbyte', 'short', 'string', 'uint', 'ulong', 'ushort', 'void',
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
export { onCommentEnd, onCommentStart }
|
package/lib/presets/lang/css.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
+
import {
|
|
3
|
+
T_BREAK, T_CLASS, T_COMMENT, T_IDENTIFIER, T_PROPERTY, T_SIGN, T_SPACE,
|
|
4
|
+
} from '../../shared.js'
|
|
5
|
+
import { tokenize as tokenizePlain } from '../../core.js'
|
|
6
|
+
|
|
2
7
|
export const keywords = new Set([
|
|
3
8
|
// css keywords like @media, @import, @keyframes, etc.
|
|
4
9
|
'@media', '@import', '@keyframes', '@font-face', '@supports', '@page', '@counter-style',
|
|
@@ -12,3 +17,84 @@ export const onCommentStart = (currentChar, nextChar) => {
|
|
|
12
17
|
export const onCommentEnd = (prevChar, currChar) => {
|
|
13
18
|
return '*/' === (prevChar + currChar) ? 1 : 0
|
|
14
19
|
}
|
|
20
|
+
|
|
21
|
+
export const onLiteral = (curr, index, code) => {
|
|
22
|
+
if (curr !== '#') return 0
|
|
23
|
+
return code.slice(index).match(/^#(?:[\da-f]{8}|[\da-f]{6}|[\da-f]{4}|[\da-f]{3})(?![\w-])/i)?.[0].length || 0
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const isIgnored = (type) => type === T_SPACE || type === T_BREAK || type === T_COMMENT
|
|
27
|
+
const isPropertyPart = ([type, value]) =>
|
|
28
|
+
type === T_IDENTIFIER || type === T_CLASS || (type === T_SIGN && value === '-')
|
|
29
|
+
|
|
30
|
+
/** Return true when a colon belongs to a nested selector instead of a declaration. */
|
|
31
|
+
const opensBlock = (tokens, start) => {
|
|
32
|
+
let parentheses = 0
|
|
33
|
+
let brackets = 0
|
|
34
|
+
for (let index = start; index < tokens.length; index++) {
|
|
35
|
+
const [type, value] = tokens[index]
|
|
36
|
+
if (type !== T_SIGN) continue
|
|
37
|
+
if (value === '(') parentheses++
|
|
38
|
+
else if (value === ')') parentheses--
|
|
39
|
+
else if (value === '[') brackets++
|
|
40
|
+
else if (value === ']') brackets--
|
|
41
|
+
else if (!parentheses && !brackets && value === '{') return true
|
|
42
|
+
else if (!parentheses && !brackets && (value === ';' || value === '}')) return false
|
|
43
|
+
}
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Add CSS declaration context after the shared plain lexer runs.
|
|
49
|
+
* @param {string} code
|
|
50
|
+
* @param {import('../../core.js').ParseOptions} options
|
|
51
|
+
*/
|
|
52
|
+
export const tokenize = (code, options) => {
|
|
53
|
+
const tokens = tokenizePlain(code, { ...options, tokenize: undefined })
|
|
54
|
+
let blockDepth = 0
|
|
55
|
+
let declarationStart = false
|
|
56
|
+
|
|
57
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
58
|
+
const [type, value] = tokens[index]
|
|
59
|
+
|
|
60
|
+
if (type === T_SIGN && value === '{') {
|
|
61
|
+
blockDepth++
|
|
62
|
+
declarationStart = true
|
|
63
|
+
continue
|
|
64
|
+
}
|
|
65
|
+
if (type === T_SIGN && value === '}') {
|
|
66
|
+
blockDepth--
|
|
67
|
+
declarationStart = false
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
if (type === T_SIGN && value === ';') {
|
|
71
|
+
declarationStart = blockDepth > 0
|
|
72
|
+
continue
|
|
73
|
+
}
|
|
74
|
+
if (!declarationStart || isIgnored(type)) continue
|
|
75
|
+
|
|
76
|
+
const propertyStart = index
|
|
77
|
+
let propertyEnd = index
|
|
78
|
+
while (propertyEnd < tokens.length && isPropertyPart(tokens[propertyEnd])) {
|
|
79
|
+
propertyEnd++
|
|
80
|
+
}
|
|
81
|
+
let colon = propertyEnd
|
|
82
|
+
while (colon < tokens.length && isIgnored(tokens[colon][0])) colon++
|
|
83
|
+
|
|
84
|
+
if (
|
|
85
|
+
propertyEnd > propertyStart &&
|
|
86
|
+
tokens[colon]?.[0] === T_SIGN &&
|
|
87
|
+
tokens[colon][1] === ':' &&
|
|
88
|
+
!opensBlock(tokens, colon + 1)
|
|
89
|
+
) {
|
|
90
|
+
const property = tokens
|
|
91
|
+
.slice(propertyStart, propertyEnd)
|
|
92
|
+
.map(([, part]) => part)
|
|
93
|
+
.join('')
|
|
94
|
+
tokens.splice(propertyStart, propertyEnd - propertyStart, [T_PROPERTY, property])
|
|
95
|
+
}
|
|
96
|
+
declarationStart = false
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return tokens
|
|
100
|
+
}
|
package/lib/presets/lang/diff.js
CHANGED
|
@@ -2,10 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
export const keywords = new Set([])
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
if (line.startsWith('
|
|
8
|
-
if (line.startsWith('
|
|
9
|
-
if (
|
|
10
|
-
|
|
5
|
+
export const annotateLine = (line) => {
|
|
6
|
+
let annotation = ''
|
|
7
|
+
if (line.value.startsWith('+') && !line.value.startsWith('+++')) annotation = 'diff-add'
|
|
8
|
+
else if (line.value.startsWith('-') && !line.value.startsWith('---')) annotation = 'diff-remove'
|
|
9
|
+
else if (line.value.startsWith('@@')) annotation = 'diff-hunk'
|
|
10
|
+
else if (/^(diff --git|index |--- |\+\+\+ )/.test(line.value)) {
|
|
11
|
+
annotation = 'diff-meta'
|
|
12
|
+
for (const token of line.tokens) {
|
|
13
|
+
if (token.type === 'property') token.type = 'identifier'
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
if (annotation) line.annotations.push(annotation)
|
|
11
17
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { onCommentEnd, onCommentStart } from './hash-comment-base.js'
|
|
3
|
+
export const caseInsensitive = true
|
|
4
|
+
export const keywords = new Set(['add','arg','cmd','copy','entrypoint','env','expose','from','healthcheck','label','maintainer','onbuild','run','shell','stopsignal','user','volume','workdir'])
|
|
5
|
+
export { onCommentEnd, onCommentStart }
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { onCommentEnd, onCommentStart } from './hash-comment-base.js'
|
|
3
|
+
export const keywords = new Set(['directive','enum','extend','fragment','implements','input','interface','mutation','on','query','repeatable','scalar','schema','subscription','type','union'])
|
|
4
|
+
export const typeKeywords = new Set(['Boolean','Float','ID','Int','String'])
|
|
5
|
+
export { onCommentEnd, onCommentStart }
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/** @param {string} currentChar */
|
|
4
|
+
export const onCommentStart = (currentChar) => currentChar === '#' ? 1 : 0
|
|
5
|
+
|
|
6
|
+
/** @param {string} _prevChar @param {string} currChar */
|
|
7
|
+
export const onCommentEnd = (_prevChar, currChar) => currChar === '\n' ? 1 : 0
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export const keywords = new Set(['false','for','if','in','null','true'])
|
|
3
|
+
export const onCommentStart = (curr, next) => curr === '#' ? 1 : curr + next === '//' ? 1 : curr + next === '/*' ? 2 : 0
|
|
4
|
+
export const onCommentEnd = (prev, curr) => curr === '\n' ? 1 : prev + curr === '*/' ? 2 : 0
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { tokenize as tokenizeJavaScript } from './javascript-runtime.js'
|
|
3
|
+
|
|
4
|
+
export const keywords = new Set([])
|
|
5
|
+
export const jsx = true
|
|
6
|
+
export const regex = false
|
|
7
|
+
export const templateStrings = false
|
|
8
|
+
export const tokenize = tokenizeJavaScript
|
|
9
|
+
|
|
10
|
+
export const onCommentStart = (_currentChar, _nextChar, index, code) =>
|
|
11
|
+
code.startsWith('<!--', index) ? 2 : 0
|
|
12
|
+
|
|
13
|
+
export const onCommentEnd = (_prevChar, _currChar, index, code) =>
|
|
14
|
+
code.slice(index - 2, index + 1) === '-->' ? 2 : 0
|