1
|
|
|
/** |
2
|
|
|
* @title rehype-all-the-thumbs-curate |
3
|
|
|
* @author Eric Moore |
4
|
|
|
* @summary Select DOM nodes that have images availble for thumbnailing |
5
|
|
|
* @description Pluck out Images, and tag the file with instructions for |
6
|
|
|
* other thumbnailing plugins to use. |
7
|
|
|
* @see https://unifiedjs.com/explore/package/hast-util-select/#support |
8
|
|
|
* |
9
|
|
|
* # Inpput/Output |
10
|
|
|
* |
11
|
|
|
* ## Implied Input (Required): |
12
|
|
|
* |
13
|
|
|
* + HTML file with a DOM tree (can be decorate with instructions) |
14
|
|
|
* |
15
|
|
|
* ## Input Config (Optional) |
16
|
|
|
* |
17
|
|
|
* - css selctor string |
18
|
|
|
* - instructions for thumbnailing images |
19
|
|
|
* |
20
|
|
|
* ## Config Preference |
21
|
|
|
* |
22
|
|
|
* HTML > Options |
23
|
|
|
* |
24
|
|
|
* ## Output |
25
|
|
|
* |
26
|
|
|
* -an unchanged tree (aka: vfile.contents) |
27
|
|
|
*/ |
28
|
|
|
var __assign = (this && this.__assign) || function () { |
29
|
|
|
__assign = Object.assign || function(t) { |
30
|
|
|
for (var s, i = 1, n = arguments.length; i < n; i++) { |
31
|
|
|
s = arguments[i]; |
32
|
|
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) |
|
|
|
|
33
|
|
|
t[p] = s[p]; |
|
|
|
|
34
|
|
|
} |
35
|
|
|
return t; |
36
|
|
|
}; |
37
|
|
|
return __assign.apply(this, arguments); |
38
|
|
|
}; |
39
|
|
|
var __spreadArray = (this && this.__spreadArray) || function (to, from) { |
40
|
|
|
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) |
41
|
|
|
to[j] = from[i]; |
|
|
|
|
42
|
|
|
return to; |
43
|
|
|
}; |
44
|
|
|
var __importDefault = (this && this.__importDefault) || function (mod) { |
45
|
|
|
return (mod && mod.__esModule) ? mod : { "default": mod }; |
46
|
|
|
}; |
47
|
|
|
(function (factory) { |
48
|
|
|
if (typeof module === "object" && typeof module.exports === "object") { |
49
|
|
|
var v = factory(require, exports); |
50
|
|
|
if (v !== undefined) module.exports = v; |
|
|
|
|
51
|
|
|
} |
52
|
|
|
else if (typeof define === "function" && define.amd) { |
|
|
|
|
53
|
|
|
define(["require", "exports", "path", "hast-util-select", "crypto"], factory); |
54
|
|
|
} |
55
|
|
|
})(function (require, exports) { |
56
|
|
|
"use strict"; |
57
|
|
|
Object.defineProperty(exports, "__esModule", { value: true }); |
58
|
|
|
exports.attacher = exports.trimmedHash = exports.localResolve = void 0; |
|
|
|
|
59
|
|
|
var path_1 = __importDefault(require("path")); |
60
|
|
|
var hast_util_select_1 = require("hast-util-select"); |
61
|
|
|
var crypto_1 = require("crypto"); |
62
|
|
|
var isArray = Array.isArray; |
63
|
|
|
// import Mustache from 'mustache' |
64
|
|
|
// const makePrettyPrinter = (indent=2) => (...a:any) => a.length === 1 |
65
|
|
|
// ? console.log(JSON.stringify( a[0], null, indent)) |
66
|
|
|
// : console.log(...a.slice(0,-1), JSON.stringify(a.slice(-1)[0], null, indent)) |
67
|
|
|
// const prettyPrint = makePrettyPrinter() |
68
|
|
|
/** |
69
|
|
|
* Resolve |
70
|
|
|
* @summary Merge path segments together |
71
|
|
|
* @description Take in path segments, |
72
|
|
|
* intelligibly merge them together to form one path. |
73
|
|
|
* @todo the up path |
74
|
|
|
*/ |
75
|
|
|
var localResolve = function () { |
76
|
|
|
var paths = []; |
77
|
|
|
for (var _i = 0; _i < arguments.length; _i++) { |
78
|
|
|
paths[_i] = arguments[_i]; |
79
|
|
|
} |
80
|
|
|
var withDotsButNoSlashes = paths.map(function (c, i, a) { |
|
|
|
|
81
|
|
|
c = c.startsWith('/') ? c.slice(1) : c; |
82
|
|
|
c = c.endsWith('/') ? c.slice(0, -1) : c; |
83
|
|
|
return c; |
84
|
|
|
}); |
85
|
|
|
var noDotDotnoSlashes = withDotsButNoSlashes.reduce(function (p, c) { |
86
|
|
|
if (c === '' || c === ' ') { |
87
|
|
|
return p; |
88
|
|
|
} |
89
|
|
|
if (c.startsWith('..')) { |
90
|
|
|
return exports.localResolve.apply(void 0, __spreadArray(__spreadArray([], p.slice(0, -1)), [c.slice(2)])).split('/'); |
|
|
|
|
91
|
|
|
} |
92
|
|
|
else { |
|
|
|
|
93
|
|
|
return __spreadArray(__spreadArray([], p), [c]); |
94
|
|
|
} |
95
|
|
|
}, []); |
96
|
|
|
return noDotDotnoSlashes.join('/'); |
97
|
|
|
}; |
98
|
|
|
exports.localResolve = localResolve; |
99
|
|
|
var trimmedHash = function (n) { return function (b) { return function () { return crypto_1.createHash('sha256').update(b).digest('hex').slice(0, n); }; }; }; |
100
|
|
|
exports.trimmedHash = trimmedHash; |
101
|
|
|
/** |
102
|
|
|
* Merge |
103
|
|
|
* @private |
104
|
|
|
*/ |
105
|
|
|
var merge = function (paths, fallback, obj) { |
106
|
|
|
return Object.entries(paths) |
107
|
|
|
.reduce(function (acc, _a) { |
108
|
|
|
var _b; |
109
|
|
|
var prop = _a[0], prepFn = _a[1]; |
110
|
|
|
return prop in obj |
111
|
|
|
? prepFn(acc, obj[prop]) |
112
|
|
|
: prop in fallback |
113
|
|
|
? __assign(__assign({}, acc), (_b = {}, _b[prop] = fallback[prop], _b)) : acc; |
|
|
|
|
114
|
|
|
}, {}); |
115
|
|
|
}; |
116
|
|
|
/** |
117
|
|
|
* Map Builder: Parse String And Swap Path |
118
|
|
|
* @private |
119
|
|
|
* @description A builder function returning a key to ƒ.transform map. |
120
|
|
|
* The 'look-up-key'º is mapped to a merge function. |
121
|
|
|
* The ƒ.merge returns a new merged object, |
122
|
|
|
* where the 'look-up-key'º is replaced with the writePath during merge, and the val is parsed |
123
|
|
|
*/ |
124
|
|
|
var parseStringsAndSwapPath = function (readPath, writePath) { |
125
|
|
|
var _a; |
126
|
|
|
return (_a = {}, _a[readPath] = function (a, s) { |
|
|
|
|
127
|
|
|
var _a; |
128
|
|
|
return (__assign(__assign({}, a), (_a = {}, _a[writePath] = JSON.parse(s), _a))); |
|
|
|
|
129
|
|
|
}, _a); |
130
|
|
|
}; |
131
|
|
|
/** |
132
|
|
|
* Map Builder: Swap Path |
133
|
|
|
* @private |
134
|
|
|
* @description A builder function returning a key to ƒ.transform map. |
135
|
|
|
* The 'look-up-key'º (aka: readPath) is mapped to a merge function. |
136
|
|
|
* The ƒ.merge function is given an accumulating merge object, and a value from one of 2 target objects depending on if its found. |
137
|
|
|
* The ƒ.merge returns a merged object, and all it does it replce the look-up-keyº with the writePath |
138
|
|
|
* and the val stays unchanged |
139
|
|
|
* @example |
140
|
|
|
* const mergeMeIn = noChange('lookForThis', 'butEventuallyMakeItThis') |
141
|
|
|
* console.log(mergeMeIn) // { lookForThis: (all, val) => ({...all, butEventuallyMakeItThis: val}) } |
142
|
|
|
*/ |
143
|
|
|
var noChangeJustSwapPath = function (readPath, writePath) { |
144
|
|
|
var _a; |
145
|
|
|
return (_a = {}, _a[readPath] = function (a, s) { |
|
|
|
|
146
|
|
|
var _a; |
147
|
|
|
return (__assign(__assign({}, a), (_a = {}, _a[writePath] = s, _a))); |
|
|
|
|
148
|
|
|
}, _a); |
149
|
|
|
}; |
150
|
|
|
/** |
151
|
|
|
* Map Builder: Indetity |
152
|
|
|
* @private |
153
|
|
|
* @description A builder function returning a key to ƒ.transform map. |
154
|
|
|
* The look-up-key maps to a ƒ.merge. |
155
|
|
|
* The ƒ.merge (inputs: (accum obj, val)) returns a merged object where the 'look-up-key'º maps to the unchanged val |
156
|
|
|
*/ |
157
|
|
|
var noChange = function (spath) { |
158
|
|
|
var _a; |
159
|
|
|
return (_a = {}, _a[spath] = function (a, s) { |
|
|
|
|
160
|
|
|
var _a; |
161
|
|
|
return (__assign(__assign({}, a), (_a = {}, _a[spath] = s, _a))); |
|
|
|
|
162
|
|
|
}, _a); |
163
|
|
|
}; |
164
|
|
|
/** |
165
|
|
|
* Map Builder: Parse The Val |
166
|
|
|
* @private |
167
|
|
|
* @description A builder function returning a key to ƒ.transform map. |
168
|
|
|
* The returned object is merged into a configuration object used for merging objects. |
169
|
|
|
* The `lookup-key` maps to a ƒ.merge. |
170
|
|
|
*/ |
171
|
|
|
var parseIfString = function (spath) { |
172
|
|
|
var _a; |
173
|
|
|
return (_a = {}, |
|
|
|
|
174
|
|
|
_a[spath] = function (a, maybeS) { |
175
|
|
|
var _a, _b; |
176
|
|
|
return typeof maybeS === 'string' |
177
|
|
|
? __assign(__assign({}, a), (_a = {}, _a[spath] = JSON.parse(maybeS), _a)) |
|
|
|
|
178
|
|
|
: __assign(__assign({}, a), (_b = {}, _b[spath] = maybeS, _b)); |
|
|
|
|
179
|
|
|
}, |
180
|
|
|
_a); |
181
|
|
|
}; |
182
|
|
|
var HASTpaths = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, noChange('selectedBy')), noChangeJustSwapPath('dataSourceprefix', 'sourcePrefix')), noChangeJustSwapPath('dataDestbasepath', 'destBasePath')), noChangeJustSwapPath('dataPrefix', 'prefix')), noChangeJustSwapPath('dataSuffix', 'suffix')), parseStringsAndSwapPath('dataHashlen', 'hashlen')), parseStringsAndSwapPath('dataClean', 'clean')), parseStringsAndSwapPath('dataWidths', 'widths')), parseStringsAndSwapPath('dataBreaks', 'breaks')), { dataAddclassnames: function (a, sa) { return (__assign(__assign({}, a), { addclassnames: sa.split(' ') })); } }), { dataTypes: function (a, s) { return (__assign(__assign({}, a), { types: s.split(',').reduce(function (p, c) { |
183
|
|
|
var _a; |
184
|
|
|
return (__assign(__assign({}, p), (_a = {}, _a[c] = {}, _a))); |
|
|
|
|
185
|
|
|
}, {}) })); } }); |
186
|
|
|
var NORMpaths = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, noChange('selectedBy')), noChange('sourcePrefix')), noChange('destBasePath')), noChange('prefix')), noChange('suffix')), noChange('hashlen')), noChange('clean')), noChange('addclassnames')), parseIfString('widths')), parseIfString('breaks')), parseIfString('types')); |
187
|
|
|
var mergeNode = function (fallback, ob) { return merge(HASTpaths, fallback, ob.properties); }; |
188
|
|
|
var mergeConfig = function (fallback, ob) { |
189
|
|
|
if (ob === void 0) { ob = {}; } |
|
|
|
|
190
|
|
|
return merge(NORMpaths, fallback, ob); |
191
|
|
|
}; |
192
|
|
|
/** |
193
|
|
|
* @exports rehype-all-the-thumbs-curate |
194
|
|
|
* @description the `rehype-all-the-thumbs-curate` plugin adds a transformer to the pipeline. |
195
|
|
|
* @param { InboundConfig } [config] - Instructions for a Resizer Algorithm to understand the types of thumbnails desired. |
196
|
|
|
*/ |
197
|
|
|
var attacher = function (config) { |
198
|
|
|
var select = !config || !config.select |
199
|
|
|
? 'picture[thumbnails="true"]>img' |
200
|
|
|
: typeof config.select === 'function' |
201
|
|
|
? config.select() |
202
|
|
|
: config.select; |
203
|
|
|
var defaults = { |
204
|
|
|
selectedBy: select, |
205
|
|
|
sourcePrefix: '/', |
206
|
|
|
destBasePath: '/', |
207
|
|
|
hashlen: 8, |
208
|
|
|
clean: true, |
209
|
|
|
types: { webp: {}, jpg: {} }, |
210
|
|
|
breaks: [640, 980, 1020], |
211
|
|
|
widths: [100, 250, 450, 600], |
212
|
|
|
addclassnames: ['all-thumbed'], |
213
|
|
|
prefix: 'optim/', |
214
|
|
|
suffix: '-{{width}}w-{{hash}}.{{ext}}' |
215
|
|
|
}; |
216
|
|
|
var cfg = mergeConfig(defaults, config); |
217
|
|
|
// console.log({select}) |
218
|
|
|
// console.log(0, {cfg}) |
219
|
|
|
// transformer |
220
|
|
|
return function (tree, vfile, next) { |
221
|
|
|
// console.log(1, JSON.stringify({ vfile1: vfile }, null, 2)) |
222
|
|
|
// console.log(2, JSON.stringify({ cfg }, null, 2)) |
223
|
|
|
var selected = hast_util_select_1.selectAll(select, tree); |
224
|
|
|
// console.log( JSON.stringify({ selected }, null, 2)) |
225
|
|
|
var srcsCompact = selected |
226
|
|
|
.map(function (node) { return ({ node: node, src: node.properties.src }); }) |
227
|
|
|
.map(function (_a) { |
228
|
|
|
var src = _a.src, node = _a.node; |
229
|
|
|
return (__assign(__assign({}, mergeConfig(cfg, mergeNode(cfg, node))), { src: src })); |
230
|
|
|
}); |
231
|
|
|
// console.log('plugin:curate--', {srcsCompact}) |
232
|
|
|
var srcs = srcsCompact.reduce(function (p, _s) { |
233
|
|
|
var s = _s; |
234
|
|
|
var partOfSet = { |
235
|
|
|
breaks: s.breaks, |
236
|
|
|
types: s.types, |
237
|
|
|
widths: s.widths, |
238
|
|
|
}; |
239
|
|
|
var accSimpleConfig = []; |
240
|
|
|
Object.entries(s.types).forEach(function (_a) { |
241
|
|
|
var format = _a[0], opts = _a[1]; |
242
|
|
|
s.widths.forEach(function (width) { |
243
|
|
|
var _a; |
244
|
|
|
var ext = path_1.default.extname(s.src).slice(1); // no dot prefix |
245
|
|
|
var fileName = path_1.default.basename(s.src, "." + ext); |
246
|
|
|
accSimpleConfig.push({ |
247
|
|
|
selectedBy: s.selectedBy, |
248
|
|
|
addclassnames: s.addclassnames, |
249
|
|
|
input: { |
250
|
|
|
ext: ext, |
251
|
|
|
fileName: fileName, |
252
|
|
|
pathPrefix: s.sourcePrefix |
253
|
|
|
}, |
254
|
|
|
output: { |
255
|
|
|
width: width, |
256
|
|
|
format: (_a = {}, _a[format] = opts, _a), |
|
|
|
|
257
|
|
|
hashlen: s.hashlen, |
258
|
|
|
hash: exports.trimmedHash(s.hashlen) |
259
|
|
|
}, |
260
|
|
|
getReadPath: function (i) { return !i |
261
|
|
|
? exports.localResolve(s.sourcePrefix, fileName + "." + ext) |
262
|
|
|
: i.render(path_1.default.resolve(s.sourcePrefix, s.src), i.data); }, |
263
|
|
|
getWritePath: function (i) { return !i |
264
|
|
|
? exports.localResolve(s.destBasePath, "" + s.prefix + fileName + s.suffix) |
265
|
|
|
: i.render(path_1.default.resolve(s.destBasePath, "" + s.prefix + fileName + s.suffix), i.data); }, |
266
|
|
|
partOfSet: partOfSet |
267
|
|
|
}); |
268
|
|
|
}); |
269
|
|
|
}); |
270
|
|
|
return __spreadArray(__spreadArray([], p), accSimpleConfig); |
271
|
|
|
}, []); |
272
|
|
|
// prettyPrint(0, 'plugin:curate--', {srcs}) |
273
|
|
|
var vfile_srcs = isArray(vfile.srcs) ? __spreadArray(__spreadArray([], vfile.srcs), srcs) : srcs; |
274
|
|
|
// prettyPrint(1, 'plugin:curate--', {vfile}) |
275
|
|
|
vfile.srcs = vfile_srcs; |
276
|
|
|
// return vfile |
277
|
|
|
next(null, tree, vfile); |
278
|
|
|
}; |
279
|
|
|
}; |
280
|
|
|
exports.attacher = attacher; |
281
|
|
|
exports.default = exports.attacher; |
282
|
|
|
}); |
283
|
|
|
// #endregion interfaces |
284
|
|
|
|
When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically: