@abreen/tada 1.0.2 → 1.2.0

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 (146) hide show
  1. package/README.md +96 -48
  2. package/bin/tada.ts +621 -0
  3. package/bin/validators.test.ts +205 -0
  4. package/bin/validators.ts +85 -0
  5. package/{webpack/apply-base-path-plugin.js → build/apply-base-path-plugin.ts} +37 -17
  6. package/build/build-manifest.test.ts +349 -0
  7. package/build/build-manifest.ts +165 -0
  8. package/build/bundle.ts +116 -0
  9. package/{webpack/code.test.js → build/code.test.ts} +10 -7
  10. package/build/colors.ts +25 -0
  11. package/build/content-watch.ts +107 -0
  12. package/build/copy.ts +118 -0
  13. package/{webpack/deflist-id-plugin.js → build/deflist-id-plugin.ts} +7 -6
  14. package/{webpack/external-links-plugin.js → build/external-links-plugin.ts} +14 -5
  15. package/build/features.ts +11 -0
  16. package/build/generate-content-assets.ts +320 -0
  17. package/build/generate-favicon.ts +172 -0
  18. package/build/generate-fonts.ts +31 -0
  19. package/build/generate-katex-assets.ts +35 -0
  20. package/{webpack/generate-manifest-plugin.js → build/generate-manifest.ts} +29 -36
  21. package/build/globals.test.ts +99 -0
  22. package/build/globals.ts +88 -0
  23. package/{webpack/heading-subtitle-plugin.js → build/heading-subtitle-plugin.ts} +4 -2
  24. package/build/json-schema.test.ts +57 -0
  25. package/build/json-schema.ts +33 -0
  26. package/build/log.test.ts +111 -0
  27. package/build/log.ts +167 -0
  28. package/build/markdown-plugins.test.ts +396 -0
  29. package/{webpack/pagefind-plugin.test.js → build/pagefind.test.ts} +74 -13
  30. package/build/pagefind.ts +339 -0
  31. package/build/pdf-text.test.ts +52 -0
  32. package/{webpack/pdf-text.js → build/pdf-text.ts} +47 -27
  33. package/build/pipeline.ts +120 -0
  34. package/{webpack/reachability.test.js → build/reachability.test.ts} +3 -3
  35. package/{webpack/reachability.js → build/reachability.ts} +77 -34
  36. package/build/serve.ts +112 -0
  37. package/build/site-variables.ts +68 -0
  38. package/{webpack/templates.js → build/templates.ts} +38 -35
  39. package/{webpack/text-to-id.js → build/text-to-id.ts} +2 -2
  40. package/build/toc-plugin.test.ts +105 -0
  41. package/{webpack/toc-plugin.js → build/toc-plugin.ts} +32 -13
  42. package/build/types.ts +181 -0
  43. package/build/util.ts +26 -0
  44. package/{webpack/utils/code.js → build/utils/code.ts} +119 -60
  45. package/{webpack/utils/content-files.js → build/utils/content-files.ts} +40 -35
  46. package/build/utils/derive-theme.test.ts +111 -0
  47. package/build/utils/derive-theme.ts +85 -0
  48. package/build/utils/file-types.test.ts +61 -0
  49. package/build/utils/file-types.ts +13 -0
  50. package/build/utils/front-matter.test.ts +77 -0
  51. package/{webpack/utils/front-matter.js → build/utils/front-matter.ts} +22 -9
  52. package/{webpack → build}/utils/jdi-runner/LiterateRunner.java +1 -1
  53. package/{webpack/utils/literate-java.js → build/utils/literate-java.ts} +68 -38
  54. package/{webpack/utils/markdown.js → build/utils/markdown.ts} +126 -49
  55. package/build/utils/paths.test.ts +91 -0
  56. package/{webpack/utils/paths.js → build/utils/paths.ts} +18 -22
  57. package/{webpack/utils/render.js → build/utils/render.ts} +208 -130
  58. package/build/utils/shiki-highlighter.ts +29 -0
  59. package/build/validate-internal-links-plugin.test.ts +106 -0
  60. package/{webpack/validate-internal-links-plugin.js → build/validate-internal-links-plugin.ts} +47 -20
  61. package/{webpack/watch-reachability-state.test.js → build/watch-reachability-state.test.ts} +8 -8
  62. package/{webpack/watch-reachability-state.js → build/watch-reachability-state.ts} +63 -24
  63. package/{webpack/watch-reload-client.js → build/watch-reload-client.ts} +3 -1
  64. package/build/watch.ts +549 -0
  65. package/fonts/google-sans-code/woff2/GoogleSansCodeVariable-Italic.woff2 +0 -0
  66. package/fonts/google-sans-code/woff2/GoogleSansCodeVariable.woff2 +0 -0
  67. package/fonts/inter/woff2/InterVariable-Italic.woff2 +0 -0
  68. package/fonts/inter/woff2/InterVariable.woff2 +0 -0
  69. package/{content → init/content}/index.md +9 -3
  70. package/{content → init/content}/lectures/index.md +1 -1
  71. package/{content → init/content}/markdown.md +28 -8
  72. package/init/content/problem_sets/index.html +14 -0
  73. package/package.json +33 -22
  74. package/{templates → schema}/nav.schema.json +1 -2
  75. package/{webpack → schema}/site.schema.json +4 -12
  76. package/src/_alerts.scss +96 -0
  77. package/src/_base.scss +145 -0
  78. package/src/{layout.scss → _layout.scss} +36 -1
  79. package/src/anchor/index.ts +0 -1
  80. package/src/anchor/style.scss +1 -9
  81. package/src/code/index.ts +3 -3
  82. package/src/code.scss +1 -1
  83. package/src/critical.scss +5 -0
  84. package/src/header/_base.scss +129 -0
  85. package/src/header/style.scss +3 -131
  86. package/src/index.ts +4 -5
  87. package/src/question/style.scss +1 -1
  88. package/src/search/index.test.ts +203 -0
  89. package/src/search/index.ts +38 -93
  90. package/src/search/pdf-utils.ts +79 -0
  91. package/src/search/style.scss +8 -28
  92. package/src/style.scss +15 -326
  93. package/src/timezone/index.ts +5 -6
  94. package/src/toc/style.scss +5 -39
  95. package/src/util.ts +9 -6
  96. package/templates/_theme.scss +38 -14
  97. package/templates/_top.html +1 -1
  98. package/tsconfig.json +10 -6
  99. package/types/dev.d.ts +1 -0
  100. package/types/file-system-access.d.ts +5 -0
  101. package/types/markdown-it-plugins.d.ts +11 -0
  102. package/types/site-variables.d.ts +6 -10
  103. package/types/untyped-modules.d.ts +47 -0
  104. package/bin/tada.js +0 -361
  105. package/config/authors.json +0 -1
  106. package/config/nav.json +0 -28
  107. package/content/problem_sets/index.md +0 -6
  108. package/types/dev.ts +0 -3
  109. package/webpack/build-state.js +0 -97
  110. package/webpack/colors.js +0 -15
  111. package/webpack/config.base.js +0 -151
  112. package/webpack/config.dev.js +0 -23
  113. package/webpack/config.prod.js +0 -32
  114. package/webpack/content-watch-plugin.js +0 -153
  115. package/webpack/features.js +0 -5
  116. package/webpack/generate-content-assets-plugin.js +0 -308
  117. package/webpack/generate-favicon-plugin.js +0 -198
  118. package/webpack/generate-fonts-plugin.js +0 -69
  119. package/webpack/globals.js +0 -74
  120. package/webpack/json-schema.js +0 -19
  121. package/webpack/log.js +0 -143
  122. package/webpack/markdown-plugins.test.js +0 -203
  123. package/webpack/pagefind-plugin.js +0 -379
  124. package/webpack/print-flair-plugin.js +0 -22
  125. package/webpack/serve.js +0 -104
  126. package/webpack/site-variables.js +0 -53
  127. package/webpack/util.js +0 -49
  128. package/webpack/utils/define-plugin.js +0 -20
  129. package/webpack/utils/file-types.js +0 -26
  130. package/webpack/utils/parse-hsl.js +0 -8
  131. package/webpack/utils/shiki-highlighter.js +0 -26
  132. package/webpack/watch.js +0 -166
  133. /package/{webpack → build}/flair.json +0 -0
  134. /package/{webpack → build}/utils/jdi-runner/LiterateRunner.class +0 -0
  135. /package/fonts/google-sans-code/{GoogleSansCodeVariable-Italic.ttf → ttf/GoogleSansCodeVariable-Italic.ttf} +0 -0
  136. /package/fonts/google-sans-code/{GoogleSansCodeVariable.ttf → ttf/GoogleSansCodeVariable.ttf} +0 -0
  137. /package/fonts/inter/{InterVariable-Italic.ttf → ttf/InterVariable-Italic.ttf} +0 -0
  138. /package/fonts/inter/{InterVariable.ttf → ttf/InterVariable.ttf} +0 -0
  139. /package/{content → init/content}/lectures/01/Pair.java.md +0 -0
  140. /package/{content → init/content}/lectures/01/Rectangle.java +0 -0
  141. /package/{content → init/content}/lectures/01/demo.py +0 -0
  142. /package/{content → init/content}/lectures/01/index.md +0 -0
  143. /package/{content → init/content}/lectures/01/lecture1.pdf +0 -0
  144. /package/{public → init/public}/avatars/alex.jpg +0 -0
  145. /package/{public → init/public}/test.txt +0 -0
  146. /package/{templates → schema}/authors.schema.json +0 -0
@@ -1,379 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { makeLogger } = require('./log');
4
- const { collectReachableSiteAssets } = require('./reachability');
5
- const ContentWatchPlugin = require('./content-watch-plugin');
6
- const {
7
- getBuildContentFiles,
8
- getContentDir,
9
- normalizeOutputPath,
10
- } = require('./util');
11
- const { assertMutoolAvailable, extractPdfPages } = require('./pdf-text');
12
-
13
- const log = makeLogger(__filename);
14
- const PAGEFIND_VERBOSE = process.env.TADA_LOG_LEVEL === 'debug';
15
- const PAGEFIND_OUTPUT_SUBDIR = 'pagefind';
16
-
17
- let pagefindModulePromise = null;
18
-
19
- function getPagefind() {
20
- if (!pagefindModulePromise) {
21
- pagefindModulePromise = import('pagefind');
22
- }
23
- return pagefindModulePromise;
24
- }
25
-
26
- function formatPagefindErrors(step, errors) {
27
- if (!errors?.length) {
28
- return null;
29
- }
30
- return `${step} failed: ${errors.join(' | ')}`;
31
- }
32
-
33
- function readAssetContent(outputFileSystem, distPath, sourcePath) {
34
- const filePath = path.join(distPath, sourcePath);
35
- return String(outputFileSystem.readFileSync(filePath, 'utf-8'));
36
- }
37
-
38
- async function addHtmlFile(index, htmlFile) {
39
- const { errors: addErrors } = await index.addHTMLFile(htmlFile);
40
- const addError = formatPagefindErrors(
41
- `index.addHTMLFile(${htmlFile.sourcePath})`,
42
- addErrors,
43
- );
44
- if (addError) {
45
- throw new Error(addError);
46
- }
47
- }
48
-
49
- async function addPdfRecord(index, record, sourcePath) {
50
- const { errors: addErrors } = await index.addCustomRecord(record);
51
- const addError = formatPagefindErrors(
52
- `index.addCustomRecord(${sourcePath})`,
53
- addErrors,
54
- );
55
- if (addError) {
56
- throw new Error(addError);
57
- }
58
- }
59
-
60
- function getPdfSourceByOutputPath(siteVariables) {
61
- const contentDir = getContentDir();
62
- const contentFiles = getBuildContentFiles(
63
- contentDir,
64
- Object.keys(siteVariables?.codeLanguages || {}),
65
- );
66
- const pdfFiles = contentFiles.filter(
67
- filePath => path.extname(filePath).toLowerCase() === '.pdf',
68
- );
69
-
70
- return new Map(
71
- pdfFiles.map(filePath => {
72
- const relPath = path.relative(contentDir, filePath);
73
- return [normalizeOutputPath(`/${relPath}`), filePath];
74
- }),
75
- );
76
- }
77
-
78
- function collectIndexTargets(
79
- htmlAssetsByPath,
80
- siteVariables,
81
- pdfSourceByOutputPath,
82
- ) {
83
- if (htmlAssetsByPath.size === 0) {
84
- return { reachableHtmlPaths: [], reachablePdfPaths: [] };
85
- }
86
-
87
- return collectReachableSiteAssets({
88
- htmlAssetsByPath,
89
- knownPdfPaths: new Set(pdfSourceByOutputPath.keys()),
90
- rootPath: 'index.html',
91
- basePath: siteVariables?.basePath || '/',
92
- });
93
- }
94
-
95
- async function buildIndex({
96
- distPath,
97
- htmlAssetsByPath,
98
- reachableHtmlPaths,
99
- reachablePdfPaths,
100
- pdfSourceByOutputPath,
101
- loadPagefind = getPagefind,
102
- checkMutool = assertMutoolAvailable,
103
- extractPages = extractPdfPages,
104
- }) {
105
- const pagefind = await loadPagefind();
106
- const { index, errors: createErrors } = await pagefind.createIndex({
107
- keepIndexUrl: true,
108
- verbose: PAGEFIND_VERBOSE,
109
- });
110
- const createError = formatPagefindErrors(
111
- 'pagefind.createIndex()',
112
- createErrors,
113
- );
114
- if (createError) {
115
- throw new Error(createError);
116
- }
117
- if (!index) {
118
- throw new Error('pagefind.createIndex() did not return an index');
119
- }
120
-
121
- try {
122
- for (const sourcePath of reachableHtmlPaths) {
123
- await addHtmlFile(index, {
124
- sourcePath,
125
- content: htmlAssetsByPath.get(sourcePath),
126
- });
127
- }
128
-
129
- let mutoolAvailable = true;
130
- if (reachablePdfPaths.length > 0) {
131
- try {
132
- await checkMutool();
133
- } catch {
134
- mutoolAvailable = false;
135
- log.warn`mutool was not found; search results will not include PDFs`;
136
- }
137
- }
138
-
139
- for (const pdfPath of mutoolAvailable ? reachablePdfPaths : []) {
140
- const sourceFilePath = pdfSourceByOutputPath.get(pdfPath);
141
- if (!sourceFilePath) {
142
- continue;
143
- }
144
-
145
- const { pages, hasExtractedText } = await extractPages(sourceFilePath);
146
- const title = path.posix.basename(pdfPath);
147
-
148
- if (!hasExtractedText) {
149
- await addPdfRecord(
150
- index,
151
- { url: pdfPath, content: title, language: 'en', meta: { title } },
152
- pdfPath,
153
- );
154
- continue;
155
- }
156
-
157
- for (const page of pages) {
158
- await addPdfRecord(
159
- index,
160
- {
161
- url: `${pdfPath}#page=${page.pageNumber}`,
162
- content: page.content,
163
- language: 'en',
164
- meta: { title, page: String(page.pageNumber) },
165
- },
166
- `${pdfPath}#page=${page.pageNumber}`,
167
- );
168
- }
169
- }
170
-
171
- const { errors: writeErrors } = await index.writeFiles({
172
- outputPath: path.join(distPath, PAGEFIND_OUTPUT_SUBDIR),
173
- });
174
- const writeError = formatPagefindErrors('index.writeFiles()', writeErrors);
175
- if (writeError) {
176
- throw new Error(writeError);
177
- }
178
- } finally {
179
- await index.deleteIndex().catch(() => null);
180
- }
181
- }
182
-
183
- class PagefindPlugin {
184
- constructor(siteVariables) {
185
- this.siteVariables = siteVariables || {};
186
- this.watchRunInProgress = false;
187
- this.watchRunQueued = false;
188
- this.lastDistPath = null;
189
- this.htmlCacheByAssetPath = new Map();
190
- }
191
-
192
- getHtmlAssetsByPath(compilation, distPath, outputFileSystem) {
193
- return new Map(
194
- compilation
195
- .getAssets()
196
- .filter(asset => asset.name.endsWith('.html'))
197
- .map(asset => [
198
- asset.name.replace(/\\/g, '/'),
199
- readAssetContent(
200
- outputFileSystem,
201
- distPath,
202
- asset.name.replace(/\\/g, '/'),
203
- ),
204
- ]),
205
- );
206
- }
207
-
208
- getIndexTargets(htmlAssetsByPath) {
209
- return collectIndexTargets(
210
- htmlAssetsByPath,
211
- this.siteVariables,
212
- getPdfSourceByOutputPath(this.siteVariables),
213
- );
214
- }
215
-
216
- runWatchIndex() {
217
- if (this.watchRunInProgress) {
218
- this.watchRunQueued = true;
219
- log.info`Indexing is still running in the background; queueing a rerun`;
220
- return;
221
- }
222
-
223
- this.watchRunInProgress = true;
224
- this.watchRunQueued = false;
225
- const distPath = this.lastDistPath;
226
- const htmlAssetsByPath = new Map(this.htmlCacheByAssetPath);
227
- const pdfSourceByOutputPath = getPdfSourceByOutputPath(this.siteVariables);
228
- const start = Date.now();
229
-
230
- log.debug`Preparing search index background snapshot`;
231
-
232
- let reachableHtmlPaths;
233
- let reachablePdfPaths;
234
- try {
235
- ({ reachableHtmlPaths, reachablePdfPaths } = collectIndexTargets(
236
- htmlAssetsByPath,
237
- this.siteVariables,
238
- pdfSourceByOutputPath,
239
- ));
240
- } catch (err) {
241
- this.watchRunInProgress = false;
242
- log.warn`Pagefind failed: ${err.message}`;
243
- if (this.watchRunQueued) {
244
- this.runWatchIndex();
245
- }
246
- return;
247
- }
248
-
249
- const snapshotReadyAt = Date.now();
250
- log.debug`Building search index in background`;
251
- buildIndex({
252
- distPath,
253
- htmlAssetsByPath,
254
- reachableHtmlPaths,
255
- reachablePdfPaths,
256
- pdfSourceByOutputPath,
257
- })
258
- .then(() => {
259
- const finishedAt = Date.now();
260
- log.info`Background search index ready in ${finishedAt - snapshotReadyAt}ms (${finishedAt - start}ms total)`;
261
- })
262
- .catch(err => {
263
- const failedAt = Date.now();
264
- log.warn`Search index failed after ${failedAt - snapshotReadyAt}ms of indexing (${failedAt - start}ms total): ${err.message}`;
265
- })
266
- .finally(() => {
267
- this.watchRunInProgress = false;
268
- if (this.watchRunQueued) {
269
- log.info`Starting queued Pagefind background rerun`;
270
- this.runWatchIndex();
271
- }
272
- });
273
- }
274
-
275
- apply(compiler) {
276
- compiler.hooks.afterEmit.tapAsync(
277
- 'PagefindPlugin',
278
- (compilation, callback) => {
279
- const distPath =
280
- compiler.options?.output?.path ||
281
- compiler.outputPath ||
282
- compilation.compiler.outputPath;
283
- const outputFileSystem =
284
- compiler.outputFileSystem ||
285
- compilation.compiler.outputFileSystem ||
286
- fs;
287
- const isWatch = !!compiler.watching;
288
-
289
- if (compilation.errors.length > 0) {
290
- callback();
291
- return;
292
- }
293
-
294
- let htmlAssetsByPath;
295
- try {
296
- htmlAssetsByPath = this.getHtmlAssetsByPath(
297
- compilation,
298
- distPath,
299
- outputFileSystem,
300
- );
301
- } catch (err) {
302
- compilation.errors.push(err);
303
- callback(err);
304
- return;
305
- }
306
-
307
- if (isWatch) {
308
- this.lastDistPath = distPath;
309
- this.htmlCacheByAssetPath = htmlAssetsByPath;
310
- callback();
311
- return;
312
- }
313
-
314
- const pdfSourceByOutputPath = getPdfSourceByOutputPath(
315
- this.siteVariables,
316
- );
317
- const start = Date.now();
318
- let reachableHtmlPaths;
319
- let reachablePdfPaths;
320
-
321
- log.info`Finding reachable pages for search index`;
322
- try {
323
- ({ reachableHtmlPaths, reachablePdfPaths } = collectIndexTargets(
324
- htmlAssetsByPath,
325
- this.siteVariables,
326
- pdfSourceByOutputPath,
327
- ));
328
- } catch (err) {
329
- compilation.errors.push(err);
330
- callback(err);
331
- return;
332
- }
333
-
334
- const snapshotReadyAt = Date.now();
335
- log.info`Building search index for ${reachableHtmlPaths.length} page(s) and ${reachablePdfPaths.length} PDF(s) after ${snapshotReadyAt - start}ms of snapshot prep`;
336
- buildIndex({
337
- distPath,
338
- htmlAssetsByPath,
339
- reachableHtmlPaths,
340
- reachablePdfPaths,
341
- pdfSourceByOutputPath,
342
- })
343
- .then(async () => {
344
- try {
345
- const pagefind = await getPagefind();
346
- await pagefind.close();
347
- } catch (_err) {
348
- // Best-effort cleanup for non-watch builds.
349
- }
350
- const finishedAt = Date.now();
351
- log.info`Search index built in ${finishedAt - snapshotReadyAt}ms (${finishedAt - start}ms total)`;
352
- callback();
353
- })
354
- .catch(err => {
355
- const failedAt = Date.now();
356
- log.error`Search indexing failed after ${failedAt - snapshotReadyAt}ms of indexing (${failedAt - start}ms total): ${err.message}`;
357
- compilation.errors.push(err);
358
- callback(err);
359
- });
360
- },
361
- );
362
-
363
- compiler.hooks.done.tap('PagefindPluginWatchRun', stats => {
364
- if (
365
- !compiler.watching ||
366
- stats.hasErrors() ||
367
- ContentWatchPlugin.needsRestart()
368
- ) {
369
- return;
370
- }
371
-
372
- setImmediate(() => this.runWatchIndex());
373
- });
374
- }
375
- }
376
-
377
- module.exports = PagefindPlugin;
378
- module.exports.buildIndex = buildIndex;
379
- module.exports.collectIndexTargets = collectIndexTargets;
@@ -1,22 +0,0 @@
1
- const { getFlair } = require('./log');
2
- const { getDistDir } = require('./util');
3
-
4
- module.exports = {
5
- apply: compiler => {
6
- compiler.hooks.afterEmit.tap('AfterEmitPlugin', compilation => {
7
- const isWatch =
8
- !!compiler.watching ||
9
- !!compiler.watchMode ||
10
- !!compilation?.compiler?.watchMode;
11
- if (isWatch) {
12
- return;
13
- }
14
-
15
- const distDir = getDistDir();
16
-
17
- console.log(getFlair());
18
- console.log(`The build output is available at ${distDir}`);
19
- console.log('Now use `tada serve` to start a local web server');
20
- });
21
- },
22
- };
package/webpack/serve.js DELETED
@@ -1,104 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { getDistDir } = require('./util');
4
- const { makeLogger } = require('./log');
5
- const { B } = require('./colors');
6
-
7
- const log = makeLogger(__filename);
8
-
9
- function messageReady(port) {
10
- if (process.send) {
11
- process.send({ ready: true, port });
12
- }
13
- }
14
-
15
- let distDir;
16
- try {
17
- distDir = getDistDir();
18
- } catch (err) {
19
- log.error`Failed to start server: ${err}`;
20
- process.exit(1);
21
- }
22
-
23
- function resolvePathname(pathname) {
24
- let decodedPath;
25
- try {
26
- decodedPath = decodeURIComponent(pathname);
27
- } catch {
28
- return null;
29
- }
30
-
31
- const resolvedPath = path.resolve(distDir, '.' + decodedPath);
32
- const relativePath = path.relative(distDir, resolvedPath);
33
- if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
34
- return null;
35
- }
36
-
37
- let stat;
38
- try {
39
- stat = fs.statSync(resolvedPath);
40
- } catch {
41
- return null;
42
- }
43
-
44
- if (stat.isDirectory()) {
45
- return null;
46
- }
47
-
48
- if (!stat.isFile()) {
49
- return null;
50
- }
51
-
52
- return resolvedPath;
53
- }
54
-
55
- function createResponse(req) {
56
- const url = new URL(req.url);
57
- const filePath = resolvePathname(url.pathname);
58
- if (!filePath) {
59
- return new Response('Not Found', { status: 404 });
60
- }
61
-
62
- return new Response(Bun.file(filePath));
63
- }
64
-
65
- function tryListen(port, fallbackPort) {
66
- return new Promise((resolve, reject) => {
67
- try {
68
- const server = Bun.serve({
69
- port,
70
- fetch: createResponse,
71
- error(error) {
72
- log.error`Request failed: ${error}`;
73
- return new Response('Internal Server Error', { status: 500 });
74
- },
75
- });
76
-
77
- log.info`Dev server: ${B`http://localhost:${server.port}/index.html`}`;
78
- messageReady(server.port);
79
- resolve(server);
80
- } catch (err) {
81
- if (err.code === 'EADDRINUSE' && fallbackPort) {
82
- log.warn`Port ${port} in use, trying fallback ${fallbackPort}...`;
83
- return tryListen(fallbackPort, null).then(resolve).catch(reject);
84
- }
85
-
86
- reject(err);
87
- }
88
- });
89
- }
90
-
91
- tryListen(8080, 8081).catch(err => {
92
- log.error`Failed to start server: ${err}`;
93
- process.exit(1);
94
- });
95
-
96
- process.on('uncaughtException', err => {
97
- log.error`Uncaught exception: ${err}`;
98
- process.exit(1);
99
- });
100
-
101
- process.on('unhandledRejection', reason => {
102
- log.error`Unhandled rejection: ${reason}`;
103
- process.exit(1);
104
- });
@@ -1,53 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { compile: compileJsonSchema, doValidation } = require('./json-schema');
4
- const { getProjectDir } = require('./utils/paths');
5
- const configDir = path.resolve(getProjectDir(), 'config');
6
-
7
- const DEFAULT = { basePath: '/', features: { search: true, code: true } };
8
-
9
- const isValid = compileJsonSchema(require('./site.schema.json'));
10
-
11
- function getJson(filePath) {
12
- return JSON.parse(
13
- fs.readFileSync(path.resolve(configDir, filePath), 'utf-8'),
14
- );
15
- }
16
-
17
- function getSiteVariables(env) {
18
- const fileName = `site.${env}.json`;
19
- const fromFile = getJson(fileName);
20
- const variables = {
21
- ...DEFAULT,
22
- ...fromFile,
23
- features: { ...DEFAULT.features, ...(fromFile.features || {}) },
24
- };
25
-
26
- // Derive faviconSymbol from symbol if not explicitly set
27
- if (variables.symbol && !variables.faviconSymbol) {
28
- variables.faviconSymbol = variables.symbol;
29
- }
30
-
31
- // Derive faviconColor from themeColor if not explicitly set
32
- if (variables.themeColor && !variables.faviconColor) {
33
- variables.faviconColor = variables.themeColor;
34
- }
35
-
36
- // Derive titlePostfix from title if not explicitly set
37
- if (variables.title && !variables.titlePostfix) {
38
- variables.titlePostfix = ` - ${variables.title}`;
39
- }
40
-
41
- doValidation(isValid, variables, fileName);
42
- return variables;
43
- }
44
-
45
- function getDevSiteVariables() {
46
- return getSiteVariables('dev');
47
- }
48
-
49
- function getProdSiteVariables() {
50
- return getSiteVariables('prod');
51
- }
52
-
53
- module.exports = { getDevSiteVariables, getProdSiteVariables };
package/webpack/util.js DELETED
@@ -1,49 +0,0 @@
1
- const {
2
- extensionIsMarkdown,
3
- getBuildContentFiles,
4
- getContentFiles,
5
- getValidInternalTargets,
6
- shouldSkipContentFile,
7
- } = require('./utils/content-files');
8
- const { createDefinePlugin } = require('./utils/define-plugin');
9
- const { createMarkdown } = require('./utils/markdown');
10
- const {
11
- createApplyBasePath,
12
- getContentDir,
13
- getDistDir,
14
- getPackageDir,
15
- getProjectDir,
16
- getPublicDir,
17
- normalizeOutputPath,
18
- } = require('./utils/paths');
19
- const {
20
- injectWebpackAssets,
21
- renderCodePageAsset,
22
- renderCopiedContentAsset,
23
- renderLiterateJavaPageAsset,
24
- renderPlainTextPageAsset,
25
- } = require('./utils/render');
26
- const { parseFrontMatter } = require('./utils/front-matter');
27
-
28
- module.exports = {
29
- createMarkdown,
30
- getContentDir,
31
- getDistDir,
32
- getPackageDir,
33
- getProjectDir,
34
- getPublicDir,
35
- getContentFiles,
36
- getBuildContentFiles,
37
- getValidInternalTargets,
38
- shouldSkipContentFile,
39
- extensionIsMarkdown,
40
- parseFrontMatter,
41
- createDefinePlugin,
42
- createApplyBasePath,
43
- injectWebpackAssets,
44
- normalizeOutputPath,
45
- renderCodePageAsset,
46
- renderCopiedContentAsset,
47
- renderLiterateJavaPageAsset,
48
- renderPlainTextPageAsset,
49
- };
@@ -1,20 +0,0 @@
1
- const { DefinePlugin } = require('webpack');
2
-
3
- function createDefinePlugin(siteVariables, isDev = false) {
4
- return new DefinePlugin({
5
- 'window.siteVariables.base': JSON.stringify(siteVariables.base),
6
- 'window.siteVariables.basePath': JSON.stringify(siteVariables.basePath),
7
- 'window.siteVariables.titlePostfix': JSON.stringify(
8
- siteVariables.titlePostfix,
9
- ),
10
- 'window.siteVariables.defaultTimeZone': JSON.stringify(
11
- siteVariables.defaultTimeZone,
12
- ),
13
- 'window.siteVariables.timezones': JSON.stringify(
14
- require('../../src/timezone/timezones.json'),
15
- ),
16
- 'window.IS_DEV': JSON.stringify(isDev),
17
- });
18
- }
19
-
20
- module.exports = { createDefinePlugin };
@@ -1,26 +0,0 @@
1
- const path = require('path');
2
-
3
- const PUBLIC_ASSET_EXTENSIONS = [
4
- 'png',
5
- 'jpg',
6
- 'jpeg',
7
- 'gif',
8
- 'svg',
9
- 'txt',
10
- 'zip',
11
- 'pdf',
12
- ];
13
-
14
- function extensionIsMarkdown(ext) {
15
- return ['.md', '.markdown'].includes(ext);
16
- }
17
-
18
- function isLiterateJava(filePath) {
19
- return path.basename(filePath).toLowerCase().endsWith('.java.md');
20
- }
21
-
22
- module.exports = {
23
- PUBLIC_ASSET_EXTENSIONS,
24
- extensionIsMarkdown,
25
- isLiterateJava,
26
- };
@@ -1,8 +0,0 @@
1
- function parseHsl(hslColor) {
2
- const [, hue, saturation, lightness] = hslColor.match(
3
- /^hsl\((\d+)(?:deg)?\s+(\d+)%\s+(\d+)%\)$/,
4
- );
5
- return { hue, saturation, lightness };
6
- }
7
-
8
- module.exports = { parseHsl };
@@ -1,26 +0,0 @@
1
- const { makeLogger } = require('../log');
2
-
3
- const log = makeLogger(__filename);
4
-
5
- let highlighter = null;
6
-
7
- async function initHighlighter(langs) {
8
- if (highlighter) {
9
- return;
10
- }
11
- log.info`Initializing syntax highlighter`;
12
- const { createHighlighter } = await import('shiki');
13
- highlighter = await createHighlighter({
14
- themes: ['github-light', 'github-dark'],
15
- langs,
16
- });
17
- }
18
-
19
- function getHighlighter() {
20
- if (!highlighter) {
21
- throw new Error('Shiki highlighter not initialized');
22
- }
23
- return highlighter;
24
- }
25
-
26
- module.exports = { initHighlighter, getHighlighter };