@abreen/tada 1.4.1 → 1.5.1

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 (103) hide show
  1. package/README.md +4 -2
  2. package/bin/tada.ts +81 -57
  3. package/build/apply-base-path-plugin.ts +22 -6
  4. package/build/code.test.ts +108 -1
  5. package/build/colors.test.ts +66 -0
  6. package/build/columns-plugin.ts +116 -0
  7. package/build/content-watch.ts +30 -21
  8. package/build/copy.ts +1 -1
  9. package/build/external-links-plugin.ts +1 -1
  10. package/build/generate-content-assets.ts +48 -6
  11. package/build/generate-favicon.ts +1 -1
  12. package/build/generate-fonts.ts +1 -1
  13. package/build/generate-katex-assets.ts +1 -1
  14. package/build/log.test.ts +7 -1
  15. package/build/log.ts +4 -1
  16. package/build/markdown-plugins.test.ts +65 -3
  17. package/build/pagefind.ts +1 -1
  18. package/build/pipeline.ts +4 -20
  19. package/build/serve.test.ts +59 -0
  20. package/build/serve.ts +29 -63
  21. package/build/templates.ts +2 -2
  22. package/build/toc-plugin.test.ts +40 -25
  23. package/build/toc-plugin.ts +9 -2
  24. package/build/{types.ts → types.d.ts} +88 -1
  25. package/build/util.ts +1 -1
  26. package/build/utils/code.ts +76 -3
  27. package/build/utils/content-files.test.ts +56 -0
  28. package/build/utils/content-files.ts +15 -11
  29. package/build/utils/file-types.test.ts +18 -0
  30. package/build/utils/file-types.ts +4 -0
  31. package/build/utils/include.test.ts +117 -0
  32. package/build/utils/include.ts +53 -0
  33. package/build/utils/jdi-runner/TraceRunner.java +416 -0
  34. package/build/utils/literate-java.ts +2 -2
  35. package/build/utils/markdown.ts +32 -14
  36. package/build/utils/paths.ts +1 -1
  37. package/build/utils/render.ts +102 -11
  38. package/build/utils/shiki-highlighter.ts +1 -1
  39. package/build/utils/trace-layout.test.ts +570 -0
  40. package/build/utils/trace-layout.ts +848 -0
  41. package/build/utils/trace-svg.test.ts +425 -0
  42. package/build/utils/trace-svg.ts +905 -0
  43. package/build/utils/trace.test.ts +169 -0
  44. package/build/utils/trace.ts +382 -0
  45. package/build/validate-internal-links-plugin.test.ts +30 -2
  46. package/build/validate-internal-links-plugin.ts +3 -3
  47. package/build/watch-reload-client.ts +4 -20
  48. package/build/watch.ts +436 -448
  49. package/init/content/index.md +10 -5
  50. package/init/content/labs/00/index.md +1 -1
  51. package/init/content/labs/01/SearchTreeDemo.java +31 -0
  52. package/init/content/labs/01/TraceDemo.java +22 -0
  53. package/init/content/labs/01/index.md +27 -0
  54. package/init/content/labs/index.md +2 -0
  55. package/init/content/lectures/01/Rectangle.java +2 -0
  56. package/init/content/lectures/01/index.md +2 -1
  57. package/init/content/lectures/01/rectangle.py +45 -0
  58. package/init/content/lectures/02/_pr1.md +5 -0
  59. package/init/content/lectures/02/index.md +11 -0
  60. package/init/content/lectures/02/subdir/_foobar.html +3 -0
  61. package/init/content/lectures/02/subdir/_pr2.md +6 -0
  62. package/init/content/lectures/index.md +3 -0
  63. package/init/content/markdown.md +30 -0
  64. package/package.json +21 -4
  65. package/src/_base.scss +13 -2
  66. package/src/_layout.scss +6 -5
  67. package/src/anchor/index.test.ts +64 -0
  68. package/src/code/index.test.ts +71 -0
  69. package/src/code/style.scss +23 -0
  70. package/src/code.scss +5 -3
  71. package/src/header/_base.scss +48 -9
  72. package/src/header/index.test.ts +89 -0
  73. package/src/header/index.ts +1 -1
  74. package/src/header/style.scss +1 -5
  75. package/src/index.ts +18 -20
  76. package/src/literate/style.scss +15 -7
  77. package/src/navigate/eligible.test.ts +101 -0
  78. package/src/navigate/eligible.ts +62 -0
  79. package/src/navigate/index.test.ts +82 -0
  80. package/src/navigate/index.ts +365 -0
  81. package/src/navigate/lifecycle.test.ts +26 -0
  82. package/src/navigate/lifecycle.ts +65 -0
  83. package/src/navigate/style.scss +61 -0
  84. package/src/print/index.test.ts +71 -0
  85. package/src/question/index.test.ts +82 -0
  86. package/src/question/style.scss +12 -0
  87. package/src/search/index.ts +38 -14
  88. package/src/search/style.scss +23 -14
  89. package/src/style.scss +25 -12
  90. package/src/timezone/index.test.ts +301 -1
  91. package/src/timezone/index.ts +68 -56
  92. package/src/toc/index.test.ts +237 -0
  93. package/src/toc/index.ts +29 -69
  94. package/src/toc/style.scss +17 -0
  95. package/src/top/index.test.ts +46 -0
  96. package/src/top/index.ts +2 -2
  97. package/src/trace/index.test.ts +554 -0
  98. package/src/trace/index.ts +258 -0
  99. package/src/trace/style.scss +210 -0
  100. package/src/trace/types.d.ts +47 -0
  101. package/src/util.test.ts +135 -0
  102. package/templates/_top.html +23 -22
  103. package/types/jsdom.d.ts +9 -0
