Server IP : 92.205.26.207 / Your IP : 216.73.216.16 Web Server : Apache System : Linux 207.26.205.92.host.secureserver.net 4.18.0-553.60.1.el8_10.x86_64 #1 SMP Thu Jul 10 04:01:16 EDT 2025 x86_64 User : zikryat ( 1002) PHP Version : 8.3.23 Disable Function : exec,passthru,shell_exec,system MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON Directory (0755) : /home/zikryat/public_html/node_modules/mjml-parser-xml/lib/ |
[ Home ] | [ C0mmand ] | [ Upload File ] |
---|
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = MJMLParser; var _flow2 = _interopRequireDefault(require("lodash/fp/flow")); var _map2 = _interopRequireDefault(require("lodash/fp/map")); var _filter2 = _interopRequireDefault(require("lodash/fp/filter")); var _find2 = _interopRequireDefault(require("lodash/find")); var _findLastIndex2 = _interopRequireDefault(require("lodash/findLastIndex")); var _isObject2 = _interopRequireDefault(require("lodash/isObject")); var _htmlparser = require("htmlparser2"); var _path = _interopRequireDefault(require("path")); var _fs = _interopRequireDefault(require("fs")); var _cleanNode = _interopRequireDefault(require("./helpers/cleanNode")); var _convertBooleansOnAttrs = _interopRequireDefault(require("./helpers/convertBooleansOnAttrs")); var _setEmptyAttributes = _interopRequireDefault(require("./helpers/setEmptyAttributes")); const isNode = require('detect-node'); const indexesForNewLine = xml => { const regex = /\n/gi; const indexes = [0]; while (regex.exec(xml)) { indexes.push(regex.lastIndex); } return indexes; }; const isSelfClosing = (indexes, parser) => indexes.startIndex === parser.startIndex && indexes.endIndex === parser.endIndex; function MJMLParser(xml, options = {}, includedIn = []) { const { addEmptyAttributes = true, components = {}, convertBooleans = true, keepComments = true, filePath = '.', actualPath = '.', ignoreIncludes = false, preprocessors = [] } = options; const endingTags = (0, _flow2.default)((0, _filter2.default)(component => component.endingTag), (0, _map2.default)(component => component.getTagName()))({ ...components }); let cwd = process.cwd(); if (isNode && filePath) { try { const isDir = _fs.default.lstatSync(filePath).isDirectory(); cwd = isDir ? filePath : _path.default.dirname(filePath); } catch (e) { throw new Error('Specified filePath does not exist'); } } let mjml = null; let cur = null; let inInclude = !!includedIn.length; let inEndingTag = 0; const cssIncludes = []; const currentEndingTagIndexes = { startIndex: 0, endIndex: 0 }; const findTag = (tagName, tree) => (0, _find2.default)(tree.children, { tagName }); const lineIndexes = indexesForNewLine(xml); const handleCssHtmlInclude = (file, attrs, line) => { const partialPath = _path.default.resolve(cwd, file); let content; try { content = _fs.default.readFileSync(partialPath, 'utf8'); } catch (e) { const newNode = { line, file, absoluteFilePath: _path.default.resolve(cwd, actualPath), parent: cur, tagName: 'mj-raw', content: `<!-- mj-include fails to read file : ${file} at ${partialPath} -->`, children: [], errors: [{ type: 'include', params: { file, partialPath } }] }; cur.children.push(newNode); return; } if (attrs.type === 'html') { const newNode = { line, file, absoluteFilePath: _path.default.resolve(cwd, actualPath), parent: cur, tagName: 'mj-raw', content }; cur.children.push(newNode); return; } const attributes = attrs['css-inline'] === 'inline' ? { inline: 'inline' } : {}; const newNode = { line, file, absoluteFilePath: _path.default.resolve(cwd, actualPath), tagName: 'mj-style', content, children: [], attributes }; cssIncludes.push(newNode); }; const handleInclude = (file, line) => { const partialPath = _path.default.resolve(cwd, file); const curBeforeInclude = cur; if ((0, _find2.default)(cur.includedIn, { file: partialPath })) throw new Error(`Circular inclusion detected on file : ${partialPath}`); let content; try { content = _fs.default.readFileSync(partialPath, 'utf8'); } catch (e) { const newNode = { line, file, absoluteFilePath: _path.default.resolve(cwd, actualPath), parent: cur, tagName: 'mj-raw', content: `<!-- mj-include fails to read file : ${file} at ${partialPath} -->`, children: [], errors: [{ type: 'include', params: { file, partialPath } }] }; cur.children.push(newNode); return; } content = content.indexOf('<mjml>') === -1 ? `<mjml><mj-body>${content}</mj-body></mjml>` : content; const partialMjml = MJMLParser(content, { ...options, filePath: partialPath, actualPath: partialPath }, [...cur.includedIn, { file: cur.absoluteFilePath, line }]); const bindToTree = (children, tree = cur) => children.map(c => ({ ...c, parent: tree })); if (partialMjml.tagName !== 'mjml') { return; } const body = findTag('mj-body', partialMjml); const head = findTag('mj-head', partialMjml); if (body) { const boundChildren = bindToTree(body.children); cur.children = [...cur.children, ...boundChildren]; } if (head) { let curHead = findTag('mj-head', mjml); if (!curHead) { mjml.children.push({ file: actualPath, absoluteFilePath: _path.default.resolve(cwd, actualPath), parent: mjml, tagName: 'mj-head', children: [], includedIn: [] }); curHead = findTag('mj-head', mjml); } const boundChildren = bindToTree(head.children, curHead); curHead.children = [...curHead.children, ...boundChildren]; } // must restore cur to the cur before include started cur = curBeforeInclude; }; const parser = new _htmlparser.Parser({ onopentag: (name, attrs) => { const isAnEndingTag = endingTags.indexOf(name) !== -1; if (inEndingTag > 0) { if (isAnEndingTag) inEndingTag += 1; return; } if (isAnEndingTag) { inEndingTag += 1; if (inEndingTag === 1) { // we're entering endingTag currentEndingTagIndexes.startIndex = parser.startIndex; currentEndingTagIndexes.endIndex = parser.endIndex; } } const line = (0, _findLastIndex2.default)(lineIndexes, i => i <= parser.startIndex) + 1; if (name === 'mj-include') { if (ignoreIncludes || !isNode) return; if (attrs.type === 'css' || attrs.type === 'html') { handleCssHtmlInclude(decodeURIComponent(attrs.path), attrs, line); return; } inInclude = true; handleInclude(decodeURIComponent(attrs.path), line); return; } if (convertBooleans) { // "true" and "false" will be converted to bools attrs = (0, _convertBooleansOnAttrs.default)(attrs); } const newNode = { file: actualPath, absoluteFilePath: isNode ? _path.default.resolve(cwd, actualPath) : actualPath, line, includedIn, parent: cur, tagName: name, attributes: attrs, children: [] }; if (cur) { cur.children.push(newNode); } else { mjml = newNode; } cur = newNode; }, onclosetag: name => { if (endingTags.indexOf(name) !== -1) { inEndingTag -= 1; if (!inEndingTag) { // we're getting out of endingTag // if self-closing tag we don't get the content if (!isSelfClosing(currentEndingTagIndexes, parser)) { const partialVal = xml.substring(currentEndingTagIndexes.endIndex + 1, parser.endIndex).trim(); const val = partialVal.substring(0, partialVal.lastIndexOf(`</${name}`)); if (val) cur.content = val.trim(); } } } if (inEndingTag > 0) return; if (inInclude) { inInclude = false; } // for includes, setting cur is handled in handleInclude because when there is // only mj-head in include it doesn't create any elements, so setting back to parent is wrong if (name !== 'mj-include') cur = cur && cur.parent || null; }, ontext: text => { if (inEndingTag > 0) return; if (text && text.trim() && cur) { cur.content = `${cur && cur.content || ''}${text.trim()}`.trim(); } }, oncomment: data => { if (inEndingTag > 0) return; if (cur && keepComments) { cur.children.push({ line: (0, _findLastIndex2.default)(lineIndexes, i => i <= parser.startIndex) + 1, tagName: 'mj-raw', content: `<!-- ${data.trim()} -->`, includedIn }); } } }, { recognizeCDATA: true, decodeEntities: false, recognizeSelfClosing: true, lowerCaseAttributeNames: false }); // Apply preprocessors to raw xml xml = (0, _flow2.default)(preprocessors)(xml); parser.write(xml); parser.end(); if (!(0, _isObject2.default)(mjml)) { throw new Error('Parsing failed. Check your mjml.'); } (0, _cleanNode.default)(mjml); // Assign "attributes" property if not set if (addEmptyAttributes) { (0, _setEmptyAttributes.default)(mjml); } if (cssIncludes.length) { const head = (0, _find2.default)(mjml.children, { tagName: 'mj-head' }); if (head) { if (head.children) { head.children = [...head.children, ...cssIncludes]; } else { head.children = cssIncludes; } } else { mjml.children.push({ file: filePath, line: 0, tagName: 'mj-head', children: cssIncludes }); } } return mjml; } module.exports = exports.default;