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