mirror of
https://github.com/KevinMidboe/inline-html.git
synced 2025-10-29 17:40:29 +00:00
Refactor. Update dependencies. Update tests. Make img plugin async.
This commit is contained in:
133
lib/css-url.js
Normal file
133
lib/css-url.js
Normal file
@@ -0,0 +1,133 @@
|
||||
const datauri = require('datauri');
|
||||
const isLocalPath = require('is-local-path');
|
||||
const isTemplateExpression = require('./is-template-expression');
|
||||
const path = require('path');
|
||||
const postcss = require('postcss');
|
||||
const postcssUrl = require('postcss-url');
|
||||
const R = require('ramda');
|
||||
const string = require('string');
|
||||
const url = require('url');
|
||||
|
||||
const collapseWhitespace = str => string(str).collapseWhitespace().toString();
|
||||
const forEachIndexed = R.addIndex(R.forEach);
|
||||
const format = (path) => url.format(path);
|
||||
const parse = (path) => url.parse(path);
|
||||
const resolve = path.resolve;
|
||||
|
||||
const augmentError = (error, filename, files) => {
|
||||
if (!error.filename) error.filename = filename;
|
||||
error.files = R.uniq(R.concat(files, error.files || []));
|
||||
return error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns url path without query string and hash if present.
|
||||
*
|
||||
* @param path
|
||||
*
|
||||
* @returns path
|
||||
*/
|
||||
const cleanUrl = R.pipe(
|
||||
parse,
|
||||
R.pick(['protocol', 'host', 'pathname']),
|
||||
format,
|
||||
decodeURI
|
||||
);
|
||||
/**
|
||||
* Convert local url data type paths to datauris.
|
||||
*
|
||||
* @param css
|
||||
* @param filename
|
||||
* @returns {{css: (css|any), files: Array}}
|
||||
*/
|
||||
const inlineUrl = R.curry((filename, css) => {
|
||||
const basePath = path.dirname(filename);
|
||||
var files = [];
|
||||
const inline = url => {
|
||||
try {
|
||||
if (isLocalPath(url) && !isTemplateExpression(url)) {
|
||||
url = cleanUrl(url);
|
||||
url = resolve(basePath, url);
|
||||
files = R.append(url, files);
|
||||
url = datauri(url);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
catch (error) { throw augmentError(error, filename, files); }
|
||||
};
|
||||
css = postcss()
|
||||
.use(postcssUrl({ url: inline }))
|
||||
.process(css)
|
||||
.css;
|
||||
files = R.uniq(files);
|
||||
return { css, files };
|
||||
});
|
||||
|
||||
const inlineStyles = ($, filename) => {
|
||||
var files = [];
|
||||
try {
|
||||
const styles = $('style')
|
||||
.toArray();
|
||||
|
||||
const contents = R.map(style => {
|
||||
const css = $(style).html();
|
||||
const result = inlineUrl(filename, css);
|
||||
files = R.concat(files, result.files);
|
||||
return result.css;
|
||||
}, styles);
|
||||
|
||||
forEachIndexed((style, index) => $(style).html(contents[index]), styles);
|
||||
|
||||
return { $, files };
|
||||
}
|
||||
catch (error) { throw augmentError(error, filename, files); }
|
||||
};
|
||||
|
||||
const prefix = 'selector {';
|
||||
const suffix = '}';
|
||||
const matchStyle = new RegExp(`^${prefix}\\s*(.*)\\s*${suffix}$`);
|
||||
const wrap = style => `${prefix}${style}${suffix}`;
|
||||
const unwrap = rule => rule.replace(matchStyle, '$1');
|
||||
|
||||
const inlineStyleAttributes = ($, filename) => {
|
||||
var files = [];
|
||||
try {
|
||||
const elements = $('*')
|
||||
.filter('[style]')
|
||||
.toArray();
|
||||
|
||||
const styles = R.map(element => {
|
||||
var style = $(element).attr('style');
|
||||
const rule = wrap(style);
|
||||
const result = inlineUrl(filename, rule);
|
||||
files = R.concat(files, result.files);
|
||||
style = R.pipe( collapseWhitespace, unwrap )(result.css);
|
||||
return style;
|
||||
}, elements);
|
||||
|
||||
forEachIndexed((element, index) => $(element).attr('style', styles[index]), elements);
|
||||
|
||||
return { $, files };
|
||||
}
|
||||
catch (error) { throw augmentError(error, filename, files); }
|
||||
};
|
||||
|
||||
const inlineCssUrl = function ($, filename) {
|
||||
var files = [];
|
||||
try {
|
||||
var result;
|
||||
result = inlineStyles($, filename);
|
||||
$ = result.$;
|
||||
files = R.concat(files, result.files);
|
||||
|
||||
result = inlineStyleAttributes($, filename);
|
||||
$ = result.$;
|
||||
files = R.concat(files, result.files);
|
||||
|
||||
files = R.uniq(files);
|
||||
return { $, files };
|
||||
}
|
||||
catch (error) { throw augmentError(error, filename, files); }
|
||||
};
|
||||
|
||||
module.exports = inlineCssUrl;
|
||||
Reference in New Issue
Block a user