@pardnchiu/nanojson
Version:
A lightweight JSON editor built with pure JavaScript and native APIs. It features visual editing, dynamic type switching, and file import/export capabilities. Suitable for website embedding and JSON data editing.
1 lines • 14.8 kB
JavaScript
!function(){const e=/\.([\w_-]+)?/gi,t=/\#([\w_-]+)?/i,i=/^\w+(?=[\#\.]*)/i,n="pd-json-editor",o="pd-json-editor-nested-child",s="button:not(.collapsed), textarea, input, select",l="appendChild",r="array",c="body",a="boolean",h="display",d="temp",f="push",u="button",p="children",y="collapsed",m="setAttribute",v="dataset",g="true",b="disabled",_="type",k="editor",w="export",C="import",A="innerHTML",j="isArray",H="label",R="section",z="length",S="toLowerCase",M="match",N="nextElementSibling",O="querySelectorAll",V="number",x="object",D="option",L="parent",T="placeholder",B="render",K="replace",E="reset",U="selected",$="string",F="target",J="textarea",I="title",P="update",q="value",Y="readonly",G="lifecycle",Q="click",W="download",X={[x]:1,[r]:1};let Z="beforeRender",ee="beforeUpdate",te="beforeDestroy",ie="rendered",ne="updated",oe="destroyed";let se={[V]:"M5.5 15v-4.5H4V9h3v6H5.5zM9 15v-2.5c0-.283.096-.52.287-.713A.967.967 0 0110 11.5h2v-1H9V9h3.5c.283 0 .52.096.713.287.191.192.287.43.287.713v1.5c0 .283-.096.52-.287.713a.968.968 0 01-.713.287h-2v1h3V15H9zm6 0v-1.5h3v-1h-2v-1h2v-1h-3V9h3.5c.283 0 .52.096.712.287.192.192.288.43.288.713v4c0 .283-.096.52-.288.713A.968.968 0 0118.5 15H15z",[$]:"M17 15a.968.968 0 01-.712-.287A.968.968 0 0116 14v-4c0-.283.096-.52.288-.713A.968.968 0 0117 9h3c.283 0 .52.096.712.287.192.192.288.43.288.713v1h-1.5v-.5h-2v3h2V13H21v1c0 .283-.096.52-.288.713A.968.968 0 0120 15h-3zm-7.5 0V9h4c.283 0 .52.096.713.287.191.192.287.43.287.713v1c0 .283-.096.52-.287.713A.968.968 0 0113.5 12c.283 0 .52.096.713.287.191.192.287.43.287.713v1c0 .283-.096.52-.287.713A.968.968 0 0113.5 15h-4zm1.5-3.75h2v-.75h-2v.75zm0 2.25h2v-.75h-2v.75zM3 15v-5c0-.283.096-.52.288-.713A.968.968 0 014 9h3c.283 0 .52.096.713.287.191.192.287.43.287.713v5H6.5v-1.5h-2V15H3zm1.5-3h2v-1.5h-2V12z",[x]:"M13.5 18v-1.5h2.25c.213 0 .39-.072.534-.216a.726.726 0 00.216-.534v-1.5c0-.475.137-.906.413-1.294A2.233 2.233 0 0118 12.131v-.262a2.233 2.233 0 01-1.087-.825A2.184 2.184 0 0116.5 9.75v-1.5a.726.726 0 00-.216-.534.726.726 0 00-.534-.216H13.5V6h2.25a2.17 2.17 0 011.594.656c.437.438.656.969.656 1.594v1.5c0 .213.072.39.216.534a.726.726 0 00.534.216h.75v3h-.75a.726.726 0 00-.534.216.726.726 0 00-.216.534v1.5a2.17 2.17 0 01-.656 1.594A2.17 2.17 0 0115.75 18H13.5zm-5.25 0a2.17 2.17 0 01-1.594-.656A2.17 2.17 0 016 15.75v-1.5a.726.726 0 00-.216-.534.726.726 0 00-.534-.216H4.5v-3h.75c.213 0 .39-.072.534-.216A.726.726 0 006 9.75v-1.5c0-.625.219-1.156.656-1.594A2.17 2.17 0 018.25 6h2.25v1.5H8.25a.726.726 0 00-.534.216.726.726 0 00-.216.534v1.5c0 .475-.138.906-.412 1.294A2.233 2.233 0 016 11.869v.262c.45.163.813.438 1.088.825.274.388.412.819.412 1.294v1.5c0 .213.072.39.216.534a.726.726 0 00.534.216h2.25V18H8.25z",[r]:"M14.625 19v-1.75h2.625V6.75h-2.625V5H19v14h-4.375zM5 19V5h4.375v1.75H6.75v10.5h2.625V19H5z",[a]:"M7.91 16.818c-1.365 0-2.524-.477-3.478-1.432C3.477 14.432 3 13.273 3 11.91c0-1.364.477-2.523 1.432-3.477C5.386 7.477 6.545 7 7.909 7h8.182c1.363 0 2.523.477 3.477 1.432.955.954 1.432 2.114 1.432 3.477 0 1.364-.477 2.523-1.432 3.477-.954.955-2.114 1.432-3.477 1.432H7.909zm0-1.636h8.18c.9 0 1.671-.32 2.312-.962.641-.64.962-1.41.962-2.31 0-.9-.32-1.671-.962-2.312a3.151 3.151 0 00-2.311-.962H7.909c-.9 0-1.67.32-2.311.962a3.151 3.151 0 00-.962 2.311c0 .9.32 1.67.962 2.311.64.641 1.411.962 2.311.962zm8.18-.818c.683 0 1.262-.239 1.74-.716a2.367 2.367 0 00.716-1.739c0-.682-.24-1.261-.716-1.739a2.367 2.367 0 00-1.74-.715c-.68 0-1.26.238-1.738.716a2.367 2.367 0 00-.716 1.738c0 .682.239 1.261.716 1.739a2.367 2.367 0 001.739.716z",right:"M10 18V6l6 6-6 6z",folder:"M4 20c-.55 0-1.02-.196-1.413-.587A1.926 1.926 0 012 18V6c0-.55.196-1.02.587-1.412A1.926 1.926 0 014 4h6l2 2h8c.55 0 1.02.196 1.413.588.391.391.587.862.587 1.412H11.175l-2-2H4v12l2.4-8h17.1l-2.575 8.575a1.95 1.95 0 01-.738 1.038A1.985 1.985 0 0119 20H4zm2.1-2H19l1.8-6H7.9l-1.8 6z",add:"M11 13H5v-2h6V5h2v6h6v2h-6v6h-2v-6z",[W]:"M12 16l-5-5 1.4-1.45 2.6 2.6V4h2v8.15l2.6-2.6L17 11l-5 5zm-6 4c-.55 0-1.02-.196-1.412-.587A1.926 1.926 0 014 18v-3h2v3h12v-3h2v3c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0118 20H6z",clear:"M17.25 18H22v2h-6.75l2-2zm-12.5 2l-2.125-2.125c-.383-.383-.58-.858-.587-1.425-.009-.567.179-1.05.562-1.45l11-11.4c.383-.4.854-.6 1.412-.6.559 0 1.03.192 1.413.575L21.4 8.55c.383.383.575.858.575 1.425 0 .567-.192 1.042-.575 1.425L13 20H4.75zm7.4-2L20 9.95 15.05 5 4 16.4 5.6 18h6.55z"};for(let e of Object.keys(se))se[e]=`<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="${se[e]}" fill="#5F6368"/></svg>`;function le(e,t,i){if(X[e[_][S]()]&&!e[y])return(R+"."+o)._([...e[p].map(((e,i)=>t(e,i))),(u+".child-add")._(se.add)._({click:i})])}function re(e){const t=X[e[_][S]()];return(u+"."+y)._({[v]:{collapsable:t?1:0,[y]:e[y]?1:0}},t?se.right:null)._({[Q]:t?t=>e.setCollapsed():e=>{}})}function ce(e){return new Promise((async(t,i)=>{if(null!=e)if(e instanceof File){const i=new FileReader;i.onload=i=>{try{const e=JSON.parse(i[F].result);t(e)}catch(i){console.error(`Failed to parse JSON from file ${e.name}: ${i}`),t()}},i.readAsText(e)}else if(typeof e===x)t(e);else if(typeof e===$)try{const i=await fetch(e);if(i.ok){const e=await i.text(),n=JSON.parse(e);t(n)}}catch(i){console.error(`Failed to fetch data from ${e}: ${i}`),t()}else console.error(`Invalid data [_type]: ${e} (${typeof e})`),t();else t()}))}function ae(e){return Array[j](e)?r:typeof e===x?x:typeof e===a?a:typeof e===V?V:$}function he(e,t,i,n,o){function s(e){return e[K](/\n/g,"")}function l(t){const i=t[F];i[q]=i[N][A]=s(i[q]),e.key=s(i[q]).trim()}return i?"span.array-index"._(t):H._([(J+"#key-"+e.id)._({[T]:"KEY",[b]:n?"":null},e.key[K](/\n/g,""))._({input:e=>{l(e),o[P]((()=>{}))},change:e=>{l(e)}}),"pre"._(s(e.key))])}document.addEventListener("DOMContentLoaded",(e=>{console.log("NanoJSON: https://github.com/pardnchiu/NanoJSON\nLicense: MIT\nCreator: Pardn Chiu")})),String.prototype._=function(n,o){const s=this.toString(),r=((s[M](i)||[])[0]||"").trim(),c=((s[M](t)||[])[1]||"").trim(),a=(e.test(s)?s[M](e):[]).map((e=>e[K](/^\./,"")));if(r[z]<1)return;let f,u,p=s===d,y=p?document.createDocumentFragment():document.createElement(r);c[z]>0&&(y.id=c);for(const e of a)y.classList.add(e);if(null==n&&null!=o&&([n,o]=[o,null]),null!=n&&null!=o)[f,u]=[n,o];else if(null==o)typeof n===$||typeof n===V||Array[j](n)?u=n:f=n;else if(null==n)return y;return(()=>{if(typeof f===x&&null!=f)for(const e in f){if(!f.hasOwnProperty(e))continue;const t=f[e];if({[q]:1,innerText:1,[A]:1,textContent:1,contentEditable:1,[U]:1,checked:1}[e])y[e]=t;else if({[h]:1,color:1,backgroundColor:1,background:1,width:1,height:1,float:1}[e])y.style[e]=t;else if(e===v&&typeof t===x)for(const e of Object.keys(t))y[v][e]=t[e];else null!=t&&y[m](e,t)}})(),(()=>{if(null==u)return;if(Array[j](u)){for(let e of u)typeof e===$||typeof e===V?p?y[l](document.createTextNode(e)):y[A]+=e:e instanceof Element&&y[l](e);return}if(typeof u===x)return;const e=u;"img"===r||"source"===r?y.src=e:r===J||"input"===r?y[q]=e:p?y[l](document.createTextNode(u)):y[A]=e})(),y},HTMLElement.prototype._=function(e={}){if(typeof e!==x)return;let t=this;for(const i of Object.keys(e))t["on"+i]=t=>e[i](t);return t};new Map;function de(e,t){if(e[_][S]()===V){const o=parseFloat(e[q]);function i(e){return isNaN(e)&&"-"!==e&&"."!==e?"":String(e)[K](/\s/g,"")}return H._([(J+"#value-"+e.id)._({[T]:"NUM"},i(o))._({input:n=>{const o=n[F];o[q]=o[N][A]=i(o[q]),e[q]=i(o[q]),t[P]((()=>{}))},change:t=>{const n=t[F];n[q]=n[N][A]=i(n[q]),e[q]=i(n[q])}}),"pre"._(i(o))])}if(e[_][S]()===a)return e[q].trim()[z]<1&&(e[q]=g),("select#value-"+e.id)._([D._({[q]:g,[U]:e[q]===g},g),D._({[q]:"false",[U]:"false"===e[q]},"false")])._({change:i=>{e[q]=i[F][q],t[P]((()=>{}))}});{const s=X[e[_][S]()];function n(e){return e[K](/\n/g,"<br>")}return H._({[h]:s?"none":"block"},[(J+"#value-"+e.id)._({[T]:"VAL"},e[q])._({input:i=>{const o=i[F];o[N][A]=n(o[q]),e[q]=o[q],t[P]((()=>{}))},change:t=>{const i=t[F];i[N][A]=n(i[q]),e[q]=i[q]}}),"pre"._(n(e[q]))])}}window.JSONEditor=class{children=[];body;editor;button=[];#e;#t=!1;#i=x;#n={};get type(){return this.#i}constructor(e={}){if(typeof e!=x)return void console.error("Failed to load config.");let t=e.css;(null==t||typeof t!==$||t.length<1)&&(t="https://cdn.jsdelivr.net/npm/@pardnchiu/nanojson@1.1.7/dist/NanoJSON.css"),function(e){for(let t of["link"._({rel:"preload",href:e,as:"style"}),"link"._({rel:"stylesheet",href:e})])document.head[l](t)}(t),this.#n=e??{},this.#o()}async#o(){this[k]="section"._();const e=this.#n.when??{},t=this.#n[I]??"",i=this.#n.description??"",o=Boolean(null==this.#n.fill?1:this.#n.fill)?1:0,r=this.#n[Y]??!1;let a=null!=this.#n[u]&&typeof this.#n[u]===x?this.#n[u]:{[C]:1,[w]:1,[E]:1};a[E]=a[E]??1,a[C]=a[C]??1,a[w]=a[w]??1,this.#e=new ue({beforeRender:e[Z],rendered:e[ie],beforeUpdate:e[ee],updated:e[ne],beforeDestroy:e[te],destroyed:e[oe]});let f=await ce(this.#n.file??this.#n.json??this.#n.path)??{};this[p]=this.#s(f);let y=d._([Math.max(t[z],i[z])>0?"header"._([t[z]>0?"strong"._(t):null,i[z]>0?"p"._(i):null]):null,this[k],"footer"._([u._({[I]:"Add"},se.add)._({[Q]:e=>this.insert()}),Boolean(a[C])?u._({[I]:"Open"},se.folder)._({[Q]:e=>e[F][N][Q]()}):null,Boolean(a[C])?"input"._({[_]:"file",accept:".json",[h]:"none"})._({change:e=>this[C](e[F].files[0])}):null,Boolean(a[w])?u._({[I]:"Download"},se[W])._({[Q]:e=>{confirm(e[F][I]+"?")&&this[w]()}}):null,Boolean(a[E])?u._({[I]:"Reset"},se.clear)._({[Q]:e=>{confirm(e[F][I]+"?")&&this[C]({})}}):null])]);null==this.#n.id?(this[c]=(R+"."+n)._(),this[c][l](y)):(this[c]=document.getElementById(this.#n.id),this[c].classList.add(n),this[c].replaceChildren(...y[p])),this[c][v].fill=o,this[p][z]<1&&this.insert(),this.#e[B]((async()=>{if(this[B](),r){this[c][v][Y]=1;for(let e of[...this[c][O](s)])e[m](b,g)}this.#t=!0}))}enable(){this[c][v][Y]=0;for(let e of[...this[c][O](s)])e.removeAttribute(b)}disable(){this[c][v][Y]=1;for(let e of[...this[c][O](s)])e[m](b,g)}#l(e){return e.render()}#s(e,t=null){const i=[];if(Array[j](e))for(let n of e){const e=ae(n),o=new fe({[_]:e,[L]:t??this,[k]:this,[G]:this.#e,[y]:null==this.#n.collapsed||Boolean(this.#n.collapsed),confirmKeyRemove:null==this.#n.confirmKeyRemove||Boolean(this.#n.confirmKeyRemove)});e===x&&null!=n||e===r?o[p]=this.#s(n,o):o[q]=String(n),i[f](o)}else for(const[n,o]of Object.entries(e)){const e=ae(o),s=new fe({key:n,[_]:e,[L]:t??this,[k]:this,[G]:this.#e,[y]:null==this.#n.collapsed||Boolean(this.#n.collapsed),confirmKeyRemove:null==this.#n.confirmKeyRemove||Boolean(this.#n.confirmKeyRemove)});e===x&&null!=o||e===r?s[p]=this.#s(o,s):null===o?(s[_]=_null,s[q]=null):s[q]=String(o),i[f](s)}return i}render(e=!1){let t=d._(this[p].map((e=>this.#l(e))));this[k].replaceChildren(...t[p]),this.#t&&e&&this.#e[P]((()=>{}))}insert(){this[p][f](new fe({[L]:this,[k]:this,[G]:this.#e,[y]:null==this.#n.collapsed||Boolean(this.#n.collapsed),confirmKeyRemove:null==this.#n.confirmKeyRemove||Boolean(this.#n.confirmKeyRemove)})),this[B]()}get json(){const e={};for(let t of this[p])t.key&&(e[t.key||0]=t.json);return JSON.stringify(e,null,4)}async import(e){let t=await ce(e)??{};this[p]=this.#s(t),this[B](!0)}reset(){this[C]({})}export(){const e={};for(let t of this[p])(t.key||1===this[p][z])&&(e[t.key||0]=t.json);const t=new Blob([JSON.stringify(e,null,4)],{[_]:"application/json"}),i=URL.createObjectURL(t),n="a"._({href:i,[W]:`NanoJSON-${Date.now()}.json`});document[c][l](n),n[Q](),document[c].removeChild(n),URL.revokeObjectURL(i)}};class fe{key="";type="string";value="";parent;children=[];collapsed=!1;#r;#c;#e;#a=!0;constructor(e={}){typeof e==x?(this.id=function(e=64){let t="";for(let i=0;i<e;i++)t+="abcdefghijklmnopqrstuvwxyz0123456789".charAt(Math.floor(36*Math.random()));return t}(),this.key=e.key??this.key,this[_]=e[_]??this[_],this[q]=e[q]??this[q],this[L]=e[L]??this[L],this[p]=e[p]??this[p],this[y]=e[y]??this[y],this.#c=e[k],this.#e=e[G],this.#a=e.confirmKeyRemove):console.error("Failed to load config form editor node.")}render(){return this.#l()}addChild(){this.#h()}updateChild(){this.#l(),this.#d()}setCollapsed(){this[y]=!this[y],this.#l()}get json(){return this.#f()}#d(){this.#e[P]((e=>{}))}#l(){let e="section.pd-json-editor-child"._(["section.pair-wrapper"._([("section#"+this.id+".input-group")._([re(this),he(this,this[L][p].indexOf(this),this[L][_]===r,"1"===this.#c[c][v][Y],this.#e),"span"._(":"),(t=this,i="1"===this.#c[c][v][Y],H._([t[_][S]()===V?se[V]:t[_][S]()===a?se[a]:t[_][S]()===r?se[r]:t[_][S]()===x?se[x]:se[$],"select"._({[b]:i?"":null},[...[$,V,a,r,x].map((e=>D._({[q]:e,[U]:e===t[_]},e)))])._({change:e=>{if(t[_]=e[F][q],X[e[F][q][S]()])t[q]="",0===t[p][z]&&t.addChild();else if(e[F][q][S]()===V){const e=parseFloat(t[q]);t[q]=isNaN(e)?"":e}else t[q]="",t[p]=[];t.updateChild(),document.getElementById("value-"+t.id).focus()}})])),de(this,this.#e),u._(se.add)._({[Q]:e=>{this.#a&&!confirm("Remove?")||this.#u()}})]),le(this,((e,t)=>{let i=e.#l();return i[v].last=t===this[p].length-1?1:0,i}),(()=>{this.#h()}))])]);var t,i;return this.#r&&this.#r.parentElement.replaceChild(e,this.#r),this.#r=e,this.#r}#h(){const e=new fe({[L]:this,[k]:this.#c,[G]:this.#e});this[p][f](e);const t=this.#r.querySelector(R+"."+o);if(null!=t){const i=t[p][t[p].length-1];for(let e of i.parentElement[p])e[v].last=0;const n=e.#l();n[v].last=1,t.insertBefore(n,i)}this.#d()}#u(){if(!this[L])return;const e=this[L][p].indexOf(this);if(-1===e)return;const t=this.#r.previousElementSibling;"1"===this.#r[v].last&&null!=t&&(t[v].last=1),this[L][p].splice(e,1),this.#r.remove(),this.#d()}#f(){if(!this[L])return;if(this[_]===r)return this[p].map((e=>e.#f()));if(this[_]===x){const e={};for(let t of this[p])(t.key||this[L][_]===r)&&(e[t.key||Object.keys(e)[z]]=t.#f());return e}let e=this[q];return this[_]===a?e=e[S]()===g:this[_]===V&&(e=Number(e)),e}}class ue{#p;#y;#m;#v;#g;#b;#_;#k;#w;constructor(e={}){this.#p=e[Z]||void 0,this.#y=e[ie]||void 0,this.#m=e[ee]||void 0,this.#v=e[ne]||void 0,this.#g=e[te]||void 0,this.#b=e[oe]||void 0}async#C(e){return new Promise(((t,i)=>{t(!1!==e())}))}#A(e){e(!1)}async render(e){this.#_=Date.now(),null!=this.#p&&!1===await this.#C(this.#p)||(await e(),this.#k=Date.now()-this.#_,console.log(`Rendered in ${this.#k}ms.`),null!=this.#y&&this.#A(this.#y))}async update(e){clearTimeout(this.#w),this.#w=setTimeout((async()=>{this.#_=Date.now(),null!=this.#m&&!1===await this.#C(this.#m)||(await e(),this.#k=Date.now()-this.#_,console.log(`Updated in ${this.#k}ms.`),null!=this.#v&&this.#A(this.#v))}),300)}async destroy(e){this.#_=Date.now(),null!=this.#g&&!1===await this.#C(this.#g)||(await e(),this.#k=Date.now()-this.#_,console.log(`Destroyed in ${this.#k}ms.`),null!=this.#b&&this.#A(this.#b))}}}("undefined"==typeof window?window={}:window);