mikel-press 0.20.0 → 0.20.2
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 +12 -4
- package/index.js +73 -38
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ Options:
|
|
|
121
121
|
- `options.extensions` (array): Defines the file extensions that should be processed. If not provided, it will use `config.extensions`.
|
|
122
122
|
- `options.basePath` (string): Specifies the base path for the output files.
|
|
123
123
|
|
|
124
|
-
### `press.
|
|
124
|
+
### `press.PartialsPlugin(options)`
|
|
125
125
|
|
|
126
126
|
An alias of `press.SourcePlugin` that will read all files in the `partials` folder and process them as a partials. The **mikel** tag `{{>file}}` can be used to include the partial in `partials/file.html`.
|
|
127
127
|
|
|
@@ -129,13 +129,21 @@ This plugin accepts the following options:
|
|
|
129
129
|
- `options.folder` (string): To change the directory to load the partials files. Default is `./partials`.
|
|
130
130
|
- `options.extensions` (array): Defines the file extensions that should be processed. If not provided, it will use `config.extensions`.
|
|
131
131
|
|
|
132
|
-
### `press.
|
|
132
|
+
### `press.DataPlugin(options)`
|
|
133
133
|
|
|
134
|
-
This plugin loads JSON files from the specified directory and makes them available in the site context.
|
|
134
|
+
This plugin loads JSON files from the specified directory and makes them available in the site context. This plugin accepts the following options:
|
|
135
135
|
|
|
136
|
-
Options:
|
|
137
136
|
- `options.folder` (string): Specifies a custom source directory for data files. If not provided, `./data` is used.
|
|
138
137
|
|
|
138
|
+
### `press.AssetsPlugin(options)`
|
|
139
|
+
|
|
140
|
+
This plugin loads additional files (aka assets) and includes them in the build folder. This plugin accepts the following options:
|
|
141
|
+
|
|
142
|
+
- `options.folder` (string): Specifies a custom source directory for assets files. If not provided, `./assets` is used.
|
|
143
|
+
- `options.extensions` (array): Defines the file extensions that should be processed. If not provided, it will use `"*"`.
|
|
144
|
+
- `options.exclude` (array): Defines the list of file names to exclude.
|
|
145
|
+
- `options.basePath` (string): Allows to specify a base path for the output files.
|
|
146
|
+
|
|
139
147
|
### `press.FrontmatterPlugin()`
|
|
140
148
|
|
|
141
149
|
This plugin processes and parses the frontmatter in each file. The parsed frontmatter content will be available in `page.attributes` field.
|
package/index.js
CHANGED
|
@@ -8,15 +8,16 @@ import mikel from "mikel";
|
|
|
8
8
|
// @param {String} config.destination - destination folder to save the files
|
|
9
9
|
// @param {Array} config.plugins - list of plugins to apply
|
|
10
10
|
const press = (config = {}) => {
|
|
11
|
-
const {source, destination, plugins, extensions, mikelOptions, ...otherConfig} = config;
|
|
11
|
+
const {source, destination, plugins, extensions, exclude, mikelOptions, ...otherConfig} = config;
|
|
12
12
|
const context = Object.freeze({
|
|
13
13
|
config: otherConfig,
|
|
14
14
|
source: path.resolve(source || "."),
|
|
15
15
|
destination: path.resolve(destination || "./www"),
|
|
16
16
|
extensions: extensions || [".html"],
|
|
17
|
+
exclude: exclude || ["node_modules", ".git", ".gitignore", ".github"],
|
|
17
18
|
template: mikel.create("{{>content}}", mikelOptions || {}),
|
|
18
19
|
plugins: [
|
|
19
|
-
SourcePlugin({folder: ".", label: press.LABEL_PAGE}),
|
|
20
|
+
press.SourcePlugin({folder: ".", label: press.LABEL_PAGE}),
|
|
20
21
|
...plugins,
|
|
21
22
|
],
|
|
22
23
|
nodes: [],
|
|
@@ -34,9 +35,13 @@ const press = (config = {}) => {
|
|
|
34
35
|
});
|
|
35
36
|
});
|
|
36
37
|
// 2. transform nodes
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
getPlugins("transform").forEach(plugin => {
|
|
39
|
+
// special hook to initialize the transform plugin
|
|
40
|
+
if (typeof plugin.beforeTransform === "function") {
|
|
41
|
+
plugin.beforeTransform(context);
|
|
42
|
+
}
|
|
43
|
+
// run the transform in all nodes
|
|
44
|
+
context.nodes.forEach((node, _, allNodes) => {
|
|
40
45
|
return plugin.transform(context, node, allNodes);
|
|
41
46
|
});
|
|
42
47
|
});
|
|
@@ -52,11 +57,15 @@ const press = (config = {}) => {
|
|
|
52
57
|
return plugin.beforeEmit(context);
|
|
53
58
|
});
|
|
54
59
|
// 5. emit each node
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
+
filteredNodes.forEach(node => {
|
|
61
|
+
// 1. if node has been processed (aka node.content is an string), write the file
|
|
62
|
+
if (typeof node.content === "string") {
|
|
63
|
+
press.utils.write(path.join(context.destination, node.path), node.content);
|
|
64
|
+
}
|
|
65
|
+
// 2. if node has not been processed, just copy the file
|
|
66
|
+
else if (fs.existsSync(node.source)) {
|
|
67
|
+
press.utils.copy(node.source, path.join(context.destination, node.path));
|
|
68
|
+
}
|
|
60
69
|
});
|
|
61
70
|
};
|
|
62
71
|
|
|
@@ -86,12 +95,12 @@ press.utils = {
|
|
|
86
95
|
fs.copyFileSync(source, target);
|
|
87
96
|
},
|
|
88
97
|
// @description get all files from the given folder and the given extensions
|
|
89
|
-
readdir: (folder, extensions = "*") => {
|
|
98
|
+
readdir: (folder, extensions = "*", exclude = []) => {
|
|
90
99
|
if (!fs.existsSync(folder) || !fs.statSync(folder).isDirectory()) {
|
|
91
100
|
return [];
|
|
92
101
|
}
|
|
93
102
|
return fs.readdirSync(folder, "utf8")
|
|
94
|
-
.filter(file => extensions === "*" || extensions.includes(path.extname(file)))
|
|
103
|
+
.filter(file => (extensions === "*" || extensions.includes(path.extname(file))) && !exclude.includes(file))
|
|
95
104
|
.filter(file => fs.statSync(path.join(folder, file)).isFile());
|
|
96
105
|
},
|
|
97
106
|
// @description frontmatter parser
|
|
@@ -117,27 +126,54 @@ press.LABEL_PARTIAL = "asset/partial";
|
|
|
117
126
|
|
|
118
127
|
// @description source plugin
|
|
119
128
|
press.SourcePlugin = (options = {}) => {
|
|
129
|
+
const shouldEmit = options?.shouldEmit ?? true;
|
|
130
|
+
const processedNodes = new Set();
|
|
120
131
|
return {
|
|
121
132
|
name: "SourcePlugin",
|
|
122
133
|
load: context => {
|
|
123
134
|
const folder = path.join(context.source, options?.folder || ".");
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
path
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
const extensions = options?.extensions || context.extensions;
|
|
136
|
+
const exclude = options?.exclude || context.exclude;
|
|
137
|
+
return press.utils.readdir(folder, extensions, exclude).map(file => {
|
|
138
|
+
processedNodes.add(path.join(folder, file)); // register this node
|
|
139
|
+
return {
|
|
140
|
+
source: path.join(folder, file),
|
|
141
|
+
label: options.label || press.LABEL_PAGE,
|
|
142
|
+
path: path.join(options?.basePath || ".", file),
|
|
143
|
+
url: path.normalize("/" + path.join(options?.basePath || ".", file)),
|
|
144
|
+
content: press.utils.read(path.join(folder, file)),
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
shouldEmit: (context, node) => {
|
|
149
|
+
return !processedNodes.has(node.source) || shouldEmit;
|
|
131
150
|
},
|
|
132
151
|
};
|
|
133
152
|
};
|
|
134
153
|
|
|
135
|
-
// @description
|
|
136
|
-
press.
|
|
137
|
-
return SourcePlugin({folder: "./data", extensions: [".json"], label: press.LABEL_DATA, ...options});
|
|
154
|
+
// @description data plugin
|
|
155
|
+
press.DataPlugin = (options = {}) => {
|
|
156
|
+
return press.SourcePlugin({folder: "./data", shouldEmit: false, extensions: [".json"], label: press.LABEL_DATA, ...options});
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// @description partials plugin
|
|
160
|
+
press.PartialsPlugin = (options = {}) => {
|
|
161
|
+
return press.SourcePlugin({folder: "./partials", shouldEmit: false, extensions: [".html"], label: press.LABEL_PARTIAL, ...options});
|
|
138
162
|
};
|
|
139
|
-
|
|
140
|
-
|
|
163
|
+
|
|
164
|
+
// @description assets plugin
|
|
165
|
+
press.AssetsPlugin = (options = {}) => {
|
|
166
|
+
return {
|
|
167
|
+
name: "AssetsPlugin",
|
|
168
|
+
load: context => {
|
|
169
|
+
const folder = path.join(context.source, options?.folder || "./assets");
|
|
170
|
+
return press.utils.readdir(folder, options?.extensions || "*", options?.exclude || context.exclude).map(file => ({
|
|
171
|
+
source: path.join(folder, file),
|
|
172
|
+
label: options.label || press.LABEL_ASSET,
|
|
173
|
+
path: path.join(options?.basePath || ".", file),
|
|
174
|
+
}));
|
|
175
|
+
},
|
|
176
|
+
};
|
|
141
177
|
};
|
|
142
178
|
|
|
143
179
|
// @description frontmatter plugin
|
|
@@ -147,7 +183,7 @@ press.FrontmatterPlugin = () => {
|
|
|
147
183
|
transform: (_, node) => {
|
|
148
184
|
if (typeof node.content === "string") {
|
|
149
185
|
const result = press.utils.frontmatter(node.content, JSON.parse);
|
|
150
|
-
node.content = result.
|
|
186
|
+
node.content = result.body || "";
|
|
151
187
|
node.attributes = result.attributes || {};
|
|
152
188
|
node.title = node.attributes?.title || node.path;
|
|
153
189
|
if (node.attributes.permalink) {
|
|
@@ -163,10 +199,7 @@ press.FrontmatterPlugin = () => {
|
|
|
163
199
|
press.ContentPagePlugin = (siteData = {}) => {
|
|
164
200
|
return {
|
|
165
201
|
name: "ContentPagePlugin",
|
|
166
|
-
|
|
167
|
-
return ![press.LABEL_ASSET, press.LABEL_DATA, press.LABEL_PARTIAL].includes(node.label);
|
|
168
|
-
},
|
|
169
|
-
beforeEmit: context => {
|
|
202
|
+
beforeTransform: context => {
|
|
170
203
|
const getNodes = label => context.nodes.filter(n => n.label === label);
|
|
171
204
|
// 1. prepare site data
|
|
172
205
|
Object.assign(siteData, context.config, {
|
|
@@ -180,19 +213,17 @@ press.ContentPagePlugin = (siteData = {}) => {
|
|
|
180
213
|
// 2. register partials into template
|
|
181
214
|
siteData.partials.forEach(partial => {
|
|
182
215
|
context.template.addPartial(path.basename(partial.path), {
|
|
183
|
-
body: partial.content,
|
|
216
|
+
body: partial.content || "",
|
|
184
217
|
attributes: partial.attributes || {},
|
|
185
218
|
});
|
|
186
219
|
});
|
|
187
220
|
},
|
|
188
|
-
|
|
221
|
+
transform: (context, node) => {
|
|
189
222
|
if (node.label === press.LABEL_PAGE && typeof node.content === "string") {
|
|
190
223
|
context.template.use(ctx => {
|
|
191
224
|
ctx.tokens = mikel.tokenize(node.content || "");
|
|
192
225
|
});
|
|
193
|
-
|
|
194
|
-
const result = context.template({site: siteData, page: node});
|
|
195
|
-
press.utils.write(path.join(context.destination, node.path), result);
|
|
226
|
+
node.content = context.template({site: siteData, page: node});
|
|
196
227
|
}
|
|
197
228
|
},
|
|
198
229
|
};
|
|
@@ -202,10 +233,14 @@ press.ContentPagePlugin = (siteData = {}) => {
|
|
|
202
233
|
press.CopyAssetsPlugin = (options = {}) => {
|
|
203
234
|
return {
|
|
204
235
|
name: "CopyAssetsPlugin",
|
|
205
|
-
|
|
206
|
-
(options
|
|
207
|
-
.filter(item =>
|
|
208
|
-
.
|
|
236
|
+
load: () => {
|
|
237
|
+
return (options?.patterns || [])
|
|
238
|
+
.filter(item => item.from && fs.existsSync(path.resolve(item.from)))
|
|
239
|
+
.map(item => ({
|
|
240
|
+
source: path.resolve(item.from),
|
|
241
|
+
path: path.join(options?.basePath || ".", item.to || path.basename(item.from)),
|
|
242
|
+
label: options?.label || press.LABEL_ASSET,
|
|
243
|
+
}));
|
|
209
244
|
},
|
|
210
245
|
};
|
|
211
246
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mikel-press",
|
|
3
3
|
"description": "A tiny and fast static site generator based on mikel templating",
|
|
4
|
-
"version": "0.20.
|
|
4
|
+
"version": "0.20.2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"node": ">=20"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"mikel": "^0.20.
|
|
22
|
+
"mikel": "^0.20.2"
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
25
|
"README.md",
|