@adecore/editor-core 0.39.0 → 0.40.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.
- package/dist/block-folds.js +5 -2
- package/dist/bracket-tracker.js +4 -3
- package/dist/brackets.d.ts +2 -12
- package/dist/brackets.js +3 -15
- package/dist/closer-tracker.js +0 -1
- package/dist/doc-comments.js +0 -1
- package/dist/document.d.ts +2 -0
- package/dist/document.js +33 -35
- package/dist/edit-regions.js +3 -4
- package/dist/enter.d.ts +2 -0
- package/dist/enter.js +11 -9
- package/dist/fold-roles.js +2 -2
- package/dist/lexical-folds.d.ts +0 -1
- package/dist/lexical-folds.js +1 -4
- package/dist/lexical.d.ts +11 -5
- package/dist/lexical.js +13 -17
- package/dist/line-commands.js +7 -15
- package/dist/line-text.d.ts +2 -0
- package/dist/line-text.js +4 -0
- package/dist/markup-regions.js +2 -3
- package/dist/paste.js +2 -7
- package/dist/structure.js +2 -1
- package/dist/typing-context.js +5 -15
- package/package.json +2 -2
- package/src/block-folds.ts +39 -2
- package/src/bracket-tracker.ts +55 -12
- package/src/brackets.ts +35 -42
- package/src/closer-tracker.ts +6 -1
- package/src/comments.ts +103 -0
- package/src/doc-comments.ts +19 -1
- package/src/document.ts +505 -36
- package/src/edit-regions.ts +26 -4
- package/src/enter.ts +104 -9
- package/src/fold-roles.ts +34 -2
- package/src/index.ts +2 -0
- package/src/languages.ts +11 -0
- package/src/lexical-folds.ts +21 -5
- package/src/lexical.ts +31 -23
- package/src/line-commands.ts +81 -17
- package/src/line-text.ts +7 -0
- package/src/markup-regions.ts +101 -3
- package/src/offsets.ts +10 -0
- package/src/paste.ts +20 -7
- package/src/php-markup.ts +23 -0
- package/src/preserve-case.ts +12 -0
- package/src/rope.ts +70 -0
- package/src/script-source.ts +10 -0
- package/src/search.ts +38 -0
- package/src/structure.ts +29 -1
- package/src/text-span.ts +53 -0
- package/src/typing-context.ts +65 -41
- package/src/typing-handlers.ts +28 -0
- package/src/words.ts +10 -0
package/src/fold-roles.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { isImportLine, rangeOf
|
|
2
|
-
import { isBlank } from './line-text.ts';
|
|
1
|
+
import { isImportLine, rangeOf } from './lexical-folds.ts';
|
|
2
|
+
import { isBlank, textStart } from './line-text.ts';
|
|
3
3
|
import type { DocumentLine } from './rope.ts';
|
|
4
4
|
import type { FoldHints, FoldRangeHint, FoldRole, FoldingRange } from './structure.ts';
|
|
5
5
|
|
|
@@ -23,26 +23,34 @@ export function commentRole(slice: (from: number, to: number) => string, from: n
|
|
|
23
23
|
export function bracketRole(slice: (from: number, to: number) => string, from: number, language: string): FoldRole | undefined {
|
|
24
24
|
const opener = slice(from, from + 1);
|
|
25
25
|
const before = slice(Math.max(0, from - LOOK_BEHIND), from);
|
|
26
|
+
|
|
26
27
|
if (language.toLowerCase() === 'php') {
|
|
27
28
|
return opener === '[' && before.endsWith('#') ? 'attribute' : undefined;
|
|
28
29
|
}
|
|
30
|
+
|
|
29
31
|
if (!SCRIPT_LANGUAGES.test(language) || (opener !== '{' && opener !== '[')) {
|
|
30
32
|
return undefined;
|
|
31
33
|
}
|
|
34
|
+
|
|
32
35
|
const head = before.slice(before.lastIndexOf('\n') + 1);
|
|
33
36
|
const trimmed = before.trimEnd();
|
|
34
37
|
const previous = trimmed.at(-1);
|
|
38
|
+
|
|
35
39
|
if (previous === undefined) {
|
|
36
40
|
return undefined;
|
|
37
41
|
}
|
|
42
|
+
|
|
38
43
|
const arrow = trimmed.endsWith('=>');
|
|
39
44
|
const value = (/[=:(,[?]/.test(previous) && !arrow) || VALUE_WORDS.test(trimmed) || (arrow && opener === '[');
|
|
45
|
+
|
|
40
46
|
if (!value) {
|
|
41
47
|
return undefined;
|
|
42
48
|
}
|
|
49
|
+
|
|
43
50
|
if (opener === '[') {
|
|
44
51
|
return 'array-literal';
|
|
45
52
|
}
|
|
53
|
+
|
|
46
54
|
// A `case x: {` and a `type A = {` are a block and a type, not a value.
|
|
47
55
|
return /^\s*(?:case\b|default\s*:|(?:export\s+)?(?:declare\s+)?(?:type|interface)\b)/.test(head) ? undefined : 'object-literal';
|
|
48
56
|
}
|
|
@@ -53,20 +61,26 @@ export function bracketRole(slice: (from: number, to: number) => string, from: n
|
|
|
53
61
|
*/
|
|
54
62
|
export function markFileHeader(ranges: FoldingRange[], getLine: (line: number) => DocumentLine, lineCount: number, language: string): void {
|
|
55
63
|
const candidate = ranges.find((range) => (range.kind === 'comment' || range.kind === 'line-comments') && range.startLine <= HEADER_LINES);
|
|
64
|
+
|
|
56
65
|
if (candidate === undefined) {
|
|
57
66
|
return;
|
|
58
67
|
}
|
|
68
|
+
|
|
59
69
|
for (let line = 0; line < candidate.startLine; line++) {
|
|
60
70
|
const text = getLine(line).text;
|
|
71
|
+
|
|
61
72
|
if (!isBlank(text) && !(line === 0 && /^(#!|<\?php\s*$)/.test(text))) {
|
|
62
73
|
return;
|
|
63
74
|
}
|
|
64
75
|
}
|
|
76
|
+
|
|
65
77
|
if (candidate.from > textStart(getLine(candidate.startLine))) {
|
|
66
78
|
return;
|
|
67
79
|
}
|
|
80
|
+
|
|
68
81
|
const next = candidate.endLine + 1 < lineCount ? getLine(candidate.endLine + 1).text : '';
|
|
69
82
|
const attached = candidate.role === 'doc-comment' && !isBlank(next) && !isImportLine(language, next.trimStart());
|
|
83
|
+
|
|
70
84
|
if (!attached) {
|
|
71
85
|
candidate.role = 'file-header';
|
|
72
86
|
}
|
|
@@ -77,12 +91,15 @@ function serverRole(kind: string | undefined, text: string): FoldRole | undefine
|
|
|
77
91
|
if (kind === 'imports') {
|
|
78
92
|
return 'imports';
|
|
79
93
|
}
|
|
94
|
+
|
|
80
95
|
if (kind === 'region') {
|
|
81
96
|
return 'region';
|
|
82
97
|
}
|
|
98
|
+
|
|
83
99
|
if (kind === 'comment') {
|
|
84
100
|
return text.startsWith('/**') ? 'doc-comment' : undefined;
|
|
85
101
|
}
|
|
102
|
+
|
|
86
103
|
return text.startsWith('<') ? 'tag' : undefined;
|
|
87
104
|
}
|
|
88
105
|
|
|
@@ -100,31 +117,40 @@ export function applyFoldHints(
|
|
|
100
117
|
minimum: number
|
|
101
118
|
): FoldingRange[] {
|
|
102
119
|
const result = ranges.map((range) => ({ ...range }));
|
|
120
|
+
|
|
103
121
|
for (const symbol of hints.symbols ?? []) {
|
|
104
122
|
const startLine = lineAt(symbol.from);
|
|
105
123
|
const endLine = lineAt(Math.max(symbol.from, symbol.to - 1));
|
|
106
124
|
const body = bodyOf(result, symbol, startLine, endLine, slice);
|
|
125
|
+
|
|
107
126
|
if (body !== undefined) {
|
|
108
127
|
body.range.role = body.role;
|
|
109
128
|
}
|
|
110
129
|
}
|
|
130
|
+
|
|
111
131
|
const starts = new Set(result.map((range) => range.startLine));
|
|
132
|
+
|
|
112
133
|
for (const hint of hints.ranges ?? []) {
|
|
113
134
|
const startLine = lineAt(hint.from);
|
|
114
135
|
const endLine = lineAt(hint.to);
|
|
115
136
|
const same = result.find((range) => range.startLine === startLine && range.endLine === endLine);
|
|
137
|
+
|
|
116
138
|
// The text's own fold of the same lines keeps its kind and role, and takes where the server hides from and shows again from.
|
|
117
139
|
if (same !== undefined) {
|
|
118
140
|
Object.assign(same, edgesOf(hint));
|
|
141
|
+
|
|
119
142
|
continue;
|
|
120
143
|
}
|
|
144
|
+
|
|
121
145
|
if (endLine - startLine < minimum || starts.has(startLine)) {
|
|
122
146
|
continue;
|
|
123
147
|
}
|
|
148
|
+
|
|
124
149
|
starts.add(startLine);
|
|
125
150
|
const role = serverRole(hint.kind, getLine(startLine).text.trimStart());
|
|
126
151
|
result.push({ ...rangeOf(startLine, endLine, getLine, 'server', role), ...edgesOf(hint) });
|
|
127
152
|
}
|
|
153
|
+
|
|
128
154
|
return result.sort((left, right) => left.startLine - right.startLine || right.endLine - left.endLine);
|
|
129
155
|
}
|
|
130
156
|
|
|
@@ -144,20 +170,26 @@ function bodyOf(
|
|
|
144
170
|
.filter((range) => range.kind === 'bracket' && range.from >= symbol.from && range.to <= symbol.to && slice(range.from, range.from + 1) === '{')
|
|
145
171
|
.filter((range) => /^[\s;,]*$/.test(slice(range.to, symbol.to)))
|
|
146
172
|
.sort((left, right) => right.to - left.to || left.from - right.from)[0];
|
|
173
|
+
|
|
147
174
|
const range =
|
|
148
175
|
brace ??
|
|
149
176
|
ranges
|
|
150
177
|
.filter((candidate) => candidate.kind === 'indentation' && candidate.endLine === endLine && candidate.startLine >= startLine)
|
|
151
178
|
.sort((left, right) => left.startLine - right.startLine)[0];
|
|
179
|
+
|
|
152
180
|
if (range === undefined) {
|
|
153
181
|
return undefined;
|
|
154
182
|
}
|
|
183
|
+
|
|
155
184
|
if (symbol.body === 'class') {
|
|
156
185
|
return { range, role: 'class-body' };
|
|
157
186
|
}
|
|
187
|
+
|
|
158
188
|
if (symbol.body === 'value') {
|
|
159
189
|
const signature = slice(symbol.from, range.from);
|
|
190
|
+
|
|
160
191
|
return /=>|\bfunction\b/.test(signature) ? { range, role: 'function-body' } : undefined;
|
|
161
192
|
}
|
|
193
|
+
|
|
162
194
|
return { range, role: symbol.body === 'method' ? 'method-body' : 'function-body' };
|
|
163
195
|
}
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { findMatches, iterateMatches, findMatchFrom, replacementText, type FindM
|
|
|
5
5
|
export { indentationColumn } from './structure.ts';
|
|
6
6
|
export { findDocComments, MAX_DOC_COMMENTS, type DocComment } from './doc-comments.ts';
|
|
7
7
|
export type { FoldHints, FoldRangeHint, FoldRole, FoldSymbolHint, FoldingOptions, FoldingRange } from './structure.ts';
|
|
8
|
+
|
|
8
9
|
export type {
|
|
9
10
|
ChangeSource,
|
|
10
11
|
CommandOptions,
|
|
@@ -18,4 +19,5 @@ export type {
|
|
|
18
19
|
Selection,
|
|
19
20
|
TextEdit
|
|
20
21
|
} from './types.ts';
|
|
22
|
+
|
|
21
23
|
export { changedSpan, changedSpans, type TextSpan } from './text-span.ts';
|
package/src/languages.ts
CHANGED
|
@@ -33,12 +33,15 @@ register(
|
|
|
33
33
|
'typescript javascript typescriptreact javascriptreact tsx jsx ts js mjs cjs mts cts java c cpp c++ csharp cs go rust rs swift kotlin kt scala dart php scss less zig groq json jsonc json5 prisma astro svelte objective-c objc glsl hlsl proto protobuf hcl terraform',
|
|
34
34
|
cLike
|
|
35
35
|
);
|
|
36
|
+
|
|
36
37
|
register('css', { line: null, block: slashStar });
|
|
37
38
|
register('html xml svg xsl markdown md mdx vue', markup);
|
|
39
|
+
|
|
38
40
|
register(
|
|
39
41
|
'python py yaml yml shellscript shell sh bash zsh fish toml ruby rb perl r make makefile docker dockerfile dotenv ignore nix graphql powershell ps1 properties julia jl elixir ex exs coffeescript coffee cmake',
|
|
40
42
|
hash
|
|
41
43
|
);
|
|
44
|
+
|
|
42
45
|
register('ini', { line: ';', block: null });
|
|
43
46
|
register('sql', { line: '--', block: slashStar });
|
|
44
47
|
register('lua', { line: '--', block: { open: '--[[', close: ']]' } });
|
|
@@ -48,18 +51,23 @@ register('plaintext text txt log', none);
|
|
|
48
51
|
/* An id nothing knows has no comment syntax, which toggling a comment answers by doing nothing. */
|
|
49
52
|
export function commentSyntax(language: string, region?: EditRegion | null): CommentSyntax {
|
|
50
53
|
const id = language.toLowerCase();
|
|
54
|
+
|
|
51
55
|
if (region === 'mixed') {
|
|
52
56
|
return none;
|
|
53
57
|
}
|
|
58
|
+
|
|
54
59
|
if (region === 'jsx') {
|
|
55
60
|
return { line: null, block: { open: '{/*', close: '*/}' } };
|
|
56
61
|
}
|
|
62
|
+
|
|
57
63
|
if (id === 'vue' || (id === 'php' && region !== null && region !== undefined)) {
|
|
58
64
|
if (region === 'script') {
|
|
59
65
|
return cLike;
|
|
60
66
|
}
|
|
67
|
+
|
|
61
68
|
return region === 'style' ? { line: null, block: slashStar } : markup;
|
|
62
69
|
}
|
|
70
|
+
|
|
63
71
|
return syntaxes.get(id) ?? none;
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -71,14 +79,17 @@ export function isPlainText(language: string): boolean {
|
|
|
71
79
|
/* The region of a `.vue` file a line is in, from the top-level tags above it. */
|
|
72
80
|
export function vueRegionAt(lineText: (line: number) => string, line: number): VueRegion | null {
|
|
73
81
|
let region: VueRegion | null = null;
|
|
82
|
+
|
|
74
83
|
for (let index = 0; index <= line; index++) {
|
|
75
84
|
const text = lineText(index);
|
|
76
85
|
const open = /^<(template|script|style)\b/.exec(text);
|
|
86
|
+
|
|
77
87
|
if (open) {
|
|
78
88
|
region = open[1] as VueRegion;
|
|
79
89
|
} else if (/^<\/(template|script|style)\s*>/.test(text) && index < line) {
|
|
80
90
|
region = null;
|
|
81
91
|
}
|
|
82
92
|
}
|
|
93
|
+
|
|
83
94
|
return region;
|
|
84
95
|
}
|
package/src/lexical-folds.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { commentSyntax } from './languages.ts';
|
|
2
|
+
import { textStart } from './line-text.ts';
|
|
2
3
|
import type { FoldRole, FoldingRange } from './structure.ts';
|
|
3
4
|
import type { DocumentLine } from './rope.ts';
|
|
4
5
|
|
|
@@ -8,6 +9,7 @@ const IMPORT_WORDS = new Map<string, RegExp>();
|
|
|
8
9
|
function register(languages: string, words: string): void {
|
|
9
10
|
// The word must stand alone, and `import(` and `import.meta` are expressions and not an import.
|
|
10
11
|
const pattern = new RegExp(`^(?:${words})\\b(?![(.=,;:])`);
|
|
12
|
+
|
|
11
13
|
for (const language of languages.split(' ')) {
|
|
12
14
|
IMPORT_WORDS.set(language, pattern);
|
|
13
15
|
}
|
|
@@ -17,6 +19,7 @@ register(
|
|
|
17
19
|
'typescript javascript typescriptreact javascriptreact tsx jsx ts js mjs cjs mts cts vue svelte astro java kotlin scala groovy go swift dart haskell elm',
|
|
18
20
|
'import'
|
|
19
21
|
);
|
|
22
|
+
|
|
20
23
|
register('python py', 'import|from');
|
|
21
24
|
register('php rust rs perl', 'use');
|
|
22
25
|
register('csharp cs', 'using');
|
|
@@ -38,6 +41,7 @@ export interface LexicalFoldOptions {
|
|
|
38
41
|
|
|
39
42
|
function bracketDelta(text: string): number {
|
|
40
43
|
let depth = 0;
|
|
44
|
+
|
|
41
45
|
for (const character of text) {
|
|
42
46
|
if (character === '{' || character === '(' || character === '[') {
|
|
43
47
|
depth++;
|
|
@@ -45,12 +49,8 @@ function bracketDelta(text: string): number {
|
|
|
45
49
|
depth--;
|
|
46
50
|
}
|
|
47
51
|
}
|
|
48
|
-
return depth;
|
|
49
|
-
}
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
export function textStart(line: DocumentLine): number {
|
|
53
|
-
return line.start + (line.text.length - line.text.trimStart().length);
|
|
53
|
+
return depth;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/* A fold of whole lines, from the end of the first to the end of the last. */
|
|
@@ -85,50 +85,64 @@ export function lexicalFolds(lineCount: number, getLine: (line: number) => Docum
|
|
|
85
85
|
let importEnd = -1;
|
|
86
86
|
let commentStart = -1;
|
|
87
87
|
let commentEnd = -1;
|
|
88
|
+
|
|
88
89
|
const flushImports = (): void => {
|
|
89
90
|
if (importStart !== -1 && importEnd > importStart) {
|
|
90
91
|
result.push(rangeOf(importStart, importEnd, getLine, 'imports', 'imports'));
|
|
91
92
|
}
|
|
93
|
+
|
|
92
94
|
importStart = -1;
|
|
93
95
|
};
|
|
96
|
+
|
|
94
97
|
const flushComments = (): void => {
|
|
95
98
|
if (commentStart !== -1 && commentEnd > commentStart) {
|
|
96
99
|
result.push(rangeOf(commentStart, commentEnd, getLine, 'line-comments'));
|
|
97
100
|
}
|
|
101
|
+
|
|
98
102
|
commentStart = -1;
|
|
99
103
|
};
|
|
104
|
+
|
|
100
105
|
for (let line = 0; line < lineCount; line++) {
|
|
101
106
|
const text = getLine(line).text;
|
|
102
107
|
const trimmed = text.trimStart();
|
|
103
108
|
const isRegionMarker = options.regions !== false && (REGION_START.test(text) || REGION_END.test(text));
|
|
109
|
+
|
|
104
110
|
if (isRegionMarker) {
|
|
105
111
|
flushComments();
|
|
112
|
+
|
|
106
113
|
if (REGION_START.test(text)) {
|
|
107
114
|
regions.push(line);
|
|
108
115
|
} else {
|
|
109
116
|
const start = regions.pop();
|
|
117
|
+
|
|
110
118
|
if (start !== undefined && line > start) {
|
|
111
119
|
result.push(rangeOf(start, line, getLine, 'region', 'region'));
|
|
112
120
|
}
|
|
113
121
|
}
|
|
122
|
+
|
|
114
123
|
continue;
|
|
115
124
|
}
|
|
125
|
+
|
|
116
126
|
if (marker !== null && trimmed.startsWith(marker)) {
|
|
117
127
|
commentStart = commentStart === -1 ? line : commentStart;
|
|
118
128
|
commentEnd = line;
|
|
119
129
|
} else {
|
|
120
130
|
flushComments();
|
|
121
131
|
}
|
|
132
|
+
|
|
122
133
|
if (words === undefined) {
|
|
123
134
|
continue;
|
|
124
135
|
}
|
|
136
|
+
|
|
125
137
|
if (words.test(trimmed)) {
|
|
126
138
|
let last = line;
|
|
127
139
|
let depth = bracketDelta(text);
|
|
140
|
+
|
|
128
141
|
while (depth > 0 && last + 1 < lineCount) {
|
|
129
142
|
last++;
|
|
130
143
|
depth += bracketDelta(getLine(last).text);
|
|
131
144
|
}
|
|
145
|
+
|
|
132
146
|
importStart = importStart === -1 ? line : importStart;
|
|
133
147
|
importEnd = last;
|
|
134
148
|
line = last;
|
|
@@ -136,7 +150,9 @@ export function lexicalFolds(lineCount: number, getLine: (line: number) => Docum
|
|
|
136
150
|
flushImports();
|
|
137
151
|
}
|
|
138
152
|
}
|
|
153
|
+
|
|
139
154
|
flushComments();
|
|
140
155
|
flushImports();
|
|
156
|
+
|
|
141
157
|
return result;
|
|
142
158
|
}
|
package/src/lexical.ts
CHANGED
|
@@ -17,7 +17,7 @@ export function startsWord(text: string, at: number): boolean {
|
|
|
17
17
|
*/
|
|
18
18
|
interface LanguageRules {
|
|
19
19
|
slash: boolean;
|
|
20
|
-
/* `any` is a comment wherever it stands, `boundary` only at the start of a word,
|
|
20
|
+
/* `any` is a comment wherever it stands, `boundary` only at the start of a word, which keeps `$#` and `${#list}` in shell code. */
|
|
21
21
|
hash: false | 'any' | 'boundary';
|
|
22
22
|
dash: boolean;
|
|
23
23
|
block: boolean;
|
|
@@ -39,6 +39,7 @@ register(
|
|
|
39
39
|
'typescript javascript typescriptreact javascriptreact tsx jsx ts js mjs cjs mts cts java c cpp c++ csharp cs go rust rs swift kotlin kt scala dart zig groq prisma astro svelte objective-c objc glsl hlsl proto protobuf scss less jsonc json5',
|
|
40
40
|
{ slash: true, block: true, braced: true }
|
|
41
41
|
);
|
|
42
|
+
|
|
42
43
|
register('php', { slash: true, hash: 'any', block: true, braced: true });
|
|
43
44
|
register('vue', { slash: true, block: true, markup: true, braced: true });
|
|
44
45
|
register('hcl terraform', { slash: true, hash: 'any', block: true, braced: true });
|
|
@@ -54,6 +55,33 @@ function rulesOf(language: string): LanguageRules {
|
|
|
54
55
|
return languageRules.get(language.toLowerCase()) ?? NO_RULES;
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
/* What the bracket and typing lexers read of a language, looked up once per scan. */
|
|
59
|
+
export interface LexerRules {
|
|
60
|
+
script: boolean;
|
|
61
|
+
php: boolean;
|
|
62
|
+
hash: boolean;
|
|
63
|
+
hashAtWordStart: boolean;
|
|
64
|
+
dash: boolean;
|
|
65
|
+
slash: boolean;
|
|
66
|
+
block: boolean;
|
|
67
|
+
markup: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function lexerRules(language: string): LexerRules {
|
|
71
|
+
const rules = rulesOf(language);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
script: isScript(language),
|
|
75
|
+
php: isPhp(language),
|
|
76
|
+
hash: hasHashComments(language),
|
|
77
|
+
hashAtWordStart: rules.hash === 'boundary',
|
|
78
|
+
dash: rules.dash,
|
|
79
|
+
slash: rules.slash,
|
|
80
|
+
block: rules.block,
|
|
81
|
+
markup: rules.markup
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
57
85
|
export function isScript(language: string): boolean {
|
|
58
86
|
return /^(typescript|javascript|typescriptreact|javascriptreact|tsx|jsx|ts|js|vue)$/i.test(language);
|
|
59
87
|
}
|
|
@@ -66,28 +94,6 @@ export function hasHashComments(language: string): boolean {
|
|
|
66
94
|
return rulesOf(language).hash !== false;
|
|
67
95
|
}
|
|
68
96
|
|
|
69
|
-
/* Whether a `#` only starts a comment at the start of a word, which keeps `$#` and `${#list}` in shell code. */
|
|
70
|
-
export function hashNeedsWordStart(language: string): boolean {
|
|
71
|
-
return rulesOf(language).hash === 'boundary';
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function hasDashComments(language: string): boolean {
|
|
75
|
-
return rulesOf(language).dash;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function hasBlockComments(language: string): boolean {
|
|
79
|
-
return rulesOf(language).block;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export function hasSlashComments(language: string): boolean {
|
|
83
|
-
return rulesOf(language).slash;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export function hasMarkupComments(language: string): boolean {
|
|
87
|
-
return rulesOf(language).markup;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/* Languages whose blocks are in braces: where a statement can be left open and a `case` label opens a block. */
|
|
91
97
|
export function isBraced(language: string): boolean {
|
|
92
98
|
return rulesOf(language).braced;
|
|
93
99
|
}
|
|
@@ -103,9 +109,11 @@ export function hasSmartSemicolon(language: string): boolean {
|
|
|
103
109
|
|
|
104
110
|
export function isWordCharacter(character: string): boolean {
|
|
105
111
|
const code = character.charCodeAt(0);
|
|
112
|
+
|
|
106
113
|
if (code < 128) {
|
|
107
114
|
return (code >= 97 && code <= 122) || (code >= 65 && code <= 90) || (code >= 48 && code <= 57) || code === 95 || code === 36;
|
|
108
115
|
}
|
|
116
|
+
|
|
109
117
|
return /[\p{L}\p{N}_$]/u.test(character);
|
|
110
118
|
}
|
|
111
119
|
|