reslop 0.2.4 → 0.2.6

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/LICENSE +1 -1
  3. package/README.md +12 -13
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -12
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +48 -18
  9. package/lib/dashboard/git.js +128 -0
  10. package/lib/dashboard/model.js +332 -0
  11. package/lib/dashboard/npm.js +193 -0
  12. package/lib/dashboard/tree.js +278 -0
  13. package/lib/deps-diff.js +196 -404
  14. package/lib/deps.js +240 -399
  15. package/lib/detect.js +8 -18
  16. package/lib/diff/align.js +41 -113
  17. package/lib/diff/diff.js +12 -43
  18. package/lib/diff/display.js +25 -36
  19. package/lib/diff/edit.js +6 -20
  20. package/lib/diff/inline.js +138 -141
  21. package/lib/diff/items.js +33 -47
  22. package/lib/diff/parse.js +28 -56
  23. package/lib/diff/patch.js +12 -33
  24. package/lib/diff/unit.js +90 -206
  25. package/lib/editor.js +98 -55
  26. package/lib/files.js +86 -103
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +182 -344
  29. package/lib/git-reword-todo.js +5 -13
  30. package/lib/git-worktree.js +141 -212
  31. package/lib/git.js +21 -49
  32. package/lib/github.js +67 -181
  33. package/lib/gitlab.js +40 -90
  34. package/lib/highlight/bash.js +55 -177
  35. package/lib/highlight/core.js +157 -132
  36. package/lib/highlight/css.js +25 -58
  37. package/lib/highlight/csv.js +19 -37
  38. package/lib/highlight/dart.js +72 -213
  39. package/lib/highlight/dot.js +16 -26
  40. package/lib/highlight/html.js +42 -63
  41. package/lib/highlight/js.js +177 -506
  42. package/lib/highlight/json.js +17 -37
  43. package/lib/highlight/log.js +22 -35
  44. package/lib/highlight/txt.js +9 -22
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +62 -85
  47. package/lib/manifest.js +67 -130
  48. package/lib/npm-commands.js +119 -189
  49. package/lib/remote.js +141 -197
  50. package/lib/render/branches.js +66 -73
  51. package/lib/render/chrome.js +264 -323
  52. package/lib/render/commits.js +187 -500
  53. package/lib/render/dash-activity.js +212 -0
  54. package/lib/render/dash-blocks.js +245 -0
  55. package/lib/render/dash-table.js +290 -0
  56. package/lib/render/dashboard.js +62 -0
  57. package/lib/render/diff.js +123 -228
  58. package/lib/render/files.js +45 -99
  59. package/lib/render/frame.js +129 -183
  60. package/lib/render/notes.js +144 -160
  61. package/lib/render/npm.js +234 -112
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +131 -170
  64. package/lib/render/render.js +5 -14
  65. package/lib/render/report.js +43 -0
  66. package/lib/render/tiles.js +260 -0
  67. package/lib/render/unit.js +15 -28
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -38
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -78
  72. package/lib/report-test.js +256 -141
  73. package/lib/report-tools.js +96 -161
  74. package/lib/review-merge.js +114 -152
  75. package/lib/review.js +115 -189
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +89 -75
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +82 -63
  80. package/lib/session/branches.js +193 -247
  81. package/lib/session/change-actions.js +171 -214
  82. package/lib/session/commit.js +280 -342
  83. package/lib/session/compose.js +559 -674
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +164 -157
  86. package/lib/session/edit-click.js +57 -0
  87. package/lib/session/files-pane.js +85 -53
  88. package/lib/session/items.js +73 -104
  89. package/lib/session/lifecycle.js +403 -541
  90. package/lib/session/load.js +48 -68
  91. package/lib/session/navigation.js +96 -87
  92. package/lib/session/npm.js +409 -345
  93. package/lib/session/ops.js +196 -63
  94. package/lib/session/pointer.js +23 -15
  95. package/lib/session/progress.js +33 -21
  96. package/lib/session/review.js +33 -54
  97. package/lib/session/tasks.js +333 -0
  98. package/lib/session/templates.js +51 -59
  99. package/lib/session/terminal.js +85 -136
  100. package/lib/session/unit.js +3 -4
  101. package/lib/session/update.js +76 -97
  102. package/lib/session/view.js +52 -83
  103. package/lib/session/watch.js +208 -204
  104. package/lib/session.js +112 -237
  105. package/lib/update.js +45 -116
  106. package/lib/utilities.js +67 -89
  107. package/lib/wrap.js +33 -44
  108. package/package.json +1 -1
  109. package/lib/session/todos.js +0 -293
@@ -1,217 +1,95 @@
1
1
  'use strict';
2
2
 
3
3
  const core = require('./core.js');
4
- const { SQUOTE, emit, wordStyle, readUntilNl } = core;
4
+ const { words, emit, wordStyles, scanWhile, lineEnd } = core;
5
5
 
6
- const BASH_QUOTE = `${SQUOTE}\``;
6
+ const SINGLE_QUOTES = `'\``;
7
7
 
8
- const KEYWORDS = [
9
- 'if',
10
- 'then',
11
- 'else',
12
- 'elif',
13
- 'fi',
14
- 'for',
15
- 'while',
16
- 'until',
17
- 'do',
18
- 'done',
19
- 'case',
20
- 'esac',
21
- 'function',
22
- 'select',
23
- 'in',
24
- 'time',
25
- 'coproc',
26
- ];
8
+ const KEYWORDS = words(`
9
+ if then else elif fi for while until do done case esac function select in
10
+ time coproc
11
+ `);
27
12
 
28
- const BUILTINS = [
29
- 'echo',
30
- 'printf',
31
- 'cd',
32
- 'pwd',
33
- 'exit',
34
- 'export',
35
- 'source',
36
- 'alias',
37
- 'unalias',
38
- 'local',
39
- 'declare',
40
- 'typeset',
41
- 'readonly',
42
- 'unset',
43
- 'shift',
44
- 'read',
45
- 'test',
46
- 'true',
47
- 'false',
48
- 'exec',
49
- 'eval',
50
- 'set',
51
- 'trap',
52
- 'wait',
53
- 'kill',
54
- 'type',
55
- 'command',
56
- 'builtin',
57
- 'return',
58
- 'break',
59
- 'continue',
60
- 'pushd',
61
- 'popd',
62
- 'dirs',
63
- 'getopts',
64
- 'mapfile',
65
- 'readarray',
66
- 'let',
67
- 'umask',
68
- 'ulimit',
69
- 'fg',
70
- 'bg',
71
- 'jobs',
72
- 'hash',
73
- 'help',
74
- 'enable',
75
- 'caller',
76
- 'bind',
77
- 'compgen',
78
- 'complete',
79
- ];
13
+ const BUILTINS = words(`
14
+ echo printf cd pwd exit export source alias unalias local declare typeset
15
+ readonly unset shift read test true false exec eval set trap wait kill type
16
+ command builtin return break continue pushd popd dirs getopts mapfile
17
+ readarray let umask ulimit fg bg jobs hash help enable caller bind compgen
18
+ complete
19
+ `);
80
20
 
81
- const WORD_STYLE = {
82
- ...wordStyle(KEYWORDS, 'control'),
83
- ...wordStyle(BUILTINS, 'function'),
84
- };
21
+ const WORD_STYLE = wordStyles({ control: KEYWORDS, function: BUILTINS });
85
22
 
86
- const readBashVar = (source, i) => {
23
+ const varEnd = (source, i) => {
87
24
  if (source[i + 1] === '{') {
88
- let j = i + 2;
89
- while (j < source.length && source[j] !== '}') j += 1;
90
- if (j < source.length) j += 1;
91
- return { text: source.slice(i, j), end: j };
92
- }
93
- if (/[0-9#?$!*@-]/.test(source[i + 1] || '')) {
94
- return { text: source.slice(i, i + 2), end: i + 2 };
25
+ const close = source.indexOf('}', i + 2);
26
+ return close < 0 ? source.length : close + 1;
95
27
  }
96
- let j = i + 1;
97
- while (j < source.length && /[A-Za-z0-9_]/.test(source[j])) j += 1;
98
- if (j === i + 1) return { text: '$', end: i + 1 };
99
- return { text: source.slice(i, j), end: j };
28
+ if (/[0-9#?$!*@-]/.test(source[i + 1] || '')) return i + 2;
29
+ return scanWhile(source, i + 1, /[A-Za-z0-9_]/);
100
30
  };
101
31
 
102
- const takeQuoted = (source, i) => {
103
- const q = source[i];
104
- let j = i + 1;
32
+ const pushDoubleQuoted = (out, source, i) => {
105
33
  const n = source.length;
106
- while (j < n && source[j] !== q) j += 1;
107
- if (j < n) j += 1;
108
- return { text: source.slice(i, j), end: j };
109
- };
110
-
111
- const takeBashDouble = (source, i, out) => {
112
- let j = i + 1;
113
34
  let chunk = '"';
114
- const n = source.length;
35
+ let j = i + 1;
115
36
  while (j < n && source[j] !== '"') {
116
37
  if (source[j] === '\\' && j + 1 < n) {
117
38
  chunk += source.slice(j, j + 2);
118
39
  j += 2;
119
- continue;
120
- }
121
- if (source[j] === '$') {
40
+ } else if (source[j] === '$') {
122
41
  emit(out, 'string', chunk);
123
42
  chunk = '';
124
- const { text, end } = readBashVar(source, j);
125
- emit(out, 'variable', text);
43
+ const end = varEnd(source, j);
44
+ emit(out, 'variable', source.slice(j, end));
126
45
  j = end;
127
- continue;
46
+ } else {
47
+ chunk += source[j];
48
+ j += 1;
128
49
  }
129
- chunk += source[j];
130
- j += 1;
131
50
  }
132
51
  if (j < n) {
133
52
  chunk += '"';
134
53
  j += 1;
135
54
  }
136
- if (chunk) emit(out, 'string', chunk);
55
+ emit(out, 'string', chunk);
137
56
  return j;
138
57
  };
139
58
 
140
- const bashWordStyle = (word, nextCh) => {
141
- const known = WORD_STYLE[word];
142
- if (known) return known;
143
- if (nextCh === '=') return 'variable';
144
- return 'plain';
145
- };
146
-
147
59
  const highlight = (source) => {
148
60
  const out = [];
149
61
  let i = 0;
150
- const n = source.length;
151
- while (i < n) {
62
+ const take = (style, end) => {
63
+ emit(out, style, source.slice(i, end));
64
+ i = end;
65
+ };
66
+ while (i < source.length) {
152
67
  const ch = source[i];
153
68
  const next = source[i + 1];
154
-
155
69
  if (ch === '#' && (i === 0 || /\s/.test(source[i - 1]))) {
156
- const { text, end } = readUntilNl(source, i);
157
- emit(out, 'comment', text);
158
- i = end;
159
- continue;
70
+ take('comment', lineEnd(source, i));
71
+ } else if (SINGLE_QUOTES.includes(ch)) {
72
+ const close = source.indexOf(ch, i + 1);
73
+ take('string', close < 0 ? source.length : close + 1);
74
+ } else if (ch === '"') {
75
+ i = pushDoubleQuoted(out, source, i);
76
+ } else if (ch === '$') {
77
+ take('variable', varEnd(source, i));
78
+ } else if (ch === '-' && /[A-Za-z0-9]/.test(next || '')) {
79
+ take('attr', scanWhile(source, i + 1, /[A-Za-z0-9_-]/));
80
+ } else if (/[A-Za-z_]/.test(ch)) {
81
+ const end = scanWhile(source, i + 1, /[A-Za-z0-9_]/);
82
+ const word = source.slice(i, end);
83
+ const assign = source[end] === '=' ? 'variable' : 'plain';
84
+ take(WORD_STYLE[word] || assign, end);
85
+ } else if (/[0-9]/.test(ch)) {
86
+ take('number', scanWhile(source, i + 1, /[0-9]/));
87
+ } else if ('|&;<>(){}'.includes(ch)) {
88
+ const doubled = '|&><'.includes(ch) && next === ch;
89
+ take('operator', i + (doubled ? 2 : 1));
90
+ } else {
91
+ take('plain', i + 1);
160
92
  }
161
-
162
- if (BASH_QUOTE.includes(ch)) {
163
- const { text, end } = takeQuoted(source, i);
164
- emit(out, 'string', text);
165
- i = end;
166
- continue;
167
- }
168
-
169
- if (ch === '"') {
170
- i = takeBashDouble(source, i, out);
171
- continue;
172
- }
173
-
174
- if (ch === '$') {
175
- const { text, end } = readBashVar(source, i);
176
- emit(out, 'variable', text);
177
- i = end;
178
- continue;
179
- }
180
-
181
- if (ch === '-' && /[A-Za-z0-9]/.test(next || '')) {
182
- let j = i + 1;
183
- while (j < n && /[A-Za-z0-9_-]/.test(source[j])) j += 1;
184
- emit(out, 'attr', source.slice(i, j));
185
- i = j;
186
- continue;
187
- }
188
-
189
- if (/[A-Za-z_]/.test(ch)) {
190
- let j = i + 1;
191
- while (j < n && /[A-Za-z0-9_]/.test(source[j])) j += 1;
192
- const word = source.slice(i, j);
193
- emit(out, bashWordStyle(word, source[j]), word);
194
- i = j;
195
- continue;
196
- }
197
-
198
- if (/[0-9]/.test(ch)) {
199
- let j = i + 1;
200
- while (j < n && /[0-9]/.test(source[j])) j += 1;
201
- emit(out, 'number', source.slice(i, j));
202
- i = j;
203
- continue;
204
- }
205
-
206
- if ('|&;<>(){}'.includes(ch)) {
207
- const j = i + ('|&><'.includes(ch) && next === ch ? 2 : 1);
208
- emit(out, 'operator', source.slice(i, j));
209
- i = j;
210
- continue;
211
- }
212
-
213
- emit(out, 'plain', ch);
214
- i += 1;
215
93
  }
216
94
  return out;
217
95
  };
@@ -1,34 +1,17 @@
1
1
  'use strict';
2
2
 
3
- const SQUOTE = '\x27';
4
- const QUOTES = `${SQUOTE}"`;
5
- const ANY_QUOTE = `${QUOTES}\``;
6
-
7
- const OP3 = ['===', '!==', '>>>', '**=', '&&=', '||=', '??='];
8
-
9
- const OP2 = [
10
- '==',
11
- '!=',
12
- '<=',
13
- '>=',
14
- '&&',
15
- '||',
16
- '??',
17
- '=>',
18
- '++',
19
- '--',
20
- '<<',
21
- '>>',
22
- '**',
23
- '+=',
24
- '-=',
25
- '*=',
26
- '/=',
27
- '%=',
28
- '&=',
29
- '|=',
30
- '^=',
31
- ];
3
+ const QUOTES = `'"`;
4
+ const ANY_QUOTE = `'"\``;
5
+ const IDENT_START = /[A-Za-z_$]/;
6
+ const IDENT_CHAR = /[A-Za-z0-9_$]/;
7
+ const CONSTANT_RE = /^[A-Z][A-Z0-9_]+$/;
8
+
9
+ const words = (text) => text.trim().split(/\s+/);
10
+
11
+ const OP3 = words('=== !== >>> **= &&= ||= ??=');
12
+ const OP2 = words(
13
+ '== != <= >= && || ?? => ++ -- << >> ** += -= *= /= %= &= |= ^=',
14
+ );
32
15
 
33
16
  const EXPECT_STYLE = {
34
17
  function: 'function',
@@ -36,159 +19,201 @@ const EXPECT_STYLE = {
36
19
  type: 'className',
37
20
  };
38
21
 
22
+ const RADIX_DIGIT = { x: /[0-9a-fA-F_]/, b: /[01_]/, o: /[0-7_]/ };
23
+
39
24
  const emit = (out, style, text) => {
40
- if (!text) return;
41
- out.push({ text, style: style || 'plain' });
25
+ if (text) out.push({ text, style });
42
26
  };
43
27
 
28
+ const highlightLines =
29
+ (highlightLine, separator = '\n') =>
30
+ (source) => {
31
+ const lines = source.split(separator);
32
+ const out = [];
33
+ for (let i = 0; i < lines.length; i += 1) {
34
+ if (i) emit(out, 'plain', '\n');
35
+ for (const token of highlightLine(lines[i])) out.push(token);
36
+ }
37
+ return out;
38
+ };
39
+
44
40
  const tokensText = (out) => {
45
- let s = '';
46
- for (const t of out) s += t.text;
47
- return s;
41
+ let text = '';
42
+ for (const token of out) text += token.text;
43
+ return text;
48
44
  };
49
45
 
50
- const wordStyle = (words, style) => {
46
+ const wordStyles = (groups) => {
51
47
  const table = Object.create(null);
52
- for (const word of words) table[word] = style;
48
+ for (const style of Object.keys(groups)) {
49
+ for (const word of groups[style]) table[word] = style;
50
+ }
53
51
  return table;
54
52
  };
55
53
 
56
- const peekIdent = (source, i) => {
57
- if (!/[A-Za-z_$]/.test(source[i] || '')) return null;
58
- let j = i + 1;
59
- while (j < source.length && /[A-Za-z0-9_$]/.test(source[j])) j += 1;
60
- return source.slice(i, j);
54
+ const appendNode = (out, node) => {
55
+ for (const token of node.tokens) out.push(token);
56
+ return node.end;
61
57
  };
62
58
 
63
- const skipWs = (source, i) => {
64
- while (i < source.length && /\s/.test(source[i])) i += 1;
59
+ const scanWhile = (source, start, re) => {
60
+ let i = start;
61
+ while (i < source.length && re.test(source[i])) i += 1;
65
62
  return i;
66
63
  };
67
64
 
68
- const readUntilNl = (source, i) => {
69
- let j = i;
70
- const n = source.length;
71
- while (j < n && source[j] !== '\n') j += 1;
72
- return { text: source.slice(i, j), end: j };
65
+ const lineEnd = (source, i) => {
66
+ const end = source.indexOf('\n', i);
67
+ return end < 0 ? source.length : end;
73
68
  };
74
69
 
75
- const readBlockComment = (source, i) => {
76
- let j = i + 2;
77
- const n = source.length;
78
- while (j < n && !(source[j] === '*' && source[j + 1] === '/')) {
79
- j += 1;
80
- }
81
- j = Math.min(j + 2, n);
82
- return { text: source.slice(i, j), end: j };
70
+ const blockCommentEnd = (source, i) => {
71
+ const end = source.indexOf('*/', i + 2);
72
+ return end < 0 ? source.length : end + 2;
83
73
  };
84
74
 
85
- const skipQuoted = (source, j) => {
86
- const q = source[j];
87
- j += 1;
88
- const n = source.length;
89
- while (j < n && source[j] !== q) {
75
+ const quotedEnd = (source, start) => {
76
+ const quote = source[start];
77
+ let j = start + 1;
78
+ while (j < source.length && source[j] !== quote) {
90
79
  if (source[j] === '\\') j += 1;
91
80
  j += 1;
92
81
  }
93
- j += 1;
94
- return j;
95
- };
96
-
97
- const readJsNumber = (source, i) => {
98
- const n = source.length;
99
- let j = i;
100
- if (source.startsWith('0x', i) || source.startsWith('0X', i)) {
101
- j += 2;
102
- while (j < n && /[0-9a-fA-F_]/.test(source[j])) j += 1;
103
- } else if (source.startsWith('0b', i) || source.startsWith('0B', i)) {
104
- j += 2;
105
- while (j < n && /[01_]/.test(source[j])) j += 1;
106
- } else if (source.startsWith('0o', i) || source.startsWith('0O', i)) {
107
- j += 2;
108
- while (j < n && /[0-7_]/.test(source[j])) j += 1;
109
- } else {
110
- while (j < n && /[0-9_n.]/.test(source[j])) j += 1;
111
- if ('eE'.includes(source[j])) {
112
- j += 1;
113
- if ('+-'.includes(source[j])) j += 1;
114
- while (j < n && /[0-9_]/.test(source[j])) j += 1;
115
- }
116
- }
117
- return { text: source.slice(i, j), end: j };
82
+ return j + 1;
118
83
  };
119
84
 
120
- const readJsOperator = (source, i) => {
121
- const two = source.slice(i, i + 2);
122
- const three = source.slice(i, i + 3);
85
+ const stringEnd = (source, i) => {
86
+ const quote = source[i];
123
87
  let j = i + 1;
124
- if (OP3.includes(three)) j = i + 3;
125
- else if (OP2.includes(two)) j = i + 2;
126
- return { text: source.slice(i, j), end: j };
127
- };
128
-
129
- const readString = (source, i) => {
130
- const q = source[i];
131
- let j = i + 1;
132
- const n = source.length;
133
- while (j < n) {
88
+ while (j < source.length) {
134
89
  if (source[j] === '\\') {
135
90
  j += 2;
136
91
  continue;
137
92
  }
138
- if (source[j] === q) {
139
- j += 1;
140
- break;
141
- }
93
+ if (source[j] === quote) return j + 1;
142
94
  if (source[j] === '\n') break;
143
95
  j += 1;
144
96
  }
145
- return { text: source.slice(i, j), end: j };
97
+ return j;
98
+ };
99
+
100
+ const numberEnd = (source, i) => {
101
+ const prefix = source[i] === '0' ? source[i + 1] : undefined;
102
+ const radix = prefix ? RADIX_DIGIT[prefix.toLowerCase()] : undefined;
103
+ if (radix) return scanWhile(source, i + 2, radix);
104
+ let j = scanWhile(source, i, /[0-9_n.]/);
105
+ if (source[j] !== 'e' && source[j] !== 'E') return j;
106
+ j += 1;
107
+ if (source[j] === '+' || source[j] === '-') j += 1;
108
+ return scanWhile(source, j, /[0-9_]/);
109
+ };
110
+
111
+ const operatorEnd = (source, i) => {
112
+ if (OP3.includes(source.slice(i, i + 3))) return i + 3;
113
+ if (OP2.includes(source.slice(i, i + 2))) return i + 2;
114
+ return i + 1;
146
115
  };
147
116
 
148
- const readTemplateInterp = (source, j) => {
117
+ const interpEnd = (source, start) => {
149
118
  let depth = 1;
150
- const start = j;
151
- const n = source.length;
152
- while (j < n && depth > 0) {
153
- if (ANY_QUOTE.includes(source[j])) {
154
- j = skipQuoted(source, j);
119
+ let j = start;
120
+ while (j < source.length) {
121
+ const ch = source[j];
122
+ if (ANY_QUOTE.includes(ch)) {
123
+ j = quotedEnd(source, j);
155
124
  continue;
156
125
  }
157
- if (source[j] === '{') depth += 1;
158
- if (source[j] === '}') {
126
+ if (ch === '{') depth += 1;
127
+ if (ch === '}') {
159
128
  depth -= 1;
160
129
  if (depth === 0) break;
161
130
  }
162
131
  j += 1;
163
132
  }
164
- return { expr: source.slice(start, j), end: j };
133
+ return j;
165
134
  };
166
135
 
167
- const styleConstant = ({ word }) =>
168
- /^[A-Z][A-Z0-9_]+$/.test(word) ? 'constant' : null;
136
+ const pushInterpolation = (out, source, start, inner) => {
137
+ const end = interpEnd(source, start);
138
+ for (const token of inner(source.slice(start, end))) out.push(token);
139
+ if (source[end] !== '}') return end;
140
+ emit(out, 'interpolation', '}');
141
+ return end + 1;
142
+ };
169
143
 
170
- const stylePascal = ({ word }) => (/^[A-Z]/.test(word) ? 'className' : null);
144
+ const highlightInterpolated = (source, start, body, kind, inner) => {
145
+ const { style, quote, raw } = kind;
146
+ const n = source.length;
147
+ const out = [];
148
+ emit(out, style, source.slice(start, body));
149
+ let j = body;
150
+ let buf = '';
151
+ const flush = () => {
152
+ emit(out, style, buf);
153
+ buf = '';
154
+ };
155
+ while (j < n) {
156
+ const ch = source[j];
157
+ if (!raw && ch === '\\') {
158
+ flush();
159
+ emit(out, 'escape', source.slice(j, j + 2));
160
+ j += 2;
161
+ continue;
162
+ }
163
+ if (source.startsWith(quote, j)) {
164
+ flush();
165
+ emit(out, style, quote);
166
+ j += quote.length;
167
+ break;
168
+ }
169
+ if (!raw && ch === '$' && source[j + 1] === '{') {
170
+ flush();
171
+ emit(out, 'interpolation', '${');
172
+ j = pushInterpolation(out, source, j + 2, inner);
173
+ continue;
174
+ }
175
+ const isDollar = !raw && ch === '$' && kind.dollarIdent;
176
+ if (isDollar && IDENT_START.test(source[j + 1] || '')) {
177
+ flush();
178
+ const end = scanWhile(source, j + 1, IDENT_CHAR);
179
+ emit(out, 'interpolation', source.slice(j, end));
180
+ j = end;
181
+ continue;
182
+ }
183
+ if (!kind.multiline && ch === '\n') break;
184
+ buf += ch;
185
+ j += 1;
186
+ }
187
+ flush();
188
+ return { tokens: out, end: j };
189
+ };
171
190
 
172
- const styleCall = ({ after }) => (after === '(' ? 'function' : null);
191
+ const nameStyle = (word, after) => {
192
+ if (CONSTANT_RE.test(word)) return 'constant';
193
+ if (/^[A-Z]/.test(word)) return 'className';
194
+ if (after === '(') return 'function';
195
+ return null;
196
+ };
173
197
 
174
198
  module.exports = {
175
- SQUOTE,
176
199
  QUOTES,
177
- ANY_QUOTE,
200
+ IDENT_START,
201
+ IDENT_CHAR,
178
202
  EXPECT_STYLE,
203
+ words,
179
204
  emit,
205
+ highlightLines,
180
206
  tokensText,
181
- wordStyle,
182
- peekIdent,
183
- skipWs,
184
- readUntilNl,
185
- readBlockComment,
186
- skipQuoted,
187
- readJsNumber,
188
- readJsOperator,
189
- readString,
190
- readTemplateInterp,
191
- styleConstant,
192
- stylePascal,
193
- styleCall,
207
+ wordStyles,
208
+ appendNode,
209
+ scanWhile,
210
+ lineEnd,
211
+ blockCommentEnd,
212
+ quotedEnd,
213
+ stringEnd,
214
+ numberEnd,
215
+ operatorEnd,
216
+ pushInterpolation,
217
+ highlightInterpolated,
218
+ nameStyle,
194
219
  };