@danielx/civet 0.8.11 → 0.8.13

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/types.d.ts CHANGED
@@ -49,6 +49,9 @@ declare module "@danielx/civet" {
49
49
  trace?: string
50
50
  parseOptions?: ParseOptions
51
51
  }
52
+ export type GenerateOptions = Omit<CompileOptions, "sourceMap"> & {
53
+ sourceMap?: undefined | SourceMap
54
+ }
52
55
  export type SyncCompileOptions = CompileOptions &
53
56
  { parseOptions?: { comptime?: false } }
54
57
 
@@ -61,6 +64,7 @@ declare module "@danielx/civet" {
61
64
  lines: SourceMapping[][]
62
65
  }
63
66
  }
67
+ export function SourceMap(source: string): SourceMap
64
68
 
65
69
  // TODO: Import ParseError class from Hera
66
70
  export type ParseError = {
@@ -93,7 +97,12 @@ declare module "@danielx/civet" {
93
97
  /** Warning: No caching */
94
98
  export function parseProgram<T extends CompileOptions>(source: string, options?: T):
95
99
  T extends { comptime: true } ? Promise<CivetAST> : CivetAST
96
- export function generate(ast: CivetAST, options?: CompileOptions): string
100
+ export function generate(ast: CivetAST, options?: GenerateOptions): string
101
+
102
+ export const lib: {
103
+ gatherRecursive(ast: CivetAST, predicate: (node: CivetAST) => boolean): CivetAST[]
104
+ gatherRecursiveAll(ast: CivetAST, predicate: (node: CivetAST) => boolean): CivetAST[]
105
+ }
97
106
 
98
107
  const Civet: {
99
108
  version: string
@@ -101,6 +110,9 @@ declare module "@danielx/civet" {
101
110
  isCompileError: typeof isCompileError
102
111
  parse: typeof parse
103
112
  generate: typeof generate
113
+ SourceMap: typeof SourceMap
114
+ ParseError: typeof ParseError
115
+ ParseErrors: typeof ParseErrors
104
116
  sourcemap: {
105
117
  locationTable(input: string): number[]
106
118
  lookupLineColumn(table: number[], pos: number): [number, number]
@@ -68,8 +68,8 @@ function cleanCivetId(id) {
68
68
  function tryStatSync(file) {
69
69
  try {
70
70
  return fs.statSync(file, { throwIfNoEntry: false });
71
- } catch {
72
- return void 0;
71
+ } catch (e) {
72
+ return;
73
73
  }
74
74
  }
75
75
  function slash(p) {
@@ -80,30 +80,44 @@ function normalizePath(id) {
80
80
  }
81
81
  function tryFsResolve(file) {
82
82
  const fileStat = tryStatSync(file);
83
- if (fileStat?.isFile())
83
+ if (fileStat?.isFile()) {
84
84
  return normalizePath(file);
85
- return void 0;
85
+ }
86
+ ;
87
+ return;
86
88
  }
87
89
  function resolveAbsolutePath(rootDir, id, implicitExtension) {
88
90
  const file = import_path.default.join(rootDir, id);
89
91
  return tryFsResolve(file) || implicitExtension && implicitCivet(file) || tryFsResolve(id) || implicitExtension && implicitCivet(id);
90
92
  }
91
93
  function implicitCivet(file) {
92
- if (tryFsResolve(file))
94
+ if (tryFsResolve(file)) {
93
95
  return;
96
+ }
94
97
  const civet2 = file + ".civet";
95
- if (tryFsResolve(civet2))
98
+ if (tryFsResolve(civet2)) {
96
99
  return civet2;
100
+ }
101
+ ;
97
102
  return;
98
103
  }
99
104
  var rawPlugin = (options = {}, meta) => {
100
105
  if (options.dts)
101
106
  options.emitDeclaration = options.dts;
102
- if (options.js)
103
- options.ts = "civet";
104
107
  let compileOptions = {};
108
+ let ts = options.ts;
109
+ if (options.js)
110
+ ts = "civet";
111
+ if (!(ts != null)) {
112
+ console.log('WARNING: You are using the default mode for `options.ts` which is `"civet"`. This mode does not support all TS features. If this is intentional, you should explicitly set `options.ts` to `"civet"`, or choose a different mode.');
113
+ ts = "civet";
114
+ }
115
+ if (!["civet", "esbuild", "tsc", "preserve"].includes(ts)) {
116
+ console.log(`WARNING: Invalid option ts: ${JSON.stringify(ts)}; switching to "civet"`);
117
+ ts = "civet";
118
+ }
105
119
  const transformTS = options.emitDeclaration || options.typecheck;
106
- const outExt = options.outputExtension ?? (options.ts === "preserve" ? ".tsx" : ".jsx");
120
+ const outExt = options.outputExtension ?? (ts === "preserve" ? ".tsx" : ".jsx");
107
121
  const implicitExtension = options.implicitExtension ?? true;
108
122
  let aliasResolver;
109
123
  let fsMap = /* @__PURE__ */ new Map();
@@ -113,7 +127,14 @@ var rawPlugin = (options = {}, meta) => {
113
127
  let esbuildOptions;
114
128
  let configErrors;
115
129
  let configFileNames;
116
- const tsPromise = transformTS || options.ts === "tsc" ? import("typescript").then(($) => $.default) : null;
130
+ let ref;
131
+ if (transformTS || ts === "tsc") {
132
+ ref = import("typescript").then(($1) => $1.default);
133
+ } else {
134
+ ref = void 0;
135
+ }
136
+ ;
137
+ const tsPromise = ref;
117
138
  const getFormatHost = (sys) => {
118
139
  return {
119
140
  getCurrentDirectory: () => sys.getCurrentDirectory(),
@@ -134,39 +155,40 @@ var rawPlugin = (options = {}, meta) => {
134
155
  ...compileOptions.parseOptions,
135
156
  ...options.parseOptions
136
157
  };
137
- if (transformTS || options.ts === "tsc") {
158
+ if (transformTS || ts === "tsc") {
138
159
  let mogrify = function(key) {
139
160
  if (key in config && Array.isArray(config[key])) {
140
161
  return config[key] = config[key].map((item) => {
141
- if (typeof item !== "string")
162
+ if (!(typeof item === "string")) {
142
163
  return item;
164
+ }
143
165
  return item.replace(/\.civet\b(?!\.)/g, ".civet.tsx");
144
166
  });
145
167
  }
146
168
  ;
147
169
  return;
148
170
  };
149
- const ts = await tsPromise;
150
- const tsConfigPath = ts.findConfigFile(process.cwd(), ts.sys.fileExists);
171
+ const ts2 = await tsPromise;
172
+ const tsConfigPath = ts2.findConfigFile(process.cwd(), ts2.sys.fileExists);
151
173
  if (!tsConfigPath) {
152
174
  throw new Error("Could not find 'tsconfig.json'");
153
175
  }
154
- const { config, error } = ts.readConfigFile(
176
+ const { config, error } = ts2.readConfigFile(
155
177
  tsConfigPath,
156
- ts.sys.readFile
178
+ ts2.sys.readFile
157
179
  );
158
180
  if (error) {
159
- console.error(ts.formatDiagnostic(error, getFormatHost(ts.sys)));
181
+ console.error(ts2.formatDiagnostic(error, getFormatHost(ts2.sys)));
160
182
  throw error;
161
183
  }
162
184
  mogrify("files");
163
- const system = { ...ts.sys };
185
+ const system = { ...ts2.sys };
164
186
  const { readDirectory: systemReadDirectory } = system;
165
187
  system.readDirectory = (path2, extensions, excludes, includes, depth) => {
166
188
  extensions = [...extensions ?? [], ".civet"];
167
- return systemReadDirectory(path2, extensions, excludes, includes, depth).map(($1) => $1.endsWith(".civet") ? $1 + ".tsx" : $1);
189
+ return systemReadDirectory(path2, extensions, excludes, includes, depth).map(($2) => $2.endsWith(".civet") ? $2 + ".tsx" : $2);
168
190
  };
169
- const configContents = ts.parseJsonConfigFileContent(
191
+ const configContents = ts2.parseJsonConfigFileContent(
170
192
  config,
171
193
  system,
172
194
  process.cwd()
@@ -175,10 +197,10 @@ var rawPlugin = (options = {}, meta) => {
175
197
  configFileNames = configContents.fileNames;
176
198
  compilerOptions = {
177
199
  ...configContents.options,
178
- target: ts.ScriptTarget.ESNext,
200
+ target: ts2.ScriptTarget.ESNext,
179
201
  composite: false
180
202
  };
181
- compilerOptions.jsx ??= ts.JsxEmit.Preserve;
203
+ compilerOptions.jsx ??= ts2.JsxEmit.Preserve;
182
204
  compilerOptionsWithSourceMap = {
183
205
  ...compilerOptions,
184
206
  sourceMap: true
@@ -188,8 +210,8 @@ var rawPlugin = (options = {}, meta) => {
188
210
  },
189
211
  async buildEnd(useConfigFileNames = false) {
190
212
  if (transformTS) {
191
- const ts = await tsPromise;
192
- const system = tsvfs.createFSBackedSystem(fsMap, process.cwd(), ts);
213
+ const ts2 = await tsPromise;
214
+ const system = tsvfs.createFSBackedSystem(fsMap, process.cwd(), ts2);
193
215
  const {
194
216
  fileExists: systemFileExists,
195
217
  readFile: systemReadFile,
@@ -203,12 +225,17 @@ var rawPlugin = (options = {}, meta) => {
203
225
  return systemFileExists(filename.slice(0, -4));
204
226
  };
205
227
  system.readDirectory = (path2) => {
206
- return systemReadDirectory(path2).map(($2) => $2.endsWith(".civet") ? $2 + ".tsx" : $2);
228
+ return systemReadDirectory(path2).map(($3) => $3.endsWith(".civet") ? $3 + ".tsx" : $3);
229
+ };
230
+ const tsCompileOptions = {
231
+ ...compileOptions,
232
+ rewriteCivetImports: false,
233
+ rewriteTsImports: true
207
234
  };
208
235
  system.readFile = (filename, encoding = "utf-8") => {
209
236
  if (import_path.default.basename(filename) === "package.json") {
210
237
  let recurse = function(node) {
211
- if (node && typeof node === "object") {
238
+ if (node != null && typeof node === "object") {
212
239
  for (const key in node) {
213
240
  const value = node[key];
214
241
  if (typeof value === "string") {
@@ -223,8 +250,9 @@ var rawPlugin = (options = {}, meta) => {
223
250
  }
224
251
  };
225
252
  const json = systemReadFile(filename, encoding);
226
- if (!json)
253
+ if (!json) {
227
254
  return json;
255
+ }
228
256
  const parsed = JSON.parse(json);
229
257
  let modified = false;
230
258
  recurse(parsed.imports);
@@ -238,58 +266,58 @@ var rawPlugin = (options = {}, meta) => {
238
266
  const rawCivetSource = fs.readFileSync(civetFilename, {
239
267
  encoding
240
268
  });
241
- const compiledTS = import_civet.default.compile(rawCivetSource, {
242
- ...compileOptions,
269
+ const { code: compiledTS, sourceMap } = import_civet.default.compile(rawCivetSource, {
270
+ ...tsCompileOptions,
243
271
  filename,
244
272
  js: false,
273
+ sourceMap: true,
245
274
  sync: true
246
275
  // TS readFile API seems to need to be synchronous
247
276
  });
248
277
  fsMap.set(filename, compiledTS);
278
+ sourceMaps.set(filename, sourceMap);
249
279
  return compiledTS;
250
280
  };
251
281
  const host = tsvfs.createVirtualCompilerHost(
252
282
  system,
253
283
  compilerOptions,
254
- ts
284
+ ts2
255
285
  );
256
- const program = ts.createProgram({
286
+ const program = ts2.createProgram({
257
287
  rootNames: useConfigFileNames ? configFileNames : [...fsMap.keys()],
258
288
  options: compilerOptions,
259
289
  host: host.compilerHost
260
290
  });
261
- const diagnostics = ts.getPreEmitDiagnostics(program).map(
262
- (diagnostic) => {
263
- const file = diagnostic.file;
264
- if (!file)
265
- return diagnostic;
266
- const sourceMap = sourceMaps.get(file.fileName);
267
- if (!sourceMap)
268
- return diagnostic;
269
- const sourcemapLines = sourceMap.data.lines;
270
- const range = (0, import_ts_diagnostic.remapRange)(
271
- {
272
- start: diagnostic.start || 0,
273
- end: (diagnostic.start || 0) + (diagnostic.length || 1)
274
- },
275
- sourcemapLines
276
- );
277
- return {
278
- ...diagnostic,
279
- messageText: (0, import_ts_diagnostic.flattenDiagnosticMessageText)(diagnostic.messageText),
280
- length: diagnostic.length,
281
- start: range.start
282
- };
283
- }
284
- );
291
+ const diagnostics = ts2.getPreEmitDiagnostics(program).map((diagnostic) => {
292
+ const file = diagnostic.file;
293
+ if (!file)
294
+ return diagnostic;
295
+ const sourceMap = sourceMaps.get(file.fileName);
296
+ if (!sourceMap)
297
+ return diagnostic;
298
+ const sourcemapLines = sourceMap.data.lines;
299
+ const range = (0, import_ts_diagnostic.remapRange)(
300
+ {
301
+ start: diagnostic.start || 0,
302
+ end: (diagnostic.start || 0) + (diagnostic.length || 1)
303
+ },
304
+ sourcemapLines
305
+ );
306
+ return {
307
+ ...diagnostic,
308
+ messageText: (0, import_ts_diagnostic.flattenDiagnosticMessageText)(diagnostic.messageText),
309
+ length: diagnostic.length,
310
+ start: range.start
311
+ };
312
+ });
285
313
  if (configErrors?.length) {
286
314
  diagnostics.unshift(...configErrors);
287
315
  }
288
316
  if (diagnostics.length > 0) {
289
317
  console.error(
290
- ts.formatDiagnosticsWithColorAndContext(
318
+ ts2.formatDiagnosticsWithColorAndContext(
291
319
  diagnostics,
292
- getFormatHost(ts.sys)
320
+ getFormatHost(ts2.sys)
293
321
  )
294
322
  );
295
323
  if (options.typecheck) {
@@ -337,9 +365,9 @@ var rawPlugin = (options = {}, meta) => {
337
365
  } else {
338
366
  console.log(`WARNING: No .d.ts extension in ${filePath}`);
339
367
  }
340
- let ref;
341
- if (ref = filePath.match(civetExtension)) {
342
- const match = ref;
368
+ let ref1;
369
+ if (ref1 = filePath.match(civetExtension)) {
370
+ const match = ref1;
343
371
  filePath = filePath.slice(0, -match[0].length);
344
372
  } else {
345
373
  console.log(`WARNING: No .civet extension in ${filePath}`);
@@ -375,6 +403,7 @@ var rawPlugin = (options = {}, meta) => {
375
403
  }
376
404
  }
377
405
  },
406
+ // forceDtsEmit
378
407
  resolveId(id, importer, options2) {
379
408
  if (aliasResolver != null) {
380
409
  id = aliasResolver(id);
@@ -386,14 +415,14 @@ var rawPlugin = (options = {}, meta) => {
386
415
  }
387
416
  let postfix;
388
417
  ({ id, postfix } = cleanCivetId(id));
389
- let ref1;
418
+ let ref2;
390
419
  if (import_path.default.isAbsolute(id)) {
391
- ref1 = resolveAbsolutePath(rootDir, id, implicitExtension);
420
+ ref2 = resolveAbsolutePath(rootDir, id, implicitExtension);
392
421
  } else {
393
- ref1 = import_path.default.resolve(import_path.default.dirname(importer ?? ""), id);
422
+ ref2 = import_path.default.resolve(import_path.default.dirname(importer ?? ""), id);
394
423
  }
395
424
  ;
396
- let resolvedId = ref1;
425
+ let resolvedId = ref2;
397
426
  if (!resolvedId)
398
427
  return null;
399
428
  if (!resolvedId.endsWith(".civet")) {
@@ -414,8 +443,9 @@ var rawPlugin = (options = {}, meta) => {
414
443
  },
415
444
  async load(id) {
416
445
  const match = isCivetTranspiled.exec(id);
417
- if (!match)
446
+ if (!match) {
418
447
  return null;
448
+ }
419
449
  const basename = id.slice(0, match.index + match[1].length);
420
450
  const filename = import_path.default.resolve(rootDir, basename);
421
451
  let mtime;
@@ -429,82 +459,96 @@ var rawPlugin = (options = {}, meta) => {
429
459
  const rawCivetSource = await fs.promises.readFile(filename, "utf-8");
430
460
  this.addWatchFile(filename);
431
461
  let compiled;
462
+ let sourceMap;
432
463
  const civetOptions = {
433
464
  ...compileOptions,
434
465
  filename: id,
435
- sourceMap: true
466
+ errors: []
436
467
  };
437
- if (options.ts === "civet" && !transformTS) {
438
- compiled = await import_civet.default.compile(rawCivetSource, {
468
+ function checkErrors() {
469
+ if (civetOptions.errors.length) {
470
+ throw new import_civet.default.ParseErrors(civetOptions.errors);
471
+ }
472
+ ;
473
+ return;
474
+ }
475
+ const ast = await import_civet.default.compile(rawCivetSource, {
476
+ ...civetOptions,
477
+ ast: true
478
+ });
479
+ const civetSourceMap = (0, import_civet.SourceMap)(rawCivetSource);
480
+ if (ts === "civet") {
481
+ compiled = await import_civet.default.generate(ast, {
439
482
  ...civetOptions,
440
- js: true
483
+ js: true,
484
+ sourceMap: civetSourceMap
441
485
  });
486
+ sourceMap = civetSourceMap;
487
+ checkErrors();
442
488
  } else {
443
- const compiledTS = await import_civet.default.compile(rawCivetSource, {
489
+ const compiledTS = await import_civet.default.generate(ast, {
444
490
  ...civetOptions,
445
- js: false
491
+ js: false,
492
+ sourceMap: civetSourceMap
446
493
  });
447
- const resolved = filename + outExt;
448
- sourceMaps.set(
449
- resolved,
450
- compiledTS.sourceMap
451
- );
452
- if (transformTS) {
453
- const tsx = filename + ".tsx";
454
- fsMap.set(tsx, compiledTS.code);
455
- const slashed = slash(tsx);
456
- if (tsx !== slashed)
457
- fsMap.set(slashed, compiledTS.code);
458
- }
459
- switch (options.ts) {
494
+ checkErrors();
495
+ switch (ts) {
460
496
  case "esbuild": {
461
497
  const esbuildTransform = (await import("esbuild")).transform;
462
- const result = await esbuildTransform(compiledTS.code, {
498
+ const result = await esbuildTransform(compiledTS, {
463
499
  jsx: "preserve",
464
500
  loader: "tsx",
465
501
  sourcefile: id,
466
502
  sourcemap: "external"
467
503
  });
468
- compiled = { code: result.code, sourceMap: result.map };
504
+ compiled = result.code;
505
+ sourceMap = result.map;
469
506
  break;
470
507
  }
471
508
  case "tsc": {
472
509
  const tsTranspile = (await tsPromise).transpileModule;
473
- const result = tsTranspile(
474
- compiledTS.code,
475
- { compilerOptions: compilerOptionsWithSourceMap }
476
- );
477
- compiled = {
478
- code: result.outputText,
479
- sourceMap: result.sourceMapText
480
- };
510
+ const result = tsTranspile(compiledTS, {
511
+ compilerOptions: compilerOptionsWithSourceMap
512
+ });
513
+ compiled = result.outputText;
514
+ sourceMap = result.sourceMapText;
481
515
  break;
482
516
  }
483
517
  case "preserve": {
484
518
  compiled = compiledTS;
485
519
  break;
486
520
  }
487
- case "civet":
488
- default: {
489
- compiled = await import_civet.default.compile(rawCivetSource, {
490
- ...civetOptions,
491
- js: true
492
- });
493
- if (options.ts == void 0) {
494
- console.log(
495
- 'WARNING: You are using the default mode for `options.ts` which is `"civet"`. This mode does not support all TS features. If this is intentional, you should explicitly set `options.ts` to `"civet"`, or choose a different mode.'
496
- );
497
- }
498
- break;
521
+ }
522
+ }
523
+ if (transformTS) {
524
+ for (let ref3 = import_civet.lib.gatherRecursive(ast, ($) => $.type === "ModuleSpecifier"), i = 0, len = ref3.length; i < len; i++) {
525
+ const _spec = ref3[i];
526
+ const spec = _spec;
527
+ if (spec.module?.input) {
528
+ spec.module.token = spec.module.input.replace(/\.([mc])?ts(['"])$/, ".$1js$2");
499
529
  }
500
530
  }
531
+ const compiledTS = await import_civet.default.generate(ast, {
532
+ ...civetOptions,
533
+ js: false,
534
+ sourceMap: civetSourceMap
535
+ });
536
+ checkErrors();
537
+ const tsx = filename + ".tsx";
538
+ fsMap.set(tsx, compiledTS);
539
+ sourceMaps.set(tsx, civetSourceMap);
540
+ const slashed = slash(tsx);
541
+ if (!(tsx === slashed)) {
542
+ fsMap.set(slashed, compiledTS);
543
+ sourceMaps.set(slashed, civetSourceMap);
544
+ }
501
545
  }
502
- const jsonSourceMap = compiled.sourceMap && (typeof compiled.sourceMap === "string" ? JSON.parse(compiled.sourceMap) : compiled.sourceMap.json(
546
+ const jsonSourceMap = sourceMap && (typeof sourceMap === "string" ? JSON.parse(sourceMap) : sourceMap.json(
503
547
  import_path.default.basename(id.replace(/\.[jt]sx$/, "")),
504
548
  import_path.default.basename(id)
505
549
  ));
506
550
  let transformed = {
507
- code: compiled.code,
551
+ code: compiled,
508
552
  map: jsonSourceMap
509
553
  };
510
554
  if (options.transformOutput) {
@@ -515,7 +559,7 @@ var rawPlugin = (options = {}, meta) => {
515
559
  },
516
560
  esbuild: {
517
561
  config(options2) {
518
- return esbuildOptions = options2;
562
+ esbuildOptions = options2;
519
563
  }
520
564
  },
521
565
  vite: {
@@ -562,9 +606,9 @@ var rawPlugin = (options = {}, meta) => {
562
606
  compiler.options.resolve.extensions.unshift(".civet");
563
607
  }
564
608
  return aliasResolver = (id) => {
565
- let ref2;
566
- for (const key in ref2 = compiler.options.resolve.alias) {
567
- const value = ref2[key];
609
+ let ref4;
610
+ for (const key in ref4 = compiler.options.resolve.alias) {
611
+ const value = ref4[key];
568
612
  if (key.endsWith("$")) {
569
613
  if (id === key.slice(0, -1)) {
570
614
  return typeof value === "string" ? value : "\0";