simple-syntax-highlighter
Version:
No chi-chi syntax highlighter for Vue.js 3 (and 2).
4 lines (3 loc) • 13.1 kB
JavaScript
;const u=require("vue"),B=["data-type","data-label"],F=["contenteditable"],H={class:"ssh-pre__original"},P={__name:"simple-syntax-highlighter",props:{language:{type:String,default:""},label:{type:[String,Boolean],default:!1},tab:{type:[Boolean,String],default:" "},dark:{type:Boolean,default:!1},copyButton:{type:Boolean,default:!1},editable:{type:Boolean,default:!1}},emits:["copied"],setup(h,{emit:C}){const o={quote:/("(?:\\"|[^"])*")|('(?:\\'|[^'])*')/,comment:/(\/\/.*?(?:\n|$)|\/\*.*?(?:\*\/|$))/,doctype:/(<!DOCTYPE.*?>)/,htmlTag:/<(?:([a-z][\w:-]*)((?:[\w\- ]+=(?:"[^"]*"|'[^']*'))*|(?:[^&]|&(?:lt|amp|quot|apos|gt);)*?)(\s*\/?)|(\/?)([a-z][\w:-]*))>/,htmlentity:/(&(?:[a-z]+|#x?\d+);)/,punctuation:new RegExp("(!==?|(?:[[\\](){}.:,+\\-?=!])+|(?<!&(?:[a-z]+|#x?\\d+));|\\|\\||<|>|&)"),number:/(-?(?:\.\d+|\d+(?:\.\d+)?))/,boolean:/\b(true|false)\b/},f={shell:{quote:o.quote,comment:/(#.*?)(?:\n|$)/,keyword:/\b(p?npm|yarn|i(?:nstall)?|run|audit|outdated|update|publish|whoami|cd|sudo|chmod|chown|ls|cat|vim?|scp|rm|mv|mkdir|ln|open|cwd|which|clear|curl|ping|systemctl|echo|export|open|bash|exit)\b/,param:/( --(?:save|save-dev))(?:\s|$)/},xml:{doctype:o.doctype,quote:o.quote,comment:/(<!--.*?(?:-->|$))/,htmlentity:o.htmlentity,tag:o.htmlTag},html:{doctype:o.doctype,quote:o.quote,comment:/(<!--.*?(?:-->|$))/,htmlentity:o.htmlentity,tag:o.htmlTag},"html-vue":{doctype:o.doctype,quote:o.quote,comment:/(<!--.*?(?:-->|$))/,htmlentity:o.htmlentity,tag:/<(?:([a-z][\w:-]*)((?:[\w-]+\s*=(?:"[^"]*"|'[^']*'))*|(?:[^&]|&(?:lt|amp|quot|apos|gt);)*?)(\s*\/?)|(\/?)([a-z][\w:-]*))>/},pug:{text:/((?:^|\n)[ \t]*|^)\|([ \t]*)([^\n]+(?=\s*(?:\n|$)))/,text2:/([ \t]*)([.#\w-]+(?:\([^)]*\))*)\.\n((?:\n+(?=\4[ \t]+)|(?=\4[ \t]+).+?(?:\n|$)*?)*)(?=\s*(?:\n|$))/,quote:o.quote,comment:/(^|\n)([ \t]*|^)(\/\/-[ \t]*(?:[^\n]*?(?:\n\10[ \t]+[^\n]*)+|[^\n]+(?=\n|$)))/,tag:/([a-z][\w:-]*|)([.#][a-z][.\w-]*|)\b(?:\((\s*(?:[#@:]?[a-z][\w-.:]+(?:=(?:"[^"]*"|'[^']*'))*\s*)*)\))?(\.?)([ \t]*)([^\n]+)?(?=\n|$)/,"inline-tag":/#\[([^[\]]+)\]/},css:{comment:/(\/\*.+?(?:\*\/|$))/,quote:/("(?:\\"|[^"])*")|('(?:\\'|[^'])*')/,pseudo:/(:(?:hover|active|focus|visited|not|before|after|(?:first|last|nth)-child))/,"selector keyword vendor":/(@-(?:moz|o|webkit|ms)-(?=keyframes\s))/,"selector keyword":/((?:@(?:import|media|font-face|keyframes)|screen|print|and)(?=[\s({])|keyframes|\s(?:ul|ol|li|table|div|pre|p|a|img|br|hr|h[1-6]|em|strong|span|html|body|iframe|video|audio|input|button|form|label|fieldset|small|abbr|i|dd|dt)\b)(?=.*\{})/,variable:/(--[a-z0-9-]+)/,selector:/((?:[.#-\w*+ >:,[\]="~\n]|>)+)(?=\s*\{)/,"attribute keyword vendor":/(-(?:moz|o|webkit|ms)-(?=transform|transition|user-select|tap-highlight-color|animation|background-size|box-shadow))/,"attribute keyword":/\b(content|float|display|position|top|left|right|bottom|(?:(?:max|min)-)?width|(?:(?:max|min|line)-)?height|font(?:-(?:family|style|size|weight|variant|stretch))?|vertical-align|color|opacity|visibility|z-index|pointer-events|user-select|transform(?:-(?:origin|style|delay|duration|property|timing-function))?|transition(?:-(?:delay|duration))?|animation(?:-(?:name|delay|duration|direction|fill-mode))?|backface-visibility|backdrop-filter|background(?:-(?:color|position|image|repeat|size|attachment|origin|clip|blend-mode))?|(?:padding|margin|border)(?:-(?:top|left|right|bottom))?|border(?:-(?:radius|color|width|style|spacing))|white-space|text-(?:align|transform|decoration|shadow|indent)|overflow(?:-(?:x|y))?|(?:letter|word)-spacing|word-break|box-(?:sizing|shadow)|stroke(?:-(?:width|opacity|dasharray|dashoffset|linecap|linejoin))?|fill|speak|outline|user-select|cursor|flex(?:-(?:direction|flow|grow|shrink|basis|wrap))?|(?:justify|align)-(?:content|self|items))(?=\s*:)/,"value keyword vendor":/(-(?:moz|o|webkit|ms)-(?=linear-gradient))/,"value keyword":/\b(inherit|initial|normal|none|unset|auto|inline(?:-(?:block|flex))?|block|flex|absolute|relative|static|fixed|sticky|hidden|visible|top|left|right|bottom|center|middle|baseline|solid|dotted|dashed|line-through|(?:over|under)line|wavy|double|(?:pre-|no)?wrap|pre|break-word|(?:upper|lower)case|capitalize|italic|bold|attr\(.*?\)|linear|ease(?:-in)?(?:-out)?|all|infinite|cubic-bezier|(?:translate|rotate)(?:[X-Z]|3d)?|skew[XY]?|scale|(?:no-)?repeat|repeat(?:-x|-y)|contain|cover|url|(?:repeating-)?(?:linear|radial)-gradient|inset|pointer|(?:flex-)?(?:start|end)|space-(?:between|evenly|around)|stretch|revert|row(?:-reverse)?|column(?:-reverse)?)(?=\s*[,;}(]|\s+[\da-z!])/,"value keyword important":/( ?!important)/,number:o.number,color:/(transparent|#(?:[\da-f]{8}|[\da-f]{6}|[\da-f]{3})|rgba?\([\d., ]*\))/,htmlentity:o.htmlentity,punctuation:/([:,;{}@#()!]+)/,attribute:/([a-z-]+)(?=\s*:)/,unit:/(px|pt|cm|%|r?em|m?s|deg|vh|vw|vmin|vmax)(?=(?:\s*[;,{}})]|\s+[-\da-z#]))/,error:/([:,;{}@#()!]+|<|>|&)/},json:{quote:/("(?:\\"|[^"])*")/,number:o.number,boolean:o.boolean,punctuation:/([[\](){}:,]+)/,error:/(&(:?lt|gt|amp);|(?!\s).)/},js:{quote:o.quote,comment:o.comment,number:/\b(\d+(?:\.\d+)?|null)\b/,boolean:o.boolean,this:/\b(this)(?=\W)/,keyword:/\b(new|getElementsBy(?:Tag|Class|)Name|getElementById|querySelector|querySelectorAll|arguments|if|else|do|return|case|default|(?:f|F)unction|typeof|instanceof|undefined|document(?:Element)?|window|console|while|for|forEach|switch|in|break|continue|delete|length|var|let|const|export|import|as|require|from|Class|constructor|Number|Boolean|String|Array|Object|RegExp|Integer|Date|Promise|Proxy|WeakMap|WeakSet|Symbol|SyncManager|File(?:Reader)?|DataTransfer|DocumentFragment|async|await|(?:clear|set)(?:Timeout|Interval)|parse(?:Int|Float)|Math(?=\.)|isNaN|atob|btoa|getComputedStyle)(?=\W)/,htmlentity:o.htmlentity,punctuation:/(!==?|[[\]!(){}:;,+\-%*/?=]+|\.+(?![a-z])|\|\||<|>|&)/,variable:/(\.?[a-z_]\w*)/,"external-var":/(\$|jQuery|JSON)(?=\W|$)/},php:{quote:o.quote,comment:o.comment,special:/(<\?(?:php)?|\?>|__(?:DIR|FILE|LINE|CLASS|METHOD|FUNCTION|NAMESPACE|TRAIT)__)/,punctuation:o.punctuation,number:o.number,boolean:o.boolean,variable:/(\$\w+)/,keyword:/\b(define|echo|die|exit|print_r|var_dump|if|else|elseif|do|return|case|default|function|\$this|while|foreach|for|switch|in|break|continue|empty|isset|unset|parse_ini_file|session_(?:start|destroy|id)|header|json_(?:encode|decode)|error_log|(require|include)(:?_once)?|try|throw|new|Exception|catch|finally|preg_(?:match|replace)|list|strlen|substr|str_replace|array_(?:keys|values))(?=\W|$)/},sql:{quote:o.quote,comment:/((?:--|#)\s.*?(?:\n|$)|\/\*.*?\*\/)/,punctuation:o.punctuation,number:/\b(\d+(?:\.\d+)?|null)\b/,boolean:o.boolean,keyword:/\b(\*|DECLARE|BEGIN|END|RETURNS|FUNCTION|CREATE|DATABASE|TABLE|VIEW|COLUMN|INDEX|GRANT|REVOKE|ALL|PRIVILEGES|IDENTIFIED|FLUSH|ALTER|MODIFY|DROP|TRUNCATE|CONSTRAINT|ADD|CHECK|(?:(?:PRIMARY|FOREIGN|UNIQUE) )?KEY|REFERENCES|AUTO_INCREMENT|COMMENT|DEFAULT|UNSIGNED|CHARSET|COLLATE|CHARACTER|ENGINE|SQL_MODE|USE|IF|THEN|NULL|EXISTS|UNIQUE|SELECT|UPDATE|DELETE|(?:INSERT|REPLACE)(?: INTO)?|VALUES|SET|FROM|WHERE|(?:ORDER|GROUP) BY|LIMIT|(?:(?:LEFT|RIGHT|INNER|OUTER|CROSS) |)JOIN|AS|ON|COUNT|AVG|SUM|MIN|MAX|CASE|TO|WHEN|BETWEEN|AND|OR|NOT|IN|LIKE|IS|CONCAT|SUBSTRING|CURRENT_(?:DATE|TIMESTAMP)|USING|HAVING?)(?=\W|$)/,"var-type":/\b((?:var)?char|(?:tiny|small|medium|big)?int|decimal|float|double|real|bit|boolean|date(?:time)?|time(?:stamp)?|year|(?:tiny|medium|long)?(?:text|blob)|enum)\b/}},x={xml:/(\s*)([a-z\d\-:]+)(?:=("|')(.*?)\3)?/g,html:/(\s*)([a-z-]+)(?:=("|')(.*?)\3)?/gs,"html-vue":/(\s*)([@:#]?[a-z\d-]+)(?:(?:=("|')(.*?)\3)|)/gs,pug:/(\s*|,)([@:#]?[a-z\d-]+)(?:(?:=("|')(.*?)\3)|)/g},R={shell:{quote:2},xml:{quote:2,tag:5},html:{quote:2,tag:5},"html-vue":{quote:2,tag:5},pug:{text:3,text2:3,quote:2,comment:3,tag:6},json:{},php:{quote:2},sql:{quote:2},css:{quote:2},js:{quote:2}},d=h,A=C,T=u.ref(Object.keys(f)),p=u.ref(null),N=u.useSlots(),w=t=>t.map(e=>{if(!e.children||typeof e.children=="string")return e.children||"";if(Array.isArray(e.children))return w(e.children);if(e.children.default)return w(e.children.default())}).join(""),y=t=>t.replace(/[<>]/g,e=>({"<":"<",">":">"})[e]),q=t=>{if(t==="transparent")return{dark:!1,alpha:0};const e=s=>s<=.03928?s/12.92:Math.pow((s+.055)/1.055,2.4);let l=0,c=0,n=0,a=1;const i=t.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/),r=t.match(/^#([\da-f]{3,8})$/i);if(i)l=parseInt(i[1])/255,c=parseInt(i[2])/255,n=parseInt(i[3])/255,i[4]&&(a=parseFloat(i[4]));else if(r){const s=r[1],g=s.length===3||s.length===4;l=parseInt(g?s[0]+s[0]:s.substring(0,2),16)/255,c=parseInt(g?s[1]+s[1]:s.substring(2,4),16)/255,n=parseInt(g?s[2]+s[2]:s.substring(4,6),16)/255,(s.length===4||s.length===8)&&(a=parseInt(g?s[3]+s[3]:s.substring(6,8),16)/255)}const b=.2126*e(l)+.7152*e(c)+.0722*e(n);return{dark:a*b+(1-a)*1<=.45,alpha:a}},L=()=>{let t="";const e=[];for(const l in f[d.language]){const c=R[d.language][l]||1;for(let n=0;n<c;n++)e.push(l);t+=(t?"|":"")+f[d.language][l].source}return[t,e]},v=t=>{const e=(l,c,n,a,i)=>`${c}<span class="attribute">${n}</span>`+(a||i?'<span class="punctuation">=</span>':"")+(a||i?`<span class="quote">${a||""}${i||""}${a||""}</span>`:"");if(d.language==="pug"){let[l,c="",n="",a="",i="",r=""]=t;return c=c.replace(/#[\w-]+/g,b=>`<span class="id">${b}</span>`).replace(/\.[\w-]+/g,b=>`<span class="class">${b}</span>`),n&&(n=n.replace(x.pug,e),n='<span class="punctuation">(</span>'+n+'<span class="punctuation">)</span>'),r&&(r=I(r)),`<span class="tag-name">${l}</span>${c}${n}`+(a?'<span class="punctuation">.</span>':"")+(i||"")+(r?`<span class="text">${r}</span>`:"")}else{const[l,c="",n="",a="",i]=t,r=c.replace(x[d.language],e);return`<span class="punctuation"><${a}</span><span class="tag-name">${l||i}</span>`+r+`<span class="punctuation">${n}></span>`}},I=t=>t.replace(new RegExp(f.pug["inline-tag"],"gsi"),(e,l)=>'<span class="inline-tag">#[</span>'+l.replace(new RegExp(f.pug.tag,"si"),(c,...n)=>(n=n.slice(0,n.length-2),v(n)))+'<span class="inline-tag">]</span>'),O=()=>{if(T.value.includes(d.language)){const t=z();p.value.innerHTML=E(p.value.innerText),k(p.value.childNodes,t)}},z=()=>{const t=window.getSelection();t.collapseToEnd();const e=new Range;return e.setStart(p.value,0),e.setEnd(t.extentNode,t.extentOffset),e.toString().length},k=(t,e)=>{var c,n;let l=0;for(const a of t){const i=((c=a.innerText)==null?void 0:c.length)||a.length;if(l+i>=e){a.childNodes.length>1?k(a.childNodes,e-l):document.getSelection().setPosition(((n=a.childNodes)==null?void 0:n[0])||a,e-l);break}l+=i}},M=t=>{switch(t.which){case 9:S(d.tab),t.preventDefault();break;case 13:S(`
`),t.preventDefault();break}},S=t=>{const e=window.getSelection(),l=e.getRangeAt(0),c=document.createTextNode(t);l.insertNode(c),e.collapseToEnd()},E=t=>{if(!T.value.includes(d.language))return t;const[e,l]=L();return y(t.replace(/&/g,"&")).replace(new RegExp(e,"gsi"),(c,...n)=>{n=n.slice(0,n.length-2);let a;const i=d.language==="pug";let r=n.find((m,s)=>m&&(a=l[s])&&m);if(["punctuation","quote","htmlentity"].includes(a))r=y(r);else if(a==="comment")if(i){const[m,s,g]=n.slice(l.indexOf("comment"));r=`${m}${s}${y(g)}`}else r=y(r);else if(a==="text"&&i){let[m,s,g]=n;return g=I(g),`${m}<span class="punctuation">|</span>${s}<span class="text">${g}</span>`}else if(a==="text2"&&i){const[,,,m,s,g]=n,U=E(s);return`${m}${U}<span class="punctuation">.</span>
<span class="text">${g}</span>`}else{if(a==="tag"&&["xml","html","html-vue","pug"].includes(d.language))return v(n.slice(l.indexOf("tag")));if(a==="variable"&&r[0]==="."&&d.language==="js")return`<span class="punctuation">.</span><span class="obj-attr">${r.substr(1)}</span>`}let b="";if(a==="color"&&d.language==="css"){const{dark:m,alpha:s}=q(r);a+=` color--${m?"dark":"light"}${s<.4||r==="transparent"?" color--transparent":""}`,b=` style="background-color: ${r}"`}return a&&`<span class="${a}"${b}>${r}</span>`||""})},$=()=>N.default&&w(N.default())||"",D=t=>{t.target.insertAdjacentHTML("afterend",`<textarea id="clipboard-textarea">${p.value.innerText}</textarea>`);const e=document.getElementById("clipboard-textarea");e.select(),e.setSelectionRange(0,99999),document.execCommand("copy"),e.remove(),A("copied",p.value.innerText)};return u.onMounted(()=>{const t=$();p.value.innerText=t,p.value.innerHTML=E(p.value.innerText)}),u.onBeforeUpdate(()=>{p.value&&(p.value.innerHTML=E($()))}),(t,e)=>(u.openBlock(),u.createElementBlock("div",{class:u.normalizeClass(["ssh-pre",{"ssh-pre--dark":h.dark}]),"data-type":h.language,"data-label":h.label||null},[h.copyButton?(u.openBlock(),u.createElementBlock("button",{key:0,class:"ssh-pre__copy",onClick:D},[u.renderSlot(t.$slots,"copy-button",{},()=>[e[1]||(e[1]=u.createTextVNode("Copy"))])])):u.createCommentVNode("",!0),e[2]||(e[2]=u.createTextVNode()),u.createElementVNode("pre",{ref_key:"codeEl",ref:p,class:"ssh-pre__content",contenteditable:h.editable?"true":"false",onKeydown:e[0]||(e[0]=l=>h.editable&&M(l)),onInput:O}," ",40,F),e[3]||(e[3]=u.createTextVNode()),u.createElementVNode("div",H,[u.renderSlot(t.$slots,"default")])],10,B))}};module.exports=P;