@changke/staticnext-build 0.1.0 → 0.2.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.2.1
8
+ 2023-06-25
9
+ ### Changed
10
+ - Updated `esbuild` to v0.18.9
11
+
12
+ ### 0.2.0
13
+ 2023-06-24
14
+ ### Changed
15
+ - Better merging object supports nested object values
16
+ ### Added
17
+ - Highlighting of code blocks in .md files
18
+ - Quick support for generating XML file for RSS-URL
19
+
7
20
  ## 0.1.0
8
21
  2023-06-23
9
22
  ### Added
package/build.mjs CHANGED
@@ -22,33 +22,36 @@ const taskEnded = taskName => {
22
22
  console.timeEnd(taskName);
23
23
  };
24
24
 
25
+ const srcPaths = conf.getSourcePaths(conf.sourcePath, conf.sourceRoot);
26
+ const tgtPaths = conf.getTargetPaths(conf.targetPath, conf.targetRoot, conf.targetAssetsRoot);
27
+
25
28
  // Set parameters of each task
26
29
  const tasks = {
27
30
  clean: () => clean([`${conf.targetRoot}/*`]),
28
31
  copy: () => copy([
29
32
  {sources: [`${conf.sourceRoot}/*`, `!${conf.sourceRoot}/*.d.ts`], target: conf.targetRoot},
30
- {sources: `${conf.sourcePath.assets}/**/*`, target: conf.targetPath.assets},
31
- {sources: `${conf.sourcePath.modules}/**/assets/**/*`, target: conf.targetPath.moduleAssets}
33
+ {sources: `${srcPaths.assets}/**/*`, target: tgtPaths.assets},
34
+ {sources: `${srcPaths.modules}/**/assets/**/*`, target: tgtPaths.moduleAssets}
32
35
  ]),
33
36
  markdown: () => markdown(
34
- conf.sourcePath.markdown,
35
- [conf.sourcePath.prototype, conf.sourcePath.modules],
37
+ srcPaths.markdown,
38
+ [srcPaths.prototype, srcPaths.modules],
36
39
  conf.njkGlobals,
37
- conf.targetPath.markdown
40
+ tgtPaths.markdown
38
41
  ),
39
42
  prototype: () => prototype(
40
- conf.sourcePath.prototype,
41
- [conf.sourcePath.modules],
43
+ srcPaths.prototype,
44
+ [srcPaths.modules],
42
45
  conf.njkGlobals,
43
- conf.targetPath.prototype
46
+ tgtPaths.prototype
44
47
  ),
45
- scripts: () => scripts(conf.scriptEntries(conf.moduleEntries), conf.targetPath.assets),
48
+ scripts: () => scripts(conf.getScriptEntries(conf.moduleEntries, conf.mainEntryFile, srcPaths), tgtPaths.assets),
46
49
  styles: () => styles([
47
- `${conf.sourcePath.css}/brands/*.css`,
48
- `${conf.sourcePath.css}/index.css`,
49
- `${conf.sourcePath.modules}/**/*.css`,
50
- `!${conf.sourcePath.modules}/**/_*.css`
51
- ], conf.targetPath.assets)
50
+ `${srcPaths.css}/brands/*.css`,
51
+ `${srcPaths.css}/index.css`,
52
+ `${srcPaths.modules}/**/*.css`,
53
+ `!${srcPaths.modules}/**/_*.css`
54
+ ], tgtPaths.assets)
52
55
  };
53
56
 
54
57
  const paraDev = () => {
package/lib/config.mjs CHANGED
@@ -4,6 +4,7 @@ import vars from './vars.mjs';
4
4
 
5
5
  class Config {
6
6
  customConfigFile = '/sn-config.mjs';
7
+ objsToMerge = ['sourcePath', 'targetPath', 'njkGlobals'];
7
8
 
8
9
  async loadConfig(configFile) {
9
10
  const defaultConf = vars;
@@ -12,12 +13,27 @@ class Config {
12
13
  const cf = configFile || `${cwd()}${this.customConfigFile}`;
13
14
  const mod = await import(cf);
14
15
  const customConf = mod.default;
15
- return Object.assign({}, defaultConf, customConf);
16
+ return this.deepMergeConfObj(defaultConf, customConf);
16
17
  } catch (e) {
17
18
  // file not exist
19
+ console.error('Error loading file: ', e);
18
20
  return defaultConf;
19
21
  }
20
22
  }
23
+
24
+ // keep nested obj values while merging
25
+ // e.g. {foo:{a:1,b:2}} merged with {foo:{b:3,c:4}} will be {foo:{a:1,b:3,c:4}}
26
+ deepMergeConfObj(defaultConf, customConf) {
27
+ const conf = Object.assign({}, defaultConf);
28
+ for (const [k, v] of Object.entries(customConf)) {
29
+ if (this.objsToMerge.includes(k)) {
30
+ conf[k] = Object.assign(conf[k], v);
31
+ } else {
32
+ conf[k] = v;
33
+ }
34
+ }
35
+ return conf;
36
+ }
21
37
  }
22
38
 
23
39
  const config = new Config();
@@ -1,7 +1,9 @@
1
1
  import {globby} from 'globby';
2
2
  import {readFile} from 'node:fs/promises';
3
3
  import {marked} from 'marked';
4
+ import {markedHighlight} from 'marked-highlight';
4
5
  import {markedXhtml} from 'marked-xhtml';
6
+ import hljs from 'highlight.js';
5
7
  import njk from 'nunjucks';
6
8
 
7
9
  import {createAndWriteToFile, getTargetPathString} from '../utils.mjs';
@@ -9,7 +11,15 @@ import {createAndWriteToFile, getTargetPathString} from '../utils.mjs';
9
11
  marked.use({
10
12
  headerIds: false,
11
13
  mangle: false
12
- }, markedXhtml());
14
+ },
15
+ markedXhtml(),
16
+ markedHighlight({
17
+ langPrefix: 'hljs language-',
18
+ highlight: (code, lang) => {
19
+ const language = hljs.getLanguage(lang) ? lang : 'plaintext';
20
+ return hljs.highlight(code, {language}).value;
21
+ }
22
+ }));
13
23
 
14
24
  const {Environment, FileSystemLoader} = njk;
15
25
 
@@ -30,7 +30,7 @@ const prototype = (prototypeSourcePathRoot, njkPaths, njkGlobals, prototypeTarge
30
30
  `${prototypeSourcePathRoot}/pages`,
31
31
  prototypeTargetPath,
32
32
  'njk',
33
- 'html'
33
+ page.endsWith('rss/index.njk') ? 'xml' : 'html' // special case for RSS
34
34
  );
35
35
  await createAndWriteToFile(targetFile, res);
36
36
  });
package/lib/vars.mjs CHANGED
@@ -1,4 +1,8 @@
1
1
  /**
2
+ * Path(suffixes) for various source/target files
3
+ * E.g. CSS source files are located in `${basePath}/css`
4
+ * Built JS in `${targetAssetsBase}/js`
5
+ *
2
6
  * @typedef {Object} PathPart
3
7
  * @property {string} assets Path for general static assets
4
8
  * @property {string=} css Path for CSS files
@@ -11,22 +15,39 @@
11
15
  */
12
16
 
13
17
  /**
18
+ * Helper to create an array with input source TS files for esbuild
19
+ *
14
20
  * @typedef {Function} ScriptEntryFunc
15
- * @param {string[]} modEntries
16
- * @param {string=} mainEntry
21
+ * @param {string[]} modEntries Array of module entry TS files
22
+ * @param {string=} mainEntry Main entry TS file, default `main.ts`
23
+ * @param {PathPart} srcPaths
17
24
  * @return {string[]}
18
25
  */
19
26
 
27
+ /**
28
+ * Helper to append base path to source/target path-suffixes
29
+ *
30
+ * @typedef {Function} GetPathFunc
31
+ *
32
+ * @param {PathPart} paths Path suffixes of various types e.g. `/css`, `/js`, `/md` (do with slash)
33
+ * @param {string} root Root path of source/target
34
+ * @param {string=} assetsRoot Only for target: assets root path e.g. `${targetRoot}/assets/_sn_`
35
+ * @return {PathPart}
36
+ */
37
+
20
38
  /**
21
39
  * @typedef {Object} SNConfig
22
40
  * @property {string} sourceRoot Root dir of source
23
41
  * @property {string} targetRoot Root dir for output (target)
24
42
  * @property {PathPart} sourcePath Paths of different types of source files
43
+ * @property {GetPathFunc} getSourcePaths
44
+ * @property {string} targetAssetsRoot
25
45
  * @property {PathPart} targetPath Paths for different output files
46
+ * @property {GetPathFunc} getTargetPaths
26
47
  * @property {string[]} tenants Theme-names
27
48
  * @property {string[]} moduleEntries List of input files of modules e.g. 'mod-foo/foo.ts'
28
49
  * @property {string} mainEntryFile The entry point of all JS e.g. main.ts
29
- * @property {ScriptEntryFunc} scriptEntries Inputs of source files for esbuild
50
+ * @property {ScriptEntryFunc} getScriptEntries Inputs of source files for esbuild
30
51
  * @property {string} assetsUrlPath Path of assets used in URL for resource loading etc.
31
52
  * @property {boolean} markdownEnabled Enable markdown feature or not
32
53
  * @property {Record<string, string>} njkGlobals Global variables assigned to Nunjucks compiler
@@ -40,38 +61,69 @@ const targetRoot = './tgt/static';
40
61
 
41
62
  /** @type {PathPart} */
42
63
  const sourcePath = {
43
- assets: `${sourceRoot}/assets`,
44
- css: `${sourceRoot}/css`,
45
- js: `${sourceRoot}/js`,
46
- modules: `${sourceRoot}/modules`,
47
- prototype: `${sourceRoot}/prototype`,
48
- test: `${sourceRoot}/test`,
49
- markdown: `${sourceRoot}/md`
64
+ assets: '/assets',
65
+ css: '/css',
66
+ js: '/js',
67
+ modules: '/modules',
68
+ prototype: '/prototype',
69
+ test: '/test',
70
+ markdown: '/md'
71
+ };
72
+
73
+ /**
74
+ * Extend source paths
75
+ *
76
+ * @type {GetPathFunc}
77
+ */
78
+ const getSourcePaths = (srcParts, srcRoot) => {
79
+ const sp = Object.assign({}, srcParts);
80
+ for (const [k, v] of Object.entries(sp)) {
81
+ sp[k] = `${srcRoot}${v}`; // extend path
82
+ }
83
+ return sp;
50
84
  };
51
85
 
52
- const targetAssetsRoot = `${targetRoot}/assets/_sn_`;
86
+ const targetAssetsRoot = '/assets/_sn_';
87
+
53
88
  const targetPath = {
54
- assets: targetAssetsRoot,
55
- css: `${targetAssetsRoot}/css`,
56
- js: `${targetAssetsRoot}/js`,
57
- moduleAssets: `${targetAssetsRoot}/modules`,
58
- prototype: `${targetRoot}/prototype`,
59
- markdown: `${targetRoot}/docs`
89
+ assets: '',
90
+ css: '/css',
91
+ js: '/js',
92
+ moduleAssets: '/modules',
93
+ prototype: '/prototype',
94
+ markdown: '/docs'
95
+ };
96
+
97
+ /**
98
+ * Target paths
99
+ *
100
+ * @type {GetPathFunc}
101
+ */
102
+ const getTargetPaths = (tgtPaths, tgtRoot = targetRoot, tgtAssetsRoot = targetAssetsRoot) => {
103
+ return {
104
+ assets: `${tgtRoot}${tgtAssetsRoot}`,
105
+ css: `${tgtRoot}${tgtAssetsRoot}${tgtPaths.css}`,
106
+ js: `${tgtRoot}${tgtAssetsRoot}${tgtPaths.js}`,
107
+ moduleAssets: `${tgtRoot}${tgtAssetsRoot}${tgtPaths.moduleAssets}`,
108
+ prototype: `${tgtRoot}${tgtPaths.prototype}`,
109
+ markdown: `${tgtRoot}${tgtPaths.markdown}`
110
+ };
60
111
  };
61
112
 
62
113
  // "themes", not in use, replaced with brands directory
63
114
  const tenants = ['one', 'two', 'three'];
64
115
 
65
- const mainEntryFile = `${sourcePath.js}/main.ts`;
116
+ const mainEntryFile = 'main.ts';
66
117
 
67
118
  // also add the main entry file
68
119
  /** @type {ScriptEntryFunc} */
69
- const scriptEntries = (modEntries, mainEntry = mainEntryFile) => {
120
+ const getScriptEntries = (modEntries, mainEntry = mainEntryFile, srcPaths) => {
121
+ const mainEntryPath = `${srcPaths.js}/${mainEntry}`;
70
122
  // For code splitting, as input config for esbuild
71
123
  const moduleEntryFiles = modEntries.map(f => {
72
- return `${sourcePath.modules}/${f}`;
124
+ return `${srcPaths.modules}/${f}`;
73
125
  });
74
- return [mainEntry].concat(moduleEntryFiles);
126
+ return [mainEntryPath].concat(moduleEntryFiles);
75
127
  };
76
128
 
77
129
  // To get relative path of assets
@@ -90,11 +142,14 @@ const config = {
90
142
  sourceRoot,
91
143
  targetRoot,
92
144
  sourcePath,
145
+ getSourcePaths,
146
+ targetAssetsRoot,
93
147
  targetPath,
148
+ getTargetPaths,
94
149
  tenants,
95
150
  moduleEntries,
96
151
  mainEntryFile,
97
- scriptEntries,
152
+ getScriptEntries,
98
153
  assetsUrlPath,
99
154
  markdownEnabled,
100
155
  njkGlobals
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@changke/staticnext-build",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Build scripts extracted from StaticNext seed project",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -25,9 +25,11 @@
25
25
  "dependencies": {
26
26
  "cpy": "^10.1.0",
27
27
  "del": "^7.0.0",
28
- "esbuild": "^0.18.6",
28
+ "esbuild": "^0.18.9",
29
29
  "globby": "^13.2.0",
30
+ "highlight.js": "^11.8.0",
30
31
  "marked": "^5.1.0",
32
+ "marked-highlight": "^2.0.1",
31
33
  "marked-xhtml": "^1.0.1",
32
34
  "nunjucks": "^3.2.4"
33
35
  }