@changke/staticnext-build 0.13.0 → 0.26.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.26.0
8
+ 2025-12-21
9
+ ### Removed
10
+ - `del`, `cpy` and `globby` to prefer node's native features (`rm`, `cp` and `glob`)
11
+ - `mocha` to prefer node's built-in test runner
12
+ ### Added
13
+ - New experimental templating system `JSTmpl` as default
14
+ - Parameter `--njk` to specify Nunjucks as template engine
15
+ - Parameter `--debug` to show verbose information for "copy" and "markdown" tasks
16
+ ### Changed
17
+ - Console outputs now with colors
18
+ - Updated various dependencies
19
+
7
20
  ## 0.13.0
8
21
  2025-09-20
9
22
  ### Changed
package/build.mjs CHANGED
@@ -1,19 +1,27 @@
1
1
  #!/usr/bin/env node
2
-
3
2
  import {argv} from 'node:process';
3
+ import path from 'node:path';
4
4
 
5
+ import './lib/typedefs.mjs';
5
6
  import Config from './lib/config.mjs';
6
7
 
7
8
  import clean from './lib/tasks/clean.mjs';
8
9
  import copy from './lib/tasks/copy.mjs';
9
- import markdown from './lib/tasks/markdown.mjs';
10
- import prototype from './lib/tasks/prototype.mjs';
10
+ import {markdown, markdown2} from './lib/tasks/markdown.mjs';
11
+ import {prototype, prototype2} from './lib/tasks/prototype.mjs';
11
12
  import scripts from './lib/tasks/scripts.mjs';
12
13
  import setEnvDev from './lib/tasks/set-env-dev.mjs';
13
14
  import setEnvProd from './lib/tasks/set-env-prod.mjs';
14
15
  import styles from './lib/tasks/styles.mjs';
16
+ import {consoleLogColored} from './lib/utils.mjs';
15
17
 
16
18
  const taskName = argv[2]?.toLowerCase() || 'dev';
19
+ const useNjk = argv.includes('--njk');
20
+ const debug = argv.includes('--debug');
21
+
22
+ if (debug) {
23
+ process.env.SN_BUILD_MODE = 'debug';
24
+ }
17
25
 
18
26
  // load config data
19
27
  const conf = await Config.loadConfig();
@@ -22,17 +30,23 @@ const taskEnded = taskName => {
22
30
  console.timeEnd(taskName);
23
31
  };
24
32
 
25
- const srcPaths = Config.getSourcePaths(conf.sourcePath, conf.sourceRoot);
26
- const tgtPaths = Config.getTargetPaths(conf.targetPath, conf.targetRoot, conf.targetAssetsRoot);
33
+ const srcPaths = Config.getSourcePaths(conf.sourcePath, path.normalize(conf.sourceRoot));
34
+ const tgtPaths = Config.getTargetPaths(conf.targetPath, path.normalize(conf.targetRoot), conf.targetAssetsRoot);
27
35
 
28
36
  // Set parameters of each task
29
37
  const tasks = {
30
- clean: () => clean([`${conf.targetRoot}/*`]),
38
+ clean: () => clean([conf.targetRoot]),
31
39
  copy: () => copy([
32
- {sources: [`${conf.sourceRoot}/*`, `!${conf.sourceRoot}/*.d.ts`], target: conf.targetRoot},
33
- {sources: `${srcPaths.assets}/**/*`, target: tgtPaths.assets},
34
- {sources: `${srcPaths.modules}/**/assets/**/*`, target: tgtPaths.moduleAssets},
35
- {sources: `${srcPaths.markdown}/**/assets/**/*`, target: tgtPaths.markdown}
40
+ // Root2root: src/main/webapp/index.html -> tgt/static/index.html
41
+ {sources: [`${conf.sourceRoot}/*.*`, `!${conf.sourceRoot}/*.d.ts`], target: conf.targetRoot, opts: {flat: true}},
42
+ // Assets: src/main/webapp/assets/dummy.txt -> tgt/static/assets/_sn_/dummy.txt
43
+ {sources: `${srcPaths.assets}/**/*.*`, target: tgtPaths.assets, opts: {levelRemoval: 4}},
44
+ // Module assets:
45
+ // src/main/webapp/modules/mod-weather/assets/weather/sample.json -> tgt/static/assets/_sn_/modules/mod-weather/assets/weather/sample.json
46
+ {sources: `${srcPaths.modules}/**/assets/**/*.*`, target: tgtPaths.moduleAssets, opts: {levelRemoval: 4}},
47
+ // Markdown file assets
48
+ // src/main/webapp/md/google-pixel-9/assets/cover.webp -> public/posts/google-pixel-9/assets/cover.webp
49
+ {sources: `${srcPaths.markdown}/**/assets/**/*.*`, target: tgtPaths.markdown, opts: {levelRemoval: 4}}
36
50
  ].concat(Config.getCopyPairs(conf.copyPairs, conf.sourceRoot, tgtPaths.assets))),
37
51
  markdown: () => markdown(
38
52
  srcPaths.markdown,
@@ -40,12 +54,22 @@ const tasks = {
40
54
  conf.njkGlobals,
41
55
  tgtPaths.markdown
42
56
  ),
57
+ markdown2: () => markdown2(
58
+ srcPaths.markdown,
59
+ conf.njkGlobals,
60
+ tgtPaths.markdown
61
+ ),
43
62
  prototype: () => prototype(
44
63
  srcPaths.prototype,
45
64
  [srcPaths.modules],
46
65
  conf.njkGlobals,
47
66
  tgtPaths.prototype
48
67
  ),
68
+ prototype2: () => prototype2(
69
+ srcPaths.prototype,
70
+ conf.njkGlobals,
71
+ tgtPaths.prototype
72
+ ),
49
73
  scripts: () => scripts(Config.getScriptEntries(conf.moduleEntries, conf.mainEntryFile, srcPaths), tgtPaths.assets),
50
74
  styles: () => styles([
51
75
  `${srcPaths.css}/brands/*.css`,
@@ -57,7 +81,7 @@ const tasks = {
57
81
 
58
82
  const paraDev = () => {
59
83
  return Promise.all([
60
- tasks.markdown().then(tasks.prototype),
84
+ useNjk ? tasks.markdown().then(tasks.prototype) : tasks.markdown2().then(tasks.prototype2),
61
85
  tasks.styles(),
62
86
  tasks.scripts()
63
87
  ]);
@@ -65,7 +89,7 @@ const paraDev = () => {
65
89
 
66
90
  const paraProd = () => {
67
91
  return Promise.all([
68
- tasks.markdown(),
92
+ useNjk ? tasks.markdown() : tasks.markdown2(),
69
93
  tasks.styles(),
70
94
  tasks.scripts()
71
95
  ]);
@@ -83,7 +107,9 @@ const taskMap = {
83
107
  'clean': tasks.clean,
84
108
  'copy': tasks.copy,
85
109
  'markdown': tasks.markdown,
110
+ 'markdown2': tasks.markdown2,
86
111
  'prototype': tasks.prototype,
112
+ 'prototype2': tasks.prototype2,
87
113
  'scripts': tasks.scripts,
88
114
  'setenvdev': setEnvDev,
89
115
  'setenvprod': setEnvProd,
@@ -94,10 +120,11 @@ const taskMap = {
94
120
 
95
121
  const task = taskMap[taskName];
96
122
 
97
- console.log('+++ SN Build +++');
123
+ consoleLogColored('+++ SN Build +++', ['bold', 'blue']);
98
124
  console.time(taskName);
99
125
  console.log(`Task "${taskName}" started...`);
100
126
  task().then(() => {
127
+ console.log('Task ended.');
101
128
  taskEnded(taskName);
102
129
  }).catch(err => {
103
130
  console.error(err);
@@ -1,14 +1,19 @@
1
- import {deleteAsync} from 'del';
1
+ import {rm} from 'node:fs/promises';
2
+ import {consoleLogColored} from '../utils.mjs';
2
3
 
3
4
  /**
4
5
  * Clean the target directory
5
6
  *
7
+ * @example
8
+ * await clean('target');
9
+ *
6
10
  * @param {(string|string[])} targetPath
7
- * @returns {Promise<string[]>}
11
+ * @returns {Promise<Awaited<void>[]>}
8
12
  */
9
13
  const clean = targetPath => {
10
- console.log('=> clean');
11
- return deleteAsync(targetPath);
14
+ consoleLogColored('=> clean');
15
+ let pa = (Array.isArray(targetPath)) ? targetPath : [targetPath];
16
+ return Promise.all(pa.map(path => rm(path, {force: true, recursive: true})));
12
17
  };
13
18
 
14
19
  export {clean};
@@ -1,15 +1,64 @@
1
- import cpy from 'cpy';
1
+ import {cp} from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import {glob2Array, consoleLogColored, isDebugMode} from '../utils.mjs';
2
4
 
3
5
  /**
4
6
  * Copy (different) assets
5
7
  *
6
8
  * @param {STPair[]} sourceTargetPairs
7
- * @return {Promise<Awaited<unknown>[]>}
9
+ * @return {Promise<Awaited<Awaited<void>[]>[]>}
8
10
  */
9
11
  const copy = sourceTargetPairs => {
10
- console.log('=> copy');
11
- return Promise.all(sourceTargetPairs.map(pair => cpy(pair.sources, pair.target, pair.opts)));
12
+ consoleLogColored('=> copy');
13
+ const debug = isDebugMode();
14
+ return Promise.all(sourceTargetPairs.map(pair => globCopy(pair.sources, pair.target, pair.opts, debug)));
12
15
  };
13
16
 
14
- export {copy};
17
+ /**
18
+ * Copy files specified as glob pattern(s)
19
+ *
20
+ * @param {string|string[]} globPatterns
21
+ * @param {string} targetRoot
22
+ * @param {CopyTaskOption} opts
23
+ * @param {boolean} verbose
24
+ * @returns {Promise<Awaited<void>[]>}
25
+ */
26
+ const globCopy = async (globPatterns, targetRoot, opts, verbose = false) => {
27
+ /** @type string[] */
28
+ const sources = await glob2Array(globPatterns);
29
+
30
+ let targetPath = '';
31
+ return Promise.all(sources.map(async src => {
32
+ if (opts.flat) {
33
+ targetPath = path.join(targetRoot, path.basename(src));
34
+ } else {
35
+ targetPath = path.join(targetRoot, genTargetPath(src, opts.levelRemoval));
36
+ }
37
+ if (verbose) {
38
+ consoleLogColored(`copying ${src} -> ${targetPath}`, 'dim');
39
+ }
40
+ return cp(src, targetPath, {recursive: true});
41
+ }));
42
+ };
43
+
44
+ /**
45
+ * Generate the target path (destination) of the file to be copied
46
+ *
47
+ * @example
48
+ * genTargetPath('src/foo/bar/a.txt', 2)
49
+ * // returns 'bar/a.txt', 2 levels of path (src/foo) are removed
50
+ *
51
+ * @param {string} sourcePath
52
+ * @param {number=} levelRemoval How many levels of path to be removed
53
+ * @returns {string}
54
+ */
55
+ const genTargetPath = (sourcePath, levelRemoval = 0) => {
56
+ const pathParts = sourcePath.split(path.sep);
57
+ const pathPartsCount = pathParts.length - 1;
58
+ const removal = levelRemoval ? Math.min(levelRemoval, pathPartsCount) : pathPartsCount;
59
+ const newPathParts = pathParts.slice(removal);
60
+ return newPathParts.join(path.sep);
61
+ };
62
+
63
+ export {copy, genTargetPath};
15
64
  export default copy;
@@ -1,12 +1,11 @@
1
- import {globby} from 'globby';
2
1
  import {readFile} from 'node:fs/promises';
3
2
  import {marked} from 'marked';
4
3
  import {markedHighlight} from 'marked-highlight';
5
4
  import {markedXhtml} from 'marked-xhtml';
6
5
  import hljs from 'highlight.js';
7
6
  import njk from 'nunjucks';
8
-
9
- import {createAndWriteToFile, getTargetPathString} from '../utils.mjs';
7
+ import {renderPageToString} from '@changke/jstmpl';
8
+ import {createAndWriteToFile, getTargetPathString, glob2Array, consoleLogColored, isDebugMode} from '../utils.mjs';
10
9
 
11
10
  marked.use({
12
11
  headerIds: false,
@@ -39,6 +38,8 @@ const getPageTitle = content => {
39
38
  return t;
40
39
  };
41
40
 
41
+ const mdArticleTemplateFile = 'md.tmpl.mjs'; // TODO: configurable?
42
+
42
43
  /**
43
44
  * Generate docs using markdown and Nunjucks
44
45
  *
@@ -49,8 +50,8 @@ const getPageTitle = content => {
49
50
  * @return {Promise<string[]>}
50
51
  */
51
52
  const markdown = (mdSourcePathRoot, njkPaths, njkGlobals, mdTargetPath) => {
52
- console.log('=> markdown');
53
- return globby(`${mdSourcePathRoot}/**/*.md`).then(docs => {
53
+ consoleLogColored('=> markdown (njk)');
54
+ return glob2Array(`${mdSourcePathRoot}/**/*.md`).then(docs => {
54
55
  const njkEnv = new Environment(new FileSystemLoader(njkPaths, {}));
55
56
  for (const [k, v] of Object.entries(njkGlobals)) {
56
57
  njkEnv.addGlobal(k, v);
@@ -85,5 +86,42 @@ const markdown = (mdSourcePathRoot, njkPaths, njkGlobals, mdTargetPath) => {
85
86
  });
86
87
  };
87
88
 
88
- export {markdown};
89
+ const markdown2 = (mdSourcePathRoot, data, mdTargetPath) => {
90
+ const debug = isDebugMode();
91
+ consoleLogColored('=> markdown2 (jstmpl)');
92
+ return glob2Array(`${mdSourcePathRoot}/**/*.md`).then(docs => {
93
+ return Promise.all(docs.map(async doc => {
94
+ const mdContent = await readFile(doc, {encoding: 'utf8'});
95
+ const mdHtml = marked.parse(mdContent);
96
+ const pageTitle = getPageTitle(mdContent);
97
+ const res = await renderPageToString(`${mdSourcePathRoot}/${mdArticleTemplateFile}`, {
98
+ ...data,
99
+ title: pageTitle,
100
+ content: mdHtml
101
+ });
102
+ const target = getTargetPathString(
103
+ doc,
104
+ mdSourcePathRoot,
105
+ mdTargetPath,
106
+ 'md',
107
+ 'html'
108
+ );
109
+ if (debug) {
110
+ consoleLogColored(`md: ${doc} -> ${target}`, 'dim');
111
+ }
112
+ await createAndWriteToFile(target, res);
113
+ // create a content-only file for RSS generating
114
+ const feedTarget = getTargetPathString(
115
+ doc,
116
+ mdSourcePathRoot,
117
+ mdTargetPath,
118
+ 'md',
119
+ 'txt'
120
+ );
121
+ await createAndWriteToFile(feedTarget, mdHtml);
122
+ }));
123
+ });
124
+ };
125
+
126
+ export {markdown, markdown2};
89
127
  export default markdown;
@@ -1,8 +1,7 @@
1
1
  import njk from 'nunjucks';
2
- import {globby} from 'globby';
3
2
  import {readFile} from 'node:fs/promises';
4
-
5
- import {getTargetPathString, createAndWriteToFile} from '../utils.mjs';
3
+ import {renderPageToString} from '@changke/jstmpl';
4
+ import {getTargetPathString, createAndWriteToFile, glob2Array, consoleLogColored} from '../utils.mjs';
6
5
 
7
6
  const {Environment, FileSystemLoader} = njk;
8
7
 
@@ -16,8 +15,8 @@ const {Environment, FileSystemLoader} = njk;
16
15
  * @return {Promise<string[]>}
17
16
  */
18
17
  const prototype = (prototypeSourcePathRoot, njkPaths, njkGlobals, prototypeTargetPath) => {
19
- console.log('=> prototype');
20
- return globby(`${prototypeSourcePathRoot}/pages/**/*.njk`).then(pages => {
18
+ consoleLogColored('=> prototype (njk)');
19
+ return glob2Array(`${prototypeSourcePathRoot}/pages/**/*.njk`).then(pages => {
21
20
  const njkEnv = new Environment(new FileSystemLoader([prototypeSourcePathRoot].concat(njkPaths), {}));
22
21
  for (const [k, v] of Object.entries(njkGlobals)) {
23
22
  njkEnv.addGlobal(k, v);
@@ -37,5 +36,30 @@ const prototype = (prototypeSourcePathRoot, njkPaths, njkGlobals, prototypeTarge
37
36
  });
38
37
  };
39
38
 
40
- export {prototype};
39
+ /**
40
+ * Generate static pages with JSTmpl
41
+ * @param {string} sourceRoot - Glob pattern for source files e.g. 'src/pages/*.mjs'
42
+ * @param {Object.<string, string>} data
43
+ * @param {string} targetPath
44
+ * @returns {Promise<void>}
45
+ */
46
+ const prototype2 = (sourceRoot, data, targetPath) => {
47
+ consoleLogColored('=> prototype (jstmpl)');
48
+ // src/main/webapp/prototype/pages/index.mjs -> ${targetPath.prototype}/index.html
49
+ return glob2Array(`${sourceRoot}/pages/**/*.mjs`).then(pages => {
50
+ return Promise.all(pages.map(async page => {
51
+ const res = await renderPageToString(page, data);
52
+ const targetFile = getTargetPathString(
53
+ page,
54
+ `${sourceRoot}/pages`,
55
+ targetPath,
56
+ 'mjs',
57
+ page.endsWith('rss/index.mjs') ? 'xml' : 'html'
58
+ );
59
+ await createAndWriteToFile(targetFile, res);
60
+ }));
61
+ });
62
+ };
63
+
64
+ export {prototype, prototype2};
41
65
  export default prototype;
@@ -1,6 +1,6 @@
1
1
  import {build} from 'esbuild';
2
-
3
2
  import isEnvProd from '../is-prod.mjs';
3
+ import {consoleLogColored} from '../utils.mjs';
4
4
 
5
5
  /**
6
6
  * Transpile / bundle JS files using esbuild
@@ -10,12 +10,12 @@ import isEnvProd from '../is-prod.mjs';
10
10
  * @return {Promise}
11
11
  */
12
12
  const esm = (entries, targetPath) => {
13
- console.log('=> scripts');
13
+ consoleLogColored('=> scripts');
14
14
  return build({
15
15
  entryPoints: entries,
16
16
  bundle: true,
17
17
  format: 'esm',
18
- target: 'es2023',
18
+ target: 'es2024',
19
19
  splitting: true,
20
20
  outdir: targetPath,
21
21
  minify: isEnvProd(), // only minify in prod build
@@ -1,6 +1,5 @@
1
1
  import {build} from 'esbuild';
2
- import {globby} from 'globby';
3
-
2
+ import {glob2Array, consoleLogColored} from '../utils.mjs';
4
3
  import isEnvProd from '../is-prod.mjs';
5
4
 
6
5
  /**
@@ -12,12 +11,12 @@ import isEnvProd from '../is-prod.mjs';
12
11
  * @return {Promise}
13
12
  */
14
13
  const styles = (sources, targetPath, external = []) => {
15
- console.log('=> styles');
16
- return globby(sources).then(entries => {
14
+ consoleLogColored('=> styles');
15
+ return glob2Array(sources).then(entries => {
17
16
  return build({
18
17
  entryPoints: entries,
19
18
  bundle: true,
20
- target: 'es2021',
19
+ target: 'es2024',
21
20
  outdir: targetPath,
22
21
  sourcemap: !isEnvProd(),
23
22
  minify: isEnvProd(),
package/lib/typedefs.mjs CHANGED
@@ -14,13 +14,21 @@
14
14
  * @property {string=} markdown Path for markdown files
15
15
  */
16
16
 
17
+ /**
18
+ * Options for "copy" task
19
+ *
20
+ * @typedef {Object} CopyTaskOption
21
+ * @property {number=} levelRemoval
22
+ * @property {boolean=} flat
23
+ */
24
+
17
25
  /**
18
26
  * Source/Target pairs for "copy" task
19
27
  *
20
28
  * @typedef {Object} STPair
21
29
  * @property {(string|string[])} sources
22
30
  * @property {string} target
23
- * @property {Object=} opts
31
+ * @property {CopyTaskOption=} opts
24
32
  */
25
33
 
26
34
  /**
package/lib/utils.mjs CHANGED
@@ -1,5 +1,7 @@
1
- import {access, mkdir, writeFile} from 'node:fs/promises';
2
- import * as path from 'node:path';
1
+ import {access, mkdir, writeFile, glob, rm, stat} from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import {styleText} from 'node:util';
4
+ import {env} from 'node:process';
3
5
 
4
6
  const getTargetPathString = (sourcePath, sourceRoot, targetRoot, srcExt, tgtExt) => {
5
7
  const baseName = path.basename(sourcePath, `.${srcExt}`);
@@ -17,7 +19,98 @@ const createAndWriteToFile = async (filePath, fileContent) => {
17
19
  await writeFile(filePath, fileContent, {flag: 'w+'});
18
20
  };
19
21
 
22
+ /**
23
+ * Extracts negative patterns into another array to feed Node's glob function
24
+ * @param {(string|string[])} globPatterns
25
+ * @returns {Object.<string, string[]>}
26
+ */
27
+ const processGlobPatterns = globPatterns => {
28
+ // extract negative patterns
29
+ let patterns = globPatterns;
30
+ if (!Array.isArray(globPatterns)) {
31
+ patterns = [globPatterns];
32
+ }
33
+ /** @type string[] */
34
+ const negativePatterns = [];
35
+ /** @type string[] */
36
+ const normalPatterns = patterns.filter(p => {
37
+ if (p.startsWith('!')) {
38
+ negativePatterns.push(p.substring(1));
39
+ return false;
40
+ } else {
41
+ return true;
42
+ }
43
+ });
44
+ return {normalPatterns, negativePatterns};
45
+ };
46
+
47
+ /**
48
+ * Convert `glob()` result to an array
49
+ * @param {(string|string[])} globPatterns
50
+ * @param {boolean} fileOnly
51
+ * @returns {Promise<string[]>}
52
+ */
53
+ const glob2Array = async (globPatterns, fileOnly = false) => {
54
+ const p = processGlobPatterns(globPatterns);
55
+ const m = glob(p.normalPatterns, {exclude: p.negativePatterns});
56
+ if (fileOnly) {
57
+ const files = [];
58
+ return Array.fromAsync(m).then(async entries => {
59
+ for (const entry of entries) {
60
+ const st = await stat(entry);
61
+ if (st.isFile()) {
62
+ files.push(entry);
63
+ }
64
+ }
65
+ return files;
66
+ });
67
+ } else {
68
+ return Array.fromAsync(m);
69
+ }
70
+ };
71
+
72
+ const createDirectory = async (dir, log = false) => {
73
+ try {
74
+ const dirUrl = new URL(dir, import.meta.url);
75
+ const createdDir = await mkdir(dirUrl, {recursive: true});
76
+ if (log) {
77
+ console.log(`Directory created: ${createdDir}`);
78
+ }
79
+ return createdDir;
80
+ } catch (err) {
81
+ console.error(err.message);
82
+ }
83
+ };
84
+
85
+ const removeDirectory = async (dir, log = false) => {
86
+ try {
87
+ await rm(dir, {recursive: true, force: true});
88
+ if (log) {
89
+ console.log(`Directory removed: ${dir}`);
90
+ }
91
+ } catch (err) {
92
+ console.error(err.message);
93
+ }
94
+ };
95
+
96
+ /**
97
+ * Print colored console messages
98
+ * @param {string} msg
99
+ * @param {(string|string[])} color
100
+ */
101
+ const consoleLogColored = (msg, color = 'cyan') => {
102
+ console.log(styleText(color, msg));
103
+ };
104
+
105
+ const isDebugMode = () => (env.SN_BUILD_MODE === 'debug');
106
+
20
107
  export {
21
108
  getTargetPathString,
22
- createAndWriteToFile
109
+ createAndWriteToFile,
110
+ processGlobPatterns,
111
+ glob2Array,
112
+ createDirectory,
113
+ removeDirectory,
114
+ consoleLogColored,
115
+ isDebugMode
23
116
  };
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@changke/staticnext-build",
3
- "version": "0.13.0",
3
+ "version": "0.26.1",
4
4
  "description": "Build scripts extracted from StaticNext seed project",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "lint": "eslint . lib test",
8
- "test": "mocha",
8
+ "test": "node --test",
9
9
  "prepublishOnly": "npm run lint && npm run test"
10
10
  },
11
11
  "engines": {
12
- "node": ">=20"
12
+ "node": ">=22.14.0"
13
13
  },
14
14
  "bin": {
15
15
  "sn-build": "build.mjs"
@@ -19,21 +19,18 @@
19
19
  "license": "ISC",
20
20
  "type": "module",
21
21
  "devDependencies": {
22
- "@eslint/js": "^9.36.0",
23
- "@stylistic/eslint-plugin": "^5.4.0",
24
- "eslint": "^9.36.0",
25
- "globals": "^16.4.0",
26
- "mocha": "^11.7.2"
22
+ "@eslint/js": "^9.39.2",
23
+ "@stylistic/eslint-plugin": "^5.6.1",
24
+ "eslint": "^9.39.2",
25
+ "globals": "^16.5.0"
27
26
  },
28
27
  "dependencies": {
29
- "cpy": "^12.0.1",
30
- "del": "^8.0.1",
31
- "esbuild": "^0.25.10",
32
- "globby": "^14.1.0",
28
+ "@changke/jstmpl": "^0.0.1",
29
+ "esbuild": "^0.27.2",
33
30
  "highlight.js": "^11.11.1",
34
- "marked": "^16.3.0",
35
- "marked-highlight": "^2.2.2",
36
- "marked-xhtml": "^1.0.13",
31
+ "marked": "^17.0.1",
32
+ "marked-highlight": "^2.2.3",
33
+ "marked-xhtml": "^1.0.14",
37
34
  "nunjucks": "^3.2.4"
38
35
  }
39
36
  }
package/eslint.config.mjs DELETED
@@ -1,30 +0,0 @@
1
- import globals from 'globals';
2
- import js from '@eslint/js';
3
- import stylistic from '@stylistic/eslint-plugin';
4
-
5
- export default [
6
- js.configs.recommended,
7
- stylistic.configs.customize({
8
- blockSpacing: false,
9
- braceStyle: '1tbs',
10
- semi: true
11
- }),
12
- {
13
- files: ['**/*.mjs'],
14
- languageOptions: {
15
- globals: {
16
- ...globals.node,
17
- ...globals.mocha
18
- }
19
- },
20
- rules: {
21
- '@stylistic/arrow-parens': ['error', 'as-needed', {requireForBlockBody: false}],
22
- '@stylistic/comma-dangle': ['error', 'never'],
23
- '@stylistic/object-curly-spacing': ['error', 'never'],
24
- '@stylistic/quotes': ['warn', 'single'],
25
- '@stylistic/quote-props': 0,
26
- '@stylistic/semi': ['error', 'always'],
27
- '@stylistic/space-before-function-paren': ['error', {anonymous: 'ignore', asyncArrow: 'always', named: 'never'}]
28
- }
29
- }
30
- ];