@zulaica/site-bundler 0.5.1 → 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 CHANGED
@@ -9,5 +9,5 @@ npm install @zulaica/site-bundler --save-dev
9
9
  ## Usage
10
10
 
11
11
  ```sh
12
- site-bundler --input <source-directory> --output <destination-directory>
12
+ site-bundler --input-dir <input-directory> --output-dir <output-directory>
13
13
  ```
@@ -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
- });
@@ -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 { Command } from 'commander';
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 program = new Command();
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 source directory')
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
- logMessage(`${EMOJI.construction} Bundling release\n`);
49
- await preflight(output);
50
- await copyAssets(input, output, files);
51
- await processCSS(input, output, files.css);
52
- await processJS(input, output, files.js);
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, logError, logMessage } from '../helpers/index.mjs';
2
+ import { EMOJI, EXCLUSIONS, logMessage } from '../helpers/index.mjs';
3
3
 
4
- const copyAssets = async (input, output, files) => {
5
- const assets = await readdir(input);
6
- for (const file in files) {
7
- assets.splice(assets.indexOf(files[file]), 1);
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 (!assets.length) {
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 (output) => {
4
+ const preflight = async (outputDir) => {
5
5
  try {
6
- const files = await readdir(output);
7
- logMessage(
8
- `${EMOJI.wastebasket} Removing old release files (0/${files.length})`
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 release files (${index + 1}/${
13
- files.length
14
- })`,
15
- true
10
+ `${EMOJI.wastebasket} Removing old ${outputDir} files (0/${files.length})`
16
11
  );
17
- await rm(`${output}/${file}`, { recursive: true, force: true });
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 release directory`);
22
- await mkdir(output);
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, logError, logMessage, OPTIONS } from '../helpers/index.mjs';
7
+ import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
8
8
 
9
- const processCSS = async (input, output, file) => {
9
+ const processCSS = async ({ inputDir, outputDir }) => {
10
10
  logMessage(`${EMOJI.artistPalette} Processing styles`);
11
- try {
12
- const data = await readFile(`${input}/${file}`, {
13
- encoding: 'utf8'
14
- });
15
- await postcss()
16
- .use(atImport())
17
- .use(postcssPresetEnv())
18
- .use(url(OPTIONS.postcss.url))
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, logError, logMessage, OPTIONS } from '../helpers/index.mjs';
5
+ import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
6
6
 
7
- const processHTML = async (input, output, file) => {
7
+ const processHTML = async ({ inputDir, outputDir }) => {
8
8
  logMessage(`${EMOJI.fileCabinet} Processing HTML`);
9
- try {
10
- const data = await readFile(`${input}/${file}`, { encoding: 'utf8' });
11
- await posthtml()
12
- .use(htmlnano(OPTIONS.posthtml.htmlnano, htmlnano.presets.safe))
13
- .use(hash({ path: output, pattern: new RegExp(/hash/) }))
14
- .process(data)
15
- .then(({ html }) => {
16
- writeFile(`${output}/${file}`, html, { encoding: 'utf8' });
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, logError, logMessage, OPTIONS } from '../helpers/index.mjs';
5
+ import { EMOJI, OPTIONS, logMessage } from '../helpers/index.mjs';
6
6
 
7
- const bundleJS = async (input, output, file) => {
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
- try {
25
- await bundleJS(input, output, file);
26
- const data = await readFile(`${output}/${file}`, {
27
- encoding: 'utf8'
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.5.1",
4
+ "version": "0.6.0",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": ">=18.19.1"