UNPKG

yoastseo

Version:

Yoast client-side content analysis

155 lines (149 loc) 5.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IGNORED_CLASSES = void 0; exports.default = _default; var _htmlparser = _interopRequireDefault(require("htmlparser2")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } /** * This file provides HTML parsing for assessments that do NOT use the HTML Parser. * We use a (simpler) external library, which can be found here: https://github.com/fb55/htmlparser2. */ /** * The array containing the text parts without ignored HTML blocks. * @type {string[]} */ let textArray = []; /** * Whether we are currently in an ignored HTML block. * @type {boolean} */ let inIgnorableBlock = false; /** * The stack of currently ignored tags, when we are in an ignorable HTML block. * @type {string[]} */ let ignoreStack = []; /** * The HTML tags that should be ignored. * @type {string[]} */ const IGNORED_TAGS = ["script", "style", "code", "pre", "blockquote", "textarea"]; /** * The classes of HTML elements that should be ignored. * @type {string[]} */ const IGNORED_CLASSES = exports.IGNORED_CLASSES = ["yoast-ai-summarize", "yoast-table-of-contents", "yoast-reading-time__wrapper", "elementor-button-wrapper", "elementor-divider", "elementor-spacer", "elementor-custom-embed", "elementor-icon-wrapper", "elementor-icon-box-wrapper", "elementor-counter", "elementor-progress-wrapper", "elementor-alert", "elementor-soundcloud-wrapper", "elementor-shortcode", "elementor-menu-anchor", "elementor-title"]; /** * Parses the text. */ const parser = new _htmlparser.default.Parser({ /** * Handles the opening tag. * If we are in an ignorable block, disregard the tag. * If the opening tag is included in the `IGNORED_TAGS` array, or the class is in the `IGNORED_CLASSES` array, * set `inIgnorableBlock` to true and add the tag to the `ignoreStack`. * Otherwise, push the tag to the `textArray`. * * @param {string} tagName The tag name. * @param {object} nodeValue The attribute with the keys and values of the tag. * * @returns {void} */ onopentag: function (tagName, nodeValue) { if (inIgnorableBlock) { ignoreStack.push(tagName); return; } const classNames = nodeValue.class ? nodeValue.class.split(" ") : []; if (IGNORED_TAGS.includes(tagName) || classNames.some(className => IGNORED_CLASSES.includes(className))) { inIgnorableBlock = true; ignoreStack.push(tagName); return; } const nodeValueType = Object.keys(nodeValue); let nodeValueString = ""; nodeValueType.forEach(function (node) { // Build the tag again. nodeValueString += " " + node + "='" + nodeValue[node] + "'"; }); textArray.push("<" + tagName + nodeValueString + ">"); }, /** * Handles the text that doesn't contain opening or closing tags. * If `inIgnorableBlock` is false, the text gets pushed to the `textArray` array. * * @param {string} text The text that doesn't contain opening or closing tags. * * @returns {void} */ ontext: function (text) { if (!inIgnorableBlock) { textArray.push(text); } }, /** * Handles the closing tag. * If the closing tag is the last tag on the `ignoreStack`, jump out of the ignorable block. * Otherwise, if we are not currently in an ignorable block, push the tag to the `textArray`. * * @param {string} tagName The tag name. * * @returns {void} */ onclosetag: function (tagName) { if (ignoreStack.length === 1 && ignoreStack[0] === tagName) { inIgnorableBlock = false; ignoreStack = []; return; } if (inIgnorableBlock) { ignoreStack.pop(); return; } textArray.push("</" + tagName + ">"); } }, { decodeEntities: true }); /** * Calls htmlparser2 and returns the text without HTML blocks that we do not want to consider for the content analysis. * Note that this function will soon be deprecated in favour of our own HTML parser. * * @param {string} text The text to parse. * @param {string[]} [ignoredClassesException] An optional array of class names to ignore, in addition to the default ignored classes. * @returns {string} The text without the HTML blocks. */ function _default(text, ignoredClassesException) { // Return the globals to their starting values. textArray = []; inIgnorableBlock = false; ignoreStack = []; const ignoredClasses = ignoredClassesException || IGNORED_CLASSES; // Extend the parser’s open-tag logic to recognize and skip elements with ignoredClasses parser._cbs.onopentag = function (tagName, nodeValue) { if (inIgnorableBlock) { ignoreStack.push(tagName); return; } const classNames = nodeValue.class ? nodeValue.class.split(" ") : []; if (IGNORED_TAGS.includes(tagName) || classNames.some(className => ignoredClasses.includes(className))) { inIgnorableBlock = true; ignoreStack.push(tagName); return; } const nodeValueType = Object.keys(nodeValue); let nodeValueString = ""; nodeValueType.forEach(function (node) { nodeValueString += " " + node + "='" + nodeValue[node] + "'"; }); textArray.push("<" + tagName + nodeValueString + ">"); }; parser.write(text); // Make sure to complete the process of parsing and reset the parser to avoid side effects. parser.parseComplete(); return textArray.join(""); } // Expose ignoredClasses in addition to the default removeHtmlBlocks. //# sourceMappingURL=htmlParser.js.map