143 lines
3.1 KiB
JavaScript
143 lines
3.1 KiB
JavaScript
|
"use strict";
|
||
|
const defaultOptions = require("./defaultOptions");
|
||
|
const each = require("promise-each");
|
||
|
const list2Array = require("list-to-array");
|
||
|
const parseMetaRefresh = require("http-equiv-refresh");
|
||
|
const parseSrcset = require("parse-srcset");
|
||
|
|
||
|
|
||
|
|
||
|
function plugin(options)
|
||
|
{
|
||
|
options = Object.assign({}, defaultOptions, options);
|
||
|
|
||
|
if (typeof options.eachURL !== "function")
|
||
|
{
|
||
|
throw new Error("eachURL must be a function");
|
||
|
}
|
||
|
|
||
|
return function PostHTML_URLs(tree)
|
||
|
{
|
||
|
const promises = [];
|
||
|
|
||
|
tree.walk( function(node)
|
||
|
{
|
||
|
if (node.attrs == null) return node;
|
||
|
|
||
|
const tagGroup = options.filter[node.tag];
|
||
|
|
||
|
if (tagGroup === undefined) return node;
|
||
|
|
||
|
Object.keys(node.attrs).forEach( function(attrName)
|
||
|
{
|
||
|
if (tagGroup[attrName] === undefined) return;
|
||
|
|
||
|
if (typeof tagGroup[attrName] === "function")
|
||
|
{
|
||
|
if (tagGroup[attrName](node, attrName) === false) return;
|
||
|
}
|
||
|
|
||
|
switch (attrName)
|
||
|
{
|
||
|
case "content":
|
||
|
{
|
||
|
promises.push( transformMetaRefresh(node, attrName, options.eachURL) );
|
||
|
break;
|
||
|
}
|
||
|
case "ping":
|
||
|
{
|
||
|
promises.push( transformCommaSeparated(node, attrName, options.eachURL) );
|
||
|
break;
|
||
|
}
|
||
|
case "srcset":
|
||
|
{
|
||
|
promises.push( transformSrcset(node, attrName, options.eachURL) );
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
{
|
||
|
promises.push( transformDefault(node, attrName, options.eachURL) );
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
return node;
|
||
|
});
|
||
|
|
||
|
return Promise.all(promises).then(() => tree);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
function transformCommaSeparated(node, attrName, transformer)
|
||
|
{
|
||
|
const values = list2Array( node.attrs[attrName], "," );
|
||
|
|
||
|
if (values.length === 0) return;
|
||
|
|
||
|
const promises = [];
|
||
|
|
||
|
values.forEach( function(value)
|
||
|
{
|
||
|
const promise = Promise.resolve( transformer(value, attrName, node.tag) );
|
||
|
promises.push(promise);
|
||
|
});
|
||
|
|
||
|
return Promise.all(promises)
|
||
|
.then(newValues => node.attrs[attrName] = newValues.join(", "));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
function transformDefault(node, attrName, transformer)
|
||
|
{
|
||
|
return Promise.resolve( transformer( node.attrs[attrName], attrName, node.tag ) )
|
||
|
.then(newValue => node.attrs[attrName] = newValue);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
function transformMetaRefresh(node, attrName, transformer)
|
||
|
{
|
||
|
const value = parseMetaRefresh( node.attrs[attrName] );
|
||
|
|
||
|
if (value.length === 0) return;
|
||
|
|
||
|
return Promise.resolve( transformer(value.url, attrName, node.tag) )
|
||
|
.then(newValue => node.attrs[attrName] = `${value.timeout}; url=${newValue}`);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
function transformSrcset(node, attrName, transformer)
|
||
|
{
|
||
|
const values = parseSrcset( node.attrs[attrName] );
|
||
|
|
||
|
if (values.length === 0) return;
|
||
|
|
||
|
const promises = [];
|
||
|
|
||
|
values.forEach( function(value)
|
||
|
{
|
||
|
const promise = Promise.resolve( transformer(value.url, attrName, node.tag) )
|
||
|
.then( function(newValue)
|
||
|
{
|
||
|
const d = value.d !== undefined ? ` ${value.d}x` : "";
|
||
|
const h = value.h !== undefined ? ` ${value.h}h` : "";
|
||
|
const w = value.w !== undefined ? ` ${value.w}w` : "";
|
||
|
|
||
|
return `${newValue}${w}${h}${d}`;
|
||
|
});
|
||
|
|
||
|
promises.push(promise);
|
||
|
});
|
||
|
|
||
|
return Promise.all(promises)
|
||
|
.then(newValues => node.attrs[attrName] = newValues.join(", "));
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
module.exports = plugin;
|