mikel-press 0.29.0 → 0.30.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 +15 -0
- package/index.js +102 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -187,6 +187,21 @@ This plugin copies static files from the source to the destination.
|
|
|
187
187
|
Options:
|
|
188
188
|
- `options.patterns` (array): List of file patterns to copy. Each pattern should have `from` and `to`.
|
|
189
189
|
|
|
190
|
+
### `press.RedirectsPlugin(options)`
|
|
191
|
+
|
|
192
|
+
The RedirectsPlugin lets you define URL redirects. For each redirect rule, the plugin generates a small HTML file that forwards visitors to the target URL using both HTML and JavaScript fallbacks.
|
|
193
|
+
|
|
194
|
+
Options:
|
|
195
|
+
- `options.redirects` (array): list of redirections. Each redirection should have `from` and `to`.
|
|
196
|
+
|
|
197
|
+
```javascript
|
|
198
|
+
press.RedirectsPlugin({
|
|
199
|
+
redirects: [
|
|
200
|
+
{ from: "/socials/github.html", to: "https://github.com/jmjuanes" },
|
|
201
|
+
],
|
|
202
|
+
});
|
|
203
|
+
```
|
|
204
|
+
|
|
190
205
|
## API
|
|
191
206
|
|
|
192
207
|
**mikel-press** exposes a single function that triggers the build with the given configuration object provided as an argument.
|
package/index.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
|
|
4
|
+
// @description internal method to get the first node that ends with the provided string
|
|
5
|
+
const getNodeFromSource = (nodes = [], endingStr = "") => {
|
|
6
|
+
return (nodes || []).find(node => (node.source || "").endsWith(endingStr || ""));
|
|
7
|
+
};
|
|
8
|
+
|
|
4
9
|
// @description get all plugins of the given type
|
|
5
10
|
const getPlugins = (context, name) => {
|
|
6
11
|
return context.plugins.filter(plugin => typeof plugin[name] === "function");
|
|
@@ -11,6 +16,26 @@ const applyLayout = page => {
|
|
|
11
16
|
return `{{>>layout:${page.attributes.layout}}}\n\n${page.content}\n\n{{/layout:${page.attributes.layout}}}\n`;
|
|
12
17
|
};
|
|
13
18
|
|
|
19
|
+
// @description generate the content for the redirection page
|
|
20
|
+
const generateRedirectHTML = (to, status) => {
|
|
21
|
+
const content = [
|
|
22
|
+
`<!DOCTYPE html>`,
|
|
23
|
+
`<html lang="en">`,
|
|
24
|
+
`<head>`,
|
|
25
|
+
` <meta charset="utf-8" />`,
|
|
26
|
+
` <title>Redirecting...</title>`,
|
|
27
|
+
` <meta http-equiv="refresh" content="0; url=${to}" />`,
|
|
28
|
+
` <link rel="canonical" href="${to}" />`,
|
|
29
|
+
` <script>window.location.replace("${to}");</script>`,
|
|
30
|
+
`</head>`,
|
|
31
|
+
`<body>`,
|
|
32
|
+
` <p>Redirectig to <a href="${to}">${to}</a>...</p>`,
|
|
33
|
+
`</body>`,
|
|
34
|
+
`</html>`,
|
|
35
|
+
];
|
|
36
|
+
return content.join("\n");
|
|
37
|
+
};
|
|
38
|
+
|
|
14
39
|
// @description press main function
|
|
15
40
|
// @param {Object} config - configuration object
|
|
16
41
|
// @param {String} config.source - source folder
|
|
@@ -41,6 +66,26 @@ press.createContext = (config = {}) => {
|
|
|
41
66
|
nodes: [],
|
|
42
67
|
actions: {},
|
|
43
68
|
});
|
|
69
|
+
// register helpers and funcions
|
|
70
|
+
context.template.addFunction("getPageUrl", params => {
|
|
71
|
+
return getNodeFromSource(params?.variables?.root?.site?.pages || [], params.args[0])?.url || "";
|
|
72
|
+
});
|
|
73
|
+
context.template.addFunction("getAssetUrl", params => {
|
|
74
|
+
return getNodeFromSource(params?.variables?.root?.site?.assets || [], params.args[0])?.url || "";
|
|
75
|
+
});
|
|
76
|
+
context.template.addHelper("pages", params => {
|
|
77
|
+
const draft = params?.options?.draft ?? params?.opt?.draft;
|
|
78
|
+
const collection = params?.opt?.collection || params?.options?.collection || null;
|
|
79
|
+
const items = (params.data?.site?.pages || []).filter(page => {
|
|
80
|
+
if (typeof draft === "boolean" && draft !== !!page?.attributes?.draft) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return !collection || page.attributes?.collection === collection;
|
|
84
|
+
});
|
|
85
|
+
const limit = Math.min(items.length, params.options?.limit || params.opt?.limit || items.length);
|
|
86
|
+
return items.slice(0, limit).reverse().map((c, i) => params.fn(c, {index: i})).join("");
|
|
87
|
+
});
|
|
88
|
+
// initialize plugins
|
|
44
89
|
getPlugins(context, "init").forEach(plugin => {
|
|
45
90
|
return plugin.init(context);
|
|
46
91
|
});
|
|
@@ -117,6 +162,10 @@ press.watchContext = (context, options = {}) => {
|
|
|
117
162
|
|
|
118
163
|
// @description general utilities
|
|
119
164
|
press.utils = {
|
|
165
|
+
// @description normalize a path
|
|
166
|
+
normalizePath: (rawPath) => {
|
|
167
|
+
return path.normalize("/" + rawPath);
|
|
168
|
+
},
|
|
120
169
|
// @description read a file from disk
|
|
121
170
|
// @param {String} file path to the file to read
|
|
122
171
|
read: (file, encoding = "utf8") => {
|
|
@@ -149,6 +198,26 @@ press.utils = {
|
|
|
149
198
|
.filter(file => (extensions === "*" || extensions.includes(path.extname(file))) && !exclude.includes(file))
|
|
150
199
|
.filter(file => fs.statSync(path.join(folder, file)).isFile());
|
|
151
200
|
},
|
|
201
|
+
// @description walk through the given folder and get all files
|
|
202
|
+
// @params {String} folder folder to walk through
|
|
203
|
+
// @params {Array|String} extensions extensions to include. Default: "*"
|
|
204
|
+
walkdir: (folder, extensions = "*", exclude = []) => {
|
|
205
|
+
const walkSync = (currentFolder, files = []) => {
|
|
206
|
+
const fullFolderPath = path.join(folder, currentFolder);
|
|
207
|
+
fs.readdirSync(fullFolderPath).forEach(file => {
|
|
208
|
+
const filePath = path.join(currentFolder, file);
|
|
209
|
+
const fullFilePath = path.join(fullFolderPath, file);
|
|
210
|
+
if (fs.statSync(fullFilePath).isDirectory()) {
|
|
211
|
+
return walkSync(filePath, files);
|
|
212
|
+
}
|
|
213
|
+
if (extensions === "*" || extensions.includes(path.extname(file))) {
|
|
214
|
+
files.push(filePath);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return files;
|
|
218
|
+
};
|
|
219
|
+
return walkSync("./", []);
|
|
220
|
+
},
|
|
152
221
|
// @description watch for file changes
|
|
153
222
|
// @param {String} filePath path to the file to watch
|
|
154
223
|
// @param {Function} listener method to listen for file changes
|
|
@@ -199,7 +268,7 @@ press.SourcePlugin = (options = {}) => {
|
|
|
199
268
|
source: path.join(folder, file),
|
|
200
269
|
label: options.label || press.LABEL_PAGE,
|
|
201
270
|
path: path.join(options?.basePath || ".", file),
|
|
202
|
-
url:
|
|
271
|
+
url: press.utils.normalizePath(path.join(options?.basePath || ".", file)),
|
|
203
272
|
};
|
|
204
273
|
});
|
|
205
274
|
},
|
|
@@ -275,7 +344,7 @@ press.FrontmatterPlugin = () => {
|
|
|
275
344
|
node.title = node.attributes?.title || node.path;
|
|
276
345
|
if (node.attributes.permalink) {
|
|
277
346
|
node.path = node.attributes.permalink;
|
|
278
|
-
node.url =
|
|
347
|
+
node.url = press.utils.normalizePath(node.path);
|
|
279
348
|
}
|
|
280
349
|
}
|
|
281
350
|
},
|
|
@@ -343,19 +412,37 @@ press.UsePlugin = mikelPlugin => {
|
|
|
343
412
|
};
|
|
344
413
|
|
|
345
414
|
// @description copy plugin
|
|
346
|
-
press.CopyAssetsPlugin = (options = {}) => {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
415
|
+
press.CopyAssetsPlugin = (options = {}) => ({
|
|
416
|
+
name: "CopyAssetsPlugin",
|
|
417
|
+
load: () => {
|
|
418
|
+
const filesToCopy = (options?.patterns || []).filter(item => {
|
|
419
|
+
return item.from && fs.existsSync(path.resolve(item.from));
|
|
420
|
+
});
|
|
421
|
+
return filesToCopy.map(item => {
|
|
422
|
+
const filePath = path.join(options?.basePath || ".", item.to || path.basename(item.from));
|
|
423
|
+
return {
|
|
424
|
+
source: path.resolve(item.from),
|
|
425
|
+
path: filePath,
|
|
426
|
+
url: press.utils.normalizePath(filePath),
|
|
427
|
+
label: options?.label || press.LABEL_ASSET,
|
|
428
|
+
};
|
|
429
|
+
});
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// @description redirections plugin
|
|
434
|
+
press.RedirectsPlugin = (options = {}) => ({
|
|
435
|
+
name: "RedirectsPlugin",
|
|
436
|
+
load: () => {
|
|
437
|
+
return (options.redirects || []).map(redirection => ({
|
|
438
|
+
source: redirection.from,
|
|
439
|
+
path: path.join(options?.basePath || ".", redirection.from),
|
|
440
|
+
url: press.utils.normalizePath(path.join(options?.basePath || ".", redirection.from)),
|
|
441
|
+
label: press.LABEL_ASSET,
|
|
442
|
+
content: generateRedirectHTML(redirection.to),
|
|
443
|
+
}));
|
|
444
|
+
},
|
|
445
|
+
});
|
|
359
446
|
|
|
360
447
|
// export press generator
|
|
361
448
|
export default press;
|