@0x1js/highlighter
Version:
5 lines (4 loc) • 8.43 kB
JavaScript
var R=new Set(["abstract","async","await","break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","if","implements","import","in","instanceof","interface","let","new","null","of","public","private","protected","readonly","return","static","super","switch","this","throw","true","try","type","typeof","undefined","var","void","while","with","yield"]),k=new Set(["string","number","boolean","object","symbol","bigint","any","unknown","never","void","Array","Promise","Set","Map","Date","RegExp","Error"]),f=new Set(["console","window","document","global","process","require","module","exports","Math","JSON","parseInt","parseFloat","isNaN","isFinite"]),y=new Set(["if","then","else","elif","fi","case","esac","for","select","while","until","do","done","in","function","time","coproc","cd","echo","export","alias","unalias","set","unset","readonly","local","declare","typeset","exit","return","break","continue","shift","test","source","eval","exec","trap","kill","jobs","bg","fg","wait","suspend","true","false"]),x=new Set(["ls","cd","pwd","mkdir","rmdir","rm","cp","mv","ln","find","grep","sed","awk","sort","uniq","cut","tr","head","tail","wc","cat","less","more","file","which","whereis","locate","man","info","help","history","alias","ps","top","htop","kill","killall","nohup","screen","tmux","ssh","scp","rsync","wget","curl","git","npm","bun","node","python","pip","docker","kubectl","make","gcc","clang","java","javac"]);function A(Q){let X=[],F=0;while(F<Q.length){let V=Q[F];if(/\s/.test(V)){F++;continue}if(V==="/"&&Q[F+1]==="/"){let U=F;while(F<Q.length&&Q[F]!==`
`)F++;X.push({type:"comment",value:Q.slice(U,F),start:U,end:F});continue}if(V==="/"&&Q[F+1]==="*"){let U=F;F+=2;while(F<Q.length-1&&!(Q[F]==="*"&&Q[F+1]==="/"))F++;F+=2,X.push({type:"comment",value:Q.slice(U,F),start:U,end:F});continue}if(V==='"'||V==="'"||V==="`"){let U=V,Z=F;F++;while(F<Q.length){if(Q[F]===U&&Q[F-1]!=="\\"){F++;break}if(Q[F]==="\\")F++;F++}X.push({type:"string",value:Q.slice(Z,F),start:Z,end:F});continue}if(/\d/.test(V)||V==="."&&/\d/.test(Q[F+1])){let U=F;while(F<Q.length&&/[\d.eE+-]/.test(Q[F]))F++;X.push({type:"number",value:Q.slice(U,F),start:U,end:F});continue}if(/[a-zA-Z_$]/.test(V)){let U=F;while(F<Q.length&&/[a-zA-Z0-9_$]/.test(Q[F]))F++;let Z=Q.slice(U,F),P="plain";if(R.has(Z))P="keyword";else if(k.has(Z))P="type";else if(f.has(Z))P="constant";else if(/^[A-Z]/.test(Z))P="type";else if(Q[F]==="(")P="function";X.push({type:P,value:Z,start:U,end:F});continue}if(/[+\-*/%=<>!&|^~?:;,.[\]{}()]/.test(V)){let U=F;if(F<Q.length-1){let Z=Q.slice(F,F+2);if(["==","!=","<=",">=","&&","||","++","--","=>","??"].includes(Z))F+=2;else if(F<Q.length-2&&["===","!=="].includes(Q.slice(F,F+3)))F+=3;else F++}else F++;X.push({type:"operator",value:Q.slice(U,F),start:U,end:F});continue}X.push({type:"plain",value:V,start:F,end:F+1}),F++}return X}function j(Q){let X=[],F=0;while(F<Q.length){let V=Q[F];if(/\s/.test(V)){F++;continue}if(V==="#"){let U=F;while(F<Q.length&&Q[F]!==`
`)F++;X.push({type:"comment",value:Q.slice(U,F),start:U,end:F});continue}if(V==='"'||V==="'"){let U=V,Z=F;F++;while(F<Q.length){if(Q[F]===U&&Q[F-1]!=="\\"){F++;break}if(Q[F]==="\\")F++;F++}X.push({type:"string",value:Q.slice(Z,F),start:Z,end:F});continue}if(V==="$"){let U=F;if(F++,Q[F]==="{"){F++;while(F<Q.length&&Q[F]!=="}")F++;F++}else while(F<Q.length&&/[a-zA-Z0-9_]/.test(Q[F]))F++;X.push({type:"variable",value:Q.slice(U,F),start:U,end:F});continue}if(/\d/.test(V)){let U=F;while(F<Q.length&&/\d/.test(Q[F]))F++;X.push({type:"number",value:Q.slice(U,F),start:U,end:F});continue}if(/[a-zA-Z_]/.test(V)){let U=F;while(F<Q.length&&/[a-zA-Z0-9_-]/.test(Q[F]))F++;let Z=Q.slice(U,F),P="plain";if(y.has(Z))P="keyword";else if(x.has(Z))P="function";X.push({type:P,value:Z,start:U,end:F});continue}if(/[|&;<>()[\]{}*?~]/.test(V)){let U=F;if(F<Q.length-1){let Z=Q.slice(F,F+2);if(["&&","||",">>","<<","2>","2&"].includes(Z))F+=2;else F++}else F++;X.push({type:"operator",value:Q.slice(U,F),start:U,end:F});continue}X.push({type:"plain",value:V,start:F,end:F+1}),F++}return X}function _(Q,X){let{language:F,showLineNumbers:V=!1,startLineNumber:U=1,maxLines:Z,wrapLines:P=!0}=X,z;switch(F){case"javascript":case"typescript":z=A(Q);break;case"bash":z=j(Q);break;case"json":z=A(Q);break;default:z=[{type:"plain",value:Q,start:0,end:Q.length}]}let W="",Y=Q.split(`
`),T=Z?Math.min(Y.length,Z):Y.length;for(let O=0;O<T;O++){let v=Y.slice(0,O).reduce((G,w)=>G+w.length+1,0),C=v+Y[O].length,$=z.filter((G)=>G.start>=v&&G.end<=C+1);if(W+='<div class="highlight-line">',V){let G=U+O;W+=`<span class="line-number" data-line="${G}">${G}</span>`}W+='<span class="line-content">';let q=v;for(let G of $){if(G.start>q)W+=E(Q.slice(q,G.start));W+=`<span class="token-${G.type}">${E(G.value)}</span>`,q=G.end}if(q<C)W+=E(Q.slice(q,C));W+="</span></div>"}if(Z&&Y.length>Z)W+=`<div class="highlight-line truncated">... ${Y.length-Z} more lines</div>`;return W}function E(Q){return Q.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function H(){return["javascript","typescript","bash","json","html","css"]}import{useEffect as B,useMemo as m,useRef as N,useState as g}from"0x1/index.js";import{jsx as K,jsxs as b}from"0x1/jsx-runtime.js";function M({children:Q,language:X,theme:F="dark",showLineNumbers:V=!1,startLineNumber:U=1,maxLines:Z,wrapLines:P=!0,className:z="",style:W,copyable:Y=!0,title:T,footer:O,onCopy:v}){let C=N(null),$=N(null),q=N(null),G=m(()=>{return _(Q,{language:X,theme:F,showLineNumbers:V,startLineNumber:U,maxLines:Z,wrapLines:P})},[Q,X,F,V,U,Z,P]),w=async()=>{if(!Y||!$.current)return;try{if(await navigator.clipboard.writeText(Q),$.current.textContent="✅",$.current.classList.add("copied"),q.current)clearTimeout(q.current);q.current=setTimeout(()=>{if($.current)$.current.textContent="\uD83D\uDCCB",$.current.classList.remove("copied")},2000)}catch(J){console.error("Failed to copy code:",J);let I=document.createElement("textarea");I.value=Q,document.body.appendChild(I),I.select();try{if(document.execCommand("copy"),$.current.textContent="✅",$.current.classList.add("copied"),q.current)clearTimeout(q.current);q.current=setTimeout(()=>{if($.current)$.current.textContent="\uD83D\uDCCB",$.current.classList.remove("copied")},2000)}catch(D){console.error("Fallback copy failed:",D)}document.body.removeChild(I)}},S=()=>{if($.current)$.current.classList.add("visible")},L=()=>{if($.current)$.current.classList.remove("visible")};return B(()=>{return()=>{if(q.current)clearTimeout(q.current)}},[]),B(()=>{let J=C.current;if(!J||!Y)return;let I=(D)=>{if((D.ctrlKey||D.metaKey)&&D.key==="c")D.preventDefault(),w()};return J.addEventListener("keydown",I),()=>J.removeEventListener("keydown",I)},[Q,Y]),b("div",{className:`syntax-highlighter-wrapper ${z}`,style:W,onMouseEnter:S,onMouseLeave:L,children:[T&&b("div",{className:"syntax-highlighter-header",children:[K("span",{className:"syntax-highlighter-title",children:T}),K("span",{className:"syntax-highlighter-language",children:X})]}),b("div",{ref:C,className:`syntax-highlighter theme-${F}`,tabIndex:0,role:"textbox","aria-label":`Code snippet in ${X}`,"aria-readonly":"true",children:[Y&&K("button",{ref:$,className:"copy-button",onClick:w,"aria-label":"Copy code to clipboard",title:"Copy code",children:"\uD83D\uDCCB"}),K("div",{className:"syntax-highlighter-content",dangerouslySetInnerHTML:{__html:G}})]}),O&&K("div",{className:"syntax-highlighter-footer",children:O})]})}function u(Q){return K(M,{...Q,language:"javascript"})}function p(Q){return K(M,{...Q,language:"typescript"})}function l(Q){return K(M,{...Q,language:"bash"})}function h(Q){return K(M,{...Q,language:"json"})}function r({children:Q,language:X="javascript",theme:F="dark"}){let V=_(Q,{language:X,theme:F});return K("code",{className:`inline-code theme-${F}`,dangerouslySetInnerHTML:{__html:V}})}function s(Q,X){let[F,V]=g("");return B(()=>{let U=_(Q,X);V(U)},[Q,X.language,X.theme]),F}var a="0.1.4",FF={highlight:_,tokenizeJavaScript:A,tokenizeBash:j,getSupportedLanguages:H,version:a};export{a as version,s as useHighlight,A as tokenizeJavaScript,j as tokenizeBash,_ as highlight,H as getSupportedLanguages,FF as default,p as TypeScriptHighlighter,M as SyntaxHighlighter,u as JavaScriptHighlighter,h as JSONHighlighter,r as InlineCode,l as BashHighlighter};