Skip to content

Commit 60f9a87

Browse files
committed
Set up CSS build step for errorpage
1 parent ed24d57 commit 60f9a87

File tree

7 files changed

+183
-148
lines changed

7 files changed

+183
-148
lines changed

special-pages/index.mjs

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { buildSync } from 'esbuild';
99
import { cwd, parseArgs } from '../scripts/script-utils.js';
1010
import inliner from 'web-resource-inliner';
1111
import { baseEsbuildOptions } from './opts.mjs';
12+
import { pages } from './pages.mjs';
1213

1314
const CWD = cwd(import.meta.url);
1415
const ROOT = join(CWD, '../');
@@ -17,65 +18,16 @@ const args = parseArgs(process.argv.slice(2), []);
1718
const NODE_ENV = args.env || 'production';
1819
const DEBUG = Boolean(args.debug);
1920

20-
export const support = {
21-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
22-
duckplayer: {
23-
integration: ['copy', 'build-js'],
24-
windows: ['copy', 'build-js'],
25-
apple: ['copy', 'build-js', 'inline-html'],
26-
android: ['copy', 'build-js'],
27-
},
28-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
29-
errorpage: {
30-
integration: ['copy'],
31-
apple: ['copy', 'inline-html'],
32-
},
33-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
34-
onboarding: {
35-
integration: ['copy', 'build-js'],
36-
windows: ['copy', 'build-js'],
37-
apple: ['copy', 'build-js'],
38-
},
39-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
40-
example: {
41-
integration: ['copy', 'build-js'],
42-
},
43-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
44-
'release-notes': {
45-
integration: ['copy', 'build-js'],
46-
apple: ['copy', 'build-js'],
47-
windows: ['copy', 'build-js'],
48-
},
49-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
50-
'special-error': {
51-
integration: ['copy', 'build-js'],
52-
apple: ['copy', 'build-js', 'inline-html'],
53-
windows: ['copy', 'build-js', 'inline-html'],
54-
},
55-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
56-
'new-tab': {
57-
integration: ['copy', 'build-js'],
58-
windows: ['copy', 'build-js'],
59-
apple: ['copy', 'build-js'],
60-
},
61-
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
62-
history: {
63-
integration: ['copy', 'build-js'],
64-
windows: ['copy', 'build-js'],
65-
apple: ['copy', 'build-js'],
66-
},
67-
};
68-
6921
/** @type {{src: string, dest: string, dist: string, injectName: string}[]} */
7022
const copyJobs = [];
71-
/** @type {{outputDir: string, injectName: ImportMeta['injectName'], pageName: string}[]} */
23+
/** @type {{outputDir: string, injectName: ImportMeta['injectName'], pageName: string, entry?: string[]}[]} */
7224
const buildJobs = [];
7325
/** @type {{src: string}[]} */
7426
const inlineJobs = [];
7527
const errors = [];
7628
const DRY_RUN = false;
7729

78-
for (const [pageName, injectNames] of Object.entries(support)) {
30+
for (const [pageName, injectNames] of Object.entries(pages)) {
7931
const publicDir = join(CWD, 'pages', pageName, 'public');
8032
if (!existsSync(publicDir)) {
8133
errors.push(`${publicDir} does not exist. Each page must have a 'src' directory`);
@@ -104,6 +56,15 @@ for (const [pageName, injectNames] of Object.entries(support)) {
10456
pageName,
10557
});
10658
}
59+
if (job === 'build-css') {
60+
const outputDir = join(pageOutputDirectory, 'dist');
61+
buildJobs.push({
62+
outputDir,
63+
injectName: /** @type {ImportMeta['injectName']} */ (injectNameKey),
64+
pageName,
65+
entry: ['index.css'],
66+
});
67+
}
10768
if (job === 'inline-html') {
10869
const htmlSrc = join(pageOutputDirectory, 'index.html');
10970
inlineJobs.push({ src: htmlSrc });
@@ -142,7 +103,10 @@ for (const buildJob of buildJobs) {
142103
if (DEBUG) console.log('\t- import.meta.env: ', NODE_ENV);
143104
if (DEBUG) console.log('\t- import.meta.injectName: ', buildJob.injectName);
144105
if (!DRY_RUN) {
145-
const opts = baseEsbuildOptions(buildJob.pageName, buildJob.injectName, NODE_ENV, buildJob.outputDir);
106+
/** @type {import('./opts.mjs').EsbuildOptionsConfig} */
107+
const config = { output: buildJob.outputDir };
108+
if (buildJob.entry) config.entry = buildJob.entry;
109+
const opts = baseEsbuildOptions(buildJob.pageName, buildJob.injectName, NODE_ENV, config);
146110
buildSync(opts);
147111
}
148112
}

special-pages/opts.mjs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@ import { join } from 'node:path';
22
import { cwd } from '../scripts/script-utils.js';
33
const CWD = cwd(import.meta.url);
44

5+
/**
6+
* @typedef {object} EsbuildOptionsConfig
7+
* @property {string} [output] - optionally change the output folder
8+
* @property {string[]} [entry] - custom entry points (defaults to ['index.js', 'inline.js'])
9+
*/
10+
511
/**
612
* @param {string} page
713
* @param {ImportMeta['injectName']} injectName
814
* @param {'development' | 'production'} nodeEnv
9-
* @param {string} [output] - optionally change the output folder
15+
* @param {EsbuildOptionsConfig} [config] - additional configuration options
1016
* @return {import('esbuild').BuildOptions}
1117
*/
12-
export function baseEsbuildOptions(page, injectName, nodeEnv, output) {
18+
export function baseEsbuildOptions(page, injectName, nodeEnv, config) {
1319
const pageDir = join(CWD, 'pages', page);
1420
const publicDir = join(pageDir, 'public');
1521
const srcDir = join(pageDir, 'src');
16-
const distDir = output || join(publicDir, 'dist');
17-
const entry = [join(srcDir, 'index.js'), join(srcDir, 'inline.js')];
22+
const distDir = config?.output || join(publicDir, 'dist');
23+
const entryFiles = config?.entry || ['index.js', 'inline.js'];
24+
const entry = entryFiles.map((file) => join(srcDir, file));
1825
return {
1926
entryPoints: entry,
2027
outdir: distDir,

special-pages/pages.mjs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Page build configuration
3+
*
4+
* Defines which build jobs each page requires for each platform.
5+
* - 'copy': Copy public/ to build output
6+
* - 'build-js': Build JS/CSS from src/index.js and src/inline.js
7+
* - 'build-css': Build CSS only from src/index.css
8+
* - 'inline-html': Inline assets into HTML for single-file distribution
9+
*/
10+
export const pages = {
11+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
12+
duckplayer: {
13+
integration: ['copy', 'build-js'],
14+
windows: ['copy', 'build-js'],
15+
apple: ['copy', 'build-js', 'inline-html'],
16+
android: ['copy', 'build-js'],
17+
},
18+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
19+
errorpage: {
20+
integration: ['copy', 'build-css'],
21+
apple: ['copy', 'build-css', 'inline-html'],
22+
},
23+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
24+
onboarding: {
25+
integration: ['copy', 'build-js'],
26+
windows: ['copy', 'build-js'],
27+
apple: ['copy', 'build-js'],
28+
},
29+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
30+
example: {
31+
integration: ['copy', 'build-js'],
32+
},
33+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
34+
'release-notes': {
35+
integration: ['copy', 'build-js'],
36+
apple: ['copy', 'build-js'],
37+
windows: ['copy', 'build-js'],
38+
},
39+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
40+
'special-error': {
41+
integration: ['copy', 'build-js'],
42+
apple: ['copy', 'build-js', 'inline-html'],
43+
windows: ['copy', 'build-js', 'inline-html'],
44+
},
45+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
46+
'new-tab': {
47+
integration: ['copy', 'build-js'],
48+
windows: ['copy', 'build-js'],
49+
apple: ['copy', 'build-js'],
50+
},
51+
/** @type {Partial<Record<ImportMeta['injectName'], string[]>>} */
52+
history: {
53+
integration: ['copy', 'build-js'],
54+
windows: ['copy', 'build-js'],
55+
apple: ['copy', 'build-js'],
56+
},
57+
};

special-pages/pages/errorpage/public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta name="viewport"
66
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
77
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8-
<link rel="stylesheet" href="style.css">
8+
<link rel="stylesheet" href="./dist/index.css">
99
</head>
1010
<body data-theme-variant="$THEME_VARIANT$">
1111
<div class="content-container">

special-pages/pages/errorpage/public/style.css

Lines changed: 0 additions & 90 deletions
This file was deleted.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
@import url("../../../shared/styles/design-tokens.css");
2+
3+
body {
4+
font-family:'-apple-system-font';
5+
background: rgb(255, 255, 255);
6+
7+
display: flex;
8+
height: 100vh;
9+
margin: 0 auto;
10+
11+
text-align: center;
12+
align-items: center;
13+
14+
cursor: default;
15+
}
16+
17+
.content-container {
18+
min-width: 320px;
19+
max-width: 580px;
20+
margin: 0 auto;
21+
}
22+
23+
.error-header {
24+
font-size: 14px;
25+
font-weight: 600;
26+
line-height: 18px;
27+
margin: 0 auto;
28+
padding: 0px;
29+
}
30+
31+
.error-description {
32+
font-size: 13px;
33+
line-height: 16px;
34+
margin: 0 auto;
35+
padding: 8px;
36+
}
37+
38+
.header-container .description-container {
39+
color: rgb(44, 44, 44);
40+
position: relative;
41+
width: 100%;
42+
word-wrap: break-word;
43+
}
44+
45+
.watermark-container {
46+
display: inline-block;
47+
position: fixed;
48+
width: 100px;
49+
height: 100px;
50+
bottom: 20px;
51+
right: 20px;
52+
opacity: 0.5;
53+
filter: grayscale(100%);
54+
pointer-events: none;
55+
}
56+
57+
.watermark {
58+
max-width: 100px;
59+
max-height: 100px;
60+
}
61+
62+
@media (prefers-color-scheme: dark) {
63+
body {
64+
background: rgb(51, 51, 51);
65+
}
66+
67+
.error-description, .error-header {
68+
color: rgb(210, 210, 210);
69+
}
70+
}
71+
72+
/* Theme variants - light mode */
73+
[data-theme-variant="coolGray"] { background: var(--ds-color-cool-gray-light-surface-primary); }
74+
[data-theme-variant="slateBlue"] { background: var(--ds-color-slate-blue-light-surface-primary); }
75+
[data-theme-variant="green"] { background: var(--ds-color-green-light-surface-primary); }
76+
[data-theme-variant="violet"] { background: var(--ds-color-violet-light-surface-primary); }
77+
[data-theme-variant="rose"] { background: var(--ds-color-rose-light-surface-primary); }
78+
[data-theme-variant="orange"] { background: var(--ds-color-orange-light-surface-primary); }
79+
[data-theme-variant="desert"] { background: var(--ds-color-desert-light-surface-primary); }
80+
81+
/* Theme variants - dark mode */
82+
@media (prefers-color-scheme: dark) {
83+
[data-theme-variant="coolGray"] { background: var(--ds-color-cool-gray-dark-surface-primary); }
84+
[data-theme-variant="slateBlue"] { background: var(--ds-color-slate-blue-dark-surface-primary); }
85+
[data-theme-variant="green"] { background: var(--ds-color-green-dark-surface-primary); }
86+
[data-theme-variant="violet"] { background: var(--ds-color-violet-dark-surface-primary); }
87+
[data-theme-variant="rose"] { background: var(--ds-color-rose-dark-surface-primary); }
88+
[data-theme-variant="orange"] { background: var(--ds-color-orange-dark-surface-primary); }
89+
[data-theme-variant="desert"] { background: var(--ds-color-desert-dark-surface-primary); }
90+
}

0 commit comments

Comments
 (0)