@metalsmith/collections 1.3.0 → 2.0.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/lib/index.js CHANGED
@@ -1,84 +1,110 @@
1
1
  import get from 'lodash.get';
2
- import { sync } from 'read-metadata';
2
+ import { resolve, relative } from 'path';
3
3
 
4
- function sortBy(key) {
4
+ function sortBy(key, order) {
5
+ order = order === 'asc' ? -1 : 1;
5
6
  let getKey = x => x[key];
6
-
7
7
  if (key.includes('.')) {
8
8
  getKey = x => get(x, key);
9
9
  }
10
-
11
10
  return function defaultSort(a, b) {
12
11
  a = getKey(a);
13
12
  b = getKey(b);
14
- if (!a && !b) return 0;
15
- if (!a) return -1;
16
- if (!b) return 1;
17
- if (b > a) return -1;
18
- if (a > b) return 1;
19
- return 0;
13
+ let ret;
14
+ if (!a && !b) ret = 0;else if (!a) ret = 1 * order;else if (!b) ret = -1 * order;else if (b > a) ret = 1 * order;else if (a > b) ret = -1 * order;else ret = 0;
15
+ return ret;
20
16
  };
21
- } // for backwards-compatibility only, date makes as little sense as "pubdate" or any custom key
22
-
23
-
24
- const defaultSort = sortBy('date');
17
+ }
25
18
 
19
+ /**
20
+ * @param {import('metalsmith').File[]} items
21
+ * @param {CollectionConfig} config
22
+ */
23
+ function Collection(items, {
24
+ metadata,
25
+ ...config
26
+ }) {
27
+ const collection = [...items];
28
+ Object.assign(collection, metadata);
29
+ collection.config = config;
30
+ collection.constructor = Collection;
31
+ Object.seal(collection);
32
+ return collection;
33
+ }
34
+ const defaultSort = sortBy('path', 'asc');
26
35
  const defaultFilter = () => true;
36
+
27
37
  /**
28
38
  * @typedef {Object} CollectionConfig
29
- * @property {string|string[]} pattern - One or more glob patterns to match files to a collection
30
- * @property {string|(a,b) => 0|1|-1} sortBy - A key to sort by (e.g. `date`,`title`, ..) or a custom sort function
31
- * @property {number} limit - Limit the amount of items in a collection to `limit`
32
- * @property {boolean} refer - Adds `next` and `previous` keys to file metadata of matched files
33
- * @property {boolean} reverse - Whether to invert the sorting function results (asc/descending)
34
- * @property {Function} filterBy - A function that gets a `Metalsmith.File` as first argument and returns `true` for every file to include in the collection
35
- * @property {Object|string} metadata - An object with metadata to attach to the collection, or a `json`/`yaml`filepath string to load data from (relative to `Metalsmith.directory`)
39
+ * @property {string|string[]} [pattern] - One or more glob patterns to match files to a collection
40
+ * @property {string|(a,b) => 0|1|-1} [sort] - a sort string of the format `'<key_or_keypath>:<asc|desc>'`, followed by the sort order, or a custom sort function
41
+ * @property {number} [limit] - Limit the amount of items in a collection to `limit`
42
+ * @property {boolean} [refer] - Adds `next`, `previous`, `first` and `last` keys to `file.collection[name]` metadata of matched files
43
+ * @property {Function} [filter] - A function that gets a `Metalsmith.File` as first argument and returns `true` for every file to include in the collection
44
+ * @property {Object|string} [metadata] - An object with metadata to attach to the collection, or a `json`/`yaml`filepath string to load data from (relative to `Metalsmith.directory`)
36
45
  */
37
46
 
38
47
  /** @type {CollectionConfig} */
39
-
40
-
41
48
  const defaultOptions = {
42
49
  pattern: null,
43
- reverse: false,
44
50
  metadata: null,
45
51
  limit: Infinity,
46
52
  refer: true,
47
- sortBy: defaultSort,
48
- filterBy: defaultFilter
53
+ sort: defaultSort,
54
+ filter: defaultFilter
49
55
  };
56
+
50
57
  /**
51
58
  * Normalize options
52
59
  * @param {Object.<string,CollectionConfig>} options
60
+ * @param {import('metalsmith').Files} files
61
+ * @param {import('metalsmith')} metalsmith
62
+ * @throws {}
53
63
  */
54
-
55
- function normalizeOptions(options) {
64
+ function normalizeOptions(options, files, metalsmith) {
56
65
  options = options || {};
57
-
66
+ const matter = metalsmith.matter;
58
67
  for (const config in options) {
59
68
  let normalized = options[config];
60
-
61
69
  if (typeof normalized === 'string' || Array.isArray(normalized)) {
62
70
  normalized = {
63
71
  pattern: normalized
64
72
  };
65
73
  }
66
-
67
74
  normalized = Object.assign({}, defaultOptions, normalized);
68
-
69
75
  if (typeof normalized.metadata === 'string') {
70
- normalized.metadata = sync(normalized.metadata);
76
+ const absPath = resolve(metalsmith.source(), normalized.metadata);
77
+ const inSourcePath = relative(metalsmith.source(), absPath);
78
+ const metadataFile = files[inSourcePath];
79
+ if (!metadataFile) {
80
+ const err = new Error(`No collection metadata file at "${absPath}"`);
81
+ err.name = '@metalsmith/collections';
82
+ throw err;
83
+ }
84
+ normalized.metadata = matter.parse(matter.wrap(metadataFile.contents.toString()));
71
85
  }
72
86
 
73
- if (typeof normalized.sortBy === 'string') {
74
- normalized.sortBy = sortBy(normalized.sortBy);
87
+ // remap sort option
88
+ let sort = normalized.sort;
89
+ if (typeof sort === 'string') {
90
+ if (!sort.includes(':')) sort += ':desc';
91
+ const [key, order] = sort.split(':');
92
+ sort = sortBy(key, order);
75
93
  }
76
-
94
+ normalized.sort = sort;
77
95
  options[config] = normalized;
78
96
  }
79
-
80
97
  return options;
81
98
  }
99
+
100
+ /**
101
+ * @typedef {import('../lib/index').ReferencesArray}
102
+ * @property {import('metalsmith').File[]} previous
103
+ * @property {import('metalsmith').File[]} next
104
+ * @property {import('metalsmith').File} first
105
+ * @property {import('metalsmith').File} last
106
+ */
107
+
82
108
  /**
83
109
  * Add `collections` of files to the global metadata as a sorted array.
84
110
  * @example
@@ -87,35 +113,37 @@ function normalizeOptions(options) {
87
113
  * portfolio: {
88
114
  * pattern: 'portfolio/*.md',
89
115
  * metadata: { title: 'My portfolio' },
90
- * sortBy: 'order'
116
+ * sort: 'date:desc'
91
117
  * }
92
118
  * }))
93
119
  *
94
120
  * @param {Object.<string,CollectionConfig|string>} options
95
121
  * @return {import('metalsmith').Plugin}
96
122
  */
97
-
98
-
99
- function initializeCollections(options) {
100
- options = normalizeOptions(options);
101
- const collectionNames = Object.keys(options);
102
- const mappedCollections = collectionNames.map(name => {
103
- return Object.assign({
104
- name: name
105
- }, options[name]);
106
- });
123
+ function collections(options) {
107
124
  return function collections(files, metalsmith, done) {
108
- const metadata = metalsmith.metadata();
125
+ try {
126
+ options = normalizeOptions(options, files, metalsmith);
127
+ } catch (err) {
128
+ done(err);
129
+ }
130
+ const collectionNames = Object.keys(options);
131
+ const mappedCollections = collectionNames.map(name => {
132
+ return Object.assign({
133
+ name: name
134
+ }, options[name]);
135
+ });
109
136
  const fileNames = Object.keys(files);
110
137
  const debug = metalsmith.debug('@metalsmith/collections');
111
- metadata.collections = {};
138
+ metalsmith.metadata({
139
+ collections: {}
140
+ });
141
+ const metadata = metalsmith.metadata();
112
142
  fileNames.forEach(filePath => {
113
- // add path property to file metadata for convenience
114
- // this is for backward-compatibility only and is pretty useless
115
143
  const file = files[filePath];
116
- file.path = file.path || filePath; // dynamically add collections with default options when encountered in file metadata,
117
- // and not explicitly defined in plugin options
118
144
 
145
+ // dynamically add collections with default options when encountered in file metadata,
146
+ // and not explicitly defined in plugin options
119
147
  if (file.collection) {
120
148
  (Array.isArray(file.collection) ? file.collection : [file.collection]).forEach(name => {
121
149
  if (!collectionNames.includes(name)) {
@@ -129,87 +157,90 @@ function initializeCollections(options) {
129
157
  }
130
158
  });
131
159
  debug('Identified %s collections: %s', mappedCollections.length, collectionNames.join());
132
- mappedCollections.forEach(collection => {
160
+ mappedCollections.forEach(collectionConfig => {
133
161
  const {
134
162
  pattern,
135
- filterBy,
136
- sortBy,
137
- reverse,
163
+ filter,
164
+ sort,
138
165
  refer,
139
166
  limit
140
- } = collection;
141
- const name = collection.name;
167
+ } = collectionConfig;
168
+ const name = collectionConfig.name;
142
169
  const matches = [];
143
- debug('Processing collection %s with options %s:', name, collection); // first match by pattern if provided
170
+ debug('Processing collection %s with options %O:', name, collectionConfig);
144
171
 
172
+ // first match by pattern if provided
145
173
  if (pattern) {
146
174
  matches.push.apply(matches, metalsmith.match(pattern, fileNames).map(filepath => {
147
- const data = files[filepath]; // pattern-matched files might or might not have a "collection" property defined in front-matter
175
+ const data = files[filepath];
176
+ // pattern-matched files might or might not have a "collection" property defined in front-matter
148
177
  // and might also be included in multiple collections
149
-
150
178
  if (!data.collection) {
151
179
  data.collection = [];
152
180
  } else if (typeof data.collection === 'string') {
153
181
  data.collection = [data.collection];
154
182
  }
155
-
156
- if (!data.collection.includes(collection.name)) {
157
- data.collection = [...data.collection, collection.name];
183
+ if (!data.collection.includes(collectionConfig.name)) {
184
+ data.collection = [...data.collection, collectionConfig.name];
158
185
  }
159
-
160
186
  return data;
161
187
  }));
162
- } // next match by "collection" key, but only push if the files haven't been added through pattern matching first
163
-
188
+ }
164
189
 
190
+ // next match by "collection" key, but only push if the files haven't been added through pattern matching first
165
191
  matches.push.apply(matches, Object.values(files).filter(file => {
166
192
  const patternMatched = matches.includes(file);
167
- const isInCollection = Array.isArray(file.collection) ? file.collection.includes(collection.name) : file.collection === collection.name;
193
+ const isInCollection = Array.isArray(file.collection) ? file.collection.includes(collectionConfig.name) : file.collection === collectionConfig.name;
168
194
  return !patternMatched && isInCollection;
195
+ }).map(file => {
196
+ if (!file.collection) {
197
+ file.collection = [];
198
+ } else if (typeof file.collection === 'string') {
199
+ file.collection = [file.collection];
200
+ }
201
+ return file;
169
202
  }));
170
203
 
171
- if (Object.prototype.hasOwnProperty.call(metadata, name)) {
172
- debug('Warning: overwriting previously set metadata property %s', name);
173
- } // apply sort, reverse, filter, limit options in this order
174
-
175
-
176
- metadata[name] = matches.sort(sortBy);
177
-
178
- if (reverse) {
179
- metadata[name].reverse();
180
- }
181
-
182
- metadata[name] = metadata[name].filter(filterBy).slice(0, limit);
183
-
184
- if (collection.metadata) {
185
- metadata[name].metadata = collection.metadata;
186
- }
187
-
188
- if (refer) {
189
- if (reverse) {
190
- metadata[name].forEach((file, i) => {
191
- Object.assign(file, {
192
- next: i > 0 ? metadata[name][i - 1] : null,
193
- previous: i < metadata[name].length - 1 ? metadata[name][i + 1] : null
194
- });
195
- });
204
+ // apply sort, filter, limit options in this order
205
+
206
+ let currentCollection = matches;
207
+ // safely add to and remove from the sorting context 'path' property
208
+ const originalPaths = [];
209
+ currentCollection.forEach(item => {
210
+ if (item.path) originalPaths.push([item, item.path]);
211
+ item.path = metalsmith.path(Object.entries(files).find(entry => entry[1] === item)[0]);
212
+ });
213
+ currentCollection = currentCollection.sort(sort).filter(filter).slice(0, limit);
214
+ currentCollection.forEach(item => {
215
+ const original = originalPaths.find(([file]) => file === item);
216
+ if (original) {
217
+ item.path = original[1];
196
218
  } else {
197
- metadata[name].forEach((file, i) => {
198
- Object.assign(file, {
199
- previous: i > 0 ? metadata[name][i - 1] : null,
200
- next: i < metadata[name].length - 1 ? metadata[name][i + 1] : null
201
- });
202
- });
219
+ delete item.path;
203
220
  }
221
+ });
222
+ metadata.collections[name] = Collection(currentCollection, collectionConfig);
223
+ if (refer) {
224
+ const lastIndex = currentCollection.length - 1;
225
+ currentCollection.forEach((file, i) => {
226
+ file.collection[name] = Object.assign(file.collection[name] || {}, {
227
+ previous: [],
228
+ next: [],
229
+ first: currentCollection[0],
230
+ last: currentCollection[lastIndex]
231
+ });
232
+ // previous and next are arrays in which resp. the last & first item are merged
233
+ // so users can easily get a single prev/next vs a list. Without it, getting the single prev is tricky, eg in NJK: {% set coll = collection.some.previous | last %}{{ coll.title }}
234
+ if (i > 0) file.collection[name].previous = Object.assign(currentCollection.slice(0, i), currentCollection[i - 1]);
235
+ if (i < lastIndex) file.collection[name].next = Object.assign(currentCollection.slice(i + 1), currentCollection[i + 1]);
236
+ });
204
237
  }
205
-
206
- metadata.collections[name] = metadata[name];
207
- debug('Added %s files to collection %s', metadata[name].length, name);
238
+ debug('Added %s files to collection %s', currentCollection.length, name);
208
239
  });
209
240
  done();
210
241
  };
211
242
  }
243
+ collections.defaults = defaultOptions;
212
244
 
213
- initializeCollections.defaults = defaultOptions;
214
-
215
- export { initializeCollections as default };
245
+ export { collections as default };
246
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.js"],"sourcesContent":["import get from 'lodash.get'\nimport { relative, resolve } from 'path'\n\nfunction sortBy(key, order) {\n order = order === 'asc' ? -1 : 1\n let getKey = (x) => x[key]\n if (key.includes('.')) {\n getKey = (x) => get(x, key)\n }\n return function defaultSort(a, b) {\n a = getKey(a)\n b = getKey(b)\n let ret\n if (!a && !b) ret = 0\n else if (!a) ret = 1 * order\n else if (!b) ret = -1 * order\n else if (b > a) ret = 1 * order\n else if (a > b) ret = -1 * order\n else ret = 0\n\n return ret\n }\n}\n\n/**\n * @param {import('metalsmith').File[]} items\n * @param {CollectionConfig} config\n */\nfunction Collection(items, { metadata, ...config }) {\n const collection = [...items]\n Object.assign(collection, metadata)\n collection.config = config\n collection.constructor = Collection\n Object.seal(collection)\n return collection\n}\n\nconst defaultSort = sortBy('path', 'asc')\nconst defaultFilter = () => true\n\n/**\n * @typedef {Object} CollectionConfig\n * @property {string|string[]} [pattern] - One or more glob patterns to match files to a collection\n * @property {string|(a,b) => 0|1|-1} [sort] - a sort string of the format `'<key_or_keypath>:<asc|desc>'`, followed by the sort order, or a custom sort function\n * @property {number} [limit] - Limit the amount of items in a collection to `limit`\n * @property {boolean} [refer] - Adds `next`, `previous`, `first` and `last` keys to `file.collection[name]` metadata of matched files\n * @property {Function} [filter] - A function that gets a `Metalsmith.File` as first argument and returns `true` for every file to include in the collection\n * @property {Object|string} [metadata] - An object with metadata to attach to the collection, or a `json`/`yaml`filepath string to load data from (relative to `Metalsmith.directory`)\n */\n\n/** @type {CollectionConfig} */\nconst defaultOptions = {\n pattern: null,\n metadata: null,\n limit: Infinity,\n refer: true,\n sort: defaultSort,\n filter: defaultFilter\n}\n\n/**\n * Normalize options\n * @param {Object.<string,CollectionConfig>} options\n * @param {import('metalsmith').Files} files\n * @param {import('metalsmith')} metalsmith\n * @throws {}\n */\nfunction normalizeOptions(options, files, metalsmith) {\n options = options || {}\n const matter = metalsmith.matter\n\n for (const config in options) {\n let normalized = options[config]\n if (typeof normalized === 'string' || Array.isArray(normalized)) {\n normalized = { pattern: normalized }\n }\n normalized = Object.assign({}, defaultOptions, normalized)\n if (typeof normalized.metadata === 'string') {\n const absPath = resolve(metalsmith.source(), normalized.metadata)\n const inSourcePath = relative(metalsmith.source(), absPath)\n const metadataFile = files[inSourcePath]\n if (!metadataFile) {\n const err = new Error(`No collection metadata file at \"${absPath}\"`)\n err.name = '@metalsmith/collections'\n throw err\n }\n normalized.metadata = matter.parse(matter.wrap(metadataFile.contents.toString()))\n }\n\n // remap sort option\n let sort = normalized.sort\n if (typeof sort === 'string') {\n if (!sort.includes(':')) sort += ':desc'\n const [key, order] = sort.split(':')\n sort = sortBy(key, order)\n }\n normalized.sort = sort\n\n options[config] = normalized\n }\n\n return options\n}\n\n/**\n * @typedef {import('../lib/index').ReferencesArray}\n * @property {import('metalsmith').File[]} previous\n * @property {import('metalsmith').File[]} next\n * @property {import('metalsmith').File} first\n * @property {import('metalsmith').File} last\n */\n\n/**\n * Add `collections` of files to the global metadata as a sorted array.\n * @example\n * metalsmith.use(collections({\n * posts: 'posts/*.md',\n * portfolio: {\n * pattern: 'portfolio/*.md',\n * metadata: { title: 'My portfolio' },\n * sort: 'date:desc'\n * }\n * }))\n *\n * @param {Object.<string,CollectionConfig|string>} options\n * @return {import('metalsmith').Plugin}\n */\nfunction collections(options) {\n return function collections(files, metalsmith, done) {\n try {\n options = normalizeOptions(options, files, metalsmith)\n } catch (err) {\n done(err)\n }\n const collectionNames = Object.keys(options)\n const mappedCollections = collectionNames.map((name) => {\n return Object.assign({ name: name }, options[name])\n })\n\n const fileNames = Object.keys(files)\n const debug = metalsmith.debug('@metalsmith/collections')\n\n metalsmith.metadata({ collections: {} })\n const metadata = metalsmith.metadata()\n\n fileNames.forEach((filePath) => {\n const file = files[filePath]\n\n // dynamically add collections with default options when encountered in file metadata,\n // and not explicitly defined in plugin options\n if (file.collection) {\n ;(Array.isArray(file.collection) ? file.collection : [file.collection]).forEach((name) => {\n if (!collectionNames.includes(name)) {\n collectionNames.push(name)\n const normalized = Object.assign({}, defaultOptions)\n mappedCollections.push(Object.assign({ name }, normalized))\n }\n })\n }\n })\n\n debug('Identified %s collections: %s', mappedCollections.length, collectionNames.join())\n\n mappedCollections.forEach((collectionConfig) => {\n const { pattern, filter, sort, refer, limit } = collectionConfig\n const name = collectionConfig.name\n const matches = []\n debug('Processing collection %s with options %O:', name, collectionConfig)\n\n // first match by pattern if provided\n if (pattern) {\n matches.push.apply(\n matches,\n metalsmith.match(pattern, fileNames).map((filepath) => {\n const data = files[filepath]\n // pattern-matched files might or might not have a \"collection\" property defined in front-matter\n // and might also be included in multiple collections\n if (!data.collection) {\n data.collection = []\n } else if (typeof data.collection === 'string') {\n data.collection = [data.collection]\n }\n if (!data.collection.includes(collectionConfig.name)) {\n data.collection = [...data.collection, collectionConfig.name]\n }\n return data\n })\n )\n }\n\n // next match by \"collection\" key, but only push if the files haven't been added through pattern matching first\n matches.push.apply(\n matches,\n Object.values(files)\n .filter((file) => {\n const patternMatched = matches.includes(file)\n const isInCollection = Array.isArray(file.collection)\n ? file.collection.includes(collectionConfig.name)\n : file.collection === collectionConfig.name\n return !patternMatched && isInCollection\n })\n .map((file) => {\n if (!file.collection) {\n file.collection = []\n } else if (typeof file.collection === 'string') {\n file.collection = [file.collection]\n }\n return file\n })\n )\n\n // apply sort, filter, limit options in this order\n\n let currentCollection = matches\n // safely add to and remove from the sorting context 'path' property\n const originalPaths = []\n currentCollection.forEach((item) => {\n if (item.path) originalPaths.push([item, item.path])\n item.path = metalsmith.path(Object.entries(files).find((entry) => entry[1] === item)[0])\n })\n\n currentCollection = currentCollection.sort(sort).filter(filter).slice(0, limit)\n\n currentCollection.forEach((item) => {\n const original = originalPaths.find(([file]) => file === item)\n if (original) {\n item.path = original[1]\n } else {\n delete item.path\n }\n })\n\n metadata.collections[name] = Collection(currentCollection, collectionConfig)\n\n if (refer) {\n const lastIndex = currentCollection.length - 1\n currentCollection.forEach((file, i) => {\n file.collection[name] = Object.assign(file.collection[name] || {}, {\n previous: [],\n next: [],\n first: currentCollection[0],\n last: currentCollection[lastIndex]\n })\n // previous and next are arrays in which resp. the last & first item are merged\n // so users can easily get a single prev/next vs a list. Without it, getting the single prev is tricky, eg in NJK: {% set coll = collection.some.previous | last %}{{ coll.title }}\n if (i > 0)\n file.collection[name].previous = Object.assign(currentCollection.slice(0, i), currentCollection[i - 1])\n if (i < lastIndex)\n file.collection[name].next = Object.assign(currentCollection.slice(i + 1), currentCollection[i + 1])\n })\n }\n\n debug('Added %s files to collection %s', currentCollection.length, name)\n })\n done()\n }\n}\n\ncollections.defaults = defaultOptions\n\nexport default collections\n"],"names":["sortBy","key","order","getKey","x","includes","get","defaultSort","a","b","ret","Collection","items","metadata","config","collection","Object","assign","constructor","seal","defaultFilter","defaultOptions","pattern","limit","Infinity","refer","sort","filter","normalizeOptions","options","files","metalsmith","matter","normalized","Array","isArray","absPath","resolve","source","inSourcePath","relative","metadataFile","err","Error","name","parse","wrap","contents","toString","split","collections","done","collectionNames","keys","mappedCollections","map","fileNames","debug","forEach","filePath","file","push","length","join","collectionConfig","matches","apply","match","filepath","data","values","patternMatched","isInCollection","currentCollection","originalPaths","item","path","entries","find","entry","slice","original","lastIndex","i","previous","next","first","last","defaults"],"mappings":"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"}
package/package.json CHANGED
@@ -15,7 +15,7 @@
15
15
  "type": "git",
16
16
  "url": "https://github.com/metalsmith/collections.git"
17
17
  },
18
- "version": "1.3.0",
18
+ "version": "2.0.0",
19
19
  "license": "MIT",
20
20
  "source": "src/index.js",
21
21
  "main": "lib/index.cjs",
@@ -23,27 +23,28 @@
23
23
  "type": "module",
24
24
  "types": "./lib/index.d.ts",
25
25
  "exports": {
26
+ "types": "./lib/index.d.ts",
26
27
  "import": "./lib/index.js",
27
28
  "require": "./lib/index.cjs"
28
29
  },
29
30
  "dependencies": {
30
- "lodash.get": "^4.4.2",
31
- "read-metadata": "^1.0.0"
31
+ "lodash.get": "^4.4.2"
32
32
  },
33
33
  "devDependencies": {
34
- "auto-changelog": "^2.4.0",
35
- "coveralls": "^3.1.1",
36
- "eslint": "^8.20.0",
37
- "eslint-config-prettier": "^8.5.0",
38
- "eslint-plugin-import": "^2.26.0",
39
- "eslint-plugin-node": "^11.1.0",
40
- "metalsmith": "^2.5.0",
41
- "microbundle": "^0.15.0",
42
- "mocha": "^9.2.2",
43
- "nodemon": "^2.0.19",
44
- "nyc": "^15.1.0",
45
- "prettier": "^2.7.1",
46
- "release-it": "^15.2.0"
34
+ "@eslint/js": "^9.39.2",
35
+ "@metalsmith/layouts": "^3.0.0",
36
+ "auto-changelog": "^2.5.0",
37
+ "c8": "^10.1.3",
38
+ "eslint": "^9.39.2",
39
+ "eslint-config-prettier": "^10.1.8",
40
+ "eslint-plugin-import": "^2.32.0",
41
+ "eslint-plugin-n": "^17.23.1",
42
+ "jstransformer-nunjucks": "^1.2.0",
43
+ "metalsmith": "^2.6.3",
44
+ "microbundle": "^0.15.1",
45
+ "mocha": "^11.7.5",
46
+ "prettier": "^3.7.4",
47
+ "release-it": "^19.2.2"
47
48
  },
48
49
  "directories": {
49
50
  "lib": "lib",
@@ -53,25 +54,24 @@
53
54
  "lib/*"
54
55
  ],
55
56
  "scripts": {
56
- "changelog": "auto-changelog -u --starting-date 2021-12-01 --sort-commits date-desc --commit-limit false --ignore-commit-pattern '(dev|Release|Merge)'",
57
- "coverage": "nyc report --reporter=text-lcov > ./coverage.info",
57
+ "changelog": "auto-changelog -u --starting-date 2021-12-01 --sort-commits date-desc --commit-limit false --ignore-commit-pattern '(dev|test|Release|Merge)'",
58
+ "coverage": "npm test && c8 report --reporter=text-lcov > ./coverage.info",
58
59
  "format": "prettier --write \"**/*.{yml,md,js,json}\"",
59
60
  "format:check": "prettier --list-different \"**/*.{yml,md,js,json}\"",
60
61
  "lint": "eslint --fix .",
61
62
  "lint:check": "eslint --fix-dry-run .",
62
- "dev": "nodemon --exec 'npm test'",
63
63
  "release": "release-it .",
64
- "build": "microbundle --target node --no-sourcemap -f cjs,esm --strict --generateTypes=false",
64
+ "build": "microbundle --target node -f cjs,esm --strict --generateTypes=false",
65
65
  "pretest": "npm run build",
66
- "test": "nyc mocha"
66
+ "test": "c8 mocha"
67
67
  },
68
68
  "publishConfig": {
69
69
  "access": "public"
70
70
  },
71
71
  "peerDependencies": {
72
- "metalsmith": "^2.5.0"
72
+ "metalsmith": "^2.6.0"
73
73
  },
74
74
  "engines": {
75
- "node": ">=12"
75
+ "node": ">=14.14.0"
76
76
  }
77
77
  }