@@ -12,8 +12,11 @@ import {
12
12
  extractJavaMethodToc,
13
13
  renderCodeSegment,
14
14
  renderCodeWithComments,
15
+ rewriteProseLinks,
15
16
  } from './code';
16
17
  import { extensionIsMarkdown } from './file-types';
18
+ import { createTraceHelpers } from './trace';
19
+ import { createIncludeFunction } from './include';
17
20
  import { createApplyBasePath, normalizeOutputPath } from './paths';
18
21
  import { parseFrontMatterAndContent } from './front-matter';
19
22
  import { createMarkdown } from './markdown';
@@ -34,7 +37,7 @@ import type {
34
37
  RenderCopiedContentOptions,
35
38
  } from '../types';
36
39
 
37
- const log = makeLogger(__filename);
40
+ const log = makeLogger(import.meta.url);
38
41
 
39
42
  const REQUIRED_FRONT_MATTER_FIELDS = ['title'];
40
43
 
@@ -95,7 +98,7 @@ function createTemplateParameters({
95
98
  subPath,
96
99
  }: TemplateParametersInput): Record<string, unknown> {
97
100
  return {
98
- ...(siteVariables.vars || {}),
101
+ vars: siteVariables.vars || {},
99
102
  ...createGlobals(pageVariables, siteVariables, subPath),
100
103
  site: siteVariables,
101
104
  base: siteVariables.base,
@@ -174,19 +177,29 @@ export function renderPlainTextPageAsset({
174
177
  siteVariables,
175
178
  validInternalTargets,
176
179
  assetFiles,
180
+ literateJavaOutputPaths,
181
+ traceCache,
182
+ javacAvailable,
177
183
  }: RenderPlainTextOptions): Asset[] {
178
184
  const { dir, name, ext } = path.parse(filePath);
179
185
  const subPath = path.relative(contentDir, path.join(dir, name));
180
186
  const applyBasePath = createApplyBasePath(siteVariables);
181
187
 
182
188
  log.info`Rendering page ${B`${subPath + ext}`}`;
183
- const { content, pageVariables, tocItems } = renderPlainTextContent(
189
+ const { content, pageVariables, tocItems, alertIds } = renderPlainTextContent(
184
190
  filePath,
185
191
  subPath,
186
192
  siteVariables,
187
193
  applyBasePath,
188
194
  validInternalTargets,
189
- { validateInternalLinks: extensionIsMarkdown(ext.toLowerCase()) },
195
+ {
196
+ validateInternalLinks: extensionIsMarkdown(ext.toLowerCase()),
197
+ traceCache,
198
+ contentDir,
199
+ distDir,
200
+ literateJavaOutputPaths,
201
+ javacAvailable,
202
+ },
190
203
  );
191
204
 
192
205
  validateFrontMatter(pageVariables, filePath);
@@ -198,6 +211,7 @@ export function renderPlainTextPageAsset({
198
211
  if (pageVariables.toc && tocItems) {
199
212
  pageVariables.tocHtml = generateTocHtml(
200
213
  tocItems as Parameters<typeof generateTocHtml>[0],
214
+ alertIds,
201
215
  );
202
216
  }
203
217
 
@@ -238,9 +252,15 @@ export function renderCodePageAsset({
238
252
  const applyBasePath = createApplyBasePath(siteVariables);
239
253
  const lang = siteVariables.codeLanguages![ext.slice(1).toLowerCase()];
240
254
  const sourceCode = fs.readFileSync(filePath, 'utf-8');
255
+ const pageDirPath = path.relative(contentDir, dir);
241
256
 
242
257
  log.info`Rendering code page ${B`${subPath + ext}`}`;
243
- const content = renderCodeWithComments(sourceCode, lang, siteVariables);
258
+ const content = renderCodeWithComments(
259
+ sourceCode,
260
+ lang,
261
+ siteVariables,
262
+ pageDirPath,
263
+ );
244
264
  const codeFilePath = applyBasePath(
245
265
  normalizeOutputPath(`/${toContentAssetPath(contentDir, filePath)}`),
246
266
  );
@@ -275,7 +295,10 @@ export function renderCodePageAsset({
275
295
 
276
296
  return [
277
297
  {
278
- assetPath: toContentAssetPath(contentDir, path.join(dir, `${name}.html`)),
298
+ assetPath: toContentAssetPath(
299
+ contentDir,
300
+ path.join(dir, `${name}${ext}.html`),
301
+ ),
279
302
  content: html,
280
303
  },
281
304
  ];
@@ -284,11 +307,24 @@ export function renderCodePageAsset({
284
307
  export function renderCopiedContentAsset({
285
308
  filePath,
286
309
  contentDir,
310
+ siteVariables,
287
311
  }: RenderCopiedContentOptions): Asset[] {
288
312
  const label = 'Copying source file';
289
313
  const relPath = toContentAssetPath(contentDir, filePath);
290
314
 
291
315
  log.info`${label} ${B`${relPath}`}`;
316
+
317
+ if (filePath.endsWith('.java') && isFeatureEnabled(siteVariables, 'code')) {
318
+ const sourceCode = fs.readFileSync(filePath, 'utf-8');
319
+ const pageDirPath = path.relative(contentDir, path.dirname(filePath));
320
+ const rewrittenLines = rewriteProseLinks(
321
+ sourceCode.split('\n'),
322
+ siteVariables,
323
+ pageDirPath,
324
+ );
325
+ return [{ assetPath: relPath, content: rewrittenLines.join('\n') }];
326
+ }
327
+
292
328
  return [{ assetPath: relPath, content: fs.readFileSync(filePath) }];
293
329
  }
294
330
 
@@ -299,11 +335,34 @@ function renderPlainTextContent(
299
335
  siteVariables: SiteVariables,
300
336
  applyBasePath: (subPath: string) => string,
301
337
  validInternalTargets: Set<string>,
302
- { validateInternalLinks = true } = {},
338
+ {
339
+ validateInternalLinks = true,
340
+ traceCache,
341
+ contentDir,
342
+ distDir,
343
+ literateJavaOutputPaths,
344
+ javacAvailable,
345
+ }: {
346
+ validateInternalLinks?: boolean;
347
+ traceCache?: Map<
348
+ string,
349
+ {
350
+ manifestUrl: string;
351
+ highlightedSource: string;
352
+ totalSteps: number;
353
+ mtime: number;
354
+ }
355
+ >;
356
+ contentDir?: string;
357
+ distDir?: string;
358
+ literateJavaOutputPaths?: Set<string>;
359
+ javacAvailable?: boolean;
360
+ } = {},
303
361
  ): {
304
362
  content: string | null;
305
363
  pageVariables: Record<string, unknown>;
306
364
  tocItems: unknown[] | null;
365
+ alertIds: string[];
307
366
  } {
308
367
  const sourceUrlPath = `/${subPath}.html`;
309
368
  const md = createMarkdown(siteVariables, {
@@ -316,6 +375,8 @@ function renderPlainTextContent(
316
375
  ? Object.keys(siteVariables.codeLanguages!)
317
376
  : [],
318
377
  },
378
+ literateJavaOutputPaths,
379
+ sourceUrlPath,
319
380
  });
320
381
 
321
382
  const ext = path.extname(filePath);
@@ -382,6 +443,20 @@ function renderPlainTextContent(
382
443
  subPath,
383
444
  });
384
445
 
446
+ if (traceCache && contentDir && distDir) {
447
+ const helpers = createTraceHelpers({
448
+ filePath,
449
+ contentDir,
450
+ distDir,
451
+ applyBasePath,
452
+ cache: traceCache,
453
+ javacAvailable,
454
+ });
455
+ params.renderTrace = helpers.renderTrace;
456
+ }
457
+
458
+ params.include = createIncludeFunction(filePath, params);
459
+
385
460
  let html: string;
386
461
  try {
387
462
  html = _.template(strippedContent)(params);
@@ -393,16 +468,19 @@ function renderPlainTextContent(
393
468
  }
394
469
 
395
470
  let tocItems: unknown[] | null = null;
471
+ let alertIds: string[] = [];
396
472
  if (extensionIsMarkdown(ext)) {
397
- const env: Record<string, unknown> = {};
473
+ const env: Record<string, unknown> = { alertIds: [] as string[] };
398
474
  html = md.render(html!, env);
399
475
  tocItems = (env.tocItems as unknown[] | undefined) || null;
476
+ alertIds = env.alertIds as string[];
400
477
  }
401
478
 
402
479
  return {
403
480
  content: html,
404
481
  pageVariables: params.page as Record<string, unknown>,
405
482
  tocItems,
483
+ alertIds,
406
484
  };
407
485
  }
408
486
 
@@ -417,6 +495,8 @@ export function renderLiterateJavaPageAsset({
417
495
  siteVariables,
418
496
  assetFiles,
419
497
  skipExecution,
498
+ validInternalTargets,
499
+ literateJavaOutputPaths,
420
500
  }: RenderLiterateJavaOptions): Asset[] {
421
501
  const { dir, name } = path.parse(filePath);
422
502
  const className = deriveClassName(filePath);
@@ -467,8 +547,18 @@ export function renderLiterateJavaPageAsset({
467
547
 
468
548
  // Render full markdown with a custom fence rule that replaces fences
469
549
  // with Shiki-highlighted code blocks and optional JDI output columns
550
+ const sourceUrlPath = `/${subPath}.java.html`;
470
551
  const md = createMarkdown(siteVariables, {
471
- validatorOptions: { enabled: false },
552
+ validatorOptions: {
553
+ filePath,
554
+ sourceUrlPath,
555
+ validTargets: validInternalTargets,
556
+ codeExtensions: isFeatureEnabled(siteVariables, 'code')
557
+ ? Object.keys(siteVariables.codeLanguages!)
558
+ : [],
559
+ },
560
+ literateJavaOutputPaths,
561
+ sourceUrlPath,
472
562
  });
473
563
  let fenceIndex = 0;
474
564
  const defaultFence = md.renderer.rules.fence!;
@@ -520,7 +610,7 @@ export function renderLiterateJavaPageAsset({
520
610
  return codeHtml;
521
611
  };
522
612
 
523
- const env: Record<string, unknown> = {};
613
+ const env: Record<string, unknown> = { alertIds: [] as string[] };
524
614
  const contentHtml = md.render(stripHtmlComments(content), env);
525
615
 
526
616
  // Build page variables
@@ -541,6 +631,7 @@ export function renderLiterateJavaPageAsset({
541
631
  if (pageVariables.toc && env.tocItems) {
542
632
  pageVariables.tocHtml = generateTocHtml(
543
633
  env.tocItems as Parameters<typeof generateTocHtml>[0],
634
+ env.alertIds as string[],
544
635
  );
545
636
  }
546
637
 
@@ -564,7 +655,7 @@ export function renderLiterateJavaPageAsset({
564
655
  {
565
656
  assetPath: toContentAssetPath(
566
657
  contentDir,
567
- path.join(dir, `${className}.html`),
658
+ path.join(dir, `${className}.java.html`),
568
659
  ),
569
660
  content: html,
570
661
  },
@@ -1,7 +1,7 @@
1
1
  import type { HighlighterGeneric, BundledLanguage, BundledTheme } from 'shiki';
2
2
  import { makeLogger } from '../log';
3
3
 
4
- const log = makeLogger(__filename);
4
+ const log = makeLogger(import.meta.url);
5
5
 
6
6
  let highlighter: HighlighterGeneric<BundledLanguage, BundledTheme> | null =
7
7
  null;