UNPKG

copy-llms-txt

Version:

A lightweight JavaScript library that lets you copy the content of a webpage as clean markdown with a simple keyboard shortcut.

62 lines (37 loc) 13.5 kB
"use strict";var B=Object.defineProperty;var P=(e,t,n)=>t in e?B(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var f=(e,t,n)=>P(e,typeof t!="symbol"?t+"":t,n);function x(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)n.hasOwnProperty(r)&&(e[r]=n[r])}return e}function y(e,t){return Array(t+1).join(e)}function M(e){return e.replace(/^\n*/,"")}function I(e){for(var t=e.length;t>0&&e[t-1]===` `;)t--;return e.substring(0,t)}var H=["ADDRESS","ARTICLE","ASIDE","AUDIO","BLOCKQUOTE","BODY","CANVAS","CENTER","DD","DIR","DIV","DL","DT","FIELDSET","FIGCAPTION","FIGURE","FOOTER","FORM","FRAMESET","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","HTML","ISINDEX","LI","MAIN","MENU","NAV","NOFRAMES","NOSCRIPT","OL","OUTPUT","P","PRE","SECTION","TABLE","TBODY","TD","TFOOT","TH","THEAD","TR","UL"];function E(e){return C(e,H)}var A=["AREA","BASE","BR","COL","COMMAND","EMBED","HR","IMG","INPUT","KEYGEN","LINK","META","PARAM","SOURCE","TRACK","WBR"];function k(e){return C(e,A)}function F(e){return R(e,A)}var b=["A","TABLE","THEAD","TBODY","TFOOT","TH","TD","IFRAME","SCRIPT","AUDIO","VIDEO"];function $(e){return C(e,b)}function V(e){return R(e,b)}function C(e,t){return t.indexOf(e.nodeName)>=0}function R(e,t){return e.getElementsByTagName&&t.some(function(n){return e.getElementsByTagName(n).length})}var s={};s.paragraph={filter:"p",replacement:function(e){return` `+e+` `}};s.lineBreak={filter:"br",replacement:function(e,t,n){return n.br+` `}};s.heading={filter:["h1","h2","h3","h4","h5","h6"],replacement:function(e,t,n){var r=Number(t.nodeName.charAt(1));if(n.headingStyle==="setext"&&r<3){var i=y(r===1?"=":"-",e.length);return` `+e+` `+i+` `}else return` `+y("#",r)+" "+e+` `}};s.blockquote={filter:"blockquote",replacement:function(e){return e=e.replace(/^\n+|\n+$/g,""),e=e.replace(/^/gm,"> "),` `+e+` `}};s.list={filter:["ul","ol"],replacement:function(e,t){var n=t.parentNode;return n.nodeName==="LI"&&n.lastElementChild===t?` `+e:` `+e+` `}};s.listItem={filter:"li",replacement:function(e,t,n){e=e.replace(/^\n+/,"").replace(/\n+$/,` `).replace(/\n/gm,` `);var r=n.bulletListMarker+" ",i=t.parentNode;if(i.nodeName==="OL"){var a=i.getAttribute("start"),o=Array.prototype.indexOf.call(i.children,t);r=(a?Number(a)+o:o+1)+". "}return r+e+(t.nextSibling&&!/\n$/.test(e)?` `:"")}};s.indentedCodeBlock={filter:function(e,t){return t.codeBlockStyle==="indented"&&e.nodeName==="PRE"&&e.firstChild&&e.firstChild.nodeName==="CODE"},replacement:function(e,t,n){return` `+t.firstChild.textContent.replace(/\n/g,` `)+` `}};s.fencedCodeBlock={filter:function(e,t){return t.codeBlockStyle==="fenced"&&e.nodeName==="PRE"&&e.firstChild&&e.firstChild.nodeName==="CODE"},replacement:function(e,t,n){for(var r=t.firstChild.getAttribute("class")||"",i=(r.match(/language-(\S+)/)||[null,""])[1],a=t.firstChild.textContent,o=n.fence.charAt(0),c=3,l=new RegExp("^"+o+"{3,}","gm"),u;u=l.exec(a);)u[0].length>=c&&(c=u[0].length+1);var h=y(o,c);return` `+h+i+` `+a.replace(/\n$/,"")+` `+h+` `}};s.horizontalRule={filter:"hr",replacement:function(e,t,n){return` `+n.hr+` `}};s.inlineLink={filter:function(e,t){return t.linkStyle==="inlined"&&e.nodeName==="A"&&e.getAttribute("href")},replacement:function(e,t){var n=t.getAttribute("href");n&&(n=n.replace(/([()])/g,"\\$1"));var r=m(t.getAttribute("title"));return r&&(r=' "'+r.replace(/"/g,'\\"')+'"'),"["+e+"]("+n+r+")"}};s.referenceLink={filter:function(e,t){return t.linkStyle==="referenced"&&e.nodeName==="A"&&e.getAttribute("href")},replacement:function(e,t,n){var r=t.getAttribute("href"),i=m(t.getAttribute("title"));i&&(i=' "'+i+'"');var a,o;switch(n.linkReferenceStyle){case"collapsed":a="["+e+"][]",o="["+e+"]: "+r+i;break;case"shortcut":a="["+e+"]",o="["+e+"]: "+r+i;break;default:var c=this.references.length+1;a="["+e+"]["+c+"]",o="["+c+"]: "+r+i}return this.references.push(o),a},references:[],append:function(e){var t="";return this.references.length&&(t=` `+this.references.join(` `)+` `,this.references=[]),t}};s.emphasis={filter:["em","i"],replacement:function(e,t,n){return e.trim()?n.emDelimiter+e+n.emDelimiter:""}};s.strong={filter:["strong","b"],replacement:function(e,t,n){return e.trim()?n.strongDelimiter+e+n.strongDelimiter:""}};s.code={filter:function(e){var t=e.previousSibling||e.nextSibling,n=e.parentNode.nodeName==="PRE"&&!t;return e.nodeName==="CODE"&&!n},replacement:function(e){if(!e)return"";e=e.replace(/\r?\n|\r/g," ");for(var t=/^`|^ .*?[^ ].* $|`$/.test(e)?" ":"",n="`",r=e.match(/`+/gm)||[];r.indexOf(n)!==-1;)n=n+"`";return n+t+e+t+n}};s.image={filter:"img",replacement:function(e,t){var n=m(t.getAttribute("alt")),r=t.getAttribute("src")||"",i=m(t.getAttribute("title")),a=i?' "'+i+'"':"";return r?"!["+n+"]("+r+a+")":""}};function m(e){return e?e.replace(/(\n+\s*)+/g,` `):""}function S(e){this.options=e,this._keep=[],this._remove=[],this.blankRule={replacement:e.blankReplacement},this.keepReplacement=e.keepReplacement,this.defaultRule={replacement:e.defaultReplacement},this.array=[];for(var t in e.rules)this.array.push(e.rules[t])}S.prototype={add:function(e,t){this.array.unshift(t)},keep:function(e){this._keep.unshift({filter:e,replacement:this.keepReplacement})},remove:function(e){this._remove.unshift({filter:e,replacement:function(){return""}})},forNode:function(e){if(e.isBlank)return this.blankRule;var t;return(t=p(this.array,e,this.options))||(t=p(this._keep,e,this.options))||(t=p(this._remove,e,this.options))?t:this.defaultRule},forEach:function(e){for(var t=0;t<this.array.length;t++)e(this.array[t],t)}};function p(e,t,n){for(var r=0;r<e.length;r++){var i=e[r];if(U(i,t,n))return i}}function U(e,t,n){var r=e.filter;if(typeof r=="string"){if(r===t.nodeName.toLowerCase())return!0}else if(Array.isArray(r)){if(r.indexOf(t.nodeName.toLowerCase())>-1)return!0}else if(typeof r=="function"){if(r.call(e,t,n))return!0}else throw new TypeError("`filter` needs to be a string, array, or function")}function W(e){var t=e.element,n=e.isBlock,r=e.isVoid,i=e.isPre||function(L){return L.nodeName==="PRE"};if(!(!t.firstChild||i(t))){for(var a=null,o=!1,c=null,l=N(c,t,i);l!==t;){if(l.nodeType===3||l.nodeType===4){var u=l.data.replace(/[ \r\n\t]+/g," ");if((!a||/ $/.test(a.data))&&!o&&u[0]===" "&&(u=u.substr(1)),!u){l=g(l);continue}l.data=u,a=l}else if(l.nodeType===1)n(l)||l.nodeName==="BR"?(a&&(a.data=a.data.replace(/ $/,"")),a=null,o=!1):r(l)||i(l)?(a=null,o=!0):a&&(o=!1);else{l=g(l);continue}var h=N(c,l,i);c=l,l=h}a&&(a.data=a.data.replace(/ $/,""),a.data||g(a))}}function g(e){var t=e.nextSibling||e.parentNode;return e.parentNode.removeChild(e),t}function N(e,t,n){return e&&e.parentNode===t||n(t)?t.nextSibling||t.parentNode:t.firstChild||t.nextSibling||t.parentNode}var w=typeof window<"u"?window:{};function z(){var e=w.DOMParser,t=!1;try{new e().parseFromString("","text/html")&&(t=!0)}catch{}return t}function _(){var e=function(){};return K()?e.prototype.parseFromString=function(t){var n=new window.ActiveXObject("htmlfile");return n.designMode="on",n.open(),n.write(t),n.close(),n}:e.prototype.parseFromString=function(t){var n=document.implementation.createHTMLDocument("");return n.open(),n.write(t),n.close(),n},e}function K(){var e=!1;try{document.implementation.createHTMLDocument("").open()}catch{w.ActiveXObject&&(e=!0)}return e}var j=z()?w.DOMParser:_();function q(e,t){var n;if(typeof e=="string"){var r=G().parseFromString('<x-turndown id="turndown-root">'+e+"</x-turndown>","text/html");n=r.getElementById("turndown-root")}else n=e.cloneNode(!0);return W({element:n,isBlock:E,isVoid:k,isPre:t.preformattedCode?X:null}),n}var v;function G(){return v=v||new j,v}function X(e){return e.nodeName==="PRE"||e.nodeName==="CODE"}function Y(e,t){return e.isBlock=E(e),e.isCode=e.nodeName==="CODE"||e.parentNode.isCode,e.isBlank=Q(e),e.flankingWhitespace=J(e,t),e}function Q(e){return!k(e)&&!$(e)&&/^\s*$/i.test(e.textContent)&&!F(e)&&!V(e)}function J(e,t){if(e.isBlock||t.preformattedCode&&e.isCode)return{leading:"",trailing:""};var n=Z(e.textContent);return n.leadingAscii&&T("left",e,t)&&(n.leading=n.leadingNonAscii),n.trailingAscii&&T("right",e,t)&&(n.trailing=n.trailingNonAscii),{leading:n.leading,trailing:n.trailing}}function Z(e){var t=e.match(/^(([ \t\r\n]*)(\s*))(?:(?=\S)[\s\S]*\S)?((\s*?)([ \t\r\n]*))$/);return{leading:t[1],leadingAscii:t[2],leadingNonAscii:t[3],trailing:t[4],trailingNonAscii:t[5],trailingAscii:t[6]}}function T(e,t,n){var r,i,a;return e==="left"?(r=t.previousSibling,i=/ $/):(r=t.nextSibling,i=/^ /),r&&(r.nodeType===3?a=i.test(r.nodeValue):n.preformattedCode&&r.nodeName==="CODE"?a=!1:r.nodeType===1&&!E(r)&&(a=i.test(r.textContent))),a}var ee=Array.prototype.reduce,te=[[/\\/g,"\\\\"],[/\*/g,"\\*"],[/^-/g,"\\-"],[/^\+ /g,"\\+ "],[/^(=+)/g,"\\$1"],[/^(#{1,6}) /g,"\\$1 "],[/`/g,"\\`"],[/^~~~/g,"\\~~~"],[/\[/g,"\\["],[/\]/g,"\\]"],[/^>/g,"\\>"],[/_/g,"\\_"],[/^(\d+)\. /g,"$1\\. "]];function d(e){if(!(this instanceof d))return new d(e);var t={rules:s,headingStyle:"setext",hr:"* * *",bulletListMarker:"*",codeBlockStyle:"indented",fence:"```",emDelimiter:"_",strongDelimiter:"**",linkStyle:"inlined",linkReferenceStyle:"full",br:" ",preformattedCode:!1,blankReplacement:function(n,r){return r.isBlock?` `:""},keepReplacement:function(n,r){return r.isBlock?` `+r.outerHTML+` `:r.outerHTML},defaultReplacement:function(n,r){return r.isBlock?` `+n+` `:n}};this.options=x({},t,e),this.rules=new S(this.options)}d.prototype={turndown:function(e){if(!ie(e))throw new TypeError(e+" is not a string, or an element/document/fragment node.");if(e==="")return"";var t=O.call(this,new q(e,this.options));return ne.call(this,t)},use:function(e){if(Array.isArray(e))for(var t=0;t<e.length;t++)this.use(e[t]);else if(typeof e=="function")e(this);else throw new TypeError("plugin must be a Function or an Array of Functions");return this},addRule:function(e,t){return this.rules.add(e,t),this},keep:function(e){return this.rules.keep(e),this},remove:function(e){return this.rules.remove(e),this},escape:function(e){return te.reduce(function(t,n){return t.replace(n[0],n[1])},e)}};function O(e){var t=this;return ee.call(e.childNodes,function(n,r){r=new Y(r,t.options);var i="";return r.nodeType===3?i=r.isCode?r.nodeValue:t.escape(r.nodeValue):r.nodeType===1&&(i=re.call(t,r)),D(n,i)},"")}function ne(e){var t=this;return this.rules.forEach(function(n){typeof n.append=="function"&&(e=D(e,n.append(t.options)))}),e.replace(/^[\t\r\n]+/,"").replace(/[\t\r\n\s]+$/,"")}function re(e){var t=this.rules.forNode(e),n=O.call(this,e),r=e.flankingWhitespace;return(r.leading||r.trailing)&&(n=n.trim()),r.leading+t.replacement(n,e,this.options)+r.trailing}function D(e,t){var n=I(e),r=M(t),i=Math.max(e.length-n.length,t.length-r.length),a=` `.substring(0,i);return n+a+r}function ie(e){return e!=null&&(typeof e=="string"||e.nodeType&&(e.nodeType===1||e.nodeType===9||e.nodeType===11))}class ae{constructor(){f(this,"options",{key:"c",meta:!1,turndownOptions:{},selectorsToRemove:["nav","header","footer","aside",".navigation",".nav",".menu",".sidebar",".ad",".ads",".advertisement","script","style","noscript","iframe"]});f(this,"turndownService");f(this,"initialized",!1);f(this,"handleKeyDown",t=>{(this.options.meta?t.metaKey:t.ctrlKey)&&t.key.toLowerCase()===this.options.key.toLowerCase()&&(t.preventDefault(),this.copyPageContent())});this.turndownService=new d}isMac(){return navigator.platform.toLowerCase().includes("mac")||navigator.userAgent.toLowerCase().includes("mac")}init(t){if(this.initialized){console.warn("CopyLlmsTxt is already initialized. Call destroy() before reinitializing.");return}const n={key:"c",meta:this.isMac(),turndownOptions:{},selectorsToRemove:["nav","header","footer","aside",".navigation",".nav",".menu",".sidebar",".ad",".ads",".advertisement","script","style","noscript","iframe"]};this.options={...n,...t},this.turndownService=new d(this.options.turndownOptions),document.addEventListener("keydown",this.handleKeyDown),this.initialized=!0,console.log(`CopyLlmsTxt initialized. Press ${this.options.meta?"Meta/Cmd":"Ctrl"}+${this.options.key} to copy content as markdown.`)}destroy(){this.initialized&&(document.removeEventListener("keydown",this.handleKeyDown),this.initialized=!1,console.log("CopyLlmsTxt destroyed."))}copyPageContent(){try{const t=document.body.cloneNode(!0);this.cleanupDOM(t);const n=this.turndownService.turndown(t);navigator.clipboard.writeText(n).then(()=>{console.log("Page content copied as markdown!")}).catch(r=>{console.error("Failed to copy text: ",r)})}catch(t){console.error("Error copying page content:",t)}}removeNonVisibleElements(t){const n=document.body.querySelectorAll("*"),r=t.querySelectorAll("*");if(n.length!==r.length)console.warn("Element count mismatch between original and clone");else for(let i=r.length-1;i>=0;i--){const a=n[i],o=r[i],c=window.getComputedStyle(a),l=a.getBoundingClientRect();(c.display==="none"||c.visibility==="hidden"||c.opacity==="0"||l.height===0||l.width===0)&&o.parentNode&&o.parentNode.removeChild(o)}}removeElementsBySelector(t){["nav","header","footer","aside",".navigation",".nav",".menu",".sidebar",".ad",".ads",".advertisement","script","style","noscript","iframe"].forEach(r=>{t.querySelectorAll(r).forEach(a=>{var o;return(o=a.parentNode)==null?void 0:o.removeChild(a)})})}cleanupDOM(t){this.removeNonVisibleElements(t),this.removeElementsBySelector(t)}copy(){this.copyPageContent()}}const le=new ae;module.exports=le;