reslop 0.2.5 → 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 (105) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/LICENSE +1 -1
  3. package/README.md +11 -11
  4. package/bin/reslop.js +3 -8
  5. package/lib/ansi.js +32 -19
  6. package/lib/capabilities.js +8 -8
  7. package/lib/cli.js +40 -74
  8. package/lib/clipboard.js +39 -47
  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 +197 -402
  14. package/lib/deps.js +113 -240
  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 +76 -144
  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 +79 -178
  25. package/lib/editor.js +52 -69
  26. package/lib/files.js +71 -89
  27. package/lib/git-branches.js +254 -416
  28. package/lib/git-deps.js +147 -272
  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 +155 -141
  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 +14 -14
  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 +19 -25
  44. package/lib/highlight/txt.js +7 -10
  45. package/lib/highlight.js +17 -46
  46. package/lib/keys.js +49 -82
  47. package/lib/manifest.js +67 -126
  48. package/lib/npm-commands.js +120 -169
  49. package/lib/remote.js +140 -190
  50. package/lib/render/branches.js +63 -61
  51. package/lib/render/chrome.js +220 -333
  52. package/lib/render/commits.js +160 -361
  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 -258
  58. package/lib/render/files.js +40 -85
  59. package/lib/render/frame.js +78 -117
  60. package/lib/render/notes.js +139 -210
  61. package/lib/render/npm.js +213 -177
  62. package/lib/render/present.js +4 -11
  63. package/lib/render/primitives.js +72 -174
  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 -31
  68. package/lib/report-model.js +110 -33
  69. package/lib/report-parse.js +56 -37
  70. package/lib/report-render.js +102 -59
  71. package/lib/report-run.js +87 -77
  72. package/lib/report-test.js +221 -99
  73. package/lib/report-tools.js +96 -154
  74. package/lib/review-merge.js +33 -41
  75. package/lib/review.js +68 -129
  76. package/lib/runs.js +225 -0
  77. package/lib/select.js +53 -91
  78. package/lib/session/accessors.js +14 -21
  79. package/lib/session/actions.js +61 -43
  80. package/lib/session/branches.js +166 -222
  81. package/lib/session/change-actions.js +49 -119
  82. package/lib/session/commit.js +274 -355
  83. package/lib/session/compose.js +556 -714
  84. package/lib/session/dashboard.js +385 -0
  85. package/lib/session/dispatch.js +162 -170
  86. package/lib/session/files-pane.js +76 -44
  87. package/lib/session/items.js +6 -17
  88. package/lib/session/lifecycle.js +393 -466
  89. package/lib/session/load.js +1 -14
  90. package/lib/session/navigation.js +2 -2
  91. package/lib/session/npm.js +403 -420
  92. package/lib/session/ops.js +5 -13
  93. package/lib/session/pointer.js +16 -14
  94. package/lib/session/progress.js +39 -30
  95. package/lib/session/review.js +1 -3
  96. package/lib/session/tasks.js +276 -235
  97. package/lib/session/templates.js +51 -59
  98. package/lib/session/terminal.js +85 -132
  99. package/lib/session/view.js +47 -81
  100. package/lib/session/watch.js +196 -212
  101. package/lib/session.js +81 -161
  102. package/lib/update.js +44 -111
  103. package/lib/utilities.js +46 -88
  104. package/lib/wrap.js +29 -55
  105. package/package.json +1 -1
@@ -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,170 +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
 
44
- const highlightLines = (highlightLine) => (source) => {
45
- const lines = source.split('\n');
46
- const out = [];
47
- for (let i = 0; i < lines.length; i += 1) {
48
- if (i) emit(out, 'plain', '\n');
49
- for (const t of highlightLine(lines[i])) out.push(t);
50
- }
51
- return out;
52
- };
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
+ };
53
39
 
54
40
  const tokensText = (out) => {
55
- let s = '';
56
- for (const t of out) s += t.text;
57
- return s;
41
+ let text = '';
42
+ for (const token of out) text += token.text;
43
+ return text;
58
44
  };
59
45
 
60
- const wordStyle = (words, style) => {
46
+ const wordStyles = (groups) => {
61
47
  const table = Object.create(null);
62
- 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
+ }
63
51
  return table;
64
52
  };
65
53
 
66
- const peekIdent = (source, i) => {
67
- if (!/[A-Za-z_$]/.test(source[i] || '')) return null;
68
- let j = i + 1;
69
- while (j < source.length && /[A-Za-z0-9_$]/.test(source[j])) j += 1;
70
- return source.slice(i, j);
54
+ const appendNode = (out, node) => {
55
+ for (const token of node.tokens) out.push(token);
56
+ return node.end;
71
57
  };
72
58
 
73
- const skipWs = (source, i) => {
74
- 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;
75
62
  return i;
76
63
  };
77
64
 
78
- const readUntilNl = (source, i) => {
79
- let j = i;
80
- const n = source.length;
81
- while (j < n && source[j] !== '\n') j += 1;
82
- 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;
83
68
  };
84
69
 
85
- const readBlockComment = (source, i) => {
86
- let j = i + 2;
87
- const n = source.length;
88
- while (j < n && !(source[j] === '*' && source[j + 1] === '/')) {
89
- j += 1;
90
- }
91
- j = Math.min(j + 2, n);
92
- 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;
93
73
  };
94
74
 
95
- const skipQuoted = (source, j) => {
96
- const q = source[j];
97
- j += 1;
98
- const n = source.length;
99
- 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) {
100
79
  if (source[j] === '\\') j += 1;
101
80
  j += 1;
102
81
  }
103
- j += 1;
104
- return j;
82
+ return j + 1;
105
83
  };
106
84
 
107
- const readJsNumber = (source, i) => {
108
- const n = source.length;
109
- let j = i;
110
- if (source.startsWith('0x', i) || source.startsWith('0X', i)) {
111
- j += 2;
112
- while (j < n && /[0-9a-fA-F_]/.test(source[j])) j += 1;
113
- } else if (source.startsWith('0b', i) || source.startsWith('0B', i)) {
114
- j += 2;
115
- while (j < n && /[01_]/.test(source[j])) j += 1;
116
- } else if (source.startsWith('0o', i) || source.startsWith('0O', i)) {
117
- j += 2;
118
- while (j < n && /[0-7_]/.test(source[j])) j += 1;
119
- } else {
120
- while (j < n && /[0-9_n.]/.test(source[j])) j += 1;
121
- if ('eE'.includes(source[j])) {
122
- j += 1;
123
- if ('+-'.includes(source[j])) j += 1;
124
- while (j < n && /[0-9_]/.test(source[j])) j += 1;
125
- }
126
- }
127
- return { text: source.slice(i, j), end: j };
128
- };
129
-
130
- const readJsOperator = (source, i) => {
131
- const two = source.slice(i, i + 2);
132
- const three = source.slice(i, i + 3);
133
- let j = i + 1;
134
- if (OP3.includes(three)) j = i + 3;
135
- else if (OP2.includes(two)) j = i + 2;
136
- return { text: source.slice(i, j), end: j };
137
- };
138
-
139
- const readString = (source, i) => {
140
- const q = source[i];
85
+ const stringEnd = (source, i) => {
86
+ const quote = source[i];
141
87
  let j = i + 1;
142
- const n = source.length;
143
- while (j < n) {
88
+ while (j < source.length) {
144
89
  if (source[j] === '\\') {
145
90
  j += 2;
146
91
  continue;
147
92
  }
148
- if (source[j] === q) {
149
- j += 1;
150
- break;
151
- }
93
+ if (source[j] === quote) return j + 1;
152
94
  if (source[j] === '\n') break;
153
95
  j += 1;
154
96
  }
155
- 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;
156
115
  };
157
116
 
158
- const readTemplateInterp = (source, j) => {
117
+ const interpEnd = (source, start) => {
159
118
  let depth = 1;
160
- const start = j;
161
- const n = source.length;
162
- while (j < n && depth > 0) {
163
- if (ANY_QUOTE.includes(source[j])) {
164
- 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);
165
124
  continue;
166
125
  }
167
- if (source[j] === '{') depth += 1;
168
- if (source[j] === '}') {
126
+ if (ch === '{') depth += 1;
127
+ if (ch === '}') {
169
128
  depth -= 1;
170
129
  if (depth === 0) break;
171
130
  }
172
131
  j += 1;
173
132
  }
174
- return { expr: source.slice(start, j), end: j };
133
+ return j;
175
134
  };
176
135
 
177
- const styleConstant = ({ word }) =>
178
- /^[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
+ };
179
143
 
180
- 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
+ };
181
190
 
182
- 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
+ };
183
197
 
184
198
  module.exports = {
185
- SQUOTE,
186
199
  QUOTES,
187
- ANY_QUOTE,
200
+ IDENT_START,
201
+ IDENT_CHAR,
188
202
  EXPECT_STYLE,
203
+ words,
189
204
  emit,
190
205
  highlightLines,
191
206
  tokensText,
192
- wordStyle,
193
- peekIdent,
194
- skipWs,
195
- readUntilNl,
196
- readBlockComment,
197
- skipQuoted,
198
- readJsNumber,
199
- readJsOperator,
200
- readString,
201
- readTemplateInterp,
202
- styleConstant,
203
- stylePascal,
204
- 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,
205
219
  };