123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- const parseCSS = require('css-rules');
- const cheerio = require('cheerio');
- const pseudoCheck = require('./pseudoCheck');
- const handleRule = require('./handleRule');
- const flatten = require('flat-util');
- const setStyleAttrs = require('./setStyleAttrs');
- const setWidthAttrs = require('./setWidthAttrs');
- const removeClassId = require('./removeClassId');
- const setTableAttrs = require('./setTableAttrs');
- const pick = require('pick-util');
-
- function replaceCodeBlock(html, re, block) {
- return html.replace(re, () => block);
- }
-
- module.exports = (html, css, options) => {
- const opts = options || {};
- let rules;
- let editedElements = [];
- const codeBlockLookup = [];
-
- const encodeCodeBlocks = _html => {
- let __html = _html;
- const blocks = opts.codeBlocks;
-
- Object.keys(blocks).forEach(key => {
- const re = new RegExp(`${blocks[key].start}([\\S\\s]*?)${blocks[key].end}`, 'g');
-
- __html = __html.replace(re, match => {
- codeBlockLookup.push(match);
- return `EXCS_CODE_BLOCK_${codeBlockLookup.length - 1}_`;
- });
- });
- return __html;
- };
-
- const decodeCodeBlocks = _html => {
- let index;
- let re;
- let __html = _html;
-
- for (index = 0; index < codeBlockLookup.length; index++) {
- re = new RegExp(`EXCS_CODE_BLOCK_${index}_(="")?`, 'gi');
- __html = replaceCodeBlock(__html, re, codeBlockLookup[index]);
- }
- return __html;
- };
-
- const encodeEntities = _html => encodeCodeBlocks(_html);
- const decodeEntities = _html => decodeCodeBlocks(_html);
- let $;
-
- $ = cheerio.load(encodeEntities(html), pick(opts, [
- 'xmlMode',
- 'decodeEntities',
- 'lowerCaseTags',
- 'lowerCaseAttributeNames',
- 'recognizeCDATA',
- 'recognizeSelfClosing'
- ]));
-
- try {
- rules = parseCSS(css);
- } catch (err) {
- throw new Error(err);
- }
-
- rules.forEach(rule => {
- let el;
- let ignoredPseudos;
-
- ignoredPseudos = pseudoCheck(rule);
-
- if (ignoredPseudos) {
- return false;
- }
-
- try {
- el = handleRule(rule, $);
-
- editedElements.push(el);
- } catch (err) {
- // skip invalid selector
- return false;
- }
- });
-
- // flatten array if nested
- editedElements = flatten(editedElements);
-
- editedElements.forEach(el => {
- setStyleAttrs(el, $);
-
- if (opts.applyWidthAttributes) {
- setWidthAttrs(el, $);
- }
-
- if (opts.removeHtmlSelectors) {
- removeClassId(el, $);
- }
- });
-
- if (opts.applyTableAttributes) {
- $('table').each((index, el) => {
- setTableAttrs(el, $);
- });
- }
-
- return decodeEntities($.html());
- };
|