UNPKG

@markedjs/html-differ

Version:
207 lines (176 loc) 4.75 kB
/** * Gets the attribute's indexes in the array of the attributes * @param {Array} attrs * @param {String} attr * @returns {Array} */ function _getIndexesInArray(attrs, attr) { const res = []; for (let i = 0; i < attrs.length; i++) { if (attrs[i].name === attr) res.push(i); } return res; } /** * Sorts the attributes in alphabetical order * @param {Array} attrs * @returns {Array} */ export function sortAttrs(attrs) { return attrs.sort(function(a, b) { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); } /** * Sorts values of the attribute 'class' * @param {Array} attrs * @returns {Array} */ export function sortCssClasses(attrs) { /** * Sorts the given CSS class attribute * @param {String} cssClasses * @returns {String} */ function _sortCssClassesValues(cssClasses) { const classList = [...new Set((cssClasses || '').split(' ').filter(i => i))]; classList.sort(); return classList.join(' '); } const classIndexes = _getIndexesInArray(attrs, 'class'); classIndexes.forEach(function(index) { attrs[index].value = _sortCssClassesValues(attrs[index].value); }); return attrs; } /** * Sorts values of attributes which have JSON format * @param {Array} attrs * @param {Array} compareAttributesAsJSON * return {Array} */ export function sortAttrsValues(attrs, compareAttributesAsJSON) { /** * Recursively sorts the given object by key * @param {Object} obj * @returns {Object} */ function _sortObj(obj) { if (obj === null || typeof obj !== 'object') { return JSON.stringify(obj); } if (Array.isArray(obj)) { return '[' + obj.map(_sortObj).join(',') + ']'; } const keys = Object.keys(obj); keys.sort(); return '{' + keys .map(function(key) { return JSON.stringify(key) + ':' + _sortObj(obj[key]); }) .join(',') + '}'; } /** * Parses the given in HTML attribute JSON * @param {String} val * @param {Boolean} [isClick] * @returns {Object} */ function _parseAttr(val, isClick) { try { if (isClick) { // eslint-disable-next-line no-new-func const fn = Function(val); return fn ? fn() : {}; } return JSON.parse(val); } catch { return undefined; } } compareAttributesAsJSON.forEach(function(attr) { if (typeof attr === 'string') { const name = attr; attr = {}; attr.name = name; attr.isFunction = false; } let attrValue; const isFunction = (attr.isFunction); const attrIndexes = _getIndexesInArray(attrs, attr.name); attrIndexes.forEach(function(index) { attrValue = _parseAttr(attrs[index].value, isFunction); attrValue = _sortObj(attrValue); attrs[index].value = (isFunction && attrValue ? 'return ' : '') + attrValue; }); }); return attrs; } /** * Replaces the values of attributes on an empty string * @param {Array} attrs * @param {Array} ignoreAttributes * @returns {Array} */ export function removeAttrsValues(attrs, ignoreAttributes) { ignoreAttributes.forEach(function(attr) { const attrIndexes = _getIndexesInArray(attrs, attr); attrIndexes.forEach(function(index) { attrs[index].value = ''; }); }); return attrs; } /** * Removes whitespaces from the text * @param {String} text * @returns {String} */ export function removeWhitespaces(text) { return text .replace(/[\n\r\t\v\f]+/g, ' ') .replace(/\s+/g, ' ') .trim(); } /** * Processes a conditional comment * @param {String} comment * @param {Function} modify * @param {Object} options * @returns {String|undefined} */ export async function getConditionalComment(comment, modify, options) { const START_IF = '^\\s*\\[if .*\\]>'; const END_IF = '<!\\[endif\\]\\s*$'; const matchedStartIF = comment.match(new RegExp(START_IF)); const matchedEndIF = comment.match(new RegExp(END_IF)); if (comment.match(new RegExp(START_IF + '\\s*$')) || comment.match(new RegExp(START_IF + '<!\\s*$')) || comment.match(new RegExp('^' + END_IF))) { return comment.trim(); } if (matchedStartIF && matchedEndIF) { const start = matchedStartIF[0]; const end = matchedEndIF[0]; const modified = await modify(comment.substring(start.length, matchedEndIF.index), options); return (start + modified + end).trim(); } } export function htmlEntities(str) { const map = { '&': '&amp;', "'": '&#39;', '"': '&quot;', '<': '&lt;', '>': '&gt;', }; return str.replace(/[&"'<>]/g, function(c) { return map[c]; }); }