UNPKG

rehype-all-the-thumbs-curate

Version:

Supporting rehype-all-the-thumbs by finding elements to be processed

283 lines (282 loc) 12.7 kB
/** * @title rehype-all-the-thumbs-curate * @author Eric Moore * @summary Select DOM nodes that have images availble for thumbnailing * @description Pluck out Images, and tag the file with instructions for * other thumbnailing plugins to use. * @see https://unifiedjs.com/explore/package/hast-util-select/#support * * # Inpput/Output * * ## Implied Input (Required): * * + HTML file with a DOM tree (can be decorate with instructions) * * ## Input Config (Optional) * * - css selctor string * - instructions for thumbnailing images * * ## Config Preference * * HTML > Options * * ## Output * * -an unchanged tree (aka: vfile.contents) */ var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __spreadArray = (this && this.__spreadArray) || function (to, from) { for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) to[j] = from[i]; return to; }; (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "path", "crypto", "hast-util-select"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.attacher = exports.pathJoin = void 0; var path_1 = require("path"); // no dot prefix var crypto_1 = require("crypto"); var hast_util_select_1 = require("hast-util-select"); var isArray = Array.isArray; /** * Resolve * @summary Merge path segments together * @description Take in path segments, * intelligibly merge them together to form one path. * @todo the up path */ var pathJoin = function () { var paths = []; for (var _i = 0; _i < arguments.length; _i++) { paths[_i] = arguments[_i]; } var pathsNoSlashes = paths.map(function (c, i, a) { c = c.startsWith('./') ? c.slice(2) : c; c = c.startsWith('/') ? c.slice(1) : c; c = c.endsWith('/') ? c.slice(0, -1) : c; return c; }); return pathsNoSlashes.reduce(function (p, c) { if (c === '' || c === ' ') { return p; } return c.startsWith('..') ? exports.pathJoin.apply(void 0, __spreadArray(__spreadArray([], p.slice(0, -1)), [c.slice(2)])).split('/') : __spreadArray(__spreadArray([], p), [c]); }, []).join('/'); }; exports.pathJoin = pathJoin; /** * Trimmed Hash * @private * @description Take in a Buffer and return a sting with length specified via N * @param n - length of the hash to return */ var trimmedHash = function (n) { return function (b) { return crypto_1.createHash('sha256').update(b).digest('hex').slice(0, n); }; }; /** * Merge * @private */ var merge = function (paths, fallback, obj) { return Object.entries(paths) .reduce(function (acc, _a) { var _b; var prop = _a[0], prepFn = _a[1]; return prop in obj ? prepFn(acc, obj[prop]) : prop in fallback ? __assign(__assign({}, acc), (_b = {}, _b[prop] = fallback[prop], _b)) : acc; }, {}); }; /** * Map Builder: Parse String And Swap Path * @private * @description A builder function returning a key to ƒ.transform map. * The 'look-up-key'º is mapped to a merge function. * The ƒ.merge returns a new merged object, * where the 'look-up-key'º is replaced with the writePath during merge, and the val is parsed */ var parseStringsAndSwapPath = function (readPath, writePath) { var _a; return (_a = {}, _a[readPath] = function (a, s) { var _a; return (__assign(__assign({}, a), (_a = {}, _a[writePath] = JSON.parse(s), _a))); }, _a); }; /** * Map Builder: Swap Path * @private * @description A builder function returning a key to ƒ.transform map. * The 'look-up-key'º (aka: readPath) is mapped to a merge function. * The ƒ.merge function is given an accumulating merge object, and a value from one of 2 target objects depending on if its found. * The ƒ.merge returns a merged object, and all it does it replce the look-up-keyº with the writePath * and the val stays unchanged * @example * const mergeMeIn = noChange('lookForThis', 'butEventuallyMakeItThis') * console.log(mergeMeIn) // { lookForThis: (all, val) => ({...all, butEventuallyMakeItThis: val}) } */ var noChangeJustSwapPath = function (readPath, writePath) { var _a; return (_a = {}, _a[readPath] = function (a, s) { var _a; return (__assign(__assign({}, a), (_a = {}, _a[writePath] = s, _a))); }, _a); }; /** * Map Builder: Indetity * @private * @description A builder function returning a key to ƒ.transform map. * The look-up-key maps to a ƒ.merge. * The ƒ.merge (inputs: (accum obj, val)) returns a merged object where the 'look-up-key'º maps to the unchanged val */ var noChange = function (spath) { var _a; return (_a = {}, _a[spath] = function (a, s) { var _a; return (__assign(__assign({}, a), (_a = {}, _a[spath] = s, _a))); }, _a); }; /** * Map Builder: Parse The Val * @private * @description A builder function returning a key to ƒ.transform map. * The returned object is merged into a configuration object used for merging objects. * The `lookup-key` maps to a ƒ.merge. */ var parseIfString = function (spath) { var _a; return (_a = {}, _a[spath] = function (a, maybeS) { var _a; // typeof maybeS === 'string' // ? { ...a, [spath]: JSON.parse(maybeS) } as ObjectOrStringDict // : return (__assign(__assign({}, a), (_a = {}, _a[spath] = maybeS, _a))); }, _a); }; var HASTpaths = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, noChange('selectedBy')), noChangeJustSwapPath('dataSourceprefix', 'sourcePrefix')), noChangeJustSwapPath('dataDestbasepath', 'destBasePath')), noChangeJustSwapPath('dataPathTmpl', 'pathTmpl')), parseStringsAndSwapPath('dataHashlen', 'hashlen')), parseStringsAndSwapPath('dataClean', 'clean')), parseStringsAndSwapPath('dataWidths', 'widths')), parseStringsAndSwapPath('dataWidthratio', 'widthratio')), 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) { var _a; return (__assign(__assign({}, p), (_a = {}, _a[c] = {}, _a))); }, {}) })); } }); var NORMpaths = __assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign(__assign({}, noChange('selectedBy')), noChange('sourcePrefix')), noChange('destBasePath')), noChange('filepathPrefix')), noChange('pathTmpl')), noChange('hashlen')), noChange('clean')), noChange('addclassnames')), parseIfString('widths')), parseIfString('widthatio')), parseIfString('breaks')), parseIfString('types')); /** * @private * @param fallback - ConfigMap * @param ob - object with a `properties` key with a ConfigMap type * @description Config sometimes has a data property prefixed in the Dict if its from the DOM */ var mergeNode = function (fallback, ob) { return merge(HASTpaths, fallback, ob.properties); }; /** * @private * @param fallback - a config map * @param ob - also a config map * @description merge the config objects via the paths, target and fallback */ var mergeConfig = function (fallback, ob) { if (ob === void 0) { ob = {}; } return merge(NORMpaths, fallback, ob); }; /** * @exports rehype-all-the-thumbs-curate * @description the `rehype-all-the-thumbs-curate` plugin adds a transformer to the pipeline. * @param { InboundConfig } [config] - Instructions for a Resizer Algorithm to understand the types of thumbnails desired. */ var attacher = function (config) { var select = !config || !config.select ? 'picture[thumbnails="true"]>img' : typeof config.select === 'function' ? config.select() : config.select; var defaults = { selectedBy: select, sourcePrefix: '/', destBasePath: '/', hashlen: 8, clean: true, types: { webp: {}, jpg: {} }, breaks: [640, 980, 1020], widths: [100, 250, 450, 600], addclassnames: ['all-thumbed'], widthratio: 1.7778, pathTmpl: '/optim/{{filename}}-{{width}}w-{{hash}}.{{ext}}' }; var cfg = mergeConfig(defaults, config); // transformer return function (tree, vfile, next) { var selected = hast_util_select_1.selectAll(select, tree); var srcsCompact = selected .map(function (node) { return ({ node: node, src: node.properties.src }); }) .map(function (_a) { var src = _a.src, node = _a.node; return (__assign({ // makes a compact config src: src }, mergeConfig(cfg, mergeNode(cfg, node) // node config goes 2nd to overrite if needed ))); }); // console.log('A.', 'srcsCompact', { srcsCompact }) var srcs = srcsCompact.reduce(function (p, _s) { var s = _s; var partOfSet = { breaks: s.breaks, types: s.types, widths: s.widths }; Object.entries(s.types).forEach(function (_a) { var format = _a[0], opts = _a[1]; s.widths.forEach(function (width) { var _a; var _b, _c; var ext = path_1.extname(s.src).slice(1); // no dot prefix ext = ext === '' ? 'Buffer' : ext; // if we can't match up src to a set of generatyed pics via postiion // then perhaps we could set an ID of the src s.data = __assign(__assign({}, s.data), { _id: s.src }); p.push({ selectedBy: s.selectedBy, addclassnames: s.addclassnames, input: { ext: ext, fileName: path_1.basename(s.src, "." + ext), filepathPrefix: path_1.dirname(s.src), rawFilePath: s.src // domPath: '' }, output: __assign({ width: width, format: (_a = {}, _a[format] = opts, _a), pathTmpl: (_c = (_b = s.pathTmpl) !== null && _b !== void 0 ? _b : cfg.pathTmpl) !== null && _c !== void 0 ? _c : defaults.pathTmpl, hash: trimmedHash(s.hashlen) }, ((s === null || s === void 0 ? void 0 : s.widthRatio) ? { widthRatio: s.widthRatio } : {})), partOfSet: partOfSet }); }); }); return p; }, []); // console.log('B.', 'srcs', { srcs }) var vfile_srcs = isArray(vfile.srcs) ? __spreadArray(__spreadArray([], vfile.srcs), srcs) : srcs; // console.log('C.', 'vfile_srcs', { vfile_srcs }) vfile.srcs = vfile_srcs; // return vfile next(null, tree, vfile); }; }; exports.attacher = attacher; exports.default = exports.attacher; }); // #endregion interfaces