您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
monkeygpt
- // ==UserScript==
- // @name monkey-gpt
- // @namespace monkeygpt
- // @version 0.0.3
- // @author monkey
- // @icon https://jisuai.cn/logo.png
- // @match *://*/*
- // @require https://cdn.jsdelivr.net/npm/vue@3.4.38/dist/vue.global.prod.js
- // @grant GM_addStyle
- // @description monkeygpt
- // ==/UserScript==
- (e => {
- if (typeof GM_addStyle == "function") {
- GM_addStyle(e);
- return
- }
- const o = document.createElement("style");
- o.textContent = e, document.head.append(o)
- })(" :root{font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}#monkeygpt{position:fixed;top:0;right:0;z-index:10000;font-size:14px;line-height:2em}#monkeygpt xmp,#monkeygpt pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word}#monkeygpt .loader{border:8px solid #f3f3f3;border-top:8px solid #3498db;border-radius:50%;width:60px;height:60px;animation:spin 1s linear infinite}#monkeygpt pre{background-color:#333;border-radius:5px;padding:.8em;font-family:Consolas,Courier New,monospace;font-size:14px;color:#c4d4d8;border:1px solid #e0e0e0}.monkeygpt-card{position:absolute;top:30vh;right:0;border-radius:.5em}.monkeygpt-card button{border:none;background:#3b5998;text-decoration:none;font-weight:700;color:#fff;cursor:pointer;width:auto;overflow:visible;padding:6px;font-size:14px;line-height:1.5em;font-family:Lucida Grande,Tahoma,Arial,Verdana,sans-serif;border-radius:.1em}.monkeygpt-warp{background-color:#fffc;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);width:30vw;height:100vh;margin:0 auto;box-shadow:-4px 4px 6px #0000001a;overflow:auto}.monkeygpt-warp .monkeygpt-card{top:0;padding:1.5em;width:100%;box-sizing:border-box}.monkeygpt-warp .monkeygpt-card button{padding:4px 15px;margin-right:8px;border-radius:2px;box-shadow:0 2px #0000000b}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@media screen and (max-width: 1560px){.monkeygpt-warp{width:50vw}.monkeygpt-warp .monkeygpt-card{padding:2em}}@media screen and (max-width: 720px){.monkeygpt-warp{width:100vw}}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}}.monkeygpt-body[data-v-1db30056]{margin-top:1em}.title[data-v-1db30056]{display:flex;align-content:center;margin-bottom:1em}.title img[data-v-1db30056]{margin-left:1em}.close[data-v-1db30056]{width:1.5em;cursor:pointer}.nav[data-v-1db30056]{display:flex;justify-content:space-between}.loading[data-v-1db30056]{width:3em} ");
- (function (vue) {
- 'use strict';
- var __defProp = Object.defineProperty;
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
- enumerable: true,
- configurable: true,
- writable: true,
- value
- }) : obj[key] = value;
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
- var Readability$1 = {
- exports: {}
- };
- (function (module) {
- function Readability2(doc, options) {
- if (options && options.documentElement) {
- doc = options;
- options = arguments[2];
- } else if (!doc || !doc.documentElement) {
- throw new Error("First argument to Readability constructor should be a document object.");
- }
- options = options || {};
- this._doc = doc;
- this._docJSDOMParser = this._doc.firstChild.__JSDOMParser__;
- this._articleTitle = null;
- this._articleByline = null;
- this._articleDir = null;
- this._articleSiteName = null;
- this._attempts = [];
- this._debug = !!options.debug;
- this._maxElemsToParse = options.maxElemsToParse || this.DEFAULT_MAX_ELEMS_TO_PARSE;
- this._nbTopCandidates = options.nbTopCandidates || this.DEFAULT_N_TOP_CANDIDATES;
- this._charThreshold = options.charThreshold || this.DEFAULT_CHAR_THRESHOLD;
- this._classesToPreserve = this.CLASSES_TO_PRESERVE.concat(options.classesToPreserve || []);
- this._keepClasses = !!options.keepClasses;
- this._serializer = options.serializer || function (el) {
- return el.innerHTML;
- };
- this._disableJSONLD = !!options.disableJSONLD;
- this._allowedVideoRegex = options.allowedVideoRegex || this.REGEXPS.videos;
- this._flags = this.FLAG_STRIP_UNLIKELYS | this.FLAG_WEIGHT_CLASSES | this.FLAG_CLEAN_CONDITIONALLY;
- if (this._debug) {
- let logNode = function (node) {
- if (node.nodeType == node.TEXT_NODE) {
- return `${node.nodeName} ("${node.textContent}")`;
- }
- let attrPairs = Array.from(node.attributes || [], function (attr) {
- return `${attr.name}="${attr.value}"`;
- }).join(" ");
- return `<${node.localName} ${attrPairs}>`;
- };
- this.log = function () {
- if (typeof console !== "undefined") {
- let args = Array.from(arguments, (arg) => {
- if (arg && arg.nodeType == this.ELEMENT_NODE) {
- return logNode(arg);
- }
- return arg;
- });
- args.unshift("Reader: (Readability)");
- console.log.apply(console, args);
- } else if (typeof dump !== "undefined") {
- var msg = Array.prototype.map.call(arguments, function (x) {
- return x && x.nodeName ? logNode(x) : x;
- }).join(" ");
- dump("Reader: (Readability) " + msg + "\n");
- }
- };
- } else {
- this.log = function () {};
- }
- }
- Readability2.prototype = {
- FLAG_STRIP_UNLIKELYS: 1,
- FLAG_WEIGHT_CLASSES: 2,
- FLAG_CLEAN_CONDITIONALLY: 4,
- // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
- ELEMENT_NODE: 1,
- TEXT_NODE: 3,
- // Max number of nodes supported by this parser. Default: 0 (no limit)
- DEFAULT_MAX_ELEMS_TO_PARSE: 0,
- // The number of top candidates to consider when analysing how
- // tight the competition is among candidates.
- DEFAULT_N_TOP_CANDIDATES: 5,
- // Element tags to score by default.
- DEFAULT_TAGS_TO_SCORE: "section,h2,h3,h4,h5,h6,p,td,pre".toUpperCase().split(","),
- // The default number of chars an article must have in order to return a result
- DEFAULT_CHAR_THRESHOLD: 500,
- // All of the regular expressions in use within readability.
- // Defined up here so we don't instantiate them repeatedly in loops.
- REGEXPS: {
- // NOTE: These two regular expressions are duplicated in
- // Readability-readerable.js. Please keep both copies in sync.
- unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
- okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i,
- positive: /article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,
- negative: /-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,
- extraneous: /print|archive|comment|discuss|e[\-]?mail|share|reply|all|login|sign|single|utility/i,
- byline: /byline|author|dateline|writtenby|p-author/i,
- replaceFonts: /<(\/?)font[^>]*>/gi,
- normalize: /\s{2,}/g,
- videos: /\/\/(www\.)?((dailymotion|youtube|youtube-nocookie|player\.vimeo|v\.qq)\.com|(archive|upload\.wikimedia)\.org|player\.twitch\.tv)/i,
- shareElements: /(\b|_)(share|sharedaddy)(\b|_)/i,
- nextLink: /(next|weiter|continue|>([^\|]|$)|»([^\|]|$))/i,
- prevLink: /(prev|earl|old|new|<|«)/i,
- tokenize: /\W+/g,
- whitespace: /^\s*$/,
- hasContent: /\S$/,
- hashUrl: /^#.+/,
- srcsetUrl: /(\S+)(\s+[\d.]+[xw])?(\s*(?:,|$))/g,
- b64DataUrl: /^data:\s*([^\s;,]+)\s*;\s*base64\s*,/i,
- // Commas as used in Latin, Sindhi, Chinese and various other scripts.
- // see: https://en.wikipedia.org/wiki/Comma#Comma_variants
- commas: /\u002C|\u060C|\uFE50|\uFE10|\uFE11|\u2E41|\u2E34|\u2E32|\uFF0C/g,
- // See: https://schema.org/Article
- jsonLdArticleTypes: /^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/
- },
- UNLIKELY_ROLES: ["menu", "menubar", "complementary", "navigation", "alert", "alertdialog", "dialog"],
- DIV_TO_P_ELEMS: /* @__PURE__ */ new Set(["BLOCKQUOTE", "DL", "DIV", "IMG", "OL", "P", "PRE", "TABLE", "UL"]),
- ALTER_TO_DIV_EXCEPTIONS: ["DIV", "ARTICLE", "SECTION", "P"],
- PRESENTATIONAL_ATTRIBUTES: ["align", "background", "bgcolor", "border", "cellpadding", "cellspacing", "frame", "hspace", "rules", "style", "valign", "vspace"],
- DEPRECATED_SIZE_ATTRIBUTE_ELEMS: ["TABLE", "TH", "TD", "HR", "PRE"],
- // The commented out elements qualify as phrasing content but tend to be
- // removed by readability when put into paragraphs, so we ignore them here.
- PHRASING_ELEMS: [
- // "CANVAS", "IFRAME", "SVG", "VIDEO",
- "ABBR",
- "AUDIO",
- "B",
- "BDO",
- "BR",
- "BUTTON",
- "CITE",
- "CODE",
- "DATA",
- "DATALIST",
- "DFN",
- "EM",
- "EMBED",
- "I",
- "IMG",
- "INPUT",
- "KBD",
- "LABEL",
- "MARK",
- "MATH",
- "METER",
- "NOSCRIPT",
- "OBJECT",
- "OUTPUT",
- "PROGRESS",
- "Q",
- "RUBY",
- "SAMP",
- "SCRIPT",
- "SELECT",
- "SMALL",
- "SPAN",
- "STRONG",
- "SUB",
- "SUP",
- "TEXTAREA",
- "TIME",
- "VAR",
- "WBR"
- ],
- // These are the classes that readability sets itself.
- CLASSES_TO_PRESERVE: ["page"],
- // These are the list of HTML entities that need to be escaped.
- HTML_ESCAPE_MAP: {
- "lt": "<",
- "gt": ">",
- "amp": "&",
- "quot": '"',
- "apos": "'"
- },
- /**
- * Run any post-process modifications to article content as necessary.
- *
- * @param Element
- * @return void
- **/
- _postProcessContent: function (articleContent) {
- this._fixRelativeUris(articleContent);
- this._simplifyNestedElements(articleContent);
- if (!this._keepClasses) {
- this._cleanClasses(articleContent);
- }
- },
- /**
- * Iterates over a NodeList, calls `filterFn` for each node and removes node
- * if function returned `true`.
- *
- * If function is not passed, removes all the nodes in node list.
- *
- * @param NodeList nodeList The nodes to operate on
- * @param Function filterFn the function to use as a filter
- * @return void
- */
- _removeNodes: function (nodeList, filterFn) {
- if (this._docJSDOMParser && nodeList._isLiveNodeList) {
- throw new Error("Do not pass live node lists to _removeNodes");
- }
- for (var i = nodeList.length - 1; i >= 0; i--) {
- var node = nodeList[i];
- var parentNode = node.parentNode;
- if (parentNode) {
- if (!filterFn || filterFn.call(this, node, i, nodeList)) {
- parentNode.removeChild(node);
- }
- }
- }
- },
- /**
- * Iterates over a NodeList, and calls _setNodeTag for each node.
- *
- * @param NodeList nodeList The nodes to operate on
- * @param String newTagName the new tag name to use
- * @return void
- */
- _replaceNodeTags: function (nodeList, newTagName) {
- if (this._docJSDOMParser && nodeList._isLiveNodeList) {
- throw new Error("Do not pass live node lists to _replaceNodeTags");
- }
- for (const node of nodeList) {
- this._setNodeTag(node, newTagName);
- }
- },
- /**
- * Iterate over a NodeList, which doesn't natively fully implement the Array
- * interface.
- *
- * For convenience, the current object context is applied to the provided
- * iterate function.
- *
- * @param NodeList nodeList The NodeList.
- * @param Function fn The iterate function.
- * @return void
- */
- _forEachNode: function (nodeList, fn) {
- Array.prototype.forEach.call(nodeList, fn, this);
- },
- /**
- * Iterate over a NodeList, and return the first node that passes
- * the supplied test function
- *
- * For convenience, the current object context is applied to the provided
- * test function.
- *
- * @param NodeList nodeList The NodeList.
- * @param Function fn The test function.
- * @return void
- */
- _findNode: function (nodeList, fn) {
- return Array.prototype.find.call(nodeList, fn, this);
- },
- /**
- * Iterate over a NodeList, return true if any of the provided iterate
- * function calls returns true, false otherwise.
- *
- * For convenience, the current object context is applied to the
- * provided iterate function.
- *
- * @param NodeList nodeList The NodeList.
- * @param Function fn The iterate function.
- * @return Boolean
- */
- _someNode: function (nodeList, fn) {
- return Array.prototype.some.call(nodeList, fn, this);
- },
- /**
- * Iterate over a NodeList, return true if all of the provided iterate
- * function calls return true, false otherwise.
- *
- * For convenience, the current object context is applied to the
- * provided iterate function.
- *
- * @param NodeList nodeList The NodeList.
- * @param Function fn The iterate function.
- * @return Boolean
- */
- _everyNode: function (nodeList, fn) {
- return Array.prototype.every.call(nodeList, fn, this);
- },
- /**
- * Concat all nodelists passed as arguments.
- *
- * @return ...NodeList
- * @return Array
- */
- _concatNodeLists: function () {
- var slice = Array.prototype.slice;
- var args = slice.call(arguments);
- var nodeLists = args.map(function (list2) {
- return slice.call(list2);
- });
- return Array.prototype.concat.apply([], nodeLists);
- },
- _getAllNodesWithTag: function (node, tagNames) {
- if (node.querySelectorAll) {
- return node.querySelectorAll(tagNames.join(","));
- }
- return [].concat.apply([], tagNames.map(function (tag2) {
- var collection = node.getElementsByTagName(tag2);
- return Array.isArray(collection) ? collection : Array.from(collection);
- }));
- },
- /**
- * Removes the class="" attribute from every element in the given
- * subtree, except those that match CLASSES_TO_PRESERVE and
- * the classesToPreserve array from the options object.
- *
- * @param Element
- * @return void
- */
- _cleanClasses: function (node) {
- var classesToPreserve = this._classesToPreserve;
- var className = (node.getAttribute("class") || "").split(/\s+/).filter(function (cls) {
- return classesToPreserve.indexOf(cls) != -1;
- }).join(" ");
- if (className) {
- node.setAttribute("class", className);
- } else {
- node.removeAttribute("class");
- }
- for (node = node.firstElementChild; node; node = node.nextElementSibling) {
- this._cleanClasses(node);
- }
- },
- /**
- * Converts each <a> and <img> uri in the given element to an absolute URI,
- * ignoring #ref URIs.
- *
- * @param Element
- * @return void
- */
- _fixRelativeUris: function (articleContent) {
- var baseURI = this._doc.baseURI;
- var documentURI = this._doc.documentURI;
- function toAbsoluteURI(uri) {
- if (baseURI == documentURI && uri.charAt(0) == "#") {
- return uri;
- }
- try {
- return new URL(uri, baseURI).href;
- } catch (ex) {}
- return uri;
- }
- var links = this._getAllNodesWithTag(articleContent, ["a"]);
- this._forEachNode(links, function (link2) {
- var href = link2.getAttribute("href");
- if (href) {
- if (href.indexOf("javascript:") === 0) {
- if (link2.childNodes.length === 1 && link2.childNodes[0].nodeType === this.TEXT_NODE) {
- var text = this._doc.createTextNode(link2.textContent);
- link2.parentNode.replaceChild(text, link2);
- } else {
- var container = this._doc.createElement("span");
- while (link2.firstChild) {
- container.appendChild(link2.firstChild);
- }
- link2.parentNode.replaceChild(container, link2);
- }
- } else {
- link2.setAttribute("href", toAbsoluteURI(href));
- }
- }
- });
- var medias = this._getAllNodesWithTag(articleContent, [
- "img",
- "picture",
- "figure",
- "video",
- "audio",
- "source"
- ]);
- this._forEachNode(medias, function (media) {
- var src = media.getAttribute("src");
- var poster = media.getAttribute("poster");
- var srcset = media.getAttribute("srcset");
- if (src) {
- media.setAttribute("src", toAbsoluteURI(src));
- }
- if (poster) {
- media.setAttribute("poster", toAbsoluteURI(poster));
- }
- if (srcset) {
- var newSrcset = srcset.replace(this.REGEXPS.srcsetUrl, function (_, p1, p2, p3) {
- return toAbsoluteURI(p1) + (p2 || "") + p3;
- });
- media.setAttribute("srcset", newSrcset);
- }
- });
- },
- _simplifyNestedElements: function (articleContent) {
- var node = articleContent;
- while (node) {
- if (node.parentNode && ["DIV", "SECTION"].includes(node.tagName) && !(node.id && node.id.startsWith("readability"))) {
- if (this._isElementWithoutContent(node)) {
- node = this._removeAndGetNext(node);
- continue;
- } else if (this._hasSingleTagInsideElement(node, "DIV") || this._hasSingleTagInsideElement(node, "SECTION")) {
- var child = node.children[0];
- for (var i = 0; i < node.attributes.length; i++) {
- child.setAttribute(node.attributes[i].name, node.attributes[i].value);
- }
- node.parentNode.replaceChild(child, node);
- node = child;
- continue;
- }
- }
- node = this._getNextNode(node);
- }
- },
- /**
- * Get the article title as an H1.
- *
- * @return string
- **/
- _getArticleTitle: function () {
- var doc = this._doc;
- var curTitle = "";
- var origTitle = "";
- try {
- curTitle = origTitle = doc.title.trim();
- if (typeof curTitle !== "string")
- curTitle = origTitle = this._getInnerText(doc.getElementsByTagName("title")[0]);
- } catch (e) {}
- var titleHadHierarchicalSeparators = false;
- function wordCount(str) {
- return str.split(/\s+/).length;
- }
- if (/ [\|\-\\\/>»] /.test(curTitle)) {
- titleHadHierarchicalSeparators = / [\\\/>»] /.test(curTitle);
- curTitle = origTitle.replace(/(.*)[\|\-\\\/>»] .*/gi, "$1");
- if (wordCount(curTitle) < 3)
- curTitle = origTitle.replace(/[^\|\-\\\/>»]*[\|\-\\\/>»](.*)/gi, "$1");
- } else if (curTitle.indexOf(": ") !== -1) {
- var headings = this._concatNodeLists(
- doc.getElementsByTagName("h1"),
- doc.getElementsByTagName("h2")
- );
- var trimmedTitle = curTitle.trim();
- var match = this._someNode(headings, function (heading2) {
- return heading2.textContent.trim() === trimmedTitle;
- });
- if (!match) {
- curTitle = origTitle.substring(origTitle.lastIndexOf(":") + 1);
- if (wordCount(curTitle) < 3) {
- curTitle = origTitle.substring(origTitle.indexOf(":") + 1);
- } else if (wordCount(origTitle.substr(0, origTitle.indexOf(":"))) > 5) {
- curTitle = origTitle;
- }
- }
- } else if (curTitle.length > 150 || curTitle.length < 15) {
- var hOnes = doc.getElementsByTagName("h1");
- if (hOnes.length === 1)
- curTitle = this._getInnerText(hOnes[0]);
- }
- curTitle = curTitle.trim().replace(this.REGEXPS.normalize, " ");
- var curTitleWordCount = wordCount(curTitle);
- if (curTitleWordCount <= 4 && (!titleHadHierarchicalSeparators || curTitleWordCount != wordCount(origTitle.replace(/[\|\-\\\/>»]+/g, "")) - 1)) {
- curTitle = origTitle;
- }
- return curTitle;
- },
- /**
- * Prepare the HTML document for readability to scrape it.
- * This includes things like stripping javascript, CSS, and handling terrible markup.
- *
- * @return void
- **/
- _prepDocument: function () {
- var doc = this._doc;
- this._removeNodes(this._getAllNodesWithTag(doc, ["style"]));
- if (doc.body) {
- this._replaceBrs(doc.body);
- }
- this._replaceNodeTags(this._getAllNodesWithTag(doc, ["font"]), "SPAN");
- },
- /**
- * Finds the next node, starting from the given node, and ignoring
- * whitespace in between. If the given node is an element, the same node is
- * returned.
- */
- _nextNode: function (node) {
- var next = node;
- while (next && next.nodeType != this.ELEMENT_NODE && this.REGEXPS.whitespace.test(next.textContent)) {
- next = next.nextSibling;
- }
- return next;
- },
- /**
- * Replaces 2 or more successive <br> elements with a single <p>.
- * Whitespace between <br> elements are ignored. For example:
- * <div>foo<br>bar<br> <br><br>abc</div>
- * will become:
- * <div>foo<br>bar<p>abc</p></div>
- */
- _replaceBrs: function (elem) {
- this._forEachNode(this._getAllNodesWithTag(elem, ["br"]), function (br2) {
- var next = br2.nextSibling;
- var replaced = false;
- while ((next = this._nextNode(next)) && next.tagName == "BR") {
- replaced = true;
- var brSibling = next.nextSibling;
- next.parentNode.removeChild(next);
- next = brSibling;
- }
- if (replaced) {
- var p = this._doc.createElement("p");
- br2.parentNode.replaceChild(p, br2);
- next = p.nextSibling;
- while (next) {
- if (next.tagName == "BR") {
- var nextElem = this._nextNode(next.nextSibling);
- if (nextElem && nextElem.tagName == "BR")
- break;
- }
- if (!this._isPhrasingContent(next))
- break;
- var sibling = next.nextSibling;
- p.appendChild(next);
- next = sibling;
- }
- while (p.lastChild && this._isWhitespace(p.lastChild)) {
- p.removeChild(p.lastChild);
- }
- if (p.parentNode.tagName === "P")
- this._setNodeTag(p.parentNode, "DIV");
- }
- });
- },
- _setNodeTag: function (node, tag2) {
- this.log("_setNodeTag", node, tag2);
- if (this._docJSDOMParser) {
- node.localName = tag2.toLowerCase();
- node.tagName = tag2.toUpperCase();
- return node;
- }
- var replacement = node.ownerDocument.createElement(tag2);
- while (node.firstChild) {
- replacement.appendChild(node.firstChild);
- }
- node.parentNode.replaceChild(replacement, node);
- if (node.readability)
- replacement.readability = node.readability;
- for (var i = 0; i < node.attributes.length; i++) {
- try {
- replacement.setAttribute(node.attributes[i].name, node.attributes[i].value);
- } catch (ex) {}
- }
- return replacement;
- },
- /**
- * Prepare the article node for display. Clean out any inline styles,
- * iframes, forms, strip extraneous <p> tags, etc.
- *
- * @param Element
- * @return void
- **/
- _prepArticle: function (articleContent) {
- this._cleanStyles(articleContent);
- this._markDataTables(articleContent);
- this._fixLazyImages(articleContent);
- this._cleanConditionally(articleContent, "form");
- this._cleanConditionally(articleContent, "fieldset");
- this._clean(articleContent, "object");
- this._clean(articleContent, "embed");
- this._clean(articleContent, "footer");
- this._clean(articleContent, "link");
- this._clean(articleContent, "aside");
- var shareElementThreshold = this.DEFAULT_CHAR_THRESHOLD;
- this._forEachNode(articleContent.children, function (topCandidate) {
- this._cleanMatchedNodes(topCandidate, function (node, matchString) {
- return this.REGEXPS.shareElements.test(matchString) && node.textContent.length < shareElementThreshold;
- });
- });
- this._clean(articleContent, "iframe");
- this._clean(articleContent, "input");
- this._clean(articleContent, "textarea");
- this._clean(articleContent, "select");
- this._clean(articleContent, "button");
- this._cleanHeaders(articleContent);
- this._cleanConditionally(articleContent, "table");
- this._cleanConditionally(articleContent, "ul");
- this._cleanConditionally(articleContent, "div");
- this._replaceNodeTags(this._getAllNodesWithTag(articleContent, ["h1"]), "h2");
- this._removeNodes(this._getAllNodesWithTag(articleContent, ["p"]), function (paragraph2) {
- var imgCount = paragraph2.getElementsByTagName("img").length;
- var embedCount = paragraph2.getElementsByTagName("embed").length;
- var objectCount = paragraph2.getElementsByTagName("object").length;
- var iframeCount = paragraph2.getElementsByTagName("iframe").length;
- var totalCount = imgCount + embedCount + objectCount + iframeCount;
- return totalCount === 0 && !this._getInnerText(paragraph2, false);
- });
- this._forEachNode(this._getAllNodesWithTag(articleContent, ["br"]), function (br2) {
- var next = this._nextNode(br2.nextSibling);
- if (next && next.tagName == "P")
- br2.parentNode.removeChild(br2);
- });
- this._forEachNode(this._getAllNodesWithTag(articleContent, ["table"]), function (table) {
- var tbody = this._hasSingleTagInsideElement(table, "TBODY") ? table.firstElementChild : table;
- if (this._hasSingleTagInsideElement(tbody, "TR")) {
- var row = tbody.firstElementChild;
- if (this._hasSingleTagInsideElement(row, "TD")) {
- var cell = row.firstElementChild;
- cell = this._setNodeTag(cell, this._everyNode(cell.childNodes, this._isPhrasingContent) ? "P" : "DIV");
- table.parentNode.replaceChild(cell, table);
- }
- }
- });
- },
- /**
- * Initialize a node with the readability object. Also checks the
- * className/id for special names to add to its score.
- *
- * @param Element
- * @return void
- **/
- _initializeNode: function (node) {
- node.readability = {
- "contentScore": 0
- };
- switch (node.tagName) {
- case "DIV":
- node.readability.contentScore += 5;
- break;
- case "PRE":
- case "TD":
- case "BLOCKQUOTE":
- node.readability.contentScore += 3;
- break;
- case "ADDRESS":
- case "OL":
- case "UL":
- case "DL":
- case "DD":
- case "DT":
- case "LI":
- case "FORM":
- node.readability.contentScore -= 3;
- break;
- case "H1":
- case "H2":
- case "H3":
- case "H4":
- case "H5":
- case "H6":
- case "TH":
- node.readability.contentScore -= 5;
- break;
- }
- node.readability.contentScore += this._getClassWeight(node);
- },
- _removeAndGetNext: function (node) {
- var nextNode = this._getNextNode(node, true);
- node.parentNode.removeChild(node);
- return nextNode;
- },
- /**
- * Traverse the DOM from node to node, starting at the node passed in.
- * Pass true for the second parameter to indicate this node itself
- * (and its kids) are going away, and we want the next node over.
- *
- * Calling this in a loop will traverse the DOM depth-first.
- */
- _getNextNode: function (node, ignoreSelfAndKids) {
- if (!ignoreSelfAndKids && node.firstElementChild) {
- return node.firstElementChild;
- }
- if (node.nextElementSibling) {
- return node.nextElementSibling;
- }
- do {
- node = node.parentNode;
- } while (node && !node.nextElementSibling);
- return node && node.nextElementSibling;
- },
- // compares second text to first one
- // 1 = same text, 0 = completely different text
- // works the way that it splits both texts into words and then finds words that are unique in second text
- // the result is given by the lower length of unique parts
- _textSimilarity: function (textA, textB) {
- var tokensA = textA.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);
- var tokensB = textB.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);
- if (!tokensA.length || !tokensB.length) {
- return 0;
- }
- var uniqTokensB = tokensB.filter((token) => !tokensA.includes(token));
- var distanceB = uniqTokensB.join(" ").length / tokensB.join(" ").length;
- return 1 - distanceB;
- },
- _checkByline: function (node, matchString) {
- if (this._articleByline) {
- return false;
- }
- if (node.getAttribute !== void 0) {
- var rel = node.getAttribute("rel");
- var itemprop = node.getAttribute("itemprop");
- }
- if ((rel === "author" || itemprop && itemprop.indexOf("author") !== -1 || this.REGEXPS.byline.test(matchString)) && this._isValidByline(node.textContent)) {
- this._articleByline = node.textContent.trim();
- return true;
- }
- return false;
- },
- _getNodeAncestors: function (node, maxDepth) {
- maxDepth = maxDepth || 0;
- var i = 0,
- ancestors = [];
- while (node.parentNode) {
- ancestors.push(node.parentNode);
- if (maxDepth && ++i === maxDepth)
- break;
- node = node.parentNode;
- }
- return ancestors;
- },
- /***
- * grabArticle - Using a variety of metrics (content score, classname, element types), find the content that is
- * most likely to be the stuff a user wants to read. Then return it wrapped up in a div.
- *
- * @param page a document to run upon. Needs to be a full document, complete with body.
- * @return Element
- **/
- _grabArticle: function (page) {
- this.log("**** grabArticle ****");
- var doc = this._doc;
- var isPaging = page !== null;
- page = page ? page : this._doc.body;
- if (!page) {
- this.log("No body found in document. Abort.");
- return null;
- }
- var pageCacheHtml = page.innerHTML;
- while (true) {
- this.log("Starting grabArticle loop");
- var stripUnlikelyCandidates = this._flagIsActive(this.FLAG_STRIP_UNLIKELYS);
- var elementsToScore = [];
- var node = this._doc.documentElement;
- let shouldRemoveTitleHeader = true;
- while (node) {
- if (node.tagName === "HTML") {
- this._articleLang = node.getAttribute("lang");
- }
- var matchString = node.className + " " + node.id;
- if (!this._isProbablyVisible(node)) {
- this.log("Removing hidden node - " + matchString);
- node = this._removeAndGetNext(node);
- continue;
- }
- if (node.getAttribute("aria-modal") == "true" && node.getAttribute("role") == "dialog") {
- node = this._removeAndGetNext(node);
- continue;
- }
- if (this._checkByline(node, matchString)) {
- node = this._removeAndGetNext(node);
- continue;
- }
- if (shouldRemoveTitleHeader && this._headerDuplicatesTitle(node)) {
- this.log("Removing header: ", node.textContent.trim(), this._articleTitle.trim());
- shouldRemoveTitleHeader = false;
- node = this._removeAndGetNext(node);
- continue;
- }
- if (stripUnlikelyCandidates) {
- if (this.REGEXPS.unlikelyCandidates.test(matchString) && !this.REGEXPS.okMaybeItsACandidate.test(matchString) && !this._hasAncestorTag(node, "table") && !this._hasAncestorTag(node, "code") && node.tagName !== "BODY" && node.tagName !== "A") {
- this.log("Removing unlikely candidate - " + matchString);
- node = this._removeAndGetNext(node);
- continue;
- }
- if (this.UNLIKELY_ROLES.includes(node.getAttribute("role"))) {
- this.log("Removing content with role " + node.getAttribute("role") + " - " + matchString);
- node = this._removeAndGetNext(node);
- continue;
- }
- }
- if ((node.tagName === "DIV" || node.tagName === "SECTION" || node.tagName === "HEADER" || node.tagName === "H1" || node.tagName === "H2" || node.tagName === "H3" || node.tagName === "H4" || node.tagName === "H5" || node.tagName === "H6") && this._isElementWithoutContent(node)) {
- node = this._removeAndGetNext(node);
- continue;
- }
- if (this.DEFAULT_TAGS_TO_SCORE.indexOf(node.tagName) !== -1) {
- elementsToScore.push(node);
- }
- if (node.tagName === "DIV") {
- var p = null;
- var childNode = node.firstChild;
- while (childNode) {
- var nextSibling = childNode.nextSibling;
- if (this._isPhrasingContent(childNode)) {
- if (p !== null) {
- p.appendChild(childNode);
- } else if (!this._isWhitespace(childNode)) {
- p = doc.createElement("p");
- node.replaceChild(p, childNode);
- p.appendChild(childNode);
- }
- } else if (p !== null) {
- while (p.lastChild && this._isWhitespace(p.lastChild)) {
- p.removeChild(p.lastChild);
- }
- p = null;
- }
- childNode = nextSibling;
- }
- if (this._hasSingleTagInsideElement(node, "P") && this._getLinkDensity(node) < 0.25) {
- var newNode = node.children[0];
- node.parentNode.replaceChild(newNode, node);
- node = newNode;
- elementsToScore.push(node);
- } else if (!this._hasChildBlockElement(node)) {
- node = this._setNodeTag(node, "P");
- elementsToScore.push(node);
- }
- }
- node = this._getNextNode(node);
- }
- var candidates = [];
- this._forEachNode(elementsToScore, function (elementToScore) {
- if (!elementToScore.parentNode || typeof elementToScore.parentNode.tagName === "undefined")
- return;
- var innerText = this._getInnerText(elementToScore);
- if (innerText.length < 25)
- return;
- var ancestors2 = this._getNodeAncestors(elementToScore, 5);
- if (ancestors2.length === 0)
- return;
- var contentScore = 0;
- contentScore += 1;
- contentScore += innerText.split(this.REGEXPS.commas).length;
- contentScore += Math.min(Math.floor(innerText.length / 100), 3);
- this._forEachNode(ancestors2, function (ancestor, level) {
- if (!ancestor.tagName || !ancestor.parentNode || typeof ancestor.parentNode.tagName === "undefined")
- return;
- if (typeof ancestor.readability === "undefined") {
- this._initializeNode(ancestor);
- candidates.push(ancestor);
- }
- if (level === 0)
- var scoreDivider = 1;
- else if (level === 1)
- scoreDivider = 2;
- else
- scoreDivider = level * 3;
- ancestor.readability.contentScore += contentScore / scoreDivider;
- });
- });
- var topCandidates = [];
- for (var c = 0, cl = candidates.length; c < cl; c += 1) {
- var candidate = candidates[c];
- var candidateScore = candidate.readability.contentScore * (1 - this._getLinkDensity(candidate));
- candidate.readability.contentScore = candidateScore;
- this.log("Candidate:", candidate, "with score " + candidateScore);
- for (var t = 0; t < this._nbTopCandidates; t++) {
- var aTopCandidate = topCandidates[t];
- if (!aTopCandidate || candidateScore > aTopCandidate.readability.contentScore) {
- topCandidates.splice(t, 0, candidate);
- if (topCandidates.length > this._nbTopCandidates)
- topCandidates.pop();
- break;
- }
- }
- }
- var topCandidate = topCandidates[0] || null;
- var neededToCreateTopCandidate = false;
- var parentOfTopCandidate;
- if (topCandidate === null || topCandidate.tagName === "BODY") {
- topCandidate = doc.createElement("DIV");
- neededToCreateTopCandidate = true;
- while (page.firstChild) {
- this.log("Moving child out:", page.firstChild);
- topCandidate.appendChild(page.firstChild);
- }
- page.appendChild(topCandidate);
- this._initializeNode(topCandidate);
- } else if (topCandidate) {
- var alternativeCandidateAncestors = [];
- for (var i = 1; i < topCandidates.length; i++) {
- if (topCandidates[i].readability.contentScore / topCandidate.readability.contentScore >= 0.75) {
- alternativeCandidateAncestors.push(this._getNodeAncestors(topCandidates[i]));
- }
- }
- var MINIMUM_TOPCANDIDATES = 3;
- if (alternativeCandidateAncestors.length >= MINIMUM_TOPCANDIDATES) {
- parentOfTopCandidate = topCandidate.parentNode;
- while (parentOfTopCandidate.tagName !== "BODY") {
- var listsContainingThisAncestor = 0;
- for (var ancestorIndex = 0; ancestorIndex < alternativeCandidateAncestors.length && listsContainingThisAncestor < MINIMUM_TOPCANDIDATES; ancestorIndex++) {
- listsContainingThisAncestor += Number(alternativeCandidateAncestors[ancestorIndex].includes(parentOfTopCandidate));
- }
- if (listsContainingThisAncestor >= MINIMUM_TOPCANDIDATES) {
- topCandidate = parentOfTopCandidate;
- break;
- }
- parentOfTopCandidate = parentOfTopCandidate.parentNode;
- }
- }
- if (!topCandidate.readability) {
- this._initializeNode(topCandidate);
- }
- parentOfTopCandidate = topCandidate.parentNode;
- var lastScore = topCandidate.readability.contentScore;
- var scoreThreshold = lastScore / 3;
- while (parentOfTopCandidate.tagName !== "BODY") {
- if (!parentOfTopCandidate.readability) {
- parentOfTopCandidate = parentOfTopCandidate.parentNode;
- continue;
- }
- var parentScore = parentOfTopCandidate.readability.contentScore;
- if (parentScore < scoreThreshold)
- break;
- if (parentScore > lastScore) {
- topCandidate = parentOfTopCandidate;
- break;
- }
- lastScore = parentOfTopCandidate.readability.contentScore;
- parentOfTopCandidate = parentOfTopCandidate.parentNode;
- }
- parentOfTopCandidate = topCandidate.parentNode;
- while (parentOfTopCandidate.tagName != "BODY" && parentOfTopCandidate.children.length == 1) {
- topCandidate = parentOfTopCandidate;
- parentOfTopCandidate = topCandidate.parentNode;
- }
- if (!topCandidate.readability) {
- this._initializeNode(topCandidate);
- }
- }
- var articleContent = doc.createElement("DIV");
- if (isPaging)
- articleContent.id = "readability-content";
- var siblingScoreThreshold = Math.max(10, topCandidate.readability.contentScore * 0.2);
- parentOfTopCandidate = topCandidate.parentNode;
- var siblings = parentOfTopCandidate.children;
- for (var s = 0, sl = siblings.length; s < sl; s++) {
- var sibling = siblings[s];
- var append = false;
- this.log("Looking at sibling node:", sibling, sibling.readability ? "with score " + sibling.readability.contentScore : "");
- this.log("Sibling has score", sibling.readability ? sibling.readability.contentScore : "Unknown");
- if (sibling === topCandidate) {
- append = true;
- } else {
- var contentBonus = 0;
- if (sibling.className === topCandidate.className && topCandidate.className !== "")
- contentBonus += topCandidate.readability.contentScore * 0.2;
- if (sibling.readability && sibling.readability.contentScore + contentBonus >= siblingScoreThreshold) {
- append = true;
- } else if (sibling.nodeName === "P") {
- var linkDensity = this._getLinkDensity(sibling);
- var nodeContent = this._getInnerText(sibling);
- var nodeLength = nodeContent.length;
- if (nodeLength > 80 && linkDensity < 0.25) {
- append = true;
- } else if (nodeLength < 80 && nodeLength > 0 && linkDensity === 0 && nodeContent.search(/\.( |$)/) !== -1) {
- append = true;
- }
- }
- }
- if (append) {
- this.log("Appending node:", sibling);
- if (this.ALTER_TO_DIV_EXCEPTIONS.indexOf(sibling.nodeName) === -1) {
- this.log("Altering sibling:", sibling, "to div.");
- sibling = this._setNodeTag(sibling, "DIV");
- }
- articleContent.appendChild(sibling);
- siblings = parentOfTopCandidate.children;
- s -= 1;
- sl -= 1;
- }
- }
- if (this._debug)
- this.log("Article content pre-prep: " + articleContent.innerHTML);
- this._prepArticle(articleContent);
- if (this._debug)
- this.log("Article content post-prep: " + articleContent.innerHTML);
- if (neededToCreateTopCandidate) {
- topCandidate.id = "readability-page-1";
- topCandidate.className = "page";
- } else {
- var div = doc.createElement("DIV");
- div.id = "readability-page-1";
- div.className = "page";
- while (articleContent.firstChild) {
- div.appendChild(articleContent.firstChild);
- }
- articleContent.appendChild(div);
- }
- if (this._debug)
- this.log("Article content after paging: " + articleContent.innerHTML);
- var parseSuccessful = true;
- var textLength = this._getInnerText(articleContent, true).length;
- if (textLength < this._charThreshold) {
- parseSuccessful = false;
- page.innerHTML = pageCacheHtml;
- if (this._flagIsActive(this.FLAG_STRIP_UNLIKELYS)) {
- this._removeFlag(this.FLAG_STRIP_UNLIKELYS);
- this._attempts.push({
- articleContent,
- textLength
- });
- } else if (this._flagIsActive(this.FLAG_WEIGHT_CLASSES)) {
- this._removeFlag(this.FLAG_WEIGHT_CLASSES);
- this._attempts.push({
- articleContent,
- textLength
- });
- } else if (this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)) {
- this._removeFlag(this.FLAG_CLEAN_CONDITIONALLY);
- this._attempts.push({
- articleContent,
- textLength
- });
- } else {
- this._attempts.push({
- articleContent,
- textLength
- });
- this._attempts.sort(function (a, b) {
- return b.textLength - a.textLength;
- });
- if (!this._attempts[0].textLength) {
- return null;
- }
- articleContent = this._attempts[0].articleContent;
- parseSuccessful = true;
- }
- }
- if (parseSuccessful) {
- var ancestors = [parentOfTopCandidate, topCandidate].concat(this._getNodeAncestors(parentOfTopCandidate));
- this._someNode(ancestors, function (ancestor) {
- if (!ancestor.tagName)
- return false;
- var articleDir = ancestor.getAttribute("dir");
- if (articleDir) {
- this._articleDir = articleDir;
- return true;
- }
- return false;
- });
- return articleContent;
- }
- }
- },
- /**
- * Check whether the input string could be a byline.
- * This verifies that the input is a string, and that the length
- * is less than 100 chars.
- *
- * @param possibleByline {string} - a string to check whether its a byline.
- * @return Boolean - whether the input string is a byline.
- */
- _isValidByline: function (byline) {
- if (typeof byline == "string" || byline instanceof String) {
- byline = byline.trim();
- return byline.length > 0 && byline.length < 100;
- }
- return false;
- },
- /**
- * Converts some of the common HTML entities in string to their corresponding characters.
- *
- * @param str {string} - a string to unescape.
- * @return string without HTML entity.
- */
- _unescapeHtmlEntities: function (str) {
- if (!str) {
- return str;
- }
- var htmlEscapeMap = this.HTML_ESCAPE_MAP;
- return str.replace(/&(quot|amp|apos|lt|gt);/g, function (_, tag2) {
- return htmlEscapeMap[tag2];
- }).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi, function (_, hex, numStr) {
- var num = parseInt(hex || numStr, hex ? 16 : 10);
- return String.fromCharCode(num);
- });
- },
- /**
- * Try to extract metadata from JSON-LD object.
- * For now, only Schema.org objects of type Article or its subtypes are supported.
- * @return Object with any metadata that could be extracted (possibly none)
- */
- _getJSONLD: function (doc) {
- var scripts = this._getAllNodesWithTag(doc, ["script"]);
- var metadata;
- this._forEachNode(scripts, function (jsonLdElement) {
- if (!metadata && jsonLdElement.getAttribute("type") === "application/ld+json") {
- try {
- var content = jsonLdElement.textContent.replace(/^\s*<!\[CDATA\[|\]\]>\s*$/g, "");
- var parsed = JSON.parse(content);
- if (!parsed["@context"] || !parsed["@context"].match(/^https?\:\/\/schema\.org$/)) {
- return;
- }
- if (!parsed["@type"] && Array.isArray(parsed["@graph"])) {
- parsed = parsed["@graph"].find(function (it) {
- return (it["@type"] || "").match(
- this.REGEXPS.jsonLdArticleTypes
- );
- });
- }
- if (!parsed || !parsed["@type"] || !parsed["@type"].match(this.REGEXPS.jsonLdArticleTypes)) {
- return;
- }
- metadata = {};
- if (typeof parsed.name === "string" && typeof parsed.headline === "string" && parsed.name !== parsed.headline) {
- var title = this._getArticleTitle();
- var nameMatches = this._textSimilarity(parsed.name, title) > 0.75;
- var headlineMatches = this._textSimilarity(parsed.headline, title) > 0.75;
- if (headlineMatches && !nameMatches) {
- metadata.title = parsed.headline;
- } else {
- metadata.title = parsed.name;
- }
- } else if (typeof parsed.name === "string") {
- metadata.title = parsed.name.trim();
- } else if (typeof parsed.headline === "string") {
- metadata.title = parsed.headline.trim();
- }
- if (parsed.author) {
- if (typeof parsed.author.name === "string") {
- metadata.byline = parsed.author.name.trim();
- } else if (Array.isArray(parsed.author) && parsed.author[0] && typeof parsed.author[0].name === "string") {
- metadata.byline = parsed.author.filter(function (author) {
- return author && typeof author.name === "string";
- }).map(function (author) {
- return author.name.trim();
- }).join(", ");
- }
- }
- if (typeof parsed.description === "string") {
- metadata.excerpt = parsed.description.trim();
- }
- if (parsed.publisher && typeof parsed.publisher.name === "string") {
- metadata.siteName = parsed.publisher.name.trim();
- }
- if (typeof parsed.datePublished === "string") {
- metadata.datePublished = parsed.datePublished.trim();
- }
- return;
- } catch (err) {
- this.log(err.message);
- }
- }
- });
- return metadata ? metadata : {};
- },
- /**
- * Attempts to get excerpt and byline metadata for the article.
- *
- * @param {Object} jsonld — object containing any metadata that
- * could be extracted from JSON-LD object.
- *
- * @return Object with optional "excerpt" and "byline" properties
- */
- _getArticleMetadata: function (jsonld) {
- var metadata = {};
- var values = {};
- var metaElements = this._doc.getElementsByTagName("meta");
- var propertyPattern = /\s*(article|dc|dcterm|og|twitter)\s*:\s*(author|creator|description|published_time|title|site_name)\s*/gi;
- var namePattern = /^\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\s*[\.:]\s*)?(author|creator|description|title|site_name)\s*$/i;
- this._forEachNode(metaElements, function (element) {
- var elementName = element.getAttribute("name");
- var elementProperty = element.getAttribute("property");
- var content = element.getAttribute("content");
- if (!content) {
- return;
- }
- var matches = null;
- var name = null;
- if (elementProperty) {
- matches = elementProperty.match(propertyPattern);
- if (matches) {
- name = matches[0].toLowerCase().replace(/\s/g, "");
- values[name] = content.trim();
- }
- }
- if (!matches && elementName && namePattern.test(elementName)) {
- name = elementName;
- if (content) {
- name = name.toLowerCase().replace(/\s/g, "").replace(/\./g, ":");
- values[name] = content.trim();
- }
- }
- });
- metadata.title = jsonld.title || values["dc:title"] || values["dcterm:title"] || values["og:title"] || values["weibo:article:title"] || values["weibo:webpage:title"] || values["title"] || values["twitter:title"];
- if (!metadata.title) {
- metadata.title = this._getArticleTitle();
- }
- metadata.byline = jsonld.byline || values["dc:creator"] || values["dcterm:creator"] || values["author"];
- metadata.excerpt = jsonld.excerpt || values["dc:description"] || values["dcterm:description"] || values["og:description"] || values["weibo:article:description"] || values["weibo:webpage:description"] || values["description"] || values["twitter:description"];
- metadata.siteName = jsonld.siteName || values["og:site_name"];
- metadata.publishedTime = jsonld.datePublished || values["article:published_time"] || null;
- metadata.title = this._unescapeHtmlEntities(metadata.title);
- metadata.byline = this._unescapeHtmlEntities(metadata.byline);
- metadata.excerpt = this._unescapeHtmlEntities(metadata.excerpt);
- metadata.siteName = this._unescapeHtmlEntities(metadata.siteName);
- metadata.publishedTime = this._unescapeHtmlEntities(metadata.publishedTime);
- return metadata;
- },
- /**
- * Check if node is image, or if node contains exactly only one image
- * whether as a direct child or as its descendants.
- *
- * @param Element
- **/
- _isSingleImage: function (node) {
- if (node.tagName === "IMG") {
- return true;
- }
- if (node.children.length !== 1 || node.textContent.trim() !== "") {
- return false;
- }
- return this._isSingleImage(node.children[0]);
- },
- /**
- * Find all <noscript> that are located after <img> nodes, and which contain only one
- * <img> element. Replace the first image with the image from inside the <noscript> tag,
- * and remove the <noscript> tag. This improves the quality of the images we use on
- * some sites (e.g. Medium).
- *
- * @param Element
- **/
- _unwrapNoscriptImages: function (doc) {
- var imgs = Array.from(doc.getElementsByTagName("img"));
- this._forEachNode(imgs, function (img) {
- for (var i = 0; i < img.attributes.length; i++) {
- var attr = img.attributes[i];
- switch (attr.name) {
- case "src":
- case "srcset":
- case "data-src":
- case "data-srcset":
- return;
- }
- if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
- return;
- }
- }
- img.parentNode.removeChild(img);
- });
- var noscripts = Array.from(doc.getElementsByTagName("noscript"));
- this._forEachNode(noscripts, function (noscript) {
- var tmp = doc.createElement("div");
- tmp.innerHTML = noscript.innerHTML;
- if (!this._isSingleImage(tmp)) {
- return;
- }
- var prevElement = noscript.previousElementSibling;
- if (prevElement && this._isSingleImage(prevElement)) {
- var prevImg = prevElement;
- if (prevImg.tagName !== "IMG") {
- prevImg = prevElement.getElementsByTagName("img")[0];
- }
- var newImg = tmp.getElementsByTagName("img")[0];
- for (var i = 0; i < prevImg.attributes.length; i++) {
- var attr = prevImg.attributes[i];
- if (attr.value === "") {
- continue;
- }
- if (attr.name === "src" || attr.name === "srcset" || /\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
- if (newImg.getAttribute(attr.name) === attr.value) {
- continue;
- }
- var attrName = attr.name;
- if (newImg.hasAttribute(attrName)) {
- attrName = "data-old-" + attrName;
- }
- newImg.setAttribute(attrName, attr.value);
- }
- }
- noscript.parentNode.replaceChild(tmp.firstElementChild, prevElement);
- }
- });
- },
- /**
- * Removes script tags from the document.
- *
- * @param Element
- **/
- _removeScripts: function (doc) {
- this._removeNodes(this._getAllNodesWithTag(doc, ["script", "noscript"]));
- },
- /**
- * Check if this node has only whitespace and a single element with given tag
- * Returns false if the DIV node contains non-empty text nodes
- * or if it contains no element with given tag or more than 1 element.
- *
- * @param Element
- * @param string tag of child element
- **/
- _hasSingleTagInsideElement: function (element, tag2) {
- if (element.children.length != 1 || element.children[0].tagName !== tag2) {
- return false;
- }
- return !this._someNode(element.childNodes, function (node) {
- return node.nodeType === this.TEXT_NODE && this.REGEXPS.hasContent.test(node.textContent);
- });
- },
- _isElementWithoutContent: function (node) {
- return node.nodeType === this.ELEMENT_NODE && node.textContent.trim().length == 0 && (node.children.length == 0 || node.children.length == node.getElementsByTagName("br").length + node.getElementsByTagName("hr").length);
- },
- /**
- * Determine whether element has any children block level elements.
- *
- * @param Element
- */
- _hasChildBlockElement: function (element) {
- return this._someNode(element.childNodes, function (node) {
- return this.DIV_TO_P_ELEMS.has(node.tagName) || this._hasChildBlockElement(node);
- });
- },
- /***
- * Determine if a node qualifies as phrasing content.
- * https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content
- **/
- _isPhrasingContent: function (node) {
- return node.nodeType === this.TEXT_NODE || this.PHRASING_ELEMS.indexOf(node.tagName) !== -1 || (node.tagName === "A" || node.tagName === "DEL" || node.tagName === "INS") && this._everyNode(node.childNodes, this._isPhrasingContent);
- },
- _isWhitespace: function (node) {
- return node.nodeType === this.TEXT_NODE && node.textContent.trim().length === 0 || node.nodeType === this.ELEMENT_NODE && node.tagName === "BR";
- },
- /**
- * Get the inner text of a node - cross browser compatibly.
- * This also strips out any excess whitespace to be found.
- *
- * @param Element
- * @param Boolean normalizeSpaces (default: true)
- * @return string
- **/
- _getInnerText: function (e, normalizeSpaces) {
- normalizeSpaces = typeof normalizeSpaces === "undefined" ? true : normalizeSpaces;
- var textContent = e.textContent.trim();
- if (normalizeSpaces) {
- return textContent.replace(this.REGEXPS.normalize, " ");
- }
- return textContent;
- },
- /**
- * Get the number of times a string s appears in the node e.
- *
- * @param Element
- * @param string - what to split on. Default is ","
- * @return number (integer)
- **/
- _getCharCount: function (e, s) {
- s = s || ",";
- return this._getInnerText(e).split(s).length - 1;
- },
- /**
- * Remove the style attribute on every e and under.
- * TODO: Test if getElementsByTagName(*) is faster.
- *
- * @param Element
- * @return void
- **/
- _cleanStyles: function (e) {
- if (!e || e.tagName.toLowerCase() === "svg")
- return;
- for (var i = 0; i < this.PRESENTATIONAL_ATTRIBUTES.length; i++) {
- e.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[i]);
- }
- if (this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(e.tagName) !== -1) {
- e.removeAttribute("width");
- e.removeAttribute("height");
- }
- var cur = e.firstElementChild;
- while (cur !== null) {
- this._cleanStyles(cur);
- cur = cur.nextElementSibling;
- }
- },
- /**
- * Get the density of links as a percentage of the content
- * This is the amount of text that is inside a link divided by the total text in the node.
- *
- * @param Element
- * @return number (float)
- **/
- _getLinkDensity: function (element) {
- var textLength = this._getInnerText(element).length;
- if (textLength === 0)
- return 0;
- var linkLength = 0;
- this._forEachNode(element.getElementsByTagName("a"), function (linkNode) {
- var href = linkNode.getAttribute("href");
- var coefficient = href && this.REGEXPS.hashUrl.test(href) ? 0.3 : 1;
- linkLength += this._getInnerText(linkNode).length * coefficient;
- });
- return linkLength / textLength;
- },
- /**
- * Get an elements class/id weight. Uses regular expressions to tell if this
- * element looks good or bad.
- *
- * @param Element
- * @return number (Integer)
- **/
- _getClassWeight: function (e) {
- if (!this._flagIsActive(this.FLAG_WEIGHT_CLASSES))
- return 0;
- var weight = 0;
- if (typeof e.className === "string" && e.className !== "") {
- if (this.REGEXPS.negative.test(e.className))
- weight -= 25;
- if (this.REGEXPS.positive.test(e.className))
- weight += 25;
- }
- if (typeof e.id === "string" && e.id !== "") {
- if (this.REGEXPS.negative.test(e.id))
- weight -= 25;
- if (this.REGEXPS.positive.test(e.id))
- weight += 25;
- }
- return weight;
- },
- /**
- * Clean a node of all elements of type "tag".
- * (Unless it's a youtube/vimeo video. People love movies.)
- *
- * @param Element
- * @param string tag to clean
- * @return void
- **/
- _clean: function (e, tag2) {
- var isEmbed = ["object", "embed", "iframe"].indexOf(tag2) !== -1;
- this._removeNodes(this._getAllNodesWithTag(e, [tag2]), function (element) {
- if (isEmbed) {
- for (var i = 0; i < element.attributes.length; i++) {
- if (this._allowedVideoRegex.test(element.attributes[i].value)) {
- return false;
- }
- }
- if (element.tagName === "object" && this._allowedVideoRegex.test(element.innerHTML)) {
- return false;
- }
- }
- return true;
- });
- },
- /**
- * Check if a given node has one of its ancestor tag name matching the
- * provided one.
- * @param HTMLElement node
- * @param String tagName
- * @param Number maxDepth
- * @param Function filterFn a filter to invoke to determine whether this node 'counts'
- * @return Boolean
- */
- _hasAncestorTag: function (node, tagName, maxDepth, filterFn) {
- maxDepth = maxDepth || 3;
- tagName = tagName.toUpperCase();
- var depth = 0;
- while (node.parentNode) {
- if (maxDepth > 0 && depth > maxDepth)
- return false;
- if (node.parentNode.tagName === tagName && (!filterFn || filterFn(node.parentNode)))
- return true;
- node = node.parentNode;
- depth++;
- }
- return false;
- },
- /**
- * Return an object indicating how many rows and columns this table has.
- */
- _getRowAndColumnCount: function (table) {
- var rows = 0;
- var columns = 0;
- var trs = table.getElementsByTagName("tr");
- for (var i = 0; i < trs.length; i++) {
- var rowspan = trs[i].getAttribute("rowspan") || 0;
- if (rowspan) {
- rowspan = parseInt(rowspan, 10);
- }
- rows += rowspan || 1;
- var columnsInThisRow = 0;
- var cells = trs[i].getElementsByTagName("td");
- for (var j = 0; j < cells.length; j++) {
- var colspan = cells[j].getAttribute("colspan") || 0;
- if (colspan) {
- colspan = parseInt(colspan, 10);
- }
- columnsInThisRow += colspan || 1;
- }
- columns = Math.max(columns, columnsInThisRow);
- }
- return {
- rows,
- columns
- };
- },
- /**
- * Look for 'data' (as opposed to 'layout') tables, for which we use
- * similar checks as
- * https://searchfox.org/mozilla-central/rev/f82d5c549f046cb64ce5602bfd894b7ae807c8f8/accessible/generic/TableAccessible.cpp#19
- */
- _markDataTables: function (root) {
- var tables = root.getElementsByTagName("table");
- for (var i = 0; i < tables.length; i++) {
- var table = tables[i];
- var role = table.getAttribute("role");
- if (role == "presentation") {
- table._readabilityDataTable = false;
- continue;
- }
- var datatable = table.getAttribute("datatable");
- if (datatable == "0") {
- table._readabilityDataTable = false;
- continue;
- }
- var summary = table.getAttribute("summary");
- if (summary) {
- table._readabilityDataTable = true;
- continue;
- }
- var caption = table.getElementsByTagName("caption")[0];
- if (caption && caption.childNodes.length > 0) {
- table._readabilityDataTable = true;
- continue;
- }
- var dataTableDescendants = ["col", "colgroup", "tfoot", "thead", "th"];
- var descendantExists = function (tag2) {
- return !!table.getElementsByTagName(tag2)[0];
- };
- if (dataTableDescendants.some(descendantExists)) {
- this.log("Data table because found data-y descendant");
- table._readabilityDataTable = true;
- continue;
- }
- if (table.getElementsByTagName("table")[0]) {
- table._readabilityDataTable = false;
- continue;
- }
- var sizeInfo = this._getRowAndColumnCount(table);
- if (sizeInfo.rows >= 10 || sizeInfo.columns > 4) {
- table._readabilityDataTable = true;
- continue;
- }
- table._readabilityDataTable = sizeInfo.rows * sizeInfo.columns > 10;
- }
- },
- /* convert images and figures that have properties like data-src into images that can be loaded without JS */
- _fixLazyImages: function (root) {
- this._forEachNode(this._getAllNodesWithTag(root, ["img", "picture", "figure"]), function (elem) {
- if (elem.src && this.REGEXPS.b64DataUrl.test(elem.src)) {
- var parts = this.REGEXPS.b64DataUrl.exec(elem.src);
- if (parts[1] === "image/svg+xml") {
- return;
- }
- var srcCouldBeRemoved = false;
- for (var i = 0; i < elem.attributes.length; i++) {
- var attr = elem.attributes[i];
- if (attr.name === "src") {
- continue;
- }
- if (/\.(jpg|jpeg|png|webp)/i.test(attr.value)) {
- srcCouldBeRemoved = true;
- break;
- }
- }
- if (srcCouldBeRemoved) {
- var b64starts = elem.src.search(/base64\s*/i) + 7;
- var b64length = elem.src.length - b64starts;
- if (b64length < 133) {
- elem.removeAttribute("src");
- }
- }
- }
- if ((elem.src || elem.srcset && elem.srcset != "null") && elem.className.toLowerCase().indexOf("lazy") === -1) {
- return;
- }
- for (var j = 0; j < elem.attributes.length; j++) {
- attr = elem.attributes[j];
- if (attr.name === "src" || attr.name === "srcset" || attr.name === "alt") {
- continue;
- }
- var copyTo = null;
- if (/\.(jpg|jpeg|png|webp)\s+\d/.test(attr.value)) {
- copyTo = "srcset";
- } else if (/^\s*\S+\.(jpg|jpeg|png|webp)\S*\s*$/.test(attr.value)) {
- copyTo = "src";
- }
- if (copyTo) {
- if (elem.tagName === "IMG" || elem.tagName === "PICTURE") {
- elem.setAttribute(copyTo, attr.value);
- } else if (elem.tagName === "FIGURE" && !this._getAllNodesWithTag(elem, ["img", "picture"]).length) {
- var img = this._doc.createElement("img");
- img.setAttribute(copyTo, attr.value);
- elem.appendChild(img);
- }
- }
- }
- });
- },
- _getTextDensity: function (e, tags) {
- var textLength = this._getInnerText(e, true).length;
- if (textLength === 0) {
- return 0;
- }
- var childrenLength = 0;
- var children = this._getAllNodesWithTag(e, tags);
- this._forEachNode(children, (child) => childrenLength += this._getInnerText(child, true).length);
- return childrenLength / textLength;
- },
- /**
- * Clean an element of all tags of type "tag" if they look fishy.
- * "Fishy" is an algorithm based on content length, classnames, link density, number of images & embeds, etc.
- *
- * @return void
- **/
- _cleanConditionally: function (e, tag2) {
- if (!this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY))
- return;
- this._removeNodes(this._getAllNodesWithTag(e, [tag2]), function (node) {
- var isDataTable = function (t) {
- return t._readabilityDataTable;
- };
- var isList = tag2 === "ul" || tag2 === "ol";
- if (!isList) {
- var listLength = 0;
- var listNodes = this._getAllNodesWithTag(node, ["ul", "ol"]);
- this._forEachNode(listNodes, (list2) => listLength += this._getInnerText(list2).length);
- isList = listLength / this._getInnerText(node).length > 0.9;
- }
- if (tag2 === "table" && isDataTable(node)) {
- return false;
- }
- if (this._hasAncestorTag(node, "table", -1, isDataTable)) {
- return false;
- }
- if (this._hasAncestorTag(node, "code")) {
- return false;
- }
- var weight = this._getClassWeight(node);
- this.log("Cleaning Conditionally", node);
- var contentScore = 0;
- if (weight + contentScore < 0) {
- return true;
- }
- if (this._getCharCount(node, ",") < 10) {
- var p = node.getElementsByTagName("p").length;
- var img = node.getElementsByTagName("img").length;
- var li = node.getElementsByTagName("li").length - 100;
- var input = node.getElementsByTagName("input").length;
- var headingDensity = this._getTextDensity(node, ["h1", "h2", "h3", "h4", "h5", "h6"]);
- var embedCount = 0;
- var embeds = this._getAllNodesWithTag(node, ["object", "embed", "iframe"]);
- for (var i = 0; i < embeds.length; i++) {
- for (var j = 0; j < embeds[i].attributes.length; j++) {
- if (this._allowedVideoRegex.test(embeds[i].attributes[j].value)) {
- return false;
- }
- }
- if (embeds[i].tagName === "object" && this._allowedVideoRegex.test(embeds[i].innerHTML)) {
- return false;
- }
- embedCount++;
- }
- var linkDensity = this._getLinkDensity(node);
- var contentLength = this._getInnerText(node).length;
- var haveToRemove = img > 1 && p / img < 0.5 && !this._hasAncestorTag(node, "figure") || !isList && li > p || input > Math.floor(p / 3) || !isList && headingDensity < 0.9 && contentLength < 25 && (img === 0 || img > 2) && !this._hasAncestorTag(node, "figure") || !isList && weight < 25 && linkDensity > 0.2 || weight >= 25 && linkDensity > 0.5 || (embedCount === 1 && contentLength < 75 || embedCount > 1);
- if (isList && haveToRemove) {
- for (var x = 0; x < node.children.length; x++) {
- let child = node.children[x];
- if (child.children.length > 1) {
- return haveToRemove;
- }
- }
- let li_count = node.getElementsByTagName("li").length;
- if (img == li_count) {
- return false;
- }
- }
- return haveToRemove;
- }
- return false;
- });
- },
- /**
- * Clean out elements that match the specified conditions
- *
- * @param Element
- * @param Function determines whether a node should be removed
- * @return void
- **/
- _cleanMatchedNodes: function (e, filter) {
- var endOfSearchMarkerNode = this._getNextNode(e, true);
- var next = this._getNextNode(e);
- while (next && next != endOfSearchMarkerNode) {
- if (filter.call(this, next, next.className + " " + next.id)) {
- next = this._removeAndGetNext(next);
- } else {
- next = this._getNextNode(next);
- }
- }
- },
- /**
- * Clean out spurious headers from an Element.
- *
- * @param Element
- * @return void
- **/
- _cleanHeaders: function (e) {
- let headingNodes = this._getAllNodesWithTag(e, ["h1", "h2"]);
- this._removeNodes(headingNodes, function (node) {
- let shouldRemove = this._getClassWeight(node) < 0;
- if (shouldRemove) {
- this.log("Removing header with low class weight:", node);
- }
- return shouldRemove;
- });
- },
- /**
- * Check if this node is an H1 or H2 element whose content is mostly
- * the same as the article title.
- *
- * @param Element the node to check.
- * @return boolean indicating whether this is a title-like header.
- */
- _headerDuplicatesTitle: function (node) {
- if (node.tagName != "H1" && node.tagName != "H2") {
- return false;
- }
- var heading2 = this._getInnerText(node, false);
- this.log("Evaluating similarity of header:", heading2, this._articleTitle);
- return this._textSimilarity(this._articleTitle, heading2) > 0.75;
- },
- _flagIsActive: function (flag) {
- return (this._flags & flag) > 0;
- },
- _removeFlag: function (flag) {
- this._flags = this._flags & ~flag;
- },
- _isProbablyVisible: function (node) {
- return (!node.style || node.style.display != "none") && (!node.style || node.style.visibility != "hidden") && !node.hasAttribute("hidden") && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1);
- },
- /**
- * Runs readability.
- *
- * Workflow:
- * 1. Prep the document by removing script tags, css, etc.
- * 2. Build readability's DOM tree.
- * 3. Grab the article content from the current dom tree.
- * 4. Replace the current DOM tree with the new one.
- * 5. Read peacefully.
- *
- * @return void
- **/
- parse: function () {
- if (this._maxElemsToParse > 0) {
- var numTags = this._doc.getElementsByTagName("*").length;
- if (numTags > this._maxElemsToParse) {
- throw new Error("Aborting parsing document; " + numTags + " elements found");
- }
- }
- this._unwrapNoscriptImages(this._doc);
- var jsonLd = this._disableJSONLD ? {} : this._getJSONLD(this._doc);
- this._removeScripts(this._doc);
- this._prepDocument();
- var metadata = this._getArticleMetadata(jsonLd);
- this._articleTitle = metadata.title;
- var articleContent = this._grabArticle();
- if (!articleContent)
- return null;
- this.log("Grabbed: " + articleContent.innerHTML);
- this._postProcessContent(articleContent);
- if (!metadata.excerpt) {
- var paragraphs = articleContent.getElementsByTagName("p");
- if (paragraphs.length > 0) {
- metadata.excerpt = paragraphs[0].textContent.trim();
- }
- }
- var textContent = articleContent.textContent;
- return {
- title: this._articleTitle,
- byline: metadata.byline || this._articleByline,
- dir: this._articleDir,
- lang: this._articleLang,
- content: this._serializer(articleContent),
- textContent,
- length: textContent.length,
- excerpt: metadata.excerpt,
- siteName: metadata.siteName || this._articleSiteName,
- publishedTime: metadata.publishedTime
- };
- }
- }; {
- module.exports = Readability2;
- }
- })(Readability$1);
- var ReadabilityExports = Readability$1.exports;
- var ReadabilityReaderable = {
- exports: {}
- };
- (function (module) {
- var REGEXPS = {
- // NOTE: These two regular expressions are duplicated in
- // Readability.js. Please keep both copies in sync.
- unlikelyCandidates: /-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,
- okMaybeItsACandidate: /and|article|body|column|content|main|shadow/i
- };
- function isNodeVisible(node) {
- return (!node.style || node.style.display != "none") && !node.hasAttribute("hidden") && (!node.hasAttribute("aria-hidden") || node.getAttribute("aria-hidden") != "true" || node.className && node.className.indexOf && node.className.indexOf("fallback-image") !== -1);
- }
- function isProbablyReaderable2(doc, options = {}) {
- if (typeof options == "function") {
- options = {
- visibilityChecker: options
- };
- }
- var defaultOptions = {
- minScore: 20,
- minContentLength: 140,
- visibilityChecker: isNodeVisible
- };
- options = Object.assign(defaultOptions, options);
- var nodes = doc.querySelectorAll("p, pre, article");
- var brNodes = doc.querySelectorAll("div > br");
- if (brNodes.length) {
- var set = new Set(nodes);
- [].forEach.call(brNodes, function (node) {
- set.add(node.parentNode);
- });
- nodes = Array.from(set);
- }
- var score = 0;
- return [].some.call(nodes, function (node) {
- if (!options.visibilityChecker(node)) {
- return false;
- }
- var matchString = node.className + " " + node.id;
- if (REGEXPS.unlikelyCandidates.test(matchString) && !REGEXPS.okMaybeItsACandidate.test(matchString)) {
- return false;
- }
- if (node.matches("li p")) {
- return false;
- }
- var textContentLength = node.textContent.trim().length;
- if (textContentLength < options.minContentLength) {
- return false;
- }
- score += Math.sqrt(textContentLength - options.minContentLength);
- if (score > options.minScore) {
- return true;
- }
- return false;
- });
- } {
- module.exports = isProbablyReaderable2;
- }
- })(ReadabilityReaderable);
- var ReadabilityReaderableExports = ReadabilityReaderable.exports;
- var Readability = ReadabilityExports;
- var isProbablyReaderable = ReadabilityReaderableExports;
- var readability = {
- Readability,
- isProbablyReaderable
- };
- function getSimpleText(doc) {
- doc = doc ? doc : document;
- doc = doc.cloneNode(true);
- const app = doc.querySelector("#monkeygpt");
- app.remove();
- let article = new readability.Readability(doc).parse();
- let str = replaceEmpty(article.textContent);
- return str;
- }
- function replaceEmpty(str) {
- while (str.includes(" ")) {
- str = str.replaceAll(" ", " ");
- }
- while (str.includes("\n\n")) {
- str = str.replaceAll("\n\n", "\n");
- }
- while (str.includes(" ")) {
- str = str.replaceAll(" ", " ");
- }
- return str;
- }
- const engineQueryKey = {
- "www.google.com": "q",
- "www.baidu.com": "wd",
- "www.bing.com": "q",
- "www.so.com": "q"
- };
- function getSearchKey() {
- const seName = getSeName();
- if (seName) {
- return new URLSearchParams(location.search).get(engineQueryKey[seName]);
- } else {
- return null;
- }
- }
- function getSeName() {
- const se = Object.keys(engineQueryKey);
- const seNames = se.filter((s) => window.location.host.includes(s));
- return seNames.length > 0 ? seNames[0] : null;
- }
- async function chat$1(messages, model = "gpt-4o-mini", apiKey, apiEndpoint = "https://api.openai.com/v1/chat/completions") {
- const headers = {
- "Content-Type": "application/json",
- "Authorization": `Bearer ${apiKey}`
- };
- const requestBody = {
- model,
- // 使用的模型名称
- messages
- };
- return fetch(apiEndpoint, {
- method: "POST",
- headers,
- body: JSON.stringify(requestBody)
- }).then((response) => response.json()).then(async (data) => {
- const reply = data.choices[0].message.content;
- return reply;
- });
- }
- const defaultConfig = {
- model: "gpt-4o-mini",
- apiKey: "",
- apiEndpoint: "https://ai.01234.fun/v1/chat/completions"
- };
- async function chat(content, config = defaultConfig) {
- return await chat$1([{
- role: "user",
- content
- }], config.model, config.apiKey, config.apiEndpoint);
- }
- async function summarize(text, config = defaultConfig) {
- return chat(`请帮忙总结一下 :"${text}"`, config);
- }
- async function ask(text, config = defaultConfig) {
- return chat(`请帮忙回复一下 :"${text}"`, config);
- }
- async function search(text, config = defaultConfig) {
- return chat(`现在你是谷歌,请帮忙回答一下 :"${text}"`, config);
- }
- function _getDefaults() {
- return {
- async: false,
- breaks: false,
- extensions: null,
- gfm: true,
- hooks: null,
- pedantic: false,
- renderer: null,
- silent: false,
- tokenizer: null,
- walkTokens: null
- };
- }
- let _defaults = _getDefaults();
- function changeDefaults(newDefaults) {
- _defaults = newDefaults;
- }
- const escapeTest = /[&<>"']/;
- const escapeReplace = new RegExp(escapeTest.source, "g");
- const escapeTestNoEncode = /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/;
- const escapeReplaceNoEncode = new RegExp(escapeTestNoEncode.source, "g");
- const escapeReplacements = {
- "&": "&",
- "<": "<",
- ">": ">",
- '"': """,
- "'": "'"
- };
- const getEscapeReplacement = (ch) => escapeReplacements[ch];
- function escape$1(html2, encode) {
- if (encode) {
- if (escapeTest.test(html2)) {
- return html2.replace(escapeReplace, getEscapeReplacement);
- }
- } else {
- if (escapeTestNoEncode.test(html2)) {
- return html2.replace(escapeReplaceNoEncode, getEscapeReplacement);
- }
- }
- return html2;
- }
- const caret = /(^|[^\[])\^/g;
- function edit(regex, opt) {
- let source = typeof regex === "string" ? regex : regex.source;
- opt = opt || "";
- const obj = {
- replace: (name, val) => {
- let valSource = typeof val === "string" ? val : val.source;
- valSource = valSource.replace(caret, "$1");
- source = source.replace(name, valSource);
- return obj;
- },
- getRegex: () => {
- return new RegExp(source, opt);
- }
- };
- return obj;
- }
- function cleanUrl(href) {
- try {
- href = encodeURI(href).replace(/%25/g, "%");
- } catch {
- return null;
- }
- return href;
- }
- const noopTest = {
- exec: () => null
- };
- function splitCells(tableRow, count) {
- const row = tableRow.replace(/\|/g, (match, offset, str) => {
- let escaped = false;
- let curr = offset;
- while (--curr >= 0 && str[curr] === "\\")
- escaped = !escaped;
- if (escaped) {
- return "|";
- } else {
- return " |";
- }
- }),
- cells = row.split(/ \|/);
- let i = 0;
- if (!cells[0].trim()) {
- cells.shift();
- }
- if (cells.length > 0 && !cells[cells.length - 1].trim()) {
- cells.pop();
- }
- if (count) {
- if (cells.length > count) {
- cells.splice(count);
- } else {
- while (cells.length < count)
- cells.push("");
- }
- }
- for (; i < cells.length; i++) {
- cells[i] = cells[i].trim().replace(/\\\|/g, "|");
- }
- return cells;
- }
- function rtrim(str, c, invert) {
- const l = str.length;
- if (l === 0) {
- return "";
- }
- let suffLen = 0;
- while (suffLen < l) {
- const currChar = str.charAt(l - suffLen - 1);
- if (currChar === c && !invert) {
- suffLen++;
- } else if (currChar !== c && invert) {
- suffLen++;
- } else {
- break;
- }
- }
- return str.slice(0, l - suffLen);
- }
- function findClosingBracket(str, b) {
- if (str.indexOf(b[1]) === -1) {
- return -1;
- }
- let level = 0;
- for (let i = 0; i < str.length; i++) {
- if (str[i] === "\\") {
- i++;
- } else if (str[i] === b[0]) {
- level++;
- } else if (str[i] === b[1]) {
- level--;
- if (level < 0) {
- return i;
- }
- }
- }
- return -1;
- }
- function outputLink(cap, link2, raw, lexer) {
- const href = link2.href;
- const title = link2.title ? escape$1(link2.title) : null;
- const text = cap[1].replace(/\\([\[\]])/g, "$1");
- if (cap[0].charAt(0) !== "!") {
- lexer.state.inLink = true;
- const token = {
- type: "link",
- raw,
- href,
- title,
- text,
- tokens: lexer.inlineTokens(text)
- };
- lexer.state.inLink = false;
- return token;
- }
- return {
- type: "image",
- raw,
- href,
- title,
- text: escape$1(text)
- };
- }
- function indentCodeCompensation(raw, text) {
- const matchIndentToCode = raw.match(/^(\s+)(?:```)/);
- if (matchIndentToCode === null) {
- return text;
- }
- const indentToCode = matchIndentToCode[1];
- return text.split("\n").map((node) => {
- const matchIndentInNode = node.match(/^\s+/);
- if (matchIndentInNode === null) {
- return node;
- }
- const [indentInNode] = matchIndentInNode;
- if (indentInNode.length >= indentToCode.length) {
- return node.slice(indentToCode.length);
- }
- return node;
- }).join("\n");
- }
- class _Tokenizer {
- // set by the lexer
- constructor(options) {
- __publicField(this, "options");
- __publicField(this, "rules");
- // set by the lexer
- __publicField(this, "lexer");
- this.options = options || _defaults;
- }
- space(src) {
- const cap = this.rules.block.newline.exec(src);
- if (cap && cap[0].length > 0) {
- return {
- type: "space",
- raw: cap[0]
- };
- }
- }
- code(src) {
- const cap = this.rules.block.code.exec(src);
- if (cap) {
- const text = cap[0].replace(/^ {1,4}/gm, "");
- return {
- type: "code",
- raw: cap[0],
- codeBlockStyle: "indented",
- text: !this.options.pedantic ? rtrim(text, "\n") : text
- };
- }
- }
- fences(src) {
- const cap = this.rules.block.fences.exec(src);
- if (cap) {
- const raw = cap[0];
- const text = indentCodeCompensation(raw, cap[3] || "");
- return {
- type: "code",
- raw,
- lang: cap[2] ? cap[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : cap[2],
- text
- };
- }
- }
- heading(src) {
- const cap = this.rules.block.heading.exec(src);
- if (cap) {
- let text = cap[2].trim();
- if (/#$/.test(text)) {
- const trimmed = rtrim(text, "#");
- if (this.options.pedantic) {
- text = trimmed.trim();
- } else if (!trimmed || / $/.test(trimmed)) {
- text = trimmed.trim();
- }
- }
- return {
- type: "heading",
- raw: cap[0],
- depth: cap[1].length,
- text,
- tokens: this.lexer.inline(text)
- };
- }
- }
- hr(src) {
- const cap = this.rules.block.hr.exec(src);
- if (cap) {
- return {
- type: "hr",
- raw: rtrim(cap[0], "\n")
- };
- }
- }
- blockquote(src) {
- const cap = this.rules.block.blockquote.exec(src);
- if (cap) {
- let lines = rtrim(cap[0], "\n").split("\n");
- let raw = "";
- let text = "";
- const tokens = [];
- while (lines.length > 0) {
- let inBlockquote = false;
- const currentLines = [];
- let i;
- for (i = 0; i < lines.length; i++) {
- if (/^ {0,3}>/.test(lines[i])) {
- currentLines.push(lines[i]);
- inBlockquote = true;
- } else if (!inBlockquote) {
- currentLines.push(lines[i]);
- } else {
- break;
- }
- }
- lines = lines.slice(i);
- const currentRaw = currentLines.join("\n");
- const currentText = currentRaw.replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g, "\n $1").replace(/^ {0,3}>[ \t]?/gm, "");
- raw = raw ? `${raw}
- ${currentRaw}` : currentRaw;
- text = text ? `${text}
- ${currentText}` : currentText;
- const top = this.lexer.state.top;
- this.lexer.state.top = true;
- this.lexer.blockTokens(currentText, tokens, true);
- this.lexer.state.top = top;
- if (lines.length === 0) {
- break;
- }
- const lastToken = tokens[tokens.length - 1];
- if ((lastToken == null ? void 0 : lastToken.type) === "code") {
- break;
- } else if ((lastToken == null ? void 0 : lastToken.type) === "blockquote") {
- const oldToken = lastToken;
- const newText = oldToken.raw + "\n" + lines.join("\n");
- const newToken = this.blockquote(newText);
- tokens[tokens.length - 1] = newToken;
- raw = raw.substring(0, raw.length - oldToken.raw.length) + newToken.raw;
- text = text.substring(0, text.length - oldToken.text.length) + newToken.text;
- break;
- } else if ((lastToken == null ? void 0 : lastToken.type) === "list") {
- const oldToken = lastToken;
- const newText = oldToken.raw + "\n" + lines.join("\n");
- const newToken = this.list(newText);
- tokens[tokens.length - 1] = newToken;
- raw = raw.substring(0, raw.length - lastToken.raw.length) + newToken.raw;
- text = text.substring(0, text.length - oldToken.raw.length) + newToken.raw;
- lines = newText.substring(tokens[tokens.length - 1].raw.length).split("\n");
- continue;
- }
- }
- return {
- type: "blockquote",
- raw,
- tokens,
- text
- };
- }
- }
- list(src) {
- let cap = this.rules.block.list.exec(src);
- if (cap) {
- let bull = cap[1].trim();
- const isordered = bull.length > 1;
- const list2 = {
- type: "list",
- raw: "",
- ordered: isordered,
- start: isordered ? +bull.slice(0, -1) : "",
- loose: false,
- items: []
- };
- bull = isordered ? `\\d{1,9}\\${bull.slice(-1)}` : `\\${bull}`;
- if (this.options.pedantic) {
- bull = isordered ? bull : "[*+-]";
- }
- const itemRegex = new RegExp(`^( {0,3}${bull})((?:[ ][^\\n]*)?(?:\\n|$))`);
- let endsWithBlankLine = false;
- while (src) {
- let endEarly = false;
- let raw = "";
- let itemContents = "";
- if (!(cap = itemRegex.exec(src))) {
- break;
- }
- if (this.rules.block.hr.test(src)) {
- break;
- }
- raw = cap[0];
- src = src.substring(raw.length);
- let line = cap[2].split("\n", 1)[0].replace(/^\t+/, (t) => " ".repeat(3 * t.length));
- let nextLine = src.split("\n", 1)[0];
- let blankLine = !line.trim();
- let indent = 0;
- if (this.options.pedantic) {
- indent = 2;
- itemContents = line.trimStart();
- } else if (blankLine) {
- indent = cap[1].length + 1;
- } else {
- indent = cap[2].search(/[^ ]/);
- indent = indent > 4 ? 1 : indent;
- itemContents = line.slice(indent);
- indent += cap[1].length;
- }
- if (blankLine && /^ *$/.test(nextLine)) {
- raw += nextLine + "\n";
- src = src.substring(nextLine.length + 1);
- endEarly = true;
- }
- if (!endEarly) {
- const nextBulletRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ ][^\\n]*)?(?:\\n|$))`);
- const hrRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`);
- const fencesBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}(?:\`\`\`|~~~)`);
- const headingBeginRegex = new RegExp(`^ {0,${Math.min(3, indent - 1)}}#`);
- while (src) {
- const rawLine = src.split("\n", 1)[0];
- nextLine = rawLine;
- if (this.options.pedantic) {
- nextLine = nextLine.replace(/^ {1,4}(?=( {4})*[^ ])/g, " ");
- }
- if (fencesBeginRegex.test(nextLine)) {
- break;
- }
- if (headingBeginRegex.test(nextLine)) {
- break;
- }
- if (nextBulletRegex.test(nextLine)) {
- break;
- }
- if (hrRegex.test(src)) {
- break;
- }
- if (nextLine.search(/[^ ]/) >= indent || !nextLine.trim()) {
- itemContents += "\n" + nextLine.slice(indent);
- } else {
- if (blankLine) {
- break;
- }
- if (line.search(/[^ ]/) >= 4) {
- break;
- }
- if (fencesBeginRegex.test(line)) {
- break;
- }
- if (headingBeginRegex.test(line)) {
- break;
- }
- if (hrRegex.test(line)) {
- break;
- }
- itemContents += "\n" + nextLine;
- }
- if (!blankLine && !nextLine.trim()) {
- blankLine = true;
- }
- raw += rawLine + "\n";
- src = src.substring(rawLine.length + 1);
- line = nextLine.slice(indent);
- }
- }
- if (!list2.loose) {
- if (endsWithBlankLine) {
- list2.loose = true;
- } else if (/\n *\n *$/.test(raw)) {
- endsWithBlankLine = true;
- }
- }
- let istask = null;
- let ischecked;
- if (this.options.gfm) {
- istask = /^\[[ xX]\] /.exec(itemContents);
- if (istask) {
- ischecked = istask[0] !== "[ ] ";
- itemContents = itemContents.replace(/^\[[ xX]\] +/, "");
- }
- }
- list2.items.push({
- type: "list_item",
- raw,
- task: !!istask,
- checked: ischecked,
- loose: false,
- text: itemContents,
- tokens: []
- });
- list2.raw += raw;
- }
- list2.items[list2.items.length - 1].raw = list2.items[list2.items.length - 1].raw.trimEnd();
- list2.items[list2.items.length - 1].text = list2.items[list2.items.length - 1].text.trimEnd();
- list2.raw = list2.raw.trimEnd();
- for (let i = 0; i < list2.items.length; i++) {
- this.lexer.state.top = false;
- list2.items[i].tokens = this.lexer.blockTokens(list2.items[i].text, []);
- if (!list2.loose) {
- const spacers = list2.items[i].tokens.filter((t) => t.type === "space");
- const hasMultipleLineBreaks = spacers.length > 0 && spacers.some((t) => /\n.*\n/.test(t.raw));
- list2.loose = hasMultipleLineBreaks;
- }
- }
- if (list2.loose) {
- for (let i = 0; i < list2.items.length; i++) {
- list2.items[i].loose = true;
- }
- }
- return list2;
- }
- }
- html(src) {
- const cap = this.rules.block.html.exec(src);
- if (cap) {
- const token = {
- type: "html",
- block: true,
- raw: cap[0],
- pre: cap[1] === "pre" || cap[1] === "script" || cap[1] === "style",
- text: cap[0]
- };
- return token;
- }
- }
- def(src) {
- const cap = this.rules.block.def.exec(src);
- if (cap) {
- const tag2 = cap[1].toLowerCase().replace(/\s+/g, " ");
- const href = cap[2] ? cap[2].replace(/^<(.*)>$/, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "";
- const title = cap[3] ? cap[3].substring(1, cap[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : cap[3];
- return {
- type: "def",
- tag: tag2,
- raw: cap[0],
- href,
- title
- };
- }
- }
- table(src) {
- const cap = this.rules.block.table.exec(src);
- if (!cap) {
- return;
- }
- if (!/[:|]/.test(cap[2])) {
- return;
- }
- const headers = splitCells(cap[1]);
- const aligns = cap[2].replace(/^\||\| *$/g, "").split("|");
- const rows = cap[3] && cap[3].trim() ? cap[3].replace(/\n[ \t]*$/, "").split("\n") : [];
- const item = {
- type: "table",
- raw: cap[0],
- header: [],
- align: [],
- rows: []
- };
- if (headers.length !== aligns.length) {
- return;
- }
- for (const align of aligns) {
- if (/^ *-+: *$/.test(align)) {
- item.align.push("right");
- } else if (/^ *:-+: *$/.test(align)) {
- item.align.push("center");
- } else if (/^ *:-+ *$/.test(align)) {
- item.align.push("left");
- } else {
- item.align.push(null);
- }
- }
- for (let i = 0; i < headers.length; i++) {
- item.header.push({
- text: headers[i],
- tokens: this.lexer.inline(headers[i]),
- header: true,
- align: item.align[i]
- });
- }
- for (const row of rows) {
- item.rows.push(splitCells(row, item.header.length).map((cell, i) => {
- return {
- text: cell,
- tokens: this.lexer.inline(cell),
- header: false,
- align: item.align[i]
- };
- }));
- }
- return item;
- }
- lheading(src) {
- const cap = this.rules.block.lheading.exec(src);
- if (cap) {
- return {
- type: "heading",
- raw: cap[0],
- depth: cap[2].charAt(0) === "=" ? 1 : 2,
- text: cap[1],
- tokens: this.lexer.inline(cap[1])
- };
- }
- }
- paragraph(src) {
- const cap = this.rules.block.paragraph.exec(src);
- if (cap) {
- const text = cap[1].charAt(cap[1].length - 1) === "\n" ? cap[1].slice(0, -1) : cap[1];
- return {
- type: "paragraph",
- raw: cap[0],
- text,
- tokens: this.lexer.inline(text)
- };
- }
- }
- text(src) {
- const cap = this.rules.block.text.exec(src);
- if (cap) {
- return {
- type: "text",
- raw: cap[0],
- text: cap[0],
- tokens: this.lexer.inline(cap[0])
- };
- }
- }
- escape(src) {
- const cap = this.rules.inline.escape.exec(src);
- if (cap) {
- return {
- type: "escape",
- raw: cap[0],
- text: escape$1(cap[1])
- };
- }
- }
- tag(src) {
- const cap = this.rules.inline.tag.exec(src);
- if (cap) {
- if (!this.lexer.state.inLink && /^<a /i.test(cap[0])) {
- this.lexer.state.inLink = true;
- } else if (this.lexer.state.inLink && /^<\/a>/i.test(cap[0])) {
- this.lexer.state.inLink = false;
- }
- if (!this.lexer.state.inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
- this.lexer.state.inRawBlock = true;
- } else if (this.lexer.state.inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
- this.lexer.state.inRawBlock = false;
- }
- return {
- type: "html",
- raw: cap[0],
- inLink: this.lexer.state.inLink,
- inRawBlock: this.lexer.state.inRawBlock,
- block: false,
- text: cap[0]
- };
- }
- }
- link(src) {
- const cap = this.rules.inline.link.exec(src);
- if (cap) {
- const trimmedUrl = cap[2].trim();
- if (!this.options.pedantic && /^</.test(trimmedUrl)) {
- if (!/>$/.test(trimmedUrl)) {
- return;
- }
- const rtrimSlash = rtrim(trimmedUrl.slice(0, -1), "\\");
- if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
- return;
- }
- } else {
- const lastParenIndex = findClosingBracket(cap[2], "()");
- if (lastParenIndex > -1) {
- const start = cap[0].indexOf("!") === 0 ? 5 : 4;
- const linkLen = start + cap[1].length + lastParenIndex;
- cap[2] = cap[2].substring(0, lastParenIndex);
- cap[0] = cap[0].substring(0, linkLen).trim();
- cap[3] = "";
- }
- }
- let href = cap[2];
- let title = "";
- if (this.options.pedantic) {
- const link2 = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
- if (link2) {
- href = link2[1];
- title = link2[3];
- }
- } else {
- title = cap[3] ? cap[3].slice(1, -1) : "";
- }
- href = href.trim();
- if (/^</.test(href)) {
- if (this.options.pedantic && !/>$/.test(trimmedUrl)) {
- href = href.slice(1);
- } else {
- href = href.slice(1, -1);
- }
- }
- return outputLink(cap, {
- href: href ? href.replace(this.rules.inline.anyPunctuation, "$1") : href,
- title: title ? title.replace(this.rules.inline.anyPunctuation, "$1") : title
- }, cap[0], this.lexer);
- }
- }
- reflink(src, links) {
- let cap;
- if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
- const linkString = (cap[2] || cap[1]).replace(/\s+/g, " ");
- const link2 = links[linkString.toLowerCase()];
- if (!link2) {
- const text = cap[0].charAt(0);
- return {
- type: "text",
- raw: text,
- text
- };
- }
- return outputLink(cap, link2, cap[0], this.lexer);
- }
- }
- emStrong(src, maskedSrc, prevChar = "") {
- let match = this.rules.inline.emStrongLDelim.exec(src);
- if (!match)
- return;
- if (match[3] && prevChar.match(/[\p{L}\p{N}]/u))
- return;
- const nextChar = match[1] || match[2] || "";
- if (!nextChar || !prevChar || this.rules.inline.punctuation.exec(prevChar)) {
- const lLength = [...match[0]].length - 1;
- let rDelim, rLength, delimTotal = lLength,
- midDelimTotal = 0;
- const endReg = match[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
- endReg.lastIndex = 0;
- maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
- while ((match = endReg.exec(maskedSrc)) != null) {
- rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
- if (!rDelim)
- continue;
- rLength = [...rDelim].length;
- if (match[3] || match[4]) {
- delimTotal += rLength;
- continue;
- } else if (match[5] || match[6]) {
- if (lLength % 3 && !((lLength + rLength) % 3)) {
- midDelimTotal += rLength;
- continue;
- }
- }
- delimTotal -= rLength;
- if (delimTotal > 0)
- continue;
- rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal);
- const lastCharLength = [...match[0]][0].length;
- const raw = src.slice(0, lLength + match.index + lastCharLength + rLength);
- if (Math.min(lLength, rLength) % 2) {
- const text2 = raw.slice(1, -1);
- return {
- type: "em",
- raw,
- text: text2,
- tokens: this.lexer.inlineTokens(text2)
- };
- }
- const text = raw.slice(2, -2);
- return {
- type: "strong",
- raw,
- text,
- tokens: this.lexer.inlineTokens(text)
- };
- }
- }
- }
- codespan(src) {
- const cap = this.rules.inline.code.exec(src);
- if (cap) {
- let text = cap[2].replace(/\n/g, " ");
- const hasNonSpaceChars = /[^ ]/.test(text);
- const hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
- if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
- text = text.substring(1, text.length - 1);
- }
- text = escape$1(text, true);
- return {
- type: "codespan",
- raw: cap[0],
- text
- };
- }
- }
- br(src) {
- const cap = this.rules.inline.br.exec(src);
- if (cap) {
- return {
- type: "br",
- raw: cap[0]
- };
- }
- }
- del(src) {
- const cap = this.rules.inline.del.exec(src);
- if (cap) {
- return {
- type: "del",
- raw: cap[0],
- text: cap[2],
- tokens: this.lexer.inlineTokens(cap[2])
- };
- }
- }
- autolink(src) {
- const cap = this.rules.inline.autolink.exec(src);
- if (cap) {
- let text, href;
- if (cap[2] === "@") {
- text = escape$1(cap[1]);
- href = "mailto:" + text;
- } else {
- text = escape$1(cap[1]);
- href = text;
- }
- return {
- type: "link",
- raw: cap[0],
- text,
- href,
- tokens: [{
- type: "text",
- raw: text,
- text
- }]
- };
- }
- }
- url(src) {
- var _a;
- let cap;
- if (cap = this.rules.inline.url.exec(src)) {
- let text, href;
- if (cap[2] === "@") {
- text = escape$1(cap[0]);
- href = "mailto:" + text;
- } else {
- let prevCapZero;
- do {
- prevCapZero = cap[0];
- const tmp = ((_a = this.rules.inline._backpedal.exec(cap[0])) == null ? void 0 : _a[0])
- cap[0] = tmp ? tmp : "";
- } while (prevCapZero !== cap[0]);
- text = escape$1(cap[0]);
- if (cap[1] === "www.") {
- href = "http://" + cap[0];
- } else {
- href = cap[0];
- }
- }
- return {
- type: "link",
- raw: cap[0],
- text,
- href,
- tokens: [{
- type: "text",
- raw: text,
- text
- }]
- };
- }
- }
- inlineText(src) {
- const cap = this.rules.inline.text.exec(src);
- if (cap) {
- let text;
- if (this.lexer.state.inRawBlock) {
- text = cap[0];
- } else {
- text = escape$1(cap[0]);
- }
- return {
- type: "text",
- raw: cap[0],
- text
- };
- }
- }
- }
- const newline = /^(?: *(?:\n|$))+/;
- const blockCode = /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/;
- const fences = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
- const hr = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
- const heading = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
- const bullet = /(?:[*+-]|\d{1,9}[.)])/;
- const lheading = edit(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g, bullet).replace(/blockCode/g, / {4}/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).getRegex();
- const _paragraph = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
- const blockText = /^[^\n]+/;
- const _blockLabel = /(?!\s*\])(?:\\.|[^\[\]\\])+/;
- const def = edit(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label", _blockLabel).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
- const list = edit(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, bullet).getRegex();
- const _tag = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
- const _comment = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
- const html = edit("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))", "i").replace("comment", _comment).replace("tag", _tag).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
- const paragraph = edit(_paragraph).replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex();
- const blockquote = edit(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", paragraph).getRegex();
- const blockNormal = {
- blockquote,
- code: blockCode,
- def,
- fences,
- heading,
- hr,
- html,
- lheading,
- list,
- newline,
- paragraph,
- table: noopTest,
- text: blockText
- };
- const gfmTable = edit("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", " {4}[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex();
- const blockGfm = {
- ...blockNormal,
- table: gfmTable,
- paragraph: edit(_paragraph).replace("hr", hr).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", gfmTable).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", _tag).getRegex()
- };
- const blockPedantic = {
- ...blockNormal,
- html: edit(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", _comment).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
- heading: /^(#{1,6})(.*)(?:\n+|$)/,
- fences: noopTest,
- // fences not supported
- lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,
- paragraph: edit(_paragraph).replace("hr", hr).replace("heading", " *#{1,6} *[^\n]").replace("lheading", lheading).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex()
- };
- const escape = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
- const inlineCode = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
- const br = /^( {2,}|\\)\n(?!\s*$)/;
- const inlineText = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
- const _punctuation = "\\p{P}\\p{S}";
- const punctuation = edit(/^((?![*_])[\spunctuation])/, "u").replace(/punctuation/g, _punctuation).getRegex();
- const blockSkip = /\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g;
- const emStrongLDelim = edit(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/, "u").replace(/punct/g, _punctuation).getRegex();
- const emStrongRDelimAst = edit("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])", "gu").replace(/punct/g, _punctuation).getRegex();
- const emStrongRDelimUnd = edit("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])", "gu").replace(/punct/g, _punctuation).getRegex();
- const anyPunctuation = edit(/\\([punct])/, "gu").replace(/punct/g, _punctuation).getRegex();
- const autolink = edit(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
- const _inlineComment = edit(_comment).replace("(?:-->|$)", "-->").getRegex();
- const tag = edit("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", _inlineComment).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
- const _inlineLabel = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
- const link = edit(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label", _inlineLabel).replace("href", /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
- const reflink = edit(/^!?\[(label)\]\[(ref)\]/).replace("label", _inlineLabel).replace("ref", _blockLabel).getRegex();
- const nolink = edit(/^!?\[(ref)\](?:\[\])?/).replace("ref", _blockLabel).getRegex();
- const reflinkSearch = edit("reflink|nolink(?!\\()", "g").replace("reflink", reflink).replace("nolink", nolink).getRegex();
- const inlineNormal = {
- _backpedal: noopTest,
- // only used for GFM url
- anyPunctuation,
- autolink,
- blockSkip,
- br,
- code: inlineCode,
- del: noopTest,
- emStrongLDelim,
- emStrongRDelimAst,
- emStrongRDelimUnd,
- escape,
- link,
- nolink,
- punctuation,
- reflink,
- reflinkSearch,
- tag,
- text: inlineText,
- url: noopTest
- };
- const inlinePedantic = {
- ...inlineNormal,
- link: edit(/^!?\[(label)\]\((.*?)\)/).replace("label", _inlineLabel).getRegex(),
- reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", _inlineLabel).getRegex()
- };
- const inlineGfm = {
- ...inlineNormal,
- escape: edit(escape).replace("])", "~|])").getRegex(),
- url: edit(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/, "i").replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(),
- _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/,
- del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
- text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
- };
- const inlineBreaks = {
- ...inlineGfm,
- br: edit(br).replace("{2,}", "*").getRegex(),
- text: edit(inlineGfm.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex()
- };
- const block = {
- normal: blockNormal,
- gfm: blockGfm,
- pedantic: blockPedantic
- };
- const inline = {
- normal: inlineNormal,
- gfm: inlineGfm,
- breaks: inlineBreaks,
- pedantic: inlinePedantic
- };
- class _Lexer {
- constructor(options) {
- __publicField(this, "tokens");
- __publicField(this, "options");
- __publicField(this, "state");
- __publicField(this, "tokenizer");
- __publicField(this, "inlineQueue");
- this.tokens = [];
- this.tokens.links = /* @__PURE__ */ Object.create(null);
- this.options = options || _defaults;
- this.options.tokenizer = this.options.tokenizer || new _Tokenizer();
- this.tokenizer = this.options.tokenizer;
- this.tokenizer.options = this.options;
- this.tokenizer.lexer = this;
- this.inlineQueue = [];
- this.state = {
- inLink: false,
- inRawBlock: false,
- top: true
- };
- const rules = {
- block: block.normal,
- inline: inline.normal
- };
- if (this.options.pedantic) {
- rules.block = block.pedantic;
- rules.inline = inline.pedantic;
- } else if (this.options.gfm) {
- rules.block = block.gfm;
- if (this.options.breaks) {
- rules.inline = inline.breaks;
- } else {
- rules.inline = inline.gfm;
- }
- }
- this.tokenizer.rules = rules;
- }
- /**
- * Expose Rules
- */
- static get rules() {
- return {
- block,
- inline
- };
- }
- /**
- * Static Lex Method
- */
- static lex(src, options) {
- const lexer = new _Lexer(options);
- return lexer.lex(src);
- }
- /**
- * Static Lex Inline Method
- */
- static lexInline(src, options) {
- const lexer = new _Lexer(options);
- return lexer.inlineTokens(src);
- }
- /**
- * Preprocessing
- */
- lex(src) {
- src = src.replace(/\r\n|\r/g, "\n");
- this.blockTokens(src, this.tokens);
- for (let i = 0; i < this.inlineQueue.length; i++) {
- const next = this.inlineQueue[i];
- this.inlineTokens(next.src, next.tokens);
- }
- this.inlineQueue = [];
- return this.tokens;
- }
- blockTokens(src, tokens = [], lastParagraphClipped = false) {
- if (this.options.pedantic) {
- src = src.replace(/\t/g, " ").replace(/^ +$/gm, "");
- } else {
- src = src.replace(/^( *)(\t+)/gm, (_, leading, tabs) => {
- return leading + " ".repeat(tabs.length);
- });
- }
- let token;
- let lastToken;
- let cutSrc;
- while (src) {
- if (this.options.extensions && this.options.extensions.block && this.options.extensions.block.some((extTokenizer) => {
- if (token = extTokenizer.call({
- lexer: this
- }, src, tokens)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- return true;
- }
- return false;
- })) {
- continue;
- }
- if (token = this.tokenizer.space(src)) {
- src = src.substring(token.raw.length);
- if (token.raw.length === 1 && tokens.length > 0) {
- tokens[tokens.length - 1].raw += "\n";
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (token = this.tokenizer.code(src)) {
- src = src.substring(token.raw.length);
- lastToken = tokens[tokens.length - 1];
- if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
- lastToken.raw += "\n" + token.raw;
- lastToken.text += "\n" + token.text;
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (token = this.tokenizer.fences(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.heading(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.hr(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.blockquote(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.list(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.html(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.def(src)) {
- src = src.substring(token.raw.length);
- lastToken = tokens[tokens.length - 1];
- if (lastToken && (lastToken.type === "paragraph" || lastToken.type === "text")) {
- lastToken.raw += "\n" + token.raw;
- lastToken.text += "\n" + token.raw;
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
- } else if (!this.tokens.links[token.tag]) {
- this.tokens.links[token.tag] = {
- href: token.href,
- title: token.title
- };
- }
- continue;
- }
- if (token = this.tokenizer.table(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.lheading(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- cutSrc = src;
- if (this.options.extensions && this.options.extensions.startBlock) {
- let startIndex = Infinity;
- const tempSrc = src.slice(1);
- let tempStart;
- this.options.extensions.startBlock.forEach((getStartIndex) => {
- tempStart = getStartIndex.call({
- lexer: this
- }, tempSrc);
- if (typeof tempStart === "number" && tempStart >= 0) {
- startIndex = Math.min(startIndex, tempStart);
- }
- });
- if (startIndex < Infinity && startIndex >= 0) {
- cutSrc = src.substring(0, startIndex + 1);
- }
- }
- if (this.state.top && (token = this.tokenizer.paragraph(cutSrc))) {
- lastToken = tokens[tokens.length - 1];
- if (lastParagraphClipped && (lastToken == null ? void 0 : lastToken.type) === "paragraph") {
- lastToken.raw += "\n" + token.raw;
- lastToken.text += "\n" + token.text;
- this.inlineQueue.pop();
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
- } else {
- tokens.push(token);
- }
- lastParagraphClipped = cutSrc.length !== src.length;
- src = src.substring(token.raw.length);
- continue;
- }
- if (token = this.tokenizer.text(src)) {
- src = src.substring(token.raw.length);
- lastToken = tokens[tokens.length - 1];
- if (lastToken && lastToken.type === "text") {
- lastToken.raw += "\n" + token.raw;
- lastToken.text += "\n" + token.text;
- this.inlineQueue.pop();
- this.inlineQueue[this.inlineQueue.length - 1].src = lastToken.text;
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (src) {
- const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
- if (this.options.silent) {
- console.error(errMsg);
- break;
- } else {
- throw new Error(errMsg);
- }
- }
- }
- this.state.top = true;
- return tokens;
- }
- inline(src, tokens = []) {
- this.inlineQueue.push({
- src,
- tokens
- });
- return tokens;
- }
- /**
- * Lexing/Compiling
- */
- inlineTokens(src, tokens = []) {
- let token, lastToken, cutSrc;
- let maskedSrc = src;
- let match;
- let keepPrevChar, prevChar;
- if (this.tokens.links) {
- const links = Object.keys(this.tokens.links);
- if (links.length > 0) {
- while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
- if (links.includes(match[0].slice(match[0].lastIndexOf("[") + 1, -1))) {
- maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
- }
- }
- }
- }
- while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
- maskedSrc = maskedSrc.slice(0, match.index) + "[" + "a".repeat(match[0].length - 2) + "]" + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
- }
- while ((match = this.tokenizer.rules.inline.anyPunctuation.exec(maskedSrc)) != null) {
- maskedSrc = maskedSrc.slice(0, match.index) + "++" + maskedSrc.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
- }
- while (src) {
- if (!keepPrevChar) {
- prevChar = "";
- }
- keepPrevChar = false;
- if (this.options.extensions && this.options.extensions.inline && this.options.extensions.inline.some((extTokenizer) => {
- if (token = extTokenizer.call({
- lexer: this
- }, src, tokens)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- return true;
- }
- return false;
- })) {
- continue;
- }
- if (token = this.tokenizer.escape(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.tag(src)) {
- src = src.substring(token.raw.length);
- lastToken = tokens[tokens.length - 1];
- if (lastToken && token.type === "text" && lastToken.type === "text") {
- lastToken.raw += token.raw;
- lastToken.text += token.text;
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (token = this.tokenizer.link(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.reflink(src, this.tokens.links)) {
- src = src.substring(token.raw.length);
- lastToken = tokens[tokens.length - 1];
- if (lastToken && token.type === "text" && lastToken.type === "text") {
- lastToken.raw += token.raw;
- lastToken.text += token.text;
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.codespan(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.br(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.del(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (token = this.tokenizer.autolink(src)) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- if (!this.state.inLink && (token = this.tokenizer.url(src))) {
- src = src.substring(token.raw.length);
- tokens.push(token);
- continue;
- }
- cutSrc = src;
- if (this.options.extensions && this.options.extensions.startInline) {
- let startIndex = Infinity;
- const tempSrc = src.slice(1);
- let tempStart;
- this.options.extensions.startInline.forEach((getStartIndex) => {
- tempStart = getStartIndex.call({
- lexer: this
- }, tempSrc);
- if (typeof tempStart === "number" && tempStart >= 0) {
- startIndex = Math.min(startIndex, tempStart);
- }
- });
- if (startIndex < Infinity && startIndex >= 0) {
- cutSrc = src.substring(0, startIndex + 1);
- }
- }
- if (token = this.tokenizer.inlineText(cutSrc)) {
- src = src.substring(token.raw.length);
- if (token.raw.slice(-1) !== "_") {
- prevChar = token.raw.slice(-1);
- }
- keepPrevChar = true;
- lastToken = tokens[tokens.length - 1];
- if (lastToken && lastToken.type === "text") {
- lastToken.raw += token.raw;
- lastToken.text += token.text;
- } else {
- tokens.push(token);
- }
- continue;
- }
- if (src) {
- const errMsg = "Infinite loop on byte: " + src.charCodeAt(0);
- if (this.options.silent) {
- console.error(errMsg);
- break;
- } else {
- throw new Error(errMsg);
- }
- }
- }
- return tokens;
- }
- }
- class _Renderer {
- // set by the parser
- constructor(options) {
- __publicField(this, "options");
- __publicField(this, "parser");
- this.options = options || _defaults;
- }
- space(token) {
- return "";
- }
- code({
- text,
- lang,
- escaped
- }) {
- var _a;
- const langString = (_a = (lang || "").match(/^\S*/)) == null ? void 0 : _a[0];
- const code = text.replace(/\n$/, "") + "\n";
- if (!langString) {
- return "<pre><code>" + (escaped ? code : escape$1(code, true)) + "</code></pre>\n";
- }
- return '<pre><code class="language-' + escape$1(langString) + '">' + (escaped ? code : escape$1(code, true)) + "</code></pre>\n";
- }
- blockquote({
- tokens
- }) {
- const body = this.parser.parse(tokens);
- return `<blockquote>
- ${body}</blockquote>
- `;
- }
- html({
- text
- }) {
- return text;
- }
- heading({
- tokens,
- depth
- }) {
- return `<h${depth}>${this.parser.parseInline(tokens)}</h${depth}>
- `;
- }
- hr(token) {
- return "<hr>\n";
- }
- list(token) {
- const ordered = token.ordered;
- const start = token.start;
- let body = "";
- for (let j = 0; j < token.items.length; j++) {
- const item = token.items[j];
- body += this.listitem(item);
- }
- const type = ordered ? "ol" : "ul";
- const startAttr = ordered && start !== 1 ? ' start="' + start + '"' : "";
- return "<" + type + startAttr + ">\n" + body + "</" + type + ">\n";
- }
- listitem(item) {
- let itemBody = "";
- if (item.task) {
- const checkbox = this.checkbox({
- checked: !!item.checked
- });
- if (item.loose) {
- if (item.tokens.length > 0 && item.tokens[0].type === "paragraph") {
- item.tokens[0].text = checkbox + " " + item.tokens[0].text;
- if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === "text") {
- item.tokens[0].tokens[0].text = checkbox + " " + item.tokens[0].tokens[0].text;
- }
- } else {
- item.tokens.unshift({
- type: "text",
- raw: checkbox + " ",
- text: checkbox + " "
- });
- }
- } else {
- itemBody += checkbox + " ";
- }
- }
- itemBody += this.parser.parse(item.tokens, !!item.loose);
- return `<li>${itemBody}</li>
- `;
- }
- checkbox({
- checked
- }) {
- return "<input " + (checked ? 'checked="" ' : "") + 'disabled="" type="checkbox">';
- }
- paragraph({
- tokens
- }) {
- return `<p>${this.parser.parseInline(tokens)}</p>
- `;
- }
- table(token) {
- let header = "";
- let cell = "";
- for (let j = 0; j < token.header.length; j++) {
- cell += this.tablecell(token.header[j]);
- }
- header += this.tablerow({
- text: cell
- });
- let body = "";
- for (let j = 0; j < token.rows.length; j++) {
- const row = token.rows[j];
- cell = "";
- for (let k = 0; k < row.length; k++) {
- cell += this.tablecell(row[k]);
- }
- body += this.tablerow({
- text: cell
- });
- }
- if (body)
- body = `<tbody>${body}</tbody>`;
- return "<table>\n<thead>\n" + header + "</thead>\n" + body + "</table>\n";
- }
- tablerow({
- text
- }) {
- return `<tr>
- ${text}</tr>
- `;
- }
- tablecell(token) {
- const content = this.parser.parseInline(token.tokens);
- const type = token.header ? "th" : "td";
- const tag2 = token.align ? `<${type} align="${token.align}">` : `<${type}>`;
- return tag2 + content + `</${type}>
- `;
- }
- /**
- * span level renderer
- */
- strong({
- tokens
- }) {
- return `<strong>${this.parser.parseInline(tokens)}</strong>`;
- }
- em({
- tokens
- }) {
- return `<em>${this.parser.parseInline(tokens)}</em>`;
- }
- codespan({
- text
- }) {
- return `<code>${text}</code>`;
- }
- br(token) {
- return "<br>";
- }
- del({
- tokens
- }) {
- return `<del>${this.parser.parseInline(tokens)}</del>`;
- }
- link({
- href,
- title,
- tokens
- }) {
- const text = this.parser.parseInline(tokens);
- const cleanHref = cleanUrl(href);
- if (cleanHref === null) {
- return text;
- }
- href = cleanHref;
- let out = '<a href="' + href + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += ">" + text + "</a>";
- return out;
- }
- image({
- href,
- title,
- text
- }) {
- const cleanHref = cleanUrl(href);
- if (cleanHref === null) {
- return text;
- }
- href = cleanHref;
- let out = `<img src="${href}" alt="${text}"`;
- if (title) {
- out += ` title="${title}"`;
- }
- out += ">";
- return out;
- }
- text(token) {
- return "tokens" in token && token.tokens ? this.parser.parseInline(token.tokens) : token.text;
- }
- }
- class _TextRenderer {
- // no need for block level renderers
- strong({
- text
- }) {
- return text;
- }
- em({
- text
- }) {
- return text;
- }
- codespan({
- text
- }) {
- return text;
- }
- del({
- text
- }) {
- return text;
- }
- html({
- text
- }) {
- return text;
- }
- text({
- text
- }) {
- return text;
- }
- link({
- text
- }) {
- return "" + text;
- }
- image({
- text
- }) {
- return "" + text;
- }
- br() {
- return "";
- }
- }
- class _Parser {
- constructor(options) {
- __publicField(this, "options");
- __publicField(this, "renderer");
- __publicField(this, "textRenderer");
- this.options = options || _defaults;
- this.options.renderer = this.options.renderer || new _Renderer();
- this.renderer = this.options.renderer;
- this.renderer.options = this.options;
- this.renderer.parser = this;
- this.textRenderer = new _TextRenderer();
- }
- /**
- * Static Parse Method
- */
- static parse(tokens, options) {
- const parser = new _Parser(options);
- return parser.parse(tokens);
- }
- /**
- * Static Parse Inline Method
- */
- static parseInline(tokens, options) {
- const parser = new _Parser(options);
- return parser.parseInline(tokens);
- }
- /**
- * Parse Loop
- */
- parse(tokens, top = true) {
- let out = "";
- for (let i = 0; i < tokens.length; i++) {
- const anyToken = tokens[i];
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
- const genericToken = anyToken;
- const ret = this.options.extensions.renderers[genericToken.type].call({
- parser: this
- }, genericToken);
- if (ret !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "paragraph", "text"].includes(genericToken.type)) {
- out += ret || "";
- continue;
- }
- }
- const token = anyToken;
- switch (token.type) {
- case "space": {
- out += this.renderer.space(token);
- continue;
- }
- case "hr": {
- out += this.renderer.hr(token);
- continue;
- }
- case "heading": {
- out += this.renderer.heading(token);
- continue;
- }
- case "code": {
- out += this.renderer.code(token);
- continue;
- }
- case "table": {
- out += this.renderer.table(token);
- continue;
- }
- case "blockquote": {
- out += this.renderer.blockquote(token);
- continue;
- }
- case "list": {
- out += this.renderer.list(token);
- continue;
- }
- case "html": {
- out += this.renderer.html(token);
- continue;
- }
- case "paragraph": {
- out += this.renderer.paragraph(token);
- continue;
- }
- case "text": {
- let textToken = token;
- let body = this.renderer.text(textToken);
- while (i + 1 < tokens.length && tokens[i + 1].type === "text") {
- textToken = tokens[++i];
- body += "\n" + this.renderer.text(textToken);
- }
- if (top) {
- out += this.renderer.paragraph({
- type: "paragraph",
- raw: body,
- text: body,
- tokens: [{
- type: "text",
- raw: body,
- text: body
- }]
- });
- } else {
- out += body;
- }
- continue;
- }
- default: {
- const errMsg = 'Token with "' + token.type + '" type was not found.';
- if (this.options.silent) {
- console.error(errMsg);
- return "";
- } else {
- throw new Error(errMsg);
- }
- }
- }
- }
- return out;
- }
- /**
- * Parse Inline Tokens
- */
- parseInline(tokens, renderer) {
- renderer = renderer || this.renderer;
- let out = "";
- for (let i = 0; i < tokens.length; i++) {
- const anyToken = tokens[i];
- if (this.options.extensions && this.options.extensions.renderers && this.options.extensions.renderers[anyToken.type]) {
- const ret = this.options.extensions.renderers[anyToken.type].call({
- parser: this
- }, anyToken);
- if (ret !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(anyToken.type)) {
- out += ret || "";
- continue;
- }
- }
- const token = anyToken;
- switch (token.type) {
- case "escape": {
- out += renderer.text(token);
- break;
- }
- case "html": {
- out += renderer.html(token);
- break;
- }
- case "link": {
- out += renderer.link(token);
- break;
- }
- case "image": {
- out += renderer.image(token);
- break;
- }
- case "strong": {
- out += renderer.strong(token);
- break;
- }
- case "em": {
- out += renderer.em(token);
- break;
- }
- case "codespan": {
- out += renderer.codespan(token);
- break;
- }
- case "br": {
- out += renderer.br(token);
- break;
- }
- case "del": {
- out += renderer.del(token);
- break;
- }
- case "text": {
- out += renderer.text(token);
- break;
- }
- default: {
- const errMsg = 'Token with "' + token.type + '" type was not found.';
- if (this.options.silent) {
- console.error(errMsg);
- return "";
- } else {
- throw new Error(errMsg);
- }
- }
- }
- }
- return out;
- }
- }
- class _Hooks {
- constructor(options) {
- __publicField(this, "options");
- __publicField(this, "block");
- this.options = options || _defaults;
- }
- /**
- * Process markdown before marked
- */
- preprocess(markdown) {
- return markdown;
- }
- /**
- * Process HTML after marked is finished
- */
- postprocess(html2) {
- return html2;
- }
- /**
- * Process all tokens before walk tokens
- */
- processAllTokens(tokens) {
- return tokens;
- }
- /**
- * Provide function to tokenize markdown
- */
- provideLexer() {
- return this.block ? _Lexer.lex : _Lexer.lexInline;
- }
- /**
- * Provide function to parse tokens
- */
- provideParser() {
- return this.block ? _Parser.parse : _Parser.parseInline;
- }
- }
- __publicField(_Hooks, "passThroughHooks", /* @__PURE__ */ new Set([
- "preprocess",
- "postprocess",
- "processAllTokens"
- ]));
- class Marked {
- constructor(...args) {
- __publicField(this, "defaults", _getDefaults());
- __publicField(this, "options", this.setOptions);
- __publicField(this, "parse", this.parseMarkdown(true));
- __publicField(this, "parseInline", this.parseMarkdown(false));
- __publicField(this, "Parser", _Parser);
- __publicField(this, "Renderer", _Renderer);
- __publicField(this, "TextRenderer", _TextRenderer);
- __publicField(this, "Lexer", _Lexer);
- __publicField(this, "Tokenizer", _Tokenizer);
- __publicField(this, "Hooks", _Hooks);
- this.use(...args);
- }
- /**
- * Run callback for every token
- */
- walkTokens(tokens, callback) {
- var _a, _b;
- let values = [];
- for (const token of tokens) {
- values = values.concat(callback.call(this, token));
- switch (token.type) {
- case "table": {
- const tableToken = token;
- for (const cell of tableToken.header) {
- values = values.concat(this.walkTokens(cell.tokens, callback));
- }
- for (const row of tableToken.rows) {
- for (const cell of row) {
- values = values.concat(this.walkTokens(cell.tokens, callback));
- }
- }
- break;
- }
- case "list": {
- const listToken = token;
- values = values.concat(this.walkTokens(listToken.items, callback));
- break;
- }
- default: {
- const genericToken = token;
- if ((_b = (_a = this.defaults.extensions) == null ? void 0 : _a.childTokens) == null ? void 0 : _b[genericToken.type]) {
- this.defaults.extensions.childTokens[genericToken.type].forEach((childTokens) => {
- const tokens2 = genericToken[childTokens].flat(Infinity);
- values = values.concat(this.walkTokens(tokens2, callback));
- });
- } else if (genericToken.tokens) {
- values = values.concat(this.walkTokens(genericToken.tokens, callback));
- }
- }
- }
- }
- return values;
- }
- use(...args) {
- const extensions = this.defaults.extensions || {
- renderers: {},
- childTokens: {}
- };
- args.forEach((pack) => {
- const opts = {
- ...pack
- };
- opts.async = this.defaults.async || opts.async || false;
- if (pack.extensions) {
- pack.extensions.forEach((ext) => {
- if (!ext.name) {
- throw new Error("extension name required");
- }
- if ("renderer" in ext) {
- const prevRenderer = extensions.renderers[ext.name];
- if (prevRenderer) {
- extensions.renderers[ext.name] = function (...args2) {
- let ret = ext.renderer.apply(this, args2);
- if (ret === false) {
- ret = prevRenderer.apply(this, args2);
- }
- return ret;
- };
- } else {
- extensions.renderers[ext.name] = ext.renderer;
- }
- }
- if ("tokenizer" in ext) {
- if (!ext.level || ext.level !== "block" && ext.level !== "inline") {
- throw new Error("extension level must be 'block' or 'inline'");
- }
- const extLevel = extensions[ext.level];
- if (extLevel) {
- extLevel.unshift(ext.tokenizer);
- } else {
- extensions[ext.level] = [ext.tokenizer];
- }
- if (ext.start) {
- if (ext.level === "block") {
- if (extensions.startBlock) {
- extensions.startBlock.push(ext.start);
- } else {
- extensions.startBlock = [ext.start];
- }
- } else if (ext.level === "inline") {
- if (extensions.startInline) {
- extensions.startInline.push(ext.start);
- } else {
- extensions.startInline = [ext.start];
- }
- }
- }
- }
- if ("childTokens" in ext && ext.childTokens) {
- extensions.childTokens[ext.name] = ext.childTokens;
- }
- });
- opts.extensions = extensions;
- }
- if (pack.renderer) {
- const renderer = this.defaults.renderer || new _Renderer(this.defaults);
- for (const prop in pack.renderer) {
- if (!(prop in renderer)) {
- throw new Error(`renderer '${prop}' does not exist`);
- }
- if (["options", "parser"].includes(prop)) {
- continue;
- }
- const rendererProp = prop;
- const rendererFunc = pack.renderer[rendererProp];
- const prevRenderer = renderer[rendererProp];
- renderer[rendererProp] = (...args2) => {
- let ret = rendererFunc.apply(renderer, args2);
- if (ret === false) {
- ret = prevRenderer.apply(renderer, args2);
- }
- return ret || "";
- };
- }
- opts.renderer = renderer;
- }
- if (pack.tokenizer) {
- const tokenizer = this.defaults.tokenizer || new _Tokenizer(this.defaults);
- for (const prop in pack.tokenizer) {
- if (!(prop in tokenizer)) {
- throw new Error(`tokenizer '${prop}' does not exist`);
- }
- if (["options", "rules", "lexer"].includes(prop)) {
- continue;
- }
- const tokenizerProp = prop;
- const tokenizerFunc = pack.tokenizer[tokenizerProp];
- const prevTokenizer = tokenizer[tokenizerProp];
- tokenizer[tokenizerProp] = (...args2) => {
- let ret = tokenizerFunc.apply(tokenizer, args2);
- if (ret === false) {
- ret = prevTokenizer.apply(tokenizer, args2);
- }
- return ret;
- };
- }
- opts.tokenizer = tokenizer;
- }
- if (pack.hooks) {
- const hooks = this.defaults.hooks || new _Hooks();
- for (const prop in pack.hooks) {
- if (!(prop in hooks)) {
- throw new Error(`hook '${prop}' does not exist`);
- }
- if (["options", "block"].includes(prop)) {
- continue;
- }
- const hooksProp = prop;
- const hooksFunc = pack.hooks[hooksProp];
- const prevHook = hooks[hooksProp];
- if (_Hooks.passThroughHooks.has(prop)) {
- hooks[hooksProp] = (arg) => {
- if (this.defaults.async) {
- return Promise.resolve(hooksFunc.call(hooks, arg)).then((ret2) => {
- return prevHook.call(hooks, ret2);
- });
- }
- const ret = hooksFunc.call(hooks, arg);
- return prevHook.call(hooks, ret);
- };
- } else {
- hooks[hooksProp] = (...args2) => {
- let ret = hooksFunc.apply(hooks, args2);
- if (ret === false) {
- ret = prevHook.apply(hooks, args2);
- }
- return ret;
- };
- }
- }
- opts.hooks = hooks;
- }
- if (pack.walkTokens) {
- const walkTokens = this.defaults.walkTokens;
- const packWalktokens = pack.walkTokens;
- opts.walkTokens = function (token) {
- let values = [];
- values.push(packWalktokens.call(this, token));
- if (walkTokens) {
- values = values.concat(walkTokens.call(this, token));
- }
- return values;
- };
- }
- this.defaults = {
- ...this.defaults,
- ...opts
- };
- });
- return this;
- }
- setOptions(opt) {
- this.defaults = {
- ...this.defaults,
- ...opt
- };
- return this;
- }
- lexer(src, options) {
- return _Lexer.lex(src, options ? options : this.defaults);
- }
- parser(tokens, options) {
- return _Parser.parse(tokens, options ? options : this.defaults);
- }
- parseMarkdown(blockType) {
- const parse = (src, options) => {
- const origOpt = {
- ...options
- };
- const opt = {
- ...this.defaults,
- ...origOpt
- };
- const throwError = this.onError(!!opt.silent, !!opt.async);
- if (this.defaults.async === true && origOpt.async === false) {
- return throwError(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
- }
- if (typeof src === "undefined" || src === null) {
- return throwError(new Error("marked(): input parameter is undefined or null"));
- }
- if (typeof src !== "string") {
- return throwError(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(src) + ", string expected"));
- }
- if (opt.hooks) {
- opt.hooks.options = opt;
- opt.hooks.block = blockType;
- }
- const lexer = opt.hooks ? opt.hooks.provideLexer() : blockType ? _Lexer.lex : _Lexer.lexInline;
- const parser = opt.hooks ? opt.hooks.provideParser() : blockType ? _Parser.parse : _Parser.parseInline;
- if (opt.async) {
- return Promise.resolve(opt.hooks ? opt.hooks.preprocess(src) : src).then((src2) => lexer(src2, opt)).then((tokens) => opt.hooks ? opt.hooks.processAllTokens(tokens) : tokens).then((tokens) => opt.walkTokens ? Promise.all(this.walkTokens(tokens, opt.walkTokens)).then(() => tokens) : tokens).then((tokens) => parser(tokens, opt)).then((html2) => opt.hooks ? opt.hooks.postprocess(html2) : html2).catch(throwError);
- }
- try {
- if (opt.hooks) {
- src = opt.hooks.preprocess(src);
- }
- let tokens = lexer(src, opt);
- if (opt.hooks) {
- tokens = opt.hooks.processAllTokens(tokens);
- }
- if (opt.walkTokens) {
- this.walkTokens(tokens, opt.walkTokens);
- }
- let html2 = parser(tokens, opt);
- if (opt.hooks) {
- html2 = opt.hooks.postprocess(html2);
- }
- return html2;
- } catch (e) {
- return throwError(e);
- }
- };
- return parse;
- }
- onError(silent, async) {
- return (e) => {
- e.message += "\nPlease report this to https://github.com/markedjs/marked.";
- if (silent) {
- const msg = "<p>An error occurred:</p><pre>" + escape$1(e.message + "", true) + "</pre>";
- if (async) {
- return Promise.resolve(msg);
- }
- return msg;
- }
- if (async) {
- return Promise.reject(e);
- }
- throw e;
- };
- }
- }
- const markedInstance = new Marked();
- function marked(src, opt) {
- return markedInstance.parse(src, opt);
- }
- marked.options = marked.setOptions = function (options) {
- markedInstance.setOptions(options);
- marked.defaults = markedInstance.defaults;
- changeDefaults(marked.defaults);
- return marked;
- };
- marked.getDefaults = _getDefaults;
- marked.defaults = _defaults;
- marked.use = function (...args) {
- markedInstance.use(...args);
- marked.defaults = markedInstance.defaults;
- changeDefaults(marked.defaults);
- return marked;
- };
- marked.walkTokens = function (tokens, callback) {
- return markedInstance.walkTokens(tokens, callback);
- };
- marked.parseInline = markedInstance.parseInline;
- marked.Parser = _Parser;
- marked.parser = _Parser.parse;
- marked.Renderer = _Renderer;
- marked.TextRenderer = _TextRenderer;
- marked.Lexer = _Lexer;
- marked.lexer = _Lexer.lex;
- marked.Tokenizer = _Tokenizer;
- marked.Hooks = _Hooks;
- marked.parse = marked;
- marked.options;
- marked.setOptions;
- marked.use;
- marked.walkTokens;
- marked.parseInline;
- _Parser.parse;
- _Lexer.lex;
- function md2html(md) {
- return marked(md);
- }
- const _export_sfc = (sfc, props) => {
- const target = sfc.__vccOpts || sfc;
- for (const [key, val] of props) {
- target[key] = val;
- }
- return target;
- };
- const _withScopeId = (n) => (vue.pushScopeId("data-v-1db30056"), n = n(), vue.popScopeId(), n);
- const _hoisted_1 = {
- class: "monkeygpt-card"
- };
- const _hoisted_2 = {
- class: "monkeygpt-header"
- };
- const _hoisted_3 = {
- key: 0,
- class: "nav"
- };
- const _hoisted_4 = {
- class: "title"
- };
- const _hoisted_5 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("a", {
- href: "https://github.com/weekend-project-space/monkey-gpt"
- }, [
- /* @__PURE__ */
- vue.createElementVNode("img", {
- src: "https://img.shields.io/github/stars/weekend-project-space/monkey-gpt.svg?style=social&label=Stars",
- alt: ""
- })
- ], -1));
- const _hoisted_6 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("path", {
- d: "M18 6L6 18M6 6l12 12",
- stroke: "black",
- "stroke-width": "2",
- "stroke-linecap": "round"
- }, null, -1));
- const _hoisted_7 = [
- _hoisted_6
- ];
- const _hoisted_8 = {
- key: 0,
- class: "monkeygpt-body"
- };
- const _hoisted_9 = {
- key: 0,
- class: "loading",
- viewBox: "0 0 100 100",
- xmlns: "http://www.w3.org/2000/svg"
- };
- const _hoisted_10 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("circle", {
- cx: "50",
- cy: "50",
- r: "0",
- fill: "black"
- }, [
- /* @__PURE__ */
- vue.createElementVNode("animate", {
- attributeName: "r",
- values: "10;30;10",
- dur: "1s",
- repeatCount: "indefinite"
- })
- ], -1));
- const _hoisted_11 = [
- _hoisted_10
- ];
- const _hoisted_12 = ["innerHTML"];
- const _sfc_main$1 = {
- __name: "MonkeyGPT",
- props: {
- msg: String
- },
- setup(__props) {
- const txt = vue.ref("");
- const loading = vue.ref(false);
- const canSearch = vue.ref(false);
- function getText() {
- loading.value = true;
- txt.value = md2html(getSimpleText());
- loading.value = false;
- }
- async function chat2(chatfun) {
- clear();
- loading.value = true;
- try {
- txt.value = md2html(await chatfun(getSimpleText()));
- } catch {
- txt.value = "生成失败,请检查配置是否正确并刷新重试!";
- }
- loading.value = false;
- }
- function clear() {
- txt.value = "";
- }
- window.addEventListener("hashchange", () => {
- clear();
- autoSearch();
- });
- window.addEventListener("popstate", () => {
- clear();
- autoSearch();
- });
- autoSearch();
- function autoSearch() {
- const searchKey = getSearchKey();
- canSearch.value = false;
- if (searchKey) {
- canSearch.value = true;
- chat2(async () => {
- return `### 以下是针对 "${searchKey}" 生成的结果
- ` + await search(searchKey);
- });
- }
- }
- const bodyShow = vue.computed(() => loading.value || txt.value);
- return (_ctx, _cache) => {
- return vue.openBlock(), vue.createElementBlock("div", {
- class: vue.normalizeClass({
- "monkeygpt-warp": bodyShow.value
- })
- }, [
- vue.createElementVNode("div", _hoisted_1, [
- vue.createElementVNode("div", _hoisted_2, [
- bodyShow.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
- vue.createElementVNode("h3", _hoisted_4, [
- vue.createTextVNode(vue.toDisplayString(__props.msg) + " ", 1),
- _hoisted_5
- ]),
- (vue.openBlock(), vue.createElementBlock("svg", {
- class: "close",
- onClick: clear,
- viewBox: "0 0 24 24",
- xmlns: "http://www.w3.org/2000/svg"
- }, _hoisted_7))
- ])) : vue.createCommentVNode("", true),
- vue.createElementVNode("div", null, [
- canSearch.value ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
- key: 0
- }, [
- vue.createElementVNode("button", {
- onClick: autoSearch
- }, "生成"),
- vue.createElementVNode("button", {
- onClick: _cache[0] || (_cache[0] = ($event) => chat2(vue.unref(summarize)))
- }, "总结本页面")
- ], 64)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, {
- key: 1
- }, [
- vue.createElementVNode("button", {
- onClick: getText
- }, "正文"),
- vue.createElementVNode("button", {
- onClick: _cache[1] || (_cache[1] = ($event) => chat2(vue.unref(summarize)))
- }, "总结"),
- vue.createElementVNode("button", {
- onClick: _cache[2] || (_cache[2] = ($event) => chat2(vue.unref(ask)))
- }, "回复")
- ], 64))
- ])
- ]),
- txt.value || loading.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_8, [
- loading.value ? (vue.openBlock(), vue.createElementBlock("svg", _hoisted_9, _hoisted_11)) : txt.value ? (vue.openBlock(), vue.createElementBlock("div", {
- key: 1,
- innerHTML: txt.value
- }, null, 8, _hoisted_12)) : vue.createCommentVNode("", true)
- ])) : vue.createCommentVNode("", true)
- ])
- ], 2);
- };
- }
- };
- const MonkeyGPT = /* @__PURE__ */ _export_sfc(_sfc_main$1, [
- ["__scopeId", "data-v-1db30056"]
- ]);
- const _sfc_main = {
- __name: "App",
- setup(__props) {
- return (_ctx, _cache) => {
- return vue.openBlock(), vue.createBlock(MonkeyGPT, {
- msg: "monkey gpt"
- });
- };
- }
- };
- vue.createApp(_sfc_main).mount(
- (() => {
- const app = document.createElement("div");
- app.id = "monkeygpt";
- const firstChild = document.body.firstChild;
- document.body.insertBefore(app, firstChild);
- return app;
- })()
- );
- })(Vue);