@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.
- package/README.md +96 -48
- package/bin/tada.ts +621 -0
- package/bin/validators.test.ts +205 -0
- package/bin/validators.ts +85 -0
- package/{webpack/apply-base-path-plugin.js → build/apply-base-path-plugin.ts} +37 -17
- package/build/build-manifest.test.ts +349 -0
- package/build/build-manifest.ts +165 -0
- package/build/bundle.ts +116 -0
- package/{webpack/code.test.js → build/code.test.ts} +10 -7
- package/build/colors.ts +25 -0
- package/build/content-watch.ts +107 -0
- package/build/copy.ts +118 -0
- package/{webpack/deflist-id-plugin.js → build/deflist-id-plugin.ts} +7 -6
- package/{webpack/external-links-plugin.js → build/external-links-plugin.ts} +14 -5
- package/build/features.ts +11 -0
- package/build/generate-content-assets.ts +320 -0
- package/build/generate-favicon.ts +172 -0
- package/build/generate-fonts.ts +31 -0
- package/build/generate-katex-assets.ts +35 -0
- package/{webpack/generate-manifest-plugin.js → build/generate-manifest.ts} +29 -36
- package/build/globals.test.ts +99 -0
- package/build/globals.ts +88 -0
- package/{webpack/heading-subtitle-plugin.js → build/heading-subtitle-plugin.ts} +4 -2
- package/build/json-schema.test.ts +57 -0
- package/build/json-schema.ts +33 -0
- package/build/log.test.ts +111 -0
- package/build/log.ts +167 -0
- package/build/markdown-plugins.test.ts +396 -0
- package/{webpack/pagefind-plugin.test.js → build/pagefind.test.ts} +74 -13
- package/build/pagefind.ts +339 -0
- package/build/pdf-text.test.ts +52 -0
- package/{webpack/pdf-text.js → build/pdf-text.ts} +47 -27
- package/build/pipeline.ts +120 -0
- package/{webpack/reachability.test.js → build/reachability.test.ts} +3 -3
- package/{webpack/reachability.js → build/reachability.ts} +77 -34
- package/build/serve.ts +112 -0
- package/build/site-variables.ts +68 -0
- package/{webpack/templates.js → build/templates.ts} +38 -35
- package/{webpack/text-to-id.js → build/text-to-id.ts} +2 -2
- package/build/toc-plugin.test.ts +105 -0
- package/{webpack/toc-plugin.js → build/toc-plugin.ts} +32 -13
- package/build/types.ts +181 -0
- package/build/util.ts +26 -0
- package/{webpack/utils/code.js → build/utils/code.ts} +119 -60
- package/{webpack/utils/content-files.js → build/utils/content-files.ts} +40 -35
- package/build/utils/derive-theme.test.ts +111 -0
- package/build/utils/derive-theme.ts +85 -0
- package/build/utils/file-types.test.ts +61 -0
- package/build/utils/file-types.ts +13 -0
- package/build/utils/front-matter.test.ts +77 -0
- package/{webpack/utils/front-matter.js → build/utils/front-matter.ts} +22 -9
- package/{webpack → build}/utils/jdi-runner/LiterateRunner.java +1 -1
- package/{webpack/utils/literate-java.js → build/utils/literate-java.ts} +68 -38
- package/{webpack/utils/markdown.js → build/utils/markdown.ts} +126 -49
- package/build/utils/paths.test.ts +91 -0
- package/{webpack/utils/paths.js → build/utils/paths.ts} +18 -22
- package/{webpack/utils/render.js → build/utils/render.ts} +208 -130
- package/build/utils/shiki-highlighter.ts +29 -0
- package/build/validate-internal-links-plugin.test.ts +106 -0
- package/{webpack/validate-internal-links-plugin.js → build/validate-internal-links-plugin.ts} +47 -20
- package/{webpack/watch-reachability-state.test.js → build/watch-reachability-state.test.ts} +8 -8
- package/{webpack/watch-reachability-state.js → build/watch-reachability-state.ts} +63 -24
- package/{webpack/watch-reload-client.js → build/watch-reload-client.ts} +3 -1
- package/build/watch.ts +549 -0
- package/fonts/google-sans-code/woff2/GoogleSansCodeVariable-Italic.woff2 +0 -0
- package/fonts/google-sans-code/woff2/GoogleSansCodeVariable.woff2 +0 -0
- package/fonts/inter/woff2/InterVariable-Italic.woff2 +0 -0
- package/fonts/inter/woff2/InterVariable.woff2 +0 -0
- package/{content → init/content}/index.md +9 -3
- package/{content → init/content}/lectures/index.md +1 -1
- package/{content → init/content}/markdown.md +28 -8
- package/init/content/problem_sets/index.html +14 -0
- package/package.json +33 -22
- package/{templates → schema}/nav.schema.json +1 -2
- package/{webpack → schema}/site.schema.json +4 -12
- package/src/_alerts.scss +96 -0
- package/src/_base.scss +145 -0
- package/src/{layout.scss → _layout.scss} +36 -1
- package/src/anchor/index.ts +0 -1
- package/src/anchor/style.scss +1 -9
- package/src/code/index.ts +3 -3
- package/src/code.scss +1 -1
- package/src/critical.scss +5 -0
- package/src/header/_base.scss +129 -0
- package/src/header/style.scss +3 -131
- package/src/index.ts +4 -5
- package/src/question/style.scss +1 -1
- package/src/search/index.test.ts +203 -0
- package/src/search/index.ts +38 -93
- package/src/search/pdf-utils.ts +79 -0
- package/src/search/style.scss +8 -28
- package/src/style.scss +15 -326
- package/src/timezone/index.ts +5 -6
- package/src/toc/style.scss +5 -39
- package/src/util.ts +9 -6
- package/templates/_theme.scss +38 -14
- package/templates/_top.html +1 -1
- package/tsconfig.json +10 -6
- package/types/dev.d.ts +1 -0
- package/types/file-system-access.d.ts +5 -0
- package/types/markdown-it-plugins.d.ts +11 -0
- package/types/site-variables.d.ts +6 -10
- package/types/untyped-modules.d.ts +47 -0
- package/bin/tada.js +0 -361
- package/config/authors.json +0 -1
- package/config/nav.json +0 -28
- package/content/problem_sets/index.md +0 -6
- package/types/dev.ts +0 -3
- package/webpack/build-state.js +0 -97
- package/webpack/colors.js +0 -15
- package/webpack/config.base.js +0 -151
- package/webpack/config.dev.js +0 -23
- package/webpack/config.prod.js +0 -32
- package/webpack/content-watch-plugin.js +0 -153
- package/webpack/features.js +0 -5
- package/webpack/generate-content-assets-plugin.js +0 -308
- package/webpack/generate-favicon-plugin.js +0 -198
- package/webpack/generate-fonts-plugin.js +0 -69
- package/webpack/globals.js +0 -74
- package/webpack/json-schema.js +0 -19
- package/webpack/log.js +0 -143
- package/webpack/markdown-plugins.test.js +0 -203
- package/webpack/pagefind-plugin.js +0 -379
- package/webpack/print-flair-plugin.js +0 -22
- package/webpack/serve.js +0 -104
- package/webpack/site-variables.js +0 -53
- package/webpack/util.js +0 -49
- package/webpack/utils/define-plugin.js +0 -20
- package/webpack/utils/file-types.js +0 -26
- package/webpack/utils/parse-hsl.js +0 -8
- package/webpack/utils/shiki-highlighter.js +0 -26
- package/webpack/watch.js +0 -166
- /package/{webpack → build}/flair.json +0 -0
- /package/{webpack → build}/utils/jdi-runner/LiterateRunner.class +0 -0
- /package/fonts/google-sans-code/{GoogleSansCodeVariable-Italic.ttf → ttf/GoogleSansCodeVariable-Italic.ttf} +0 -0
- /package/fonts/google-sans-code/{GoogleSansCodeVariable.ttf → ttf/GoogleSansCodeVariable.ttf} +0 -0
- /package/fonts/inter/{InterVariable-Italic.ttf → ttf/InterVariable-Italic.ttf} +0 -0
- /package/fonts/inter/{InterVariable.ttf → ttf/InterVariable.ttf} +0 -0
- /package/{content → init/content}/lectures/01/Pair.java.md +0 -0
- /package/{content → init/content}/lectures/01/Rectangle.java +0 -0
- /package/{content → init/content}/lectures/01/demo.py +0 -0
- /package/{content → init/content}/lectures/01/index.md +0 -0
- /package/{content → init/content}/lectures/01/lecture1.pdf +0 -0
- /package/{public → init/public}/avatars/alex.jpg +0 -0
- /package/{public → init/public}/test.txt +0 -0
- /package/{templates → schema}/authors.schema.json +0 -0
package/webpack/build-state.js
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
const watchStateByCompiler = new WeakMap();
|
|
2
|
-
const buildDeltaByCompiler = new WeakMap();
|
|
3
|
-
|
|
4
|
-
function cloneSet(values) {
|
|
5
|
-
return new Set(values || []);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
function getEmptyBuildDelta() {
|
|
9
|
-
return {
|
|
10
|
-
changedSourceFiles: new Set(),
|
|
11
|
-
changedHtmlAssetPaths: new Set(),
|
|
12
|
-
removedHtmlAssetPaths: new Set(),
|
|
13
|
-
templatesChanged: false,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function setWatchState(compiler, watchState) {
|
|
18
|
-
watchStateByCompiler.set(compiler, {
|
|
19
|
-
contentFiles: cloneSet(watchState?.contentFiles),
|
|
20
|
-
buildContentFiles: cloneSet(watchState?.buildContentFiles),
|
|
21
|
-
changedContentFiles: cloneSet(watchState?.changedContentFiles),
|
|
22
|
-
templatesChanged: Boolean(watchState?.templatesChanged),
|
|
23
|
-
structureChanged: Boolean(watchState?.structureChanged),
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function getWatchState(compiler) {
|
|
28
|
-
const state = watchStateByCompiler.get(compiler);
|
|
29
|
-
if (!state) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
contentFiles: cloneSet(state.contentFiles),
|
|
35
|
-
buildContentFiles: cloneSet(state.buildContentFiles),
|
|
36
|
-
changedContentFiles: cloneSet(state.changedContentFiles),
|
|
37
|
-
templatesChanged: state.templatesChanged,
|
|
38
|
-
structureChanged: state.structureChanged,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function setBuildDelta(compiler, buildDelta) {
|
|
43
|
-
buildDeltaByCompiler.set(compiler, {
|
|
44
|
-
changedSourceFiles: cloneSet(buildDelta?.changedSourceFiles),
|
|
45
|
-
changedHtmlAssetPaths: cloneSet(buildDelta?.changedHtmlAssetPaths),
|
|
46
|
-
removedHtmlAssetPaths: cloneSet(buildDelta?.removedHtmlAssetPaths),
|
|
47
|
-
templatesChanged: Boolean(buildDelta?.templatesChanged),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function mergeIntoSet(target, values) {
|
|
52
|
-
if (!values) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
for (const value of values) {
|
|
57
|
-
target.add(value);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function updateBuildDelta(compiler, buildDelta) {
|
|
62
|
-
const current = getBuildDelta(compiler);
|
|
63
|
-
mergeIntoSet(current.changedSourceFiles, buildDelta?.changedSourceFiles);
|
|
64
|
-
mergeIntoSet(
|
|
65
|
-
current.changedHtmlAssetPaths,
|
|
66
|
-
buildDelta?.changedHtmlAssetPaths,
|
|
67
|
-
);
|
|
68
|
-
mergeIntoSet(
|
|
69
|
-
current.removedHtmlAssetPaths,
|
|
70
|
-
buildDelta?.removedHtmlAssetPaths,
|
|
71
|
-
);
|
|
72
|
-
current.templatesChanged =
|
|
73
|
-
current.templatesChanged || Boolean(buildDelta?.templatesChanged);
|
|
74
|
-
buildDeltaByCompiler.set(compiler, current);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function getBuildDelta(compiler) {
|
|
78
|
-
const delta = buildDeltaByCompiler.get(compiler);
|
|
79
|
-
if (!delta) {
|
|
80
|
-
return getEmptyBuildDelta();
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return {
|
|
84
|
-
changedSourceFiles: cloneSet(delta.changedSourceFiles),
|
|
85
|
-
changedHtmlAssetPaths: cloneSet(delta.changedHtmlAssetPaths),
|
|
86
|
-
removedHtmlAssetPaths: cloneSet(delta.removedHtmlAssetPaths),
|
|
87
|
-
templatesChanged: delta.templatesChanged,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
module.exports = {
|
|
92
|
-
getBuildDelta,
|
|
93
|
-
getWatchState,
|
|
94
|
-
setBuildDelta,
|
|
95
|
-
setWatchState,
|
|
96
|
-
updateBuildDelta,
|
|
97
|
-
};
|
package/webpack/colors.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const util = require('util');
|
|
2
|
-
|
|
3
|
-
const R = (str, ...args) => util.styleText(['red'], String.raw(str, ...args));
|
|
4
|
-
const G = (str, ...args) => util.styleText(['green'], String.raw(str, ...args));
|
|
5
|
-
const B = (str, ...args) => util.styleText(['blue'], String.raw(str, ...args));
|
|
6
|
-
const Y = (str, ...args) =>
|
|
7
|
-
util.styleText(['yellow'], String.raw(str, ...args));
|
|
8
|
-
const L = (str, ...args) =>
|
|
9
|
-
util.styleText(['blackBright'], String.raw(str, ...args));
|
|
10
|
-
const P = (str, ...args) =>
|
|
11
|
-
util.styleText(['magenta'], String.raw(str, ...args));
|
|
12
|
-
const I = (str, ...args) =>
|
|
13
|
-
util.styleText(['italic', 'bold'], String.raw(str, ...args));
|
|
14
|
-
|
|
15
|
-
module.exports = { R, G, B, Y, L, P, I };
|
package/webpack/config.base.js
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const os = require('os');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const _ = require('lodash');
|
|
5
|
-
const CopyPlugin = require('copy-webpack-plugin');
|
|
6
|
-
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
7
|
-
const GenerateContentAssetsPlugin = require('./generate-content-assets-plugin');
|
|
8
|
-
const PagefindPlugin = require('./pagefind-plugin');
|
|
9
|
-
const GenerateFaviconPlugin = require('./generate-favicon-plugin');
|
|
10
|
-
const GenerateManifestPlugin = require('./generate-manifest-plugin');
|
|
11
|
-
const GenerateFontsPlugin = require('./generate-fonts-plugin');
|
|
12
|
-
const { getDistDir, createDefinePlugin } = require('./util');
|
|
13
|
-
const { isFeatureEnabled } = require('./features');
|
|
14
|
-
const {
|
|
15
|
-
getContentDir,
|
|
16
|
-
getPackageDir,
|
|
17
|
-
getProjectDir,
|
|
18
|
-
getPublicDir,
|
|
19
|
-
} = require('./utils/paths');
|
|
20
|
-
const { parseHsl } = require('./utils/parse-hsl');
|
|
21
|
-
|
|
22
|
-
const distDir = getDistDir();
|
|
23
|
-
|
|
24
|
-
function renderThemeScss(siteVariables) {
|
|
25
|
-
const templatePath = path.join(getPackageDir(), 'templates/_theme.scss');
|
|
26
|
-
const template = fs.readFileSync(templatePath, 'utf-8');
|
|
27
|
-
const { hue, saturation, lightness } = parseHsl(siteVariables.themeColor);
|
|
28
|
-
const tintHue = siteVariables.tintHue ?? 20;
|
|
29
|
-
const tintAmount = siteVariables.tintAmount ?? 100;
|
|
30
|
-
const rendered = _.template(template)({
|
|
31
|
-
themeHue: hue,
|
|
32
|
-
themeSaturation: saturation,
|
|
33
|
-
themeLightness: lightness,
|
|
34
|
-
tintHue,
|
|
35
|
-
tintAmount,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tada-'));
|
|
39
|
-
const configDir = path.join(tmpDir, 'config');
|
|
40
|
-
fs.mkdirSync(configDir);
|
|
41
|
-
fs.writeFileSync(path.join(configDir, '_theme.scss'), rendered);
|
|
42
|
-
|
|
43
|
-
return tmpDir;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function createModuleRules(siteVariables) {
|
|
47
|
-
const packageDir = getPackageDir();
|
|
48
|
-
const themeDir = renderThemeScss(siteVariables);
|
|
49
|
-
|
|
50
|
-
return [
|
|
51
|
-
{ test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } },
|
|
52
|
-
{
|
|
53
|
-
test: /\.tsx?$/,
|
|
54
|
-
include: path.resolve(packageDir, 'src'),
|
|
55
|
-
loader: 'ts-loader',
|
|
56
|
-
options: { configFile: path.resolve(packageDir, 'tsconfig.json') },
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
test: /\.(sa|sc|c)ss$/,
|
|
60
|
-
use: [
|
|
61
|
-
MiniCssExtractPlugin.loader,
|
|
62
|
-
{
|
|
63
|
-
loader: 'css-loader',
|
|
64
|
-
options: {
|
|
65
|
-
url: {
|
|
66
|
-
// Don't bundle fonts (they are handled by GenerateFontsPlugin)
|
|
67
|
-
filter: url => !url.endsWith('.woff2'),
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
{
|
|
72
|
-
loader: 'sass-loader',
|
|
73
|
-
options: { sassOptions: { loadPaths: [themeDir, getProjectDir()] } },
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function createPlugins(
|
|
81
|
-
siteVariables,
|
|
82
|
-
{ defineIsDev = false, plugins = [] } = {},
|
|
83
|
-
) {
|
|
84
|
-
return [
|
|
85
|
-
new GenerateContentAssetsPlugin(siteVariables),
|
|
86
|
-
createDefinePlugin(siteVariables, defineIsDev),
|
|
87
|
-
new MiniCssExtractPlugin({
|
|
88
|
-
filename: '[name].css',
|
|
89
|
-
chunkFilename: '[id].css',
|
|
90
|
-
}),
|
|
91
|
-
new CopyPlugin({
|
|
92
|
-
patterns: [
|
|
93
|
-
{ from: getPublicDir(), to: '.', noErrorOnMissing: true },
|
|
94
|
-
{
|
|
95
|
-
from: '**/*.{png,jpg,jpeg,gif,svg,txt,zip}',
|
|
96
|
-
context: getContentDir(),
|
|
97
|
-
to: '[path][name][ext]',
|
|
98
|
-
noErrorOnMissing: true,
|
|
99
|
-
},
|
|
100
|
-
],
|
|
101
|
-
}),
|
|
102
|
-
isFeatureEnabled(siteVariables, 'search')
|
|
103
|
-
? new PagefindPlugin(siteVariables)
|
|
104
|
-
: null,
|
|
105
|
-
isFeatureEnabled(siteVariables, 'favicon')
|
|
106
|
-
? new GenerateFaviconPlugin(siteVariables)
|
|
107
|
-
: null,
|
|
108
|
-
isFeatureEnabled(siteVariables, 'favicon')
|
|
109
|
-
? new GenerateManifestPlugin(siteVariables)
|
|
110
|
-
: null,
|
|
111
|
-
new GenerateFontsPlugin(),
|
|
112
|
-
...plugins,
|
|
113
|
-
require('./print-flair-plugin'),
|
|
114
|
-
].filter(Boolean);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
async function createBaseConfig({
|
|
118
|
-
mode,
|
|
119
|
-
siteVariables,
|
|
120
|
-
entry,
|
|
121
|
-
devtool,
|
|
122
|
-
defineIsDev = false,
|
|
123
|
-
optimization,
|
|
124
|
-
plugins,
|
|
125
|
-
}) {
|
|
126
|
-
const packageDir = getPackageDir();
|
|
127
|
-
return {
|
|
128
|
-
mode,
|
|
129
|
-
entry,
|
|
130
|
-
output: {
|
|
131
|
-
path: distDir,
|
|
132
|
-
publicPath: siteVariables.basePath,
|
|
133
|
-
filename: '[name].bundle.js',
|
|
134
|
-
},
|
|
135
|
-
resolve: { extensions: ['.ts', '.js', '.json'] },
|
|
136
|
-
resolveLoader: {
|
|
137
|
-
modules: [
|
|
138
|
-
path.resolve(packageDir, 'node_modules'),
|
|
139
|
-
path.resolve(packageDir, '..', '..'),
|
|
140
|
-
'node_modules',
|
|
141
|
-
],
|
|
142
|
-
},
|
|
143
|
-
devtool,
|
|
144
|
-
module: { rules: createModuleRules(siteVariables) },
|
|
145
|
-
...(optimization && { optimization }),
|
|
146
|
-
plugins: await createPlugins(siteVariables, { defineIsDev, plugins }),
|
|
147
|
-
stats: 'errors-only',
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
module.exports = { createBaseConfig };
|
package/webpack/config.dev.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const ContentWatchPlugin = require('./content-watch-plugin');
|
|
3
|
-
const { createBaseConfig } = require('./config.base');
|
|
4
|
-
const { getDevSiteVariables } = require('./site-variables');
|
|
5
|
-
const { getPackageDir } = require('./utils/paths');
|
|
6
|
-
|
|
7
|
-
module.exports = async (env = {}) => {
|
|
8
|
-
const siteVariables = getDevSiteVariables();
|
|
9
|
-
const packageDir = getPackageDir();
|
|
10
|
-
const entry = { index: path.resolve(packageDir, 'src/index.ts') };
|
|
11
|
-
if (env.watchMode) {
|
|
12
|
-
entry.reload = path.resolve(packageDir, 'webpack/watch-reload-client.js');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return createBaseConfig({
|
|
16
|
-
mode: 'development',
|
|
17
|
-
devtool: 'inline-source-map',
|
|
18
|
-
siteVariables,
|
|
19
|
-
entry,
|
|
20
|
-
defineIsDev: true,
|
|
21
|
-
plugins: [new ContentWatchPlugin(siteVariables)],
|
|
22
|
-
});
|
|
23
|
-
};
|
package/webpack/config.prod.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const TerserPlugin = require('terser-webpack-plugin');
|
|
3
|
-
const { createBaseConfig } = require('./config.base');
|
|
4
|
-
const { compileTemplates } = require('./templates');
|
|
5
|
-
const { getProdSiteVariables } = require('./site-variables');
|
|
6
|
-
const { getPackageDir } = require('./utils/paths');
|
|
7
|
-
|
|
8
|
-
const siteVariables = getProdSiteVariables();
|
|
9
|
-
|
|
10
|
-
module.exports = async () => {
|
|
11
|
-
compileTemplates(siteVariables);
|
|
12
|
-
|
|
13
|
-
return createBaseConfig({
|
|
14
|
-
mode: 'production',
|
|
15
|
-
siteVariables,
|
|
16
|
-
entry: { index: path.resolve(getPackageDir(), 'src/index.ts') },
|
|
17
|
-
devtool: false,
|
|
18
|
-
optimization: {
|
|
19
|
-
minimizer: [
|
|
20
|
-
/*
|
|
21
|
-
* Bun's event loop doesn't track TerserPlugin's worker threads,
|
|
22
|
-
* causing a premature exit; set parallel to false to prevent worker
|
|
23
|
-
* threads from being used.
|
|
24
|
-
*/
|
|
25
|
-
new TerserPlugin({
|
|
26
|
-
parallel: false,
|
|
27
|
-
terserOptions: { output: { comments: false } },
|
|
28
|
-
}),
|
|
29
|
-
],
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
};
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const {
|
|
4
|
-
getContentDir,
|
|
5
|
-
getContentFiles,
|
|
6
|
-
getBuildContentFiles,
|
|
7
|
-
} = require('./util');
|
|
8
|
-
const { setWatchState } = require('./build-state');
|
|
9
|
-
const {
|
|
10
|
-
compileTemplates,
|
|
11
|
-
getHtmlTemplatesDir,
|
|
12
|
-
getJsonDataDir,
|
|
13
|
-
JSON_DATA_FILES,
|
|
14
|
-
} = require('./templates');
|
|
15
|
-
const { getProjectDir } = require('./utils/paths');
|
|
16
|
-
|
|
17
|
-
let _needsRestart = false;
|
|
18
|
-
|
|
19
|
-
class ContentWatchPlugin {
|
|
20
|
-
constructor(siteVariables) {
|
|
21
|
-
this.siteVariables = siteVariables;
|
|
22
|
-
this.siteConfigPath = path.resolve(
|
|
23
|
-
getProjectDir(),
|
|
24
|
-
'config',
|
|
25
|
-
'site.dev.json',
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
apply(compiler) {
|
|
30
|
-
let lastSig = null;
|
|
31
|
-
|
|
32
|
-
compiler.hooks.make.tap('ContentWatchPlugin', compilation => {
|
|
33
|
-
const htmlTemplatesDir = getHtmlTemplatesDir();
|
|
34
|
-
const jsonDataDir = getJsonDataDir();
|
|
35
|
-
|
|
36
|
-
// Refresh templates cache from disk
|
|
37
|
-
try {
|
|
38
|
-
compileTemplates(this.siteVariables);
|
|
39
|
-
} catch (err) {
|
|
40
|
-
compilation.errors.push(err);
|
|
41
|
-
for (const fileName of fs.readdirSync(htmlTemplatesDir)) {
|
|
42
|
-
compilation.fileDependencies.add(
|
|
43
|
-
path.join(htmlTemplatesDir, fileName),
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
for (const dataFile of JSON_DATA_FILES) {
|
|
47
|
-
const dataPath = path.join(jsonDataDir, dataFile);
|
|
48
|
-
if (fs.existsSync(dataPath)) {
|
|
49
|
-
compilation.fileDependencies.add(dataPath);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const contentDir = getContentDir();
|
|
56
|
-
const modifiedFiles = new Set(
|
|
57
|
-
[...(compiler.modifiedFiles || [])].map(filePath =>
|
|
58
|
-
path.resolve(filePath),
|
|
59
|
-
),
|
|
60
|
-
);
|
|
61
|
-
const normalizedContentDir = path.resolve(contentDir) + path.sep;
|
|
62
|
-
const normalizedHtmlDir = path.resolve(htmlTemplatesDir) + path.sep;
|
|
63
|
-
const contentFiles = getContentFiles(
|
|
64
|
-
contentDir,
|
|
65
|
-
Object.keys(this.siteVariables.codeLanguages),
|
|
66
|
-
);
|
|
67
|
-
const buildContentFiles = getBuildContentFiles(
|
|
68
|
-
contentDir,
|
|
69
|
-
Object.keys(this.siteVariables.codeLanguages),
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
// Detect structural changes (files added or deleted) that require a
|
|
73
|
-
// fresh compiler with updated content asset caches
|
|
74
|
-
const sig = buildContentFiles.slice().sort().join('\0');
|
|
75
|
-
let structureChanged = false;
|
|
76
|
-
if (lastSig !== null && sig !== lastSig) {
|
|
77
|
-
_needsRestart = true;
|
|
78
|
-
structureChanged = true;
|
|
79
|
-
}
|
|
80
|
-
lastSig = sig;
|
|
81
|
-
|
|
82
|
-
const changedContentFiles = new Set(
|
|
83
|
-
[...modifiedFiles].filter(filePath =>
|
|
84
|
-
filePath.startsWith(normalizedContentDir),
|
|
85
|
-
),
|
|
86
|
-
);
|
|
87
|
-
|
|
88
|
-
// Check if any HTML template or JSON data file changed
|
|
89
|
-
const jsonDataPaths = JSON_DATA_FILES.map(f =>
|
|
90
|
-
path.resolve(jsonDataDir, f),
|
|
91
|
-
);
|
|
92
|
-
const templatesChanged = [...modifiedFiles].some(
|
|
93
|
-
filePath =>
|
|
94
|
-
filePath === path.resolve(htmlTemplatesDir) ||
|
|
95
|
-
filePath.startsWith(normalizedHtmlDir) ||
|
|
96
|
-
jsonDataPaths.includes(filePath),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
setWatchState(compiler, {
|
|
100
|
-
contentFiles,
|
|
101
|
-
buildContentFiles,
|
|
102
|
-
changedContentFiles,
|
|
103
|
-
templatesChanged,
|
|
104
|
-
structureChanged,
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
// Tell webpack to watch all content files
|
|
108
|
-
for (const filePath of contentFiles) {
|
|
109
|
-
compilation.fileDependencies.add(filePath);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Watch content directories so webpack detects newly added files
|
|
113
|
-
function addDirs(dir) {
|
|
114
|
-
compilation.contextDependencies.add(dir);
|
|
115
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
116
|
-
if (entry.isDirectory()) {
|
|
117
|
-
addDirs(path.join(dir, entry.name));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
addDirs(contentDir);
|
|
122
|
-
|
|
123
|
-
// Watch HTML template files from the package
|
|
124
|
-
for (const fileName of fs.readdirSync(htmlTemplatesDir)) {
|
|
125
|
-
compilation.fileDependencies.add(path.join(htmlTemplatesDir, fileName));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Watch JSON data files from the project config
|
|
129
|
-
for (const dataFile of JSON_DATA_FILES) {
|
|
130
|
-
const dataPath = path.join(jsonDataDir, dataFile);
|
|
131
|
-
if (fs.existsSync(dataPath)) {
|
|
132
|
-
compilation.fileDependencies.add(dataPath);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Watch the site config file and restart when it changes
|
|
137
|
-
compilation.fileDependencies.add(this.siteConfigPath);
|
|
138
|
-
const siteConfigChanged = modifiedFiles.has(
|
|
139
|
-
path.resolve(this.siteConfigPath),
|
|
140
|
-
);
|
|
141
|
-
if (siteConfigChanged) {
|
|
142
|
-
_needsRestart = true;
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
ContentWatchPlugin.needsRestart = () => _needsRestart;
|
|
149
|
-
ContentWatchPlugin.clearRestart = () => {
|
|
150
|
-
_needsRestart = false;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
module.exports = ContentWatchPlugin;
|