mikel-press 0.1.0 → 0.2.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/index.d.ts +18 -13
- package/index.js +91 -51
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -4,11 +4,6 @@ interface MikelTemplateOptions {
|
|
|
4
4
|
partials: {[key: string]: string};
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
interface FrontmatterOptions {
|
|
8
|
-
separator?: string;
|
|
9
|
-
parse?: (front: string) => any;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
7
|
interface FrontmatterResult {
|
|
13
8
|
body: string;
|
|
14
9
|
attributes: any;
|
|
@@ -19,15 +14,22 @@ interface VirtualPageOptions {
|
|
|
19
14
|
file?: string;
|
|
20
15
|
extname?: string;
|
|
21
16
|
basename?: string;
|
|
17
|
+
frontmatter?: (str: string) => FrontmatterResult;
|
|
18
|
+
transform?: (str: string) => string;
|
|
22
19
|
}
|
|
23
20
|
|
|
24
21
|
interface VirtualPage {
|
|
25
|
-
content: string
|
|
26
|
-
attributes: any
|
|
27
|
-
name: string
|
|
28
|
-
extname: string
|
|
29
|
-
basename: string
|
|
30
|
-
url: string
|
|
22
|
+
content: string;
|
|
23
|
+
attributes: any;
|
|
24
|
+
name: string;
|
|
25
|
+
extname: string;
|
|
26
|
+
basename: string;
|
|
27
|
+
url: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface PostsPluginOptions {
|
|
31
|
+
dir: string;
|
|
32
|
+
parser: (str: string) => string;
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
interface SiteConfig {
|
|
@@ -38,13 +40,16 @@ interface SiteConfig {
|
|
|
38
40
|
dataDir: string;
|
|
39
41
|
pagesDir: string;
|
|
40
42
|
assetsDir: string;
|
|
41
|
-
frontmatter:
|
|
43
|
+
frontmatter: (str: string) => FrontmatterResult;
|
|
42
44
|
mikel: Partial<MikelTemplateOptions>;
|
|
43
45
|
plugins: any[];
|
|
44
46
|
}
|
|
45
47
|
|
|
46
48
|
declare module "mikel-press" {
|
|
47
|
-
export function frontmatter(str: string
|
|
49
|
+
export function frontmatter(str: string): FrontmatterResult;
|
|
48
50
|
export function createVirtualPage(options: VirtualPageOptions): VirtualPage;
|
|
49
51
|
export function run(config: Partial<SiteConfig>): void;
|
|
52
|
+
|
|
53
|
+
export function postsPlugin(options: PostsPluginOptions): any;
|
|
54
|
+
export function progressPlugin(): any;
|
|
50
55
|
}
|
package/index.js
CHANGED
|
@@ -2,16 +2,28 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import mikel from "mikel";
|
|
4
4
|
|
|
5
|
+
// @description tiny yaml parser
|
|
6
|
+
const parseYaml = (str = "") => {
|
|
7
|
+
const lines = str.split("\n").filter(line => line.trim() !== "" && !line.trim().startsWith("#"));
|
|
8
|
+
return Object.fromEntries(lines.map(line => {
|
|
9
|
+
const [key, value] = line.split(":").map(part => part.trim());
|
|
10
|
+
if (!isNaN(value)) {
|
|
11
|
+
return [key, Number(value)];
|
|
12
|
+
}
|
|
13
|
+
if (value === "true" || value === "false" || value === "null") {
|
|
14
|
+
return [key, JSON.parse(value)];
|
|
15
|
+
}
|
|
16
|
+
return [key, value.replaceAll(/^["']|["']$/g, "")];
|
|
17
|
+
}));
|
|
18
|
+
};
|
|
19
|
+
|
|
5
20
|
// @description tiny front-matter parser
|
|
6
|
-
const frontmatter = (str = ""
|
|
21
|
+
const frontmatter = (str = "") => {
|
|
7
22
|
let body = (str || "").trim(), attributes = {};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
body = body.substring(matches[1].index + matches[1][1].length).trim();
|
|
13
|
-
attributes = typeof options.parse === "function" ? options.parse(front) : front;
|
|
14
|
-
}
|
|
23
|
+
const matches = Array.from(body.matchAll(/^(--- *)/gm));
|
|
24
|
+
if (matches?.length === 2 && matches[0].index === 0) {
|
|
25
|
+
attributes = parseYaml(body.substring(0 + matches[0][1].length, matches[1].index).trim());
|
|
26
|
+
body = body.substring(matches[1].index + matches[1][1].length).trim();
|
|
15
27
|
}
|
|
16
28
|
return {body, attributes};
|
|
17
29
|
};
|
|
@@ -37,10 +49,11 @@ const getLayoutContent = config => {
|
|
|
37
49
|
content = config.layoutContent || config.templateContent;
|
|
38
50
|
}
|
|
39
51
|
// parse with frontmatter
|
|
40
|
-
const {body, attributes} = frontmatter
|
|
52
|
+
const {body, attributes} = typeof config.frontmatter == "function" ? config.frontmatter(content) : {body: content, attributes: {}};
|
|
41
53
|
return {
|
|
42
54
|
content: body,
|
|
43
55
|
data: attributes || {},
|
|
56
|
+
attributes: attributes || {},
|
|
44
57
|
};
|
|
45
58
|
};
|
|
46
59
|
|
|
@@ -49,7 +62,7 @@ const createVirtualPage = (options = {}) => {
|
|
|
49
62
|
const content = options.content || fs.readFileSync(options.file, "utf8");
|
|
50
63
|
const extname = options.extname || path.extname(options.file || "") || ".html";
|
|
51
64
|
const basename = options.basename || path.basename(options.file || "", extname) || "virtual";
|
|
52
|
-
const {body, attributes} = frontmatter
|
|
65
|
+
const {body, attributes} = typeof options?.frontmatter == "function" ? options.frontmatter(content) : {body: content, attributes: {}};
|
|
53
66
|
return {
|
|
54
67
|
name: basename + extname,
|
|
55
68
|
basename: basename,
|
|
@@ -57,61 +70,56 @@ const createVirtualPage = (options = {}) => {
|
|
|
57
70
|
url: options.url || attributes?.permalink || path.join("/", basename + extname),
|
|
58
71
|
data: attributes || {}, // DEPRECATED
|
|
59
72
|
attributes: attributes || {},
|
|
60
|
-
content: typeof options.
|
|
73
|
+
content: typeof options.transform === "function" ? options.transform(body) : body,
|
|
61
74
|
};
|
|
62
75
|
};
|
|
63
76
|
|
|
64
77
|
// @description get pages from input folder
|
|
65
|
-
const readPages = (folder, extensions = ".html", fm = null,
|
|
78
|
+
const readPages = (folder, extensions = ".html", fm = null, transform = null) => {
|
|
66
79
|
const extensionsList = new Set([extensions].flat());
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
if (fs.existsSync(folder) && fs.lstatSync(folder).isDirectory()) {
|
|
81
|
+
return fs.readdirSync(folder, "utf8")
|
|
82
|
+
.filter(file => extensionsList.has(path.extname(file)))
|
|
83
|
+
.map(file => {
|
|
84
|
+
return createVirtualPage({
|
|
85
|
+
file: path.join(folder, file),
|
|
86
|
+
frontmatter: fm,
|
|
87
|
+
transform: transform,
|
|
88
|
+
extname: ".html",
|
|
89
|
+
});
|
|
75
90
|
});
|
|
76
|
-
|
|
91
|
+
}
|
|
92
|
+
return [];
|
|
77
93
|
};
|
|
78
94
|
|
|
79
95
|
// @description get assets
|
|
80
96
|
const readAssets = (folder, fm = null) => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
if (fs.existsSync(folder) && fs.lstatSync(folder).isDirectory()) {
|
|
98
|
+
const assetPaths = fs.readdirSync(folder, "utf8");
|
|
99
|
+
return Object.fromEntries(assetPaths.map(file => {
|
|
100
|
+
const asset = createVirtualPage({
|
|
101
|
+
file: path.join(folder, file),
|
|
102
|
+
frontmatter: fm,
|
|
103
|
+
});
|
|
104
|
+
const assetName = asset.basename.replaceAll(".", "_").replaceAll("-", "_");
|
|
105
|
+
return [assetName, asset];
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
return {};
|
|
90
109
|
};
|
|
91
110
|
|
|
92
111
|
// @description read a data folder
|
|
93
112
|
const readData = folder => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return Object.fromEntries(files);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
// @description plugins
|
|
104
|
-
const plugins = {
|
|
105
|
-
// plugin to read and include posts in markdown
|
|
106
|
-
posts: (options = {}) => {
|
|
107
|
-
return context => {
|
|
108
|
-
context.hooks.beforeEmit.add(() => {
|
|
109
|
-
const posts = readPages(path.join(context.source, options?.dir || "posts"), [".md"], context.site.frontmatter, options?.parser);
|
|
110
|
-
context.site.posts = posts; // posts will be accesible in site.posts
|
|
111
|
-
context.site.pages = [...context.site.pages, ...posts]; // posts will be included as pages also
|
|
113
|
+
if (fs.existsSync(folder) && fs.lstatSync(folder).isDirectory()) {
|
|
114
|
+
const files = fs.readdirSync(folder, "utf8")
|
|
115
|
+
.filter(file => path.extname(file) === ".json")
|
|
116
|
+
.map(file => path.join(folder, file))
|
|
117
|
+
.map(file => {
|
|
118
|
+
return [path.basename(file, ".json"), JSON.parse(fs.readFileSync(file, "utf8"))];
|
|
112
119
|
});
|
|
113
|
-
|
|
114
|
-
}
|
|
120
|
+
return Object.fromEntries(files);
|
|
121
|
+
}
|
|
122
|
+
return {};
|
|
115
123
|
};
|
|
116
124
|
|
|
117
125
|
// @description run mikel press with the provided configuration
|
|
@@ -160,5 +168,37 @@ const run = (config = {}) => {
|
|
|
160
168
|
dispatch("done", []);
|
|
161
169
|
};
|
|
162
170
|
|
|
171
|
+
// plugin to read and include posts in markdown
|
|
172
|
+
const postsPlugin = (options = {}) => {
|
|
173
|
+
return context => {
|
|
174
|
+
context.hooks.beforeEmit.add(() => {
|
|
175
|
+
const posts = readPages(path.join(context.source, options?.dir || "posts"), [".md"], context.site.frontmatter, options?.parser);
|
|
176
|
+
context.site.posts = posts; // posts will be accesible in site.posts
|
|
177
|
+
context.site.pages = [...context.site.pages, ...posts]; // posts will be included as pages also
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
// progress plugin
|
|
183
|
+
const progressPlugin = () => {
|
|
184
|
+
return context => {
|
|
185
|
+
const timeStart = Date.now();
|
|
186
|
+
const log = (status, msg) => console.log(`[${new Date().toISOString()}] (${status}) ${msg}`);
|
|
187
|
+
context.hooks.initialize.add(() => {
|
|
188
|
+
log("info", `source directory: ${context.source}`);
|
|
189
|
+
log("info", `destination directory: ${context.destination}`);
|
|
190
|
+
});
|
|
191
|
+
context.hooks.emitPage.add(page => {
|
|
192
|
+
log("info", `saving page: ${page.url} --> ${path.join(context.destination, page.url)}`);
|
|
193
|
+
});
|
|
194
|
+
context.hooks.emitAsset.add(asset => {
|
|
195
|
+
log("info", `saving asset: ${asset.url} --> ${path.join(context.destination, asset.url)}`);
|
|
196
|
+
});
|
|
197
|
+
context.hooks.done.add(() => {
|
|
198
|
+
log("done", `build completed in ${Date.now() - timeStart}ms`);
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
|
|
163
203
|
// export
|
|
164
|
-
export default {run, createVirtualPage, frontmatter,
|
|
204
|
+
export default {run, createVirtualPage, frontmatter, postsPlugin, progressPlugin};
|