-
Notifications
You must be signed in to change notification settings - Fork 1
/
html-widget.min.js
1 lines (1 loc) · 14.1 KB
/
html-widget.min.js
1
async function htmlWidget(t,e,a){const n={colour:{async add(t,e,a){const n=e.split("-");$(`${a}.${t} = ${2==n.length?`Color.dynamic(${await b(n[0])}, ${await b(n[1])})`:await b(n[0])}`)},validate(){}},posInt:{add(t,e,a){$("refreshAfterDate"===t?`let date = new Date()\ndate.setMinutes(date.getMinutes() + ${e})\nwidget.refreshAfterDate = date`:`${a}.${t} = ${e}`)},validate(t,e,a){/^\d+$/.test(a)||v("`{}` {} must be a positive integer: `{}`.",t,e,a)}},decimal:{add(t,e,a){e.endsWith("%")&&(e=Number(e.replace("%","")),e/=100),$(`${a}.${t} = ${e}`)},validate(t,e,a){/^\d*((\.\d+)|\d\.?)%?$/.test(a)||v("`{}` {} must be a positive integer or float with an optional `%` at the end: `{}`.",t,e,a)}},gradient:{async add(t,e,a){d++;let n,o=e.split(/,(?![^(]*\))(?![^"']*["'](?:[^"']*["'][^"']*["'])*[^"']*$)/).map((t=>t.trim()));const i={"to left":90,"to right":270,"to top":180,"to bottom":0,"to top left":135,"to top right":225,"to bottom left":45,"to bottom right":315,"to left top":135,"to right top":225,"to left bottom":45,"to right bottom":315};n=o[0]in i?i[o.shift()]:/\d+\s*deg/.test(o[0])?Number(o.shift().match(/(\d+)\s*deg/)[1]):0;const l=[];for(const t of o){const e=t.replace(/\s+\d*((\.\d+)|\d\.?)%?$/,"").split("-");2==e.length?l.push(`Color.dynamic(${await b(e[0])},${await b(e[1])})`):l.push(await b(e[0]))}let r=o.map((t=>{let e=t.match(/\s+\d*((\.\d+)|\d\.?)%?$/),a=e&&e[0];return a&&a.endsWith("%")&&(a=Number(a.replace("%",""))/100),null===a?null:Number(a)}));null===r[0]&&(r[0]=0),null===r[r.length-1]&&(r[r.length-1]=1);for(let t=0;t<r.length;t++){let e=r[t],a=t+1;for(;a<r.length&&null===r[a];)a++;let n=(r[a]-r[t])/(a-t);for(let o=1;o<a-t;o++)r[t+o]=n*o+e}const s=1-(.5+.5*Math.cos(Math.PI*(n+90)/180)),c=1-(.5+.5*Math.sin(Math.PI*(n+90)/180)),u=.5+.5*Math.cos(Math.PI*(n+90)/180),g=.5+.5*Math.sin(Math.PI*(n+90)/180);$(`let gradient${d} = new LinearGradient()\ngradient${d}.colors = [${l}]\ngradient${d}.locations = [${r}]\ngradient${d}.startPoint = new Point(${s}, ${c})\ngradient${d}.endPoint = new Point(${u}, ${g})\n${a}.backgroundGradient = gradient${d}`)},validate(t,e,a){let n=a.split(/,(?![^(]*\))(?![^"']*["'](?:[^"']*["'][^"']*["'])*[^"']*$)/).map((t=>t.trim()));(["to left","to right","to top","to bottom","to top left","to top right","to bottom left","to bottom right","to left top","to right top","to left bottom","to right bottom"].includes(n[0])||/\d+\s*deg/.test(n[0]))&&n.shift();let o=n.map((t=>{let e=t.match(/\s+\d*((\.\d+)|\d\.?)%?$/),a=e&&e[0];return a&&a.endsWith("%")&&(a=Number(a.replace("%",""))/100),null===a?null:Number(a)})),i=0;for(let n=0;n<o.length;n++){let l=o[n];l&&(i>l&&v("`{}` {} locations must be in ascending order: `{}`.",t,e,a),l<0&&v("`{}` {} locations must be equal or greater than `0`: `{}`.",t,e,a),l>1&&v("`{}` {} locations must be equal or less than `1`: `{}`.",t,e,a),i=l)}}},padding:{add(t,e,a){if("default"===e)$(`${a}.useDefaultPadding()`);else{let t=e.match(/\d+/g);1==t.length?t=[t[0],t[0],t[0],t[0]]:2==t.length&&(t=[t[0],t[1],t[0],t[1]]),$(`${a}.setPadding(${t.join(", ")})`)}},validate(t,e,a){/^(\d+((\s*,\s*\d+){3}|(\s*,\s*\d+))?|default)$/g.test(a)||v("`{}` {} must be 1, 2 or 4 positive integers separated by commas or be `default`: `{}`.",t,e,a)}},size:{add(t,e,a){let n=e.match(/\d+/g);$(`${a}.${t} = new Size(${n[0]}, ${n[1]})`)},validate(t,e,a){/^\d+\s*,\s*\d+$/.test(a)||v("`{}` {} must be 2 positive integers separated by commas: `{}`.",t,e,a)}},font:{add(t,e,a){let n=/^(((black|bold|medium|light|heavy|regular|semibold|thin|ultraLight)(MonospacedSystemFont|RoundedSystemFont|SystemFont)\s*,\s*(\d+))|(body|callout|caption1|caption2|footnote|subheadline|headline|largeTitle|title1|title2|title3)|((italicSystemFont)\s*,\s*(\d+)))$/;n.test(e)?$(`${a}.font = Font.${e.replace(n,"$3$4$6$8($5$9)")}`):$(`${a}.font = new Font("${e.split(",")[0].replace(/"/g,"")}",${e.split(",")[1].match(/\d+/g)[0]})`)},validate(t,e,a){/^[^,]+,\s*\d+$/.test(a)||["body","callout","caption1","caption2","footnote","subheadline","headline","italicSystemFont","largeTitle","title1","title2","title3"].includes(a)||v("`{}` {} must be 1 font name and 1 positive integer separated by commas or be a content-based font: `{}`.",t,e,a)}},point:{add(t,e,a){const n=e.split(",");$(`${a}.shadowOffset = new Point(${n[0]},${n[1]})`)},validate(t,e,a){/^-?\d+\s*,\s*-?\d+$/.test(a)||v("`{}` {} must be 2 integers separated by commas: `{}`.",t,e,a)}},bool:{add(t,e,a){"resizable"===t&&"false"!==e?$(`${a}.resizable = false`):"containerRelativeShape"===t&&"false"!==e&&$(`${a}.containerRelativeShape = true`)},validate(){}},url:{add:(t,e,a)=>{$(`${a}.url = "${e.replace(/"/g,"")}"`)},validate(t,e,a){/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/.test(a)||v("`{}` {} must be a valid URL: `{}.`",t,e,a)}},image:{add(t,e,a){e.startsWith("data:image/")?$(`${a}.backgroundImage = Image.fromData(Data.fromBase64String("${e.replace(/data:image\/\w+;base64,/,"").replace(/"/g,"")}"))`):$(`${a}.backgroundImage = await new Request("${e.replace(/"/g,"")}").loadImage()`)},validate(t,e,a){/^(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))|(data:image\/\w+?;base64,[a-zA-Z0-9+/]+={0,2})$/.test(a)||v("`{}` {} must be a valid url or base encoded data link: `{}`.",t,e,a)}},layout:{add(t,e,a){$(`${a}.layout${e[0].toUpperCase()+e.slice(1)}()`)},validate(t,e,a){"vertically"!==a&&"horizontally"!==a&&v("`{}` {} must be `vertically` or `horizontally`: `{}`.",t,e,a)}},alignText:{add(t,e,a){$(`${a}.${e}AlignText()`)},validate(t,e,a){["center","left","right"].includes(a)||v("`{}` {} must be `left`, `right` or `center`: `{}.`",t,e,a)}},alignImage:{add(t,e,a){$(`${a}.${e}AlignImage()`)},validate(t,e,a){["center","left","right"].includes(a)||v("`{}` {} must be `left`, `right` or `center`: `{}`.",t,e,a)}},alignContent:{add(t,e,a){$(`${a}.${e}AlignContent()`)},validate(t,e,a){["center","top","bottom"].includes(a)||v("`{}` {} must be `top`, `bottom` or `center`: `{}`.",t,e,a)}},applyStyle:{add(t,e,a){$(`${a}.apply${e[0].toUpperCase()+e.slice(1)}Style()`)},validate(t,e,a){["date","timer","offset","relative","time"].includes(a)||v("`{}` {} must be `date`, `timer` , `relative`, `time`, or `offset`: `{}`.",t,e,a)}},contentMode:{add(t,e,a){$(`${a}.apply${e[0].toUpperCase()+e.slice(1)}ContentMode()`)},validate(t,e,a){["filling","fitting"].includes(a)||v("`{}` {} must be `filling` or `fitting`: `{}`.",t,e,a)}}},o=u(t).children.find((t=>{if("widget"==t.name)return t}));o||v("`widget` tag must be the root tag.");const i=function(t){const e=[],a=t.match(/[\s\S]+?{[\s\S]*?}/g)||[];for(let t of a){/^\s*(\.?[\w\-]+|\*)(\s*[,>]\s*(\.?[\w\-]+|\*))*\s*\{(\s*[\w\-]+\s*:\s*[^\n]+?\s*;)*?\s*([\w\-]+\s*:\s*[^\n]+\s*;?)?\s*\}/.test(t)||v("Invalid CSS rule: `{}`.",t.trim());const a={},n=t.match(/\{([\s\S]*)\}/)[1].split(";");for(let t of n){if(t=t.trim(),!t)continue;const e=t.split(/:/)[0].trim(),n=t.split(/:/).splice(1).join(":").trim();a[w(e)]=n}t.match(/(\.?[\w\-]+|\*)(\s*[>,]\s*(\.?[\w\-]+|\*))*/)[0].split(",").forEach((t=>e.push({selector:g(t),css:a})))}return e}(o.children.filter((t=>"style"==t.name)).map((t=>t.innerText)).join("\n"));let l;!function t(e,a){if("style"==e.name)return;for(let t of a)m(e,t,0);if(e.children)for(let n of e.children)t(n,a)}(o,i);let r="",s={},d=-1;await async function t(e){if("style"==e.name)return;"widget"==e.name&&r&&v("`widget` tag must not be nestled.");r&&$("");e.name in s?s[e.name]+=1:s[e.name]=0;const o=s[e.name],i=e.innerText.replace(/</g,"<").replace(/>/g,">").replace(/&/g,"&").replace(/\n\s+/g,"\\n"),d={};Object.entries(e.attrs).forEach((([t,e])=>{["class","no-css","children"].includes(t)||(d[w(t)]=e.trim())}));let c={};e.css&&!("no-css"in e.attrs)&&e.css.forEach((t=>Object.entries(t.css).forEach((([t,e])=>c[t]=e))));if(c={...c,...d},"spacer"===e.name){$(`let spacer${o} = ${l}.addSpacer(${d.space&&"null"!==d.space?d.space:""})`);f(d,c,{space:"posInt"})}else if("widget"===e.name){r+="let widget = new ListWidget()";const m={background:["gradient","image","colour"],refreshAfterDate:"posInt",spacing:"posInt",url:"url",padding:"padding"};f(d,c,m);for(const[S,I]of Object.entries(c)){if("null"===I)continue;const C="widget";if("background"===S)try{n.url.validate("background",!0,I),n.image.add(S,I,C)}catch(k){1===I.split(/,(?![^(]*\))(?![^"']*["'](?:[^"']*["'][^"']*["'])*[^"']*$)/).length?await n.colour.add("backgroundColor",I,C):await n.gradient.add("backgroundGradient",I,C)}else{const x=n[m[S]].add;y(x)?await x(S,I,C):x(S,I,C)}}const b=r.split("\n").length;for(const z of e.children)l="widget",await t(z);h(b)}else if("stack"===e.name){$(`let stack${o} = ${l}.addStack()`);const A={background:["gradient","image","colour"],spacing:"posInt",url:"url",padding:"padding",borderColor:"colour",borderWidth:"posInt",size:"size",cornerRadius:"posInt",alignContent:"alignContent",layout:"layout"};f(d,c,A);for(const[T,j]of Object.entries(c)){if("null"===j)continue;const P="stack"+o;if("background"===T)try{n.image.validate("background",!0,j),n.image.add(T,j,P)}catch(R){1===j.split(/,(?![^(]*\))(?![^"']*["'](?:[^"']*["'][^"']*["'])*[^"']*$)/).length?await n.colour.add("backgroundColor",j,P):await n.gradient.add("backgroundGradient",j,P)}else{const D=n[A[T]].add;y(D)?await D(T,j,P):D(T,j,P)}}const M=r.split("\n").length,O="stack"+o;for(let W of e.children)l=O,await t(W);h(M)}else if("img"===e.name){let E;d.src&&"null"!==d.src||v("`img` tag must have a `src` attribute."),E=d.src.startsWith("data:image/")?`Image.fromData(Data.fromBase64String("${d.src.replace(/data:image\/.*?;base64,/,"").replace(/"/g,"")}"))`:`await new Request("${d.src.replace(/"/g,"")}").loadImage()`,$(`let img${o} = ${l}.addImage(${E})`);const F={src:"image",url:"url",borderColor:"colour",borderWidth:"posInt",cornerRadius:"posInt",imageSize:"size",imageOpacity:"decimal",tintColor:"colour",resizable:"bool",containerRelativeShape:"bool",contentMode:"contentMode",alignImage:"alignImage"};f(d,c,F);for(const[L,Z]of Object.entries(c)){if("null"===Z||"src"===L)continue;const N="img"+o,U=n[F[L]].add;y(U)?await U(L,Z,N):U(L,Z,N)}}else if("text"===e.name){$(`let text${o} = ${l}.addText("${i.replace(/"/g,"")}")`);const _={url:"url",font:"font",lineLimit:"posInt",minimumScaleFactor:"decimal",shadowColor:"colour",shadowOffset:"point",shadowRadius:"posInt",textColor:"colour",textOpacity:"decimal",alignText:"alignText"};f(d,c,_);for(const[q,G]of Object.entries(c)){if("null"===G)continue;const B="text"+o,H=n[_[q]].add;y(H)?await H(q,G,B):H(q,G,B)}}else if("date"===e.name){$(`let date${o} = ${l}.addDate(new Date("${i.replace(/"/g,"")}"))`);const J={url:"url",font:"font",lineLimit:"posInt",minimumScaleFactor:"decimal",shadowColor:"colour",shadowOffset:"point",shadowRadius:"posInt",textColor:"colour",textOpacity:"decimal",alignText:"alignText",applyStyle:"applyStyle"};f(d,c,J);for(const[V,X]of Object.entries(c)){if("null"===X)continue;const K="date"+o,Q=n[J[V]].add;y(Q)?await Q(V,X,K):Q(V,X,K)}}else{e.name in a||v("Invalid tag name: `{}`.",e.name),$(`// <${e.name}>`);const Y=[f,g,p,c,d,i];async function g(a){let n=u(a);n.children=n.children.map((t=>s(t,e.children)));let o=l;const i=r.split("\n").length;for(let e of n.children)l=o,await t(e);function s(t,e){if(t.children&&t.children.map((t=>{s(t,e)})),"children"in t.attrs)for(let a of e)t.children.push(a);return t.attrs["no-css"]="",t}h(i)}y(a[e.name])?await a[e.name](...Y):a[e.name](...Y),$(`// </${e.name}>`)}}(o),1==e&&console.log(r);const c=new(0,Object.getPrototypeOf((async function(){})).constructor)(r+"\nreturn widget");return await c();function u(t){const e=new XMLParser(t),a={isRoot:!0,name:"root",children:[]};let n=a;const o={};return e.didStartElement=(t,e)=>{const a=Symbol();o[a]=n;const i={name:t,attrs:e,innerText:"",children:[],end:a};n.children.push(i),n=i},e.foundCharacters=t=>{n.innerText+=""===n.innerText?t:" "+t},e.didEndElement=()=>{const t=n.end;n=o[t]},e.parseErrorOccurred=()=>{v("A parse error occurred, ensure your widget is formatted properly.")},a.isRoot||v("A parse error occurred, ensure all self closing tags are closed: <{}>.",a.name),e.parse(),a}function g(t){t=t.trim();let e=0;const a=[];let n=a.push({classes:[]});for(;e<t.length;){let o=t[e];if("."===o){o=t[++e];let i=/[-a-zA-Z_0-9]/;i.test(o)||v("A css parse error occurred: `{}`.",t);let l="";for(;o&&i.test(o);)l+=o,o=t[++e];a[n-1].classes.push(l)}let i=/ /;if(/>/.test(o)){for(o=t[++e];o&&i.test(o);)o=t[++e];n=a.push({classes:[]})}let l=/[a-z]/i;if(l.test(o)){let i="";for(;o&&l.test(o);)i+=o,o=t[++e];a[n-1].tag=i}/\*/.test(o)&&(o=t[++e],a[n-1].tag="*"),i.test(o)&&(o=t[++e])}return a}function m(t,e,a){if("style"!==t.name){for(let n of e.selector[a].classes){if(!t.attrs.class)return;if(!t.attrs.class.split(" ").includes(n))return}if(!e.selector[a].tag||"*"===e.selector[a].tag||e.selector[a].tag===t.name)if(e.selector.length-1===a)t.css||(t.css=[]),t.css.push(e);else if(t.children)for(let n of t.children)m(n,e,a+1)}}function f(t,e,a){for(const e in t)if("null"!==t[e])if(a[e]||v("Unknown attribute: `{}`.",e),"string"==typeof a[e])n[a[e]].validate(e,"attribute",t[e]);else{let o=!1;for(let i of a[e])try{n[i].validate(e,"attribute",t[e]),o=!0}catch(t){}o||v("`{}` attribute must be a {} type: `{}`",e,a[e].join(", ").replace(/,([^,]*?)$/," or$1"),t[e])}for(let t in e)if("null"!==e[t])if(a[t])if("string"==typeof a[t])n[a[t]].validate(t,"property",e[t]);else{let o=!1;for(let i of a[t])try{n[i].validate(t,"property",e[t]),o=!0}catch(t){}o||v("`{}` property must be a {} type: `{}`.",attr,a[t].join(", ").replace(/,([^,]*?)$/," or$1"),e[t])}else delete e[t]}function p(t,e){for(let a in e)a in t||(t[a]="null");return t}function h(t){const e=r.split("\n");for(let a=e.length-1;a>=t;a--)e[a]=" "+e[a];r=e.join("\n")}function $(t){r+=`\n${t}`}async function b(t){let e=new WebView;return await e.loadHTML(`<div id="div"style="color:${t}"></div>`),function(t,e,a,n){t=t.toString(16),e=e.toString(16),a=a.toString(16),1==t.length&&(t="0"+t);1==e.length&&(e="0"+e);1==a.length&&(a="0"+a);n=n?1==n.length?",0"+n:","+n:"";return`new Color("${"#"+t+e+a}"${n})`}(...(await e.evaluateJavaScript('window.getComputedStyle(document.getElementById("div")).color')).match(/\d+(\.\d+)?/g).map((t=>Number(t))))}function w(t){return t.replace(/-(.)/g,((t,e)=>e.toUpperCase()))}function y(t){return"AsyncFunction"===t.constructor.name}function v(t,...e){for(let a of e)t=t.replace("{}",a);throw new Error(t)}}module.exports=htmlWidget;