prettier-plugin-noshift.js 0.0.0 → 0.0.2

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/src/convert.js CHANGED
@@ -1,373 +1,373 @@
1
- /**
2
- * NoShift.js → JavaScript 変換器 (self-contained)
3
- * prettier-plugin-noshift.js 用のスタンドアロン版
4
- */
5
-
6
- // ======
7
- // NoShift.js → JavaScript 置換用マップ
8
- // ======
9
- const noShiftMap = {
10
- "^4^[": "${", // テンプレート式展開開始
11
- "^1": "!",
12
- "^2": '"',
13
- "^4": "$",
14
- "^5": "%",
15
- "^6": "&",
16
- "^7": "'",
17
- "^8": "(",
18
- "^9": ")",
19
- "^-": "=",
20
- "^^": "~",
21
- "^\\": "|",
22
- "^@": "`",
23
- "^[": "{",
24
- "^]": "}",
25
- "^;": "+",
26
- "^:": "*",
27
- "^,": "<",
28
- "^.": ">",
29
- "^/": "?",
30
- };
31
-
32
- /**
33
- * NoShift.js コードを JavaScript コードに変換する。
34
- * @param {string} nsjsCode
35
- * @param {{ capitalizeInStrings?: boolean }} [options={}]
36
- * @returns {string}
37
- */
38
- export function convertNsjsToJs(nsjsCode, options = {}) {
39
- const capitalizeInStrings = options.capitalizeInStrings !== false;
40
- let jsCode = "";
41
- let i = 0;
42
- const len_ns = nsjsCode.length;
43
-
44
- const STATE = {
45
- NORMAL: "NORMAL",
46
- IN_DQ_STRING: "IN_DQ_STRING",
47
- IN_SQ_STRING: "IN_SQ_STRING",
48
- IN_BT_SINGLE_STRING: "IN_BT_SINGLE_STRING",
49
- IN_BT_MULTI_STRING: "IN_BT_MULTI_STRING",
50
- IN_TEMPLATE_EXPRESSION: "IN_TEMPLATE_EXPRESSION",
51
- RAW_DQ_IN_EXPR: "RAW_DQ_IN_EXPR",
52
- RAW_SQ_IN_EXPR: "RAW_SQ_IN_EXPR",
53
- IN_LINE_COMMENT: "IN_LINE_COMMENT",
54
- IN_BLOCK_COMMENT: "IN_BLOCK_COMMENT",
55
- };
56
-
57
- let currentState = STATE.NORMAL;
58
- const stateStack = [];
59
-
60
- const sortedNsKeys = Object.keys(noShiftMap).sort(
61
- (a, b) => b.length - a.length,
62
- );
63
-
64
- function tryConsumeNsjsSequence() {
65
- let allowGeneral = false;
66
- if (
67
- currentState === STATE.NORMAL ||
68
- currentState === STATE.IN_TEMPLATE_EXPRESSION
69
- ) {
70
- allowGeneral = true;
71
- }
72
-
73
- for (const nsKey of sortedNsKeys) {
74
- if (!nsjsCode.startsWith(nsKey, i)) continue;
75
-
76
- // テンプレートリテラル中の式展開開始
77
- if (
78
- (nsKey === "^4^[" || nsjsCode.startsWith("^4[", i)) &&
79
- (currentState === STATE.IN_BT_SINGLE_STRING ||
80
- currentState === STATE.IN_BT_MULTI_STRING)
81
- ) {
82
- jsCode += "${";
83
- i += nsKey === "^4^[" ? nsKey.length : 3;
84
- stateStack.push(currentState);
85
- currentState = STATE.IN_TEMPLATE_EXPRESSION;
86
- return true;
87
- }
88
-
89
- // テンプレート式中の式閉じ
90
- if (nsKey === "^]" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
91
- jsCode += "}";
92
- i += nsKey.length;
93
- currentState = stateStack.pop();
94
- return true;
95
- }
96
-
97
- // ダブルクォート開閉
98
- if (nsKey === "^2" && currentState === STATE.NORMAL) {
99
- jsCode += '"';
100
- i += nsKey.length;
101
- stateStack.push(currentState);
102
- currentState = STATE.IN_DQ_STRING;
103
- return true;
104
- }
105
- if (nsKey === "^2" && currentState === STATE.IN_DQ_STRING) {
106
- jsCode += '"';
107
- i += nsKey.length;
108
- currentState = stateStack.pop();
109
- return true;
110
- }
111
-
112
- // シングルクォート開閉
113
- if (nsKey === "^7" && currentState === STATE.NORMAL) {
114
- jsCode += "'";
115
- i += nsKey.length;
116
- stateStack.push(currentState);
117
- currentState = STATE.IN_SQ_STRING;
118
- return true;
119
- }
120
- if (nsKey === "^7" && currentState === STATE.IN_SQ_STRING) {
121
- jsCode += "'";
122
- i += nsKey.length;
123
- currentState = stateStack.pop();
124
- return true;
125
- }
126
-
127
- // バックチック開閉
128
- if (
129
- nsKey === "^@" &&
130
- (currentState === STATE.NORMAL ||
131
- currentState === STATE.IN_TEMPLATE_EXPRESSION)
132
- ) {
133
- jsCode += "`";
134
- i += nsKey.length;
135
- stateStack.push(currentState);
136
- currentState = STATE.IN_BT_SINGLE_STRING;
137
- return true;
138
- }
139
- if (nsKey === "^@" && currentState === STATE.IN_BT_SINGLE_STRING) {
140
- jsCode += "`";
141
- i += nsKey.length;
142
- currentState = stateStack.pop();
143
- return true;
144
- }
145
-
146
- // テンプレート式中の文字列開閉
147
- if (nsKey === "^2" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
148
- jsCode += '"';
149
- i += nsKey.length;
150
- stateStack.push(currentState);
151
- currentState = STATE.RAW_DQ_IN_EXPR;
152
- return true;
153
- }
154
- if (nsKey === "^7" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
155
- jsCode += "'";
156
- i += nsKey.length;
157
- stateStack.push(currentState);
158
- currentState = STATE.RAW_SQ_IN_EXPR;
159
- return true;
160
- }
161
-
162
- // RAW 文字列終端
163
- if (nsKey === "^2" && currentState === STATE.RAW_DQ_IN_EXPR) {
164
- jsCode += '"';
165
- i += nsKey.length;
166
- currentState = stateStack.pop();
167
- return true;
168
- }
169
- if (nsKey === "^7" && currentState === STATE.RAW_SQ_IN_EXPR) {
170
- jsCode += "'";
171
- i += nsKey.length;
172
- currentState = stateStack.pop();
173
- return true;
174
- }
175
-
176
- // 通常の置換
177
- if (allowGeneral) {
178
- jsCode += noShiftMap[nsKey];
179
- i += nsKey.length;
180
- return true;
181
- }
182
- }
183
-
184
- return false;
185
- }
186
-
187
- // メインループ
188
- while (i < len_ns) {
189
- let consumed = false;
190
-
191
- // エスケープ処理
192
- if (currentState === STATE.IN_DQ_STRING) {
193
- if (nsjsCode.startsWith("\\^3", i)) {
194
- jsCode += "^3";
195
- i += 3;
196
- consumed = true;
197
- } else if (nsjsCode.startsWith("\\^2", i)) {
198
- jsCode += "^2";
199
- i += 3;
200
- consumed = true;
201
- } else if (nsjsCode.startsWith("\\\\", i)) {
202
- jsCode += "\\\\\\\\";
203
- i += 2;
204
- consumed = true;
205
- }
206
- } else if (currentState === STATE.IN_SQ_STRING) {
207
- if (nsjsCode.startsWith("\\^3", i)) {
208
- jsCode += "^3";
209
- i += 3;
210
- consumed = true;
211
- } else if (nsjsCode.startsWith("\\^7", i)) {
212
- jsCode += "^7";
213
- i += 3;
214
- consumed = true;
215
- } else if (nsjsCode.startsWith("\\\\", i)) {
216
- jsCode += "\\\\\\\\";
217
- i += 2;
218
- consumed = true;
219
- }
220
- } else if (currentState === STATE.RAW_DQ_IN_EXPR) {
221
- if (nsjsCode.startsWith("\\^3", i)) {
222
- jsCode += "^3";
223
- i += 3;
224
- consumed = true;
225
- } else if (nsjsCode.startsWith("\\^2", i)) {
226
- jsCode += "^2";
227
- i += 3;
228
- consumed = true;
229
- } else if (nsjsCode.startsWith("\\\\", i)) {
230
- jsCode += "\\\\\\\\";
231
- i += 2;
232
- consumed = true;
233
- } else if (nsjsCode.startsWith("^2", i)) {
234
- jsCode += '"';
235
- i += 2;
236
- currentState = stateStack.pop();
237
- consumed = true;
238
- }
239
- if (consumed) continue;
240
- jsCode += nsjsCode[i];
241
- i += 1;
242
- continue;
243
- } else if (currentState === STATE.RAW_SQ_IN_EXPR) {
244
- if (nsjsCode.startsWith("\\^3", i)) {
245
- jsCode += "^3";
246
- i += 3;
247
- consumed = true;
248
- } else if (nsjsCode.startsWith("\\^7", i)) {
249
- jsCode += "^7";
250
- i += 3;
251
- consumed = true;
252
- } else if (nsjsCode.startsWith("\\\\", i)) {
253
- jsCode += "\\\\\\\\";
254
- i += 2;
255
- consumed = true;
256
- } else if (nsjsCode.startsWith("^7", i)) {
257
- jsCode += "'";
258
- i += 2;
259
- currentState = stateStack.pop();
260
- consumed = true;
261
- }
262
- if (consumed) continue;
263
- jsCode += nsjsCode[i];
264
- i += 1;
265
- continue;
266
- } else if (currentState === STATE.IN_BT_SINGLE_STRING) {
267
- if (nsjsCode.startsWith("\\^3", i)) {
268
- jsCode += "^3";
269
- i += 3;
270
- consumed = true;
271
- } else if (nsjsCode.startsWith("\\^@", i)) {
272
- jsCode += "^@";
273
- i += 3;
274
- consumed = true;
275
- } else if (nsjsCode.startsWith("\\\\", i)) {
276
- jsCode += "\\\\\\\\";
277
- i += 2;
278
- consumed = true;
279
- }
280
- } else if (currentState === STATE.IN_BT_MULTI_STRING) {
281
- if (nsjsCode.startsWith("\\\\", i)) {
282
- jsCode += "\\\\\\\\";
283
- i += 2;
284
- consumed = true;
285
- }
286
- }
287
-
288
- // ^3 大文字化モディファイア
289
- if (
290
- !consumed &&
291
- currentState !== STATE.RAW_DQ_IN_EXPR &&
292
- currentState !== STATE.RAW_SQ_IN_EXPR &&
293
- currentState !== STATE.IN_LINE_COMMENT &&
294
- currentState !== STATE.IN_BLOCK_COMMENT
295
- ) {
296
- if (nsjsCode.startsWith("^3", i)) {
297
- const inString =
298
- currentState === STATE.IN_DQ_STRING ||
299
- currentState === STATE.IN_SQ_STRING ||
300
- currentState === STATE.IN_BT_SINGLE_STRING ||
301
- currentState === STATE.IN_BT_MULTI_STRING;
302
- if (!inString || capitalizeInStrings) {
303
- i += 2;
304
- if (i < len_ns) {
305
- jsCode += nsjsCode[i].toUpperCase();
306
- i += 1;
307
- }
308
- consumed = true;
309
- }
310
- }
311
- }
312
-
313
- // コメント処理
314
- if (!consumed) {
315
- if (currentState === STATE.NORMAL && nsjsCode.startsWith("//", i)) {
316
- jsCode += "//";
317
- i += 2;
318
- stateStack.push(currentState);
319
- currentState = STATE.IN_LINE_COMMENT;
320
- consumed = true;
321
- } else if (currentState === STATE.IN_LINE_COMMENT) {
322
- if (nsjsCode[i] === "\n") {
323
- jsCode += "\n";
324
- i += 1;
325
- currentState = stateStack.pop();
326
- } else {
327
- jsCode += nsjsCode[i];
328
- i += 1;
329
- }
330
- consumed = true;
331
- } else if (
332
- currentState === STATE.NORMAL &&
333
- nsjsCode.startsWith("/^:", i)
334
- ) {
335
- jsCode += "/*";
336
- i += 3;
337
- stateStack.push(currentState);
338
- currentState = STATE.IN_BLOCK_COMMENT;
339
- consumed = true;
340
- } else if (
341
- currentState === STATE.IN_BLOCK_COMMENT &&
342
- nsjsCode.startsWith("^:/", i)
343
- ) {
344
- jsCode += "*/";
345
- i += 3;
346
- currentState = stateStack.pop();
347
- consumed = true;
348
- } else if (currentState === STATE.IN_BLOCK_COMMENT) {
349
- jsCode += nsjsCode[i];
350
- i += 1;
351
- consumed = true;
352
- }
353
- }
354
-
355
- // NoShift シーケンス
356
- if (!consumed) {
357
- consumed = tryConsumeNsjsSequence();
358
- }
359
-
360
- // そのまま出力
361
- if (!consumed) {
362
- jsCode += nsjsCode[i];
363
- i += 1;
364
- }
365
- }
366
-
367
- if (stateStack.length > 0) {
368
- console.warn(
369
- `Warning: Unmatched literal/templating states. Final state: ${currentState}, Remaining stack: ${stateStack.join(", ")}`,
370
- );
371
- }
372
- return jsCode;
373
- }
1
+ /**
2
+ * NoShift.js → JavaScript 変換器 (self-contained)
3
+ * prettier-plugin-noshift.js 用のスタンドアロン版
4
+ */
5
+
6
+ // ======
7
+ // NoShift.js → JavaScript 置換用マップ
8
+ // ======
9
+ const noShiftMap = {
10
+ "^4^[": "${", // テンプレート式展開開始
11
+ "^1": "!",
12
+ "^2": '"',
13
+ "^4": "$",
14
+ "^5": "%",
15
+ "^6": "&",
16
+ "^7": "'",
17
+ "^8": "(",
18
+ "^9": ")",
19
+ "^-": "=",
20
+ "^^": "~",
21
+ "^\\": "|",
22
+ "^@": "`",
23
+ "^[": "{",
24
+ "^]": "}",
25
+ "^;": "+",
26
+ "^:": "*",
27
+ "^,": "<",
28
+ "^.": ">",
29
+ "^/": "?",
30
+ };
31
+
32
+ /**
33
+ * NoShift.js コードを JavaScript コードに変換する。
34
+ * @param {string} nsjsCode
35
+ * @param {{ capitalizeInStrings?: boolean }} [options={}]
36
+ * @returns {string}
37
+ */
38
+ export function convertNsjsToJs(nsjsCode, options = {}) {
39
+ const capitalizeInStrings = options.capitalizeInStrings !== false;
40
+ let jsCode = "";
41
+ let i = 0;
42
+ const len_ns = nsjsCode.length;
43
+
44
+ const STATE = {
45
+ NORMAL: "NORMAL",
46
+ IN_DQ_STRING: "IN_DQ_STRING",
47
+ IN_SQ_STRING: "IN_SQ_STRING",
48
+ IN_BT_SINGLE_STRING: "IN_BT_SINGLE_STRING",
49
+ IN_BT_MULTI_STRING: "IN_BT_MULTI_STRING",
50
+ IN_TEMPLATE_EXPRESSION: "IN_TEMPLATE_EXPRESSION",
51
+ RAW_DQ_IN_EXPR: "RAW_DQ_IN_EXPR",
52
+ RAW_SQ_IN_EXPR: "RAW_SQ_IN_EXPR",
53
+ IN_LINE_COMMENT: "IN_LINE_COMMENT",
54
+ IN_BLOCK_COMMENT: "IN_BLOCK_COMMENT",
55
+ };
56
+
57
+ let currentState = STATE.NORMAL;
58
+ const stateStack = [];
59
+
60
+ const sortedNsKeys = Object.keys(noShiftMap).sort(
61
+ (a, b) => b.length - a.length,
62
+ );
63
+
64
+ function tryConsumeNsjsSequence() {
65
+ let allowGeneral = false;
66
+ if (
67
+ currentState === STATE.NORMAL ||
68
+ currentState === STATE.IN_TEMPLATE_EXPRESSION
69
+ ) {
70
+ allowGeneral = true;
71
+ }
72
+
73
+ for (const nsKey of sortedNsKeys) {
74
+ if (!nsjsCode.startsWith(nsKey, i)) continue;
75
+
76
+ // テンプレートリテラル中の式展開開始
77
+ if (
78
+ (nsKey === "^4^[" || nsjsCode.startsWith("^4[", i)) &&
79
+ (currentState === STATE.IN_BT_SINGLE_STRING ||
80
+ currentState === STATE.IN_BT_MULTI_STRING)
81
+ ) {
82
+ jsCode += "${";
83
+ i += nsKey === "^4^[" ? nsKey.length : 3;
84
+ stateStack.push(currentState);
85
+ currentState = STATE.IN_TEMPLATE_EXPRESSION;
86
+ return true;
87
+ }
88
+
89
+ // テンプレート式中の式閉じ
90
+ if (nsKey === "^]" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
91
+ jsCode += "}";
92
+ i += nsKey.length;
93
+ currentState = stateStack.pop();
94
+ return true;
95
+ }
96
+
97
+ // ダブルクォート開閉
98
+ if (nsKey === "^2" && currentState === STATE.NORMAL) {
99
+ jsCode += '"';
100
+ i += nsKey.length;
101
+ stateStack.push(currentState);
102
+ currentState = STATE.IN_DQ_STRING;
103
+ return true;
104
+ }
105
+ if (nsKey === "^2" && currentState === STATE.IN_DQ_STRING) {
106
+ jsCode += '"';
107
+ i += nsKey.length;
108
+ currentState = stateStack.pop();
109
+ return true;
110
+ }
111
+
112
+ // シングルクォート開閉
113
+ if (nsKey === "^7" && currentState === STATE.NORMAL) {
114
+ jsCode += "'";
115
+ i += nsKey.length;
116
+ stateStack.push(currentState);
117
+ currentState = STATE.IN_SQ_STRING;
118
+ return true;
119
+ }
120
+ if (nsKey === "^7" && currentState === STATE.IN_SQ_STRING) {
121
+ jsCode += "'";
122
+ i += nsKey.length;
123
+ currentState = stateStack.pop();
124
+ return true;
125
+ }
126
+
127
+ // バックチック開閉
128
+ if (
129
+ nsKey === "^@" &&
130
+ (currentState === STATE.NORMAL ||
131
+ currentState === STATE.IN_TEMPLATE_EXPRESSION)
132
+ ) {
133
+ jsCode += "`";
134
+ i += nsKey.length;
135
+ stateStack.push(currentState);
136
+ currentState = STATE.IN_BT_SINGLE_STRING;
137
+ return true;
138
+ }
139
+ if (nsKey === "^@" && currentState === STATE.IN_BT_SINGLE_STRING) {
140
+ jsCode += "`";
141
+ i += nsKey.length;
142
+ currentState = stateStack.pop();
143
+ return true;
144
+ }
145
+
146
+ // テンプレート式中の文字列開閉
147
+ if (nsKey === "^2" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
148
+ jsCode += '"';
149
+ i += nsKey.length;
150
+ stateStack.push(currentState);
151
+ currentState = STATE.RAW_DQ_IN_EXPR;
152
+ return true;
153
+ }
154
+ if (nsKey === "^7" && currentState === STATE.IN_TEMPLATE_EXPRESSION) {
155
+ jsCode += "'";
156
+ i += nsKey.length;
157
+ stateStack.push(currentState);
158
+ currentState = STATE.RAW_SQ_IN_EXPR;
159
+ return true;
160
+ }
161
+
162
+ // RAW 文字列終端
163
+ if (nsKey === "^2" && currentState === STATE.RAW_DQ_IN_EXPR) {
164
+ jsCode += '"';
165
+ i += nsKey.length;
166
+ currentState = stateStack.pop();
167
+ return true;
168
+ }
169
+ if (nsKey === "^7" && currentState === STATE.RAW_SQ_IN_EXPR) {
170
+ jsCode += "'";
171
+ i += nsKey.length;
172
+ currentState = stateStack.pop();
173
+ return true;
174
+ }
175
+
176
+ // 通常の置換
177
+ if (allowGeneral) {
178
+ jsCode += noShiftMap[nsKey];
179
+ i += nsKey.length;
180
+ return true;
181
+ }
182
+ }
183
+
184
+ return false;
185
+ }
186
+
187
+ // メインループ
188
+ while (i < len_ns) {
189
+ let consumed = false;
190
+
191
+ // エスケープ処理
192
+ if (currentState === STATE.IN_DQ_STRING) {
193
+ if (nsjsCode.startsWith("\\^3", i)) {
194
+ jsCode += "^3";
195
+ i += 3;
196
+ consumed = true;
197
+ } else if (nsjsCode.startsWith("\\^2", i)) {
198
+ jsCode += "^2";
199
+ i += 3;
200
+ consumed = true;
201
+ } else if (nsjsCode.startsWith("\\\\", i)) {
202
+ jsCode += "\\\\\\\\";
203
+ i += 2;
204
+ consumed = true;
205
+ }
206
+ } else if (currentState === STATE.IN_SQ_STRING) {
207
+ if (nsjsCode.startsWith("\\^3", i)) {
208
+ jsCode += "^3";
209
+ i += 3;
210
+ consumed = true;
211
+ } else if (nsjsCode.startsWith("\\^7", i)) {
212
+ jsCode += "^7";
213
+ i += 3;
214
+ consumed = true;
215
+ } else if (nsjsCode.startsWith("\\\\", i)) {
216
+ jsCode += "\\\\\\\\";
217
+ i += 2;
218
+ consumed = true;
219
+ }
220
+ } else if (currentState === STATE.RAW_DQ_IN_EXPR) {
221
+ if (nsjsCode.startsWith("\\^3", i)) {
222
+ jsCode += "^3";
223
+ i += 3;
224
+ consumed = true;
225
+ } else if (nsjsCode.startsWith("\\^2", i)) {
226
+ jsCode += "^2";
227
+ i += 3;
228
+ consumed = true;
229
+ } else if (nsjsCode.startsWith("\\\\", i)) {
230
+ jsCode += "\\\\\\\\";
231
+ i += 2;
232
+ consumed = true;
233
+ } else if (nsjsCode.startsWith("^2", i)) {
234
+ jsCode += '"';
235
+ i += 2;
236
+ currentState = stateStack.pop();
237
+ consumed = true;
238
+ }
239
+ if (consumed) continue;
240
+ jsCode += nsjsCode[i];
241
+ i += 1;
242
+ continue;
243
+ } else if (currentState === STATE.RAW_SQ_IN_EXPR) {
244
+ if (nsjsCode.startsWith("\\^3", i)) {
245
+ jsCode += "^3";
246
+ i += 3;
247
+ consumed = true;
248
+ } else if (nsjsCode.startsWith("\\^7", i)) {
249
+ jsCode += "^7";
250
+ i += 3;
251
+ consumed = true;
252
+ } else if (nsjsCode.startsWith("\\\\", i)) {
253
+ jsCode += "\\\\\\\\";
254
+ i += 2;
255
+ consumed = true;
256
+ } else if (nsjsCode.startsWith("^7", i)) {
257
+ jsCode += "'";
258
+ i += 2;
259
+ currentState = stateStack.pop();
260
+ consumed = true;
261
+ }
262
+ if (consumed) continue;
263
+ jsCode += nsjsCode[i];
264
+ i += 1;
265
+ continue;
266
+ } else if (currentState === STATE.IN_BT_SINGLE_STRING) {
267
+ if (nsjsCode.startsWith("\\^3", i)) {
268
+ jsCode += "^3";
269
+ i += 3;
270
+ consumed = true;
271
+ } else if (nsjsCode.startsWith("\\^@", i)) {
272
+ jsCode += "^@";
273
+ i += 3;
274
+ consumed = true;
275
+ } else if (nsjsCode.startsWith("\\\\", i)) {
276
+ jsCode += "\\\\\\\\";
277
+ i += 2;
278
+ consumed = true;
279
+ }
280
+ } else if (currentState === STATE.IN_BT_MULTI_STRING) {
281
+ if (nsjsCode.startsWith("\\\\", i)) {
282
+ jsCode += "\\\\\\\\";
283
+ i += 2;
284
+ consumed = true;
285
+ }
286
+ }
287
+
288
+ // ^3 大文字化モディファイア
289
+ if (
290
+ !consumed &&
291
+ currentState !== STATE.RAW_DQ_IN_EXPR &&
292
+ currentState !== STATE.RAW_SQ_IN_EXPR &&
293
+ currentState !== STATE.IN_LINE_COMMENT &&
294
+ currentState !== STATE.IN_BLOCK_COMMENT
295
+ ) {
296
+ if (nsjsCode.startsWith("^3", i)) {
297
+ const inString =
298
+ currentState === STATE.IN_DQ_STRING ||
299
+ currentState === STATE.IN_SQ_STRING ||
300
+ currentState === STATE.IN_BT_SINGLE_STRING ||
301
+ currentState === STATE.IN_BT_MULTI_STRING;
302
+ if (!inString || capitalizeInStrings) {
303
+ i += 2;
304
+ if (i < len_ns) {
305
+ jsCode += nsjsCode[i].toUpperCase();
306
+ i += 1;
307
+ }
308
+ consumed = true;
309
+ }
310
+ }
311
+ }
312
+
313
+ // コメント処理
314
+ if (!consumed) {
315
+ if (currentState === STATE.NORMAL && nsjsCode.startsWith("//", i)) {
316
+ jsCode += "//";
317
+ i += 2;
318
+ stateStack.push(currentState);
319
+ currentState = STATE.IN_LINE_COMMENT;
320
+ consumed = true;
321
+ } else if (currentState === STATE.IN_LINE_COMMENT) {
322
+ if (nsjsCode[i] === "\n") {
323
+ jsCode += "\n";
324
+ i += 1;
325
+ currentState = stateStack.pop();
326
+ } else {
327
+ jsCode += nsjsCode[i];
328
+ i += 1;
329
+ }
330
+ consumed = true;
331
+ } else if (
332
+ currentState === STATE.NORMAL &&
333
+ nsjsCode.startsWith("/^:", i)
334
+ ) {
335
+ jsCode += "/*";
336
+ i += 3;
337
+ stateStack.push(currentState);
338
+ currentState = STATE.IN_BLOCK_COMMENT;
339
+ consumed = true;
340
+ } else if (
341
+ currentState === STATE.IN_BLOCK_COMMENT &&
342
+ nsjsCode.startsWith("^:/", i)
343
+ ) {
344
+ jsCode += "*/";
345
+ i += 3;
346
+ currentState = stateStack.pop();
347
+ consumed = true;
348
+ } else if (currentState === STATE.IN_BLOCK_COMMENT) {
349
+ jsCode += nsjsCode[i];
350
+ i += 1;
351
+ consumed = true;
352
+ }
353
+ }
354
+
355
+ // NoShift シーケンス
356
+ if (!consumed) {
357
+ consumed = tryConsumeNsjsSequence();
358
+ }
359
+
360
+ // そのまま出力
361
+ if (!consumed) {
362
+ jsCode += nsjsCode[i];
363
+ i += 1;
364
+ }
365
+ }
366
+
367
+ if (stateStack.length > 0) {
368
+ console.warn(
369
+ `Warning: Unmatched literal/templating states. Final state: ${currentState}, Remaining stack: ${stateStack.join(", ")}`,
370
+ );
371
+ }
372
+ return jsCode;
373
+ }