mikel-press 0.26.2 → 0.27.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.
Files changed (3) hide show
  1. package/README.md +13 -3
  2. package/index.js +62 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -98,8 +98,9 @@ Each HTML file processed by **mikel-press** will be handled by the mikel templat
98
98
  | Variable | Description |
99
99
  |----------|-------------|
100
100
  | `site.pages` | A list containing all pages processed by **mikel-press**. |
101
- | `site.data` | An object containing all data items loaded by `DataLoaderPlugin`. |
102
- | `site.partials` | A list containing all partials files loaded by the `PartialsLoaderPlugin`. |
101
+ | `site.data` | An object containing all data items loaded by `DataPlugin`. |
102
+ | `site.partials` | A list containing all partials files loaded by the `PartialsPlugin`. |
103
+ | `site.layouts` | A list containing all layout files loaded by the `LayoutsPlugin`. |
103
104
  | `site.*` | All the additional configuration fields provided in the configuration. |
104
105
 
105
106
  #### Page variables
@@ -133,6 +134,15 @@ This plugin accepts the following options:
133
134
  - `options.folder` (string): To change the directory to load the partials files. Default is `./partials`.
134
135
  - `options.extensions` (array): Defines the file extensions that should be processed. If not provided, it will use `config.extensions`.
135
136
 
137
+ ### `press.LayoutsPlugin(options)`
138
+
139
+ An alias of `press.SourcePlugin` that will read all files in the `layouts` folder and include them as layouts. In each page, you can use the `attributes.layout` field to set the layout to apply to this page.
140
+
141
+ This plugin accepts the following options:
142
+
143
+ - `options.folder` (string): To change the directory to load the layouts files. Default is `./layouts`.
144
+ - `options.extensions` (array): Defines the file extensions that should be processed. If not provided, it will use `config.extensions`.
145
+
136
146
  ### `press.DataPlugin(options)`
137
147
 
138
148
  This plugin loads JSON files from the specified directory and makes them available in the site context. This plugin accepts the following options:
@@ -154,7 +164,7 @@ This plugin processes and parses the frontmatter in each file. The parsed frontm
154
164
 
155
165
  ### `press.ContentPagePlugin()`
156
166
 
157
- This plugin processes each page and saves it into `config.destination`.
167
+ This plugin processes each page using the mikel templating.
158
168
 
159
169
  ### `press.CopyAssetsPlugin(options)`
160
170
 
package/index.js CHANGED
@@ -6,6 +6,11 @@ const getPlugins = (context, name) => {
6
6
  return context.plugins.filter(plugin => typeof plugin[name] === "function");
7
7
  };
8
8
 
9
+ // @description apply the layout to the provided node
10
+ const applyLayout = page => {
11
+ return `{{>>layout:${page.attributes.layout}}}\n\n${page.content}\n\n{{/layout:${page.attributes.layout}}}\n`;
12
+ };
13
+
9
14
  // @description press main function
10
15
  // @param {Object} config - configuration object
11
16
  // @param {String} config.source - source folder
@@ -21,16 +26,16 @@ const press = (config = {}) => {
21
26
 
22
27
  // @description create a context object
23
28
  press.createContext = (config = {}) => {
24
- const {source, destination, plugins, extensions, exclude, template, watch, ...otherConfig} = config;
29
+ const { source, destination, plugins, extensions, exclude, template, watch, ...otherConfig } = config;
25
30
  const context = Object.freeze({
26
31
  config: otherConfig,
27
32
  source: path.resolve(source || "."),
28
33
  destination: path.resolve(destination || "./www"),
29
- extensions: extensions || [".html"],
30
- exclude: exclude || ["node_modules", ".git", ".gitignore", ".github"],
34
+ extensions: extensions || [ ".html", ".mustache" ],
35
+ exclude: exclude || [ "node_modules", ".git", ".gitignore", ".github" ],
31
36
  template: template,
32
37
  plugins: [
33
- press.SourcePlugin({folder: ".", label: press.LABEL_PAGE}),
38
+ press.SourcePlugin({ folder: ".", label: press.LABEL_PAGE }),
34
39
  ...plugins,
35
40
  ],
36
41
  nodes: [],
@@ -168,13 +173,13 @@ press.LABEL_PAGE = "page";
168
173
  press.LABEL_ASSET = "asset";
169
174
  press.LABEL_DATA = "asset/data";
170
175
  press.LABEL_PARTIAL = "asset/partial";
176
+ press.LABEL_LAYOUT = "asset/layout";
171
177
 
172
178
  // @description source plugin
173
179
  press.SourcePlugin = (options = {}) => {
174
180
  const shouldEmit = options?.emit ?? true, shouldRead = options.read ?? true;
175
181
  const processedNodes = new Set();
176
182
  return {
177
- name: "SourcePlugin",
178
183
  load: context => {
179
184
  const folder = path.join(context.source, options?.folder || ".");
180
185
  const extensions = options?.extensions || context.extensions;
@@ -202,23 +207,49 @@ press.SourcePlugin = (options = {}) => {
202
207
 
203
208
  // @description data plugin
204
209
  press.DataPlugin = (options = {}) => {
205
- return press.SourcePlugin({folder: "./data", emit: false, extensions: [".json"], label: press.LABEL_DATA, ...options});
210
+ return press.SourcePlugin({
211
+ folder: "./data",
212
+ emit: false,
213
+ extensions: [".json"],
214
+ label: press.LABEL_DATA,
215
+ ...options,
216
+ });
206
217
  };
207
218
 
208
219
  // @description partials plugin
209
220
  press.PartialsPlugin = (options = {}) => {
210
- return press.SourcePlugin({folder: "./partials", emit: false, extensions: [".html"], label: press.LABEL_PARTIAL, ...options});
221
+ return press.SourcePlugin({
222
+ folder: "./partials",
223
+ emit: false,
224
+ label: press.LABEL_PARTIAL,
225
+ ...options,
226
+ });
211
227
  };
212
228
 
213
229
  // @description assets plugin
214
230
  press.AssetsPlugin = (options = {}) => {
215
- return press.SourcePlugin({folder: "./assets", read: false, extensions: "*", label: press.LABEL_ASSET, ...options});
231
+ return press.SourcePlugin({
232
+ folder: "./assets",
233
+ read: false,
234
+ extensions: "*",
235
+ label: press.LABEL_ASSET,
236
+ ...options,
237
+ });
238
+ };
239
+
240
+ // @description layouts plugin
241
+ press.LayoutsPlugin = (options = {}) => {
242
+ return press.SourcePlugin({
243
+ folder: "./layouts",
244
+ label: press.LABEL_LAYOUT,
245
+ emit: false,
246
+ ...options,
247
+ });
216
248
  };
217
249
 
218
250
  // @description frontmatter plugin
219
251
  press.FrontmatterPlugin = () => {
220
252
  return {
221
- name: "FrontmatterPlugin",
222
253
  transform: (_, node) => {
223
254
  if (typeof node.content === "string") {
224
255
  const result = press.utils.frontmatter(node.content, JSON.parse);
@@ -237,7 +268,6 @@ press.FrontmatterPlugin = () => {
237
268
  // @description plugin to generate pages content
238
269
  press.ContentPagePlugin = (siteData = {}) => {
239
270
  return {
240
- name: "ContentPagePlugin",
241
271
  beforeTransform: context => {
242
272
  const getNodes = label => context.nodes.filter(n => n.label === label);
243
273
  // 1. prepare site data
@@ -247,6 +277,7 @@ press.ContentPagePlugin = (siteData = {}) => {
247
277
  return [path.basename(node.path, ".json"), JSON.parse(node.content)];
248
278
  })),
249
279
  partials: getNodes(press.LABEL_PARTIAL),
280
+ layouts: getNodes(press.LABEL_LAYOUT),
250
281
  assets: getNodes(press.LABEL_ASSET),
251
282
  });
252
283
  // 2. register partials into template
@@ -256,10 +287,30 @@ press.ContentPagePlugin = (siteData = {}) => {
256
287
  attributes: partial.attributes || {},
257
288
  });
258
289
  });
290
+ // 3. process layouts files
291
+ siteData.layouts.forEach(layout => {
292
+ // 3.1. apply the layout to this layout node
293
+ if (layout?.attributes?.layout && layout?.content) {
294
+ layout.content = applyLayout(layout);
295
+ }
296
+ // 3.2. register layouts into the template
297
+ context.template.addPartial("layout:" + path.basename(layout.path), {
298
+ body: layout.content || "",
299
+ attributes: layout.attributes || {},
300
+ });
301
+ });
302
+ // 4. apply layouts to all pages
303
+ if (siteData.layouts.length > 0 && siteData.pages.length > 0) {
304
+ siteData.pages.forEach(page => {
305
+ if (page?.attributes?.layout && page?.content) {
306
+ page.content = applyLayout(page);
307
+ }
308
+ });
309
+ }
259
310
  },
260
311
  transform: (context, node) => {
261
312
  if (node.label === press.LABEL_PAGE && typeof node.content === "string") {
262
- node.content = context.template(node.content || "", {site: siteData, page: node});
313
+ node.content = context.template(node.content, { site: siteData, page: node });
263
314
  }
264
315
  },
265
316
  };
@@ -268,7 +319,6 @@ press.ContentPagePlugin = (siteData = {}) => {
268
319
  // @description plugin to register mikel helpers and functions
269
320
  press.UsePlugin = mikelPlugin => {
270
321
  return {
271
- name: "UsePlugin",
272
322
  init: context => {
273
323
  context.template.use(mikelPlugin);
274
324
  },
@@ -278,7 +328,6 @@ press.UsePlugin = mikelPlugin => {
278
328
  // @description copy plugin
279
329
  press.CopyAssetsPlugin = (options = {}) => {
280
330
  return {
281
- name: "CopyAssetsPlugin",
282
331
  load: () => {
283
332
  return (options?.patterns || [])
284
333
  .filter(item => item.from && fs.existsSync(path.resolve(item.from)))
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.26.2",
4
+ "version": "0.27.0",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": {