diff options
Diffstat (limited to 'node_modules/@11ty/posthtml-urls/lib')
| -rw-r--r-- | node_modules/@11ty/posthtml-urls/lib/defaultOptions.js | 37 | ||||
| -rw-r--r-- | node_modules/@11ty/posthtml-urls/lib/index.js | 142 |
2 files changed, 179 insertions, 0 deletions
diff --git a/node_modules/@11ty/posthtml-urls/lib/defaultOptions.js b/node_modules/@11ty/posthtml-urls/lib/defaultOptions.js new file mode 100644 index 0000000..eee863c --- /dev/null +++ b/node_modules/@11ty/posthtml-urls/lib/defaultOptions.js @@ -0,0 +1,37 @@ +"use strict"; +const HTTP_EQUIV = "http-equiv"; +const REFRESH = "refresh"; + +const isHttpEquiv = ({ attrs }) => { + return attrs && (HTTP_EQUIV in attrs) && attrs[HTTP_EQUIV].toLowerCase() === REFRESH; +}; + +// Fork: pruned some deprecated tag/attribute combos here. +const DEFAULT_OPTIONS = { + filter: { + a: { href: true, ping: true }, + area: { href: true, ping: true }, + audio: { src: true }, + base: { href: true }, + blockquote: { cite: true }, + button: { formaction: true }, + del: { cite: true }, + embed: { src: true }, + form: { action: true }, + iframe: { src: true }, + img: { src: true, srcset: true }, + input: { formaction: true, src: true }, + ins: { cite: true }, + link: { href: true }, + meta: { content: isHttpEquiv }, + object: { data: true }, + q: { cite: true }, + script: { src: true }, + source: { src: true, srcset: true }, + track: { src: true }, + // video does not yet have srcset: https://scottjehl.com/posts/using-responsive-video/ + video: { poster: true, src: true }, + }, +}; + +module.exports = DEFAULT_OPTIONS; diff --git a/node_modules/@11ty/posthtml-urls/lib/index.js b/node_modules/@11ty/posthtml-urls/lib/index.js new file mode 100644 index 0000000..f9a49f0 --- /dev/null +++ b/node_modules/@11ty/posthtml-urls/lib/index.js @@ -0,0 +1,142 @@ +"use strict"; +const DEFAULT_OPTIONS = require("./defaultOptions"); +const evaluateValue = require("evaluate-value"); +const list2Array = require("list-to-array"); +const parseMetaRefresh = require("http-equiv-refresh"); +const parseSrcset = require("parse-srcset"); + +const CONTENT_ATTR = "content"; +const PING_ATTR = "ping"; +const SRCSET_ATTR = "srcset"; + +const DELIMITER = ","; +const EMPTY_STRING = ""; +const EMPTY_TAG_GROUP = Object.freeze({}); +const FUNCTION_TYPE = "function"; +const PRETTY_DELIMITER = ", "; + + + +const plugin = options => +{ + const {eachURL, filter} = Object.assign({}, DEFAULT_OPTIONS, options); + + if (typeof eachURL !== FUNCTION_TYPE) + { + throw new TypeError("eachURL option must be a function"); + } + + // const tagMatchers = Object.keys(filter).map(tagName => ({ tag: tagName })); + + // Called by PostHTML + return tree => + { + const promises = []; + + tree.walk(node => + // tree.match(tagMatchers, (node) => + { + if (node.attrs === undefined) { + return node; + } + + const tagGroup = filter[node.tag] || EMPTY_TAG_GROUP; + + Object.keys(node.attrs).forEach(attrName => + { + const isAcceptedTagAttr = attrName in tagGroup && evaluateValue(tagGroup[attrName], node, attrName); + + if (isAcceptedTagAttr) + { + switch (attrName) + { + case CONTENT_ATTR: + { + promises.push( transformMetaRefresh(node, attrName, eachURL) ); + break; + } + case PING_ATTR: + { + promises.push( transformCommaSeparated(node, attrName, eachURL) ); + break; + } + case SRCSET_ATTR: + { + promises.push( transformSrcset(node, attrName, eachURL) ); + break; + } + default: + { + promises.push( transformDefault(node, attrName, eachURL) ); + } + } + } + }); + + return node; + }); + + return Promise.all(promises).then(() => tree); + }; +}; + + + +const transformCommaSeparated = ({attrs, tag}, attrName, transformer) => +{ + const urls = list2Array( attrs[attrName], DELIMITER ); + + if (urls.length > 0) + { + const promises = urls.map(value => Promise.resolve( transformer(value, attrName, tag) )); + + return Promise.all(promises).then(newUrls => attrs[attrName] = newUrls.join(PRETTY_DELIMITER)); + } +}; + + + +const transformDefault = ({attrs, tag}, attrName, transformer) => +{ + return Promise.resolve( transformer( attrs[attrName], attrName, tag ) ) + .then(newUrl => attrs[attrName] = newUrl); +}; + + + +const transformMetaRefresh = ({attrs, tag}, attrName, transformer) => +{ + const {timeout, url} = parseMetaRefresh( attrs[attrName] ); + + if (timeout !== null) + { + return Promise.resolve( transformer(url || "", attrName, tag) ) + .then(newUrl => attrs[attrName] = `${timeout}; url=${newUrl}`); + } +}; + + + +const transformSrcset = ({attrs, tag}, attrName, transformer) => +{ + const values = parseSrcset( attrs[attrName] ); + + if (values.length > 0) + { + const promises = values.map(({d, h, url, w}) => Promise.resolve( transformer(url, attrName, tag) ) + .then(newUrl => + { + d = d !== undefined ? ` ${d}x` : EMPTY_STRING; + h = h !== undefined ? ` ${h}h` : EMPTY_STRING; + w = w !== undefined ? ` ${w}w` : EMPTY_STRING; + + return `${newUrl}${w}${h}${d}`; + })); + + return Promise.all(promises).then(newValues => attrs[attrName] = newValues.join(PRETTY_DELIMITER)); + } +}; + + + +module.exports = plugin; |
