@zulaica/site-bundler 0.5.0 → 0.6.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 +1 -1
- package/lib/helpers/constants.mjs +20 -13
- package/lib/helpers/index.mjs +2 -2
- package/lib/index.mjs +12 -34
- package/lib/modules/copyAssets.mjs +9 -16
- package/lib/modules/preflight.mjs +18 -16
- package/lib/modules/processCSS.mjs +21 -22
- package/lib/modules/processHTML.mjs +19 -16
- package/lib/modules/processJS.mjs +23 -31
- package/package.json +9 -6
- package/.eslintrc.json +0 -19
- package/.gitattributes +0 -7
- package/.github/workflows/lint.yml +0 -17
- package/.prettierrc.json +0 -7
- package/.vscode/extensions.json +0 -11
- package/.vscode/settings.json +0 -15
package/README.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
export const EMOJI = Object.freeze({
|
|
2
|
+
artistPalette: '\uD83C\uDFA8',
|
|
3
|
+
barChart: '\uD83D\uDCCA',
|
|
4
|
+
cardIndexDividers: '\uD83D\uDDC2',
|
|
5
|
+
constructionWorker: '\uD83D\uDC77',
|
|
6
|
+
fileCabinet: '\uD83D\uDDC4 ',
|
|
7
|
+
fileFolder: '\uD83D\uDCC1',
|
|
8
|
+
noEntry: '\u26D4\uFE0F',
|
|
9
|
+
package: '\uD83D\uDCE6',
|
|
10
|
+
wastebasket: '\ud83d\uddd1\ufe0f '
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const EXCLUSIONS = Object.freeze([
|
|
14
|
+
'index.html',
|
|
15
|
+
'script.hash.js',
|
|
16
|
+
'scripts',
|
|
17
|
+
'style.hash.css',
|
|
18
|
+
'styles'
|
|
19
|
+
]);
|
|
20
|
+
|
|
1
21
|
export const OPTIONS = Object.freeze({
|
|
2
22
|
babel: {
|
|
3
23
|
presets: [
|
|
@@ -59,16 +79,3 @@ export const OPTIONS = Object.freeze({
|
|
|
59
79
|
}
|
|
60
80
|
}
|
|
61
81
|
});
|
|
62
|
-
|
|
63
|
-
export const EMOJI = Object.freeze({
|
|
64
|
-
artistPalette: '\uD83C\uDFA8',
|
|
65
|
-
barChart: '\uD83D\uDCCA',
|
|
66
|
-
cardIndexDividers: '\uD83D\uDDC2',
|
|
67
|
-
construction: '\uD83D\uDEA7',
|
|
68
|
-
constructionWorker: '\uD83D\uDC77',
|
|
69
|
-
fileCabinet: '\uD83D\uDDC4 ',
|
|
70
|
-
fileFolder: '\uD83D\uDCC1',
|
|
71
|
-
noEntry: '\u26D4\uFE0F',
|
|
72
|
-
package: '\uD83D\uDCE6',
|
|
73
|
-
wastebasket: '\ud83d\uddd1\ufe0f '
|
|
74
|
-
});
|
package/lib/helpers/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EMOJI, OPTIONS } from './constants.mjs';
|
|
1
|
+
import { EMOJI, EXCLUSIONS, OPTIONS } from './constants.mjs';
|
|
2
2
|
import { logError, logMessage } from './loggers.mjs';
|
|
3
3
|
|
|
4
|
-
export { EMOJI, OPTIONS, logError, logMessage };
|
|
4
|
+
export { EMOJI, EXCLUSIONS, OPTIONS, logError, logMessage };
|
package/lib/index.mjs
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { program } from 'commander';
|
|
4
4
|
import { readFile } from 'fs/promises';
|
|
5
|
-
import { createRequire } from 'module';
|
|
6
|
-
import { extname } from 'path';
|
|
7
|
-
import posthtml from 'posthtml';
|
|
8
5
|
import { EMOJI, logError, logMessage } from './helpers/index.mjs';
|
|
9
6
|
import {
|
|
10
7
|
copyAssets,
|
|
@@ -14,43 +11,24 @@ import {
|
|
|
14
11
|
processJS
|
|
15
12
|
} from './modules/index.mjs';
|
|
16
13
|
|
|
17
|
-
const require = createRequire(import.meta.url);
|
|
18
|
-
const { version } = require('../package.json');
|
|
19
|
-
|
|
20
14
|
(async () => {
|
|
21
|
-
const
|
|
15
|
+
const { version } = JSON.parse(
|
|
16
|
+
await readFile(new URL('../package.json', import.meta.url))
|
|
17
|
+
);
|
|
22
18
|
program
|
|
23
19
|
.version(version)
|
|
24
|
-
.requiredOption('-i, --input <input>', 'The
|
|
25
|
-
.requiredOption('-o, --output <output>', 'The output directory')
|
|
20
|
+
.requiredOption('-i, --input-dir <input>', 'The input directory')
|
|
21
|
+
.requiredOption('-o, --output-dir <output>', 'The output directory')
|
|
26
22
|
.parse();
|
|
27
|
-
|
|
28
|
-
const { input, output } = program.opts();
|
|
29
|
-
const files = { html: 'index.html', scripts: 'scripts', styles: 'styles' };
|
|
30
|
-
const data = await readFile(`${input}/index.html`, { encoding: 'utf8' });
|
|
31
|
-
posthtml()
|
|
32
|
-
.process(data)
|
|
33
|
-
.then(({ tree }) => {
|
|
34
|
-
tree.match(
|
|
35
|
-
[{ tag: 'script' }, { tag: 'link', attrs: { rel: 'stylesheet' } }],
|
|
36
|
-
(node) => {
|
|
37
|
-
if (node.attrs?.src || node.attrs?.href) {
|
|
38
|
-
const file = node.attrs.src ?? node.attrs.href;
|
|
39
|
-
const extension = extname(file).slice(1);
|
|
40
|
-
files[extension] = file;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
});
|
|
23
|
+
const opts = program.opts();
|
|
45
24
|
|
|
46
25
|
try {
|
|
47
26
|
logMessage(`${EMOJI.constructionWorker} Site Bundler v${version}\n\n`);
|
|
48
|
-
|
|
49
|
-
await
|
|
50
|
-
await
|
|
51
|
-
await
|
|
52
|
-
await
|
|
53
|
-
await processHTML(input, output, files.html);
|
|
27
|
+
await preflight(opts.outputDir);
|
|
28
|
+
await copyAssets(opts);
|
|
29
|
+
await processCSS(opts);
|
|
30
|
+
await processJS(opts);
|
|
31
|
+
await processHTML(opts);
|
|
54
32
|
logMessage(`${EMOJI.package} Finished!`);
|
|
55
33
|
} catch (error) {
|
|
56
34
|
logError(error);
|
|
@@ -1,34 +1,27 @@
|
|
|
1
1
|
import { cp, readdir } from 'fs/promises';
|
|
2
|
-
import { EMOJI,
|
|
2
|
+
import { EMOJI, EXCLUSIONS, logMessage } from '../helpers/index.mjs';
|
|
3
3
|
|
|
4
|
-
const copyAssets = async (
|
|
5
|
-
const assets = await readdir(
|
|
6
|
-
for (const
|
|
7
|
-
assets.splice(assets.indexOf(
|
|
4
|
+
const copyAssets = async ({ inputDir, outputDir }) => {
|
|
5
|
+
const assets = await readdir(inputDir);
|
|
6
|
+
for (const exclusion in EXCLUSIONS) {
|
|
7
|
+
assets.splice(assets.indexOf(exclusion), 1);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
if (
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
try {
|
|
10
|
+
if (assets.length) {
|
|
15
11
|
logMessage(
|
|
16
12
|
`${EMOJI.cardIndexDividers} Copying assets (0/${assets.length})`
|
|
17
13
|
);
|
|
18
14
|
for (const [index, asset] of assets.entries()) {
|
|
19
|
-
await cp(`${input}/${asset}`, `${output}/${asset}`, {
|
|
20
|
-
recursive: true
|
|
21
|
-
});
|
|
22
15
|
logMessage(
|
|
23
16
|
`${EMOJI.cardIndexDividers} Copying assets (${index + 1}/${
|
|
24
17
|
assets.length
|
|
25
18
|
})`,
|
|
26
19
|
true
|
|
27
20
|
);
|
|
21
|
+
await cp(`${inputDir}/${asset}`, `${outputDir}/${asset}`, {
|
|
22
|
+
recursive: true
|
|
23
|
+
});
|
|
28
24
|
}
|
|
29
|
-
} catch (error) {
|
|
30
|
-
logError(error);
|
|
31
|
-
} finally {
|
|
32
25
|
logMessage('\n');
|
|
33
26
|
}
|
|
34
27
|
};
|
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import { mkdir, readdir, rm } from 'fs/promises';
|
|
2
2
|
import { EMOJI, logError, logMessage } from '../helpers/index.mjs';
|
|
3
3
|
|
|
4
|
-
const preflight = async (
|
|
4
|
+
const preflight = async (outputDir) => {
|
|
5
5
|
try {
|
|
6
|
-
const files = await readdir(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
);
|
|
10
|
-
for (const [index, file] of files.entries()) {
|
|
6
|
+
const files = await readdir(outputDir);
|
|
7
|
+
|
|
8
|
+
if (files.length) {
|
|
11
9
|
logMessage(
|
|
12
|
-
`${EMOJI.wastebasket} Removing old
|
|
13
|
-
files.length
|
|
14
|
-
})`,
|
|
15
|
-
true
|
|
10
|
+
`${EMOJI.wastebasket} Removing old ${outputDir} files (0/${files.length})`
|
|
16
11
|
);
|
|
17
|
-
|
|
12
|
+
for (const [index, file] of files.entries()) {
|
|
13
|
+
logMessage(
|
|
14
|
+
`${EMOJI.wastebasket} Removing old ${outputDir} files (${index + 1}/${
|
|
15
|
+
files.length
|
|
16
|
+
})`,
|
|
17
|
+
true
|
|
18
|
+
);
|
|
19
|
+
await rm(`${outputDir}/${file}`, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
logMessage('\n');
|
|
18
22
|
}
|
|
19
23
|
} catch (error) {
|
|
20
24
|
if (error.code === 'ENOENT') {
|
|
21
|
-
logMessage(`${EMOJI.fileFolder} Creating
|
|
22
|
-
await mkdir(
|
|
25
|
+
logMessage(`${EMOJI.fileFolder} Creating ${outputDir} directory\n`);
|
|
26
|
+
await mkdir(outputDir);
|
|
23
27
|
} else {
|
|
24
|
-
logError(error);
|
|
28
|
+
logError(`${error} \n`);
|
|
25
29
|
}
|
|
26
|
-
} finally {
|
|
27
|
-
logMessage('\n');
|
|
28
30
|
}
|
|
29
31
|
};
|
|
30
32
|
|
|
@@ -4,30 +4,29 @@ import postcss from 'postcss';
|
|
|
4
4
|
import atImport from 'postcss-import';
|
|
5
5
|
import postcssPresetEnv from 'postcss-preset-env';
|
|
6
6
|
import url from 'postcss-url';
|
|
7
|
-
import { EMOJI,
|
|
7
|
+
import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
|
|
8
8
|
|
|
9
|
-
const processCSS = async (
|
|
9
|
+
const processCSS = async ({ inputDir, outputDir }) => {
|
|
10
10
|
logMessage(`${EMOJI.artistPalette} Processing styles`);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
.use(cssnanoPlugin(OPTIONS.postcss.cssnano))
|
|
20
|
-
.process(data, {
|
|
21
|
-
from: `${input}/${file}`
|
|
22
|
-
})
|
|
23
|
-
.then(({ css }) => {
|
|
24
|
-
writeFile(`${output}/${file}`, css, { encoding: 'utf8' });
|
|
25
|
-
});
|
|
26
|
-
} catch (error) {
|
|
27
|
-
logError(error);
|
|
28
|
-
} finally {
|
|
29
|
-
logMessage('\n');
|
|
30
|
-
}
|
|
11
|
+
const file = 'style.hash.css';
|
|
12
|
+
const input = `${inputDir}/${file}`;
|
|
13
|
+
const output = `${outputDir}/${file}`;
|
|
14
|
+
|
|
15
|
+
const data = await readFile(input, { encoding: 'utf8' });
|
|
16
|
+
const code = await _processData(input, data);
|
|
17
|
+
await writeFile(output, code);
|
|
18
|
+
logMessage('\n');
|
|
31
19
|
};
|
|
32
20
|
|
|
21
|
+
async function _processData(input, data) {
|
|
22
|
+
const { css } = await postcss()
|
|
23
|
+
.use(atImport())
|
|
24
|
+
.use(postcssPresetEnv())
|
|
25
|
+
.use(url(OPTIONS.postcss.url))
|
|
26
|
+
.use(cssnanoPlugin(OPTIONS.postcss.cssnano))
|
|
27
|
+
.process(data, { from: input });
|
|
28
|
+
|
|
29
|
+
return css;
|
|
30
|
+
}
|
|
31
|
+
|
|
33
32
|
export default processCSS;
|
|
@@ -2,24 +2,27 @@ import { readFile, writeFile } from 'fs/promises';
|
|
|
2
2
|
import htmlnano from 'htmlnano';
|
|
3
3
|
import posthtml from 'posthtml';
|
|
4
4
|
import { hash } from 'posthtml-hash';
|
|
5
|
-
import { EMOJI,
|
|
5
|
+
import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
|
|
6
6
|
|
|
7
|
-
const processHTML = async (
|
|
7
|
+
const processHTML = async ({ inputDir, outputDir }) => {
|
|
8
8
|
logMessage(`${EMOJI.fileCabinet} Processing HTML`);
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
} catch (error) {
|
|
19
|
-
logError(error);
|
|
20
|
-
} finally {
|
|
21
|
-
logMessage('\n');
|
|
22
|
-
}
|
|
9
|
+
const file = 'index.html';
|
|
10
|
+
const input = `${inputDir}/${file}`;
|
|
11
|
+
const output = `${outputDir}/${file}`;
|
|
12
|
+
|
|
13
|
+
const data = await readFile(input, { encoding: 'utf8' });
|
|
14
|
+
const code = await _processData(outputDir, data);
|
|
15
|
+
await writeFile(output, code);
|
|
16
|
+
logMessage('\n');
|
|
23
17
|
};
|
|
24
18
|
|
|
19
|
+
async function _processData(outputDir, data) {
|
|
20
|
+
const { html } = await posthtml()
|
|
21
|
+
.use(htmlnano(OPTIONS.posthtml.htmlnano, htmlnano.presets.safe))
|
|
22
|
+
.use(hash({ path: outputDir, pattern: new RegExp(/hash/) }))
|
|
23
|
+
.process(data);
|
|
24
|
+
|
|
25
|
+
return html;
|
|
26
|
+
}
|
|
27
|
+
|
|
25
28
|
export default processHTML;
|
|
@@ -2,40 +2,32 @@ import { transformFromAstAsync } from '@babel/core';
|
|
|
2
2
|
import { parse } from '@babel/parser';
|
|
3
3
|
import { readFile, writeFile } from 'fs/promises';
|
|
4
4
|
import { rollup } from 'rollup';
|
|
5
|
-
import { EMOJI,
|
|
5
|
+
import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
try {
|
|
9
|
-
const bundle = await rollup({
|
|
10
|
-
input: `${input}/${file}`
|
|
11
|
-
});
|
|
12
|
-
await bundle.write({
|
|
13
|
-
file: `${output}/${file}`
|
|
14
|
-
});
|
|
15
|
-
await bundle.close();
|
|
16
|
-
} catch (error) {
|
|
17
|
-
logError(error);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const processJS = async (input, output, file) => {
|
|
7
|
+
const processJS = async ({ inputDir, outputDir }) => {
|
|
22
8
|
logMessage(`${EMOJI.barChart} Processing scripts`);
|
|
9
|
+
const file = 'script.hash.js';
|
|
10
|
+
const input = `${inputDir}/${file}`;
|
|
11
|
+
const output = `${outputDir}/${file}`;
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const ast = parse(data, {
|
|
30
|
-
sourceType: 'module'
|
|
31
|
-
});
|
|
32
|
-
const { code } = await transformFromAstAsync(ast, data, OPTIONS.babel);
|
|
33
|
-
await writeFile(`${output}/${file}`, code, { encoding: 'utf8' });
|
|
34
|
-
} catch (error) {
|
|
35
|
-
logError(error);
|
|
36
|
-
} finally {
|
|
37
|
-
logMessage('\n');
|
|
38
|
-
}
|
|
13
|
+
await _bundleJS(input, output);
|
|
14
|
+
const data = await readFile(output, { encoding: 'utf8' });
|
|
15
|
+
const code = await _processData(data);
|
|
16
|
+
await writeFile(output, code);
|
|
17
|
+
logMessage('\n');
|
|
39
18
|
};
|
|
40
19
|
|
|
20
|
+
async function _bundleJS(input, output) {
|
|
21
|
+
const bundle = await rollup({ input });
|
|
22
|
+
await bundle.write({ file: output });
|
|
23
|
+
await bundle.close();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function _processData(data) {
|
|
27
|
+
const ast = parse(data, { sourceType: 'module' });
|
|
28
|
+
const { code } = await transformFromAstAsync(ast, data, OPTIONS.babel);
|
|
29
|
+
|
|
30
|
+
return code;
|
|
31
|
+
}
|
|
32
|
+
|
|
41
33
|
export default processJS;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zulaica/site-bundler",
|
|
3
3
|
"author": "David Zulaica",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=18.19.1"
|
|
@@ -10,6 +10,14 @@
|
|
|
10
10
|
"bin": {
|
|
11
11
|
"site-bundler": "lib/index.mjs"
|
|
12
12
|
},
|
|
13
|
+
"description": "",
|
|
14
|
+
"main": "index.mjs",
|
|
15
|
+
"directories": {
|
|
16
|
+
"lib": "lib"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"/lib"
|
|
20
|
+
],
|
|
13
21
|
"scripts": {
|
|
14
22
|
"lint": "eslint \"lib/**\"",
|
|
15
23
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -44,11 +52,6 @@
|
|
|
44
52
|
"eslint-plugin-prettier": "5.1.3",
|
|
45
53
|
"prettier": "3.2.5"
|
|
46
54
|
},
|
|
47
|
-
"description": "",
|
|
48
|
-
"main": "index.mjs",
|
|
49
|
-
"directories": {
|
|
50
|
-
"lib": "lib"
|
|
51
|
-
},
|
|
52
55
|
"volta": {
|
|
53
56
|
"node": "18.19.1",
|
|
54
57
|
"npm": "10.2.4"
|
package/.eslintrc.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"es2022": true,
|
|
4
|
-
"node": true
|
|
5
|
-
},
|
|
6
|
-
"extends": [
|
|
7
|
-
"eslint:recommended",
|
|
8
|
-
"plugin:prettier/recommended"
|
|
9
|
-
],
|
|
10
|
-
"parserOptions": {
|
|
11
|
-
"sourceType": "module"
|
|
12
|
-
},
|
|
13
|
-
"plugins": [
|
|
14
|
-
"prettier"
|
|
15
|
-
],
|
|
16
|
-
"rules": {
|
|
17
|
-
"no-var": "error"
|
|
18
|
-
}
|
|
19
|
-
}
|
package/.gitattributes
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
name: Lint Code Base
|
|
2
|
-
|
|
3
|
-
on: pull_request
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
lint_javascript:
|
|
7
|
-
name: Lint JavaScript Files
|
|
8
|
-
runs-on: ubuntu-latest
|
|
9
|
-
steps:
|
|
10
|
-
- name: Check out branch
|
|
11
|
-
uses: actions/checkout@v3
|
|
12
|
-
- name: Install Node.js
|
|
13
|
-
uses: volta-cli/action@v1
|
|
14
|
-
- name: Install dependencies
|
|
15
|
-
run: npm ci
|
|
16
|
-
- name: Run lint script
|
|
17
|
-
run: npm run lint
|
package/.prettierrc.json
DELETED
package/.vscode/extensions.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
|
3
|
-
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
|
4
|
-
// List of extensions which should be recommended for users of this workspace.
|
|
5
|
-
"recommendations": [
|
|
6
|
-
"dbaeumer.vscode-eslint",
|
|
7
|
-
"esbenp.prettier-vscode"
|
|
8
|
-
],
|
|
9
|
-
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
|
10
|
-
"unwantedRecommendations": []
|
|
11
|
-
}
|
package/.vscode/settings.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"editor.codeActionsOnSave": {
|
|
3
|
-
"source.organizeImports": "explicit"
|
|
4
|
-
},
|
|
5
|
-
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
|
6
|
-
"editor.formatOnSave": true,
|
|
7
|
-
"eslint.run": "onSave",
|
|
8
|
-
"files.exclude": {
|
|
9
|
-
"**/.git": true,
|
|
10
|
-
"**/node_modules": true,
|
|
11
|
-
"**/.DS_Store": true,
|
|
12
|
-
"**/Thumbs.db": true
|
|
13
|
-
},
|
|
14
|
-
"search.exclude": {}
|
|
15
|
-
}
|