;(async function() { //Init const url = new URLSearchParams(window.location.search) const {data:templates} = await axios.get("/templates.list") const {data:plugins} = await axios.get("/plugins.list") const {data:base} = await axios.get("/plugins.base.parts.list") //App return new Vue({ //Initialization el:"main", async mounted() { await this.load() }, //Data initialization data:{ user:url.get("user") || "", palette:url.get("palette") || "light", plugins:{ base, list:plugins, enabled:{base:Object.fromEntries(base.map(key => [key, true]))}, descriptions:{ pagespeed:"Website performances", languages:"Most used languages", followup:"Issues and pull requests", traffic:"Pages views", lines:"Lines of code changed", habits:"Coding habits", selfskip:"Skip metrics commits", "base.header":"Header", "base.activity":"Account activity", "base.community":"Community stats", "base.repositories":"Repositories metrics", "base.metadata":"Metadata", }, }, templates:{ list:templates, selected:url.get("template") || templates[0], loaded:{}, placeholder:"", descriptions:{ classic:"Classic template", terminal:"Terminal template", }, }, generated:{ pending:false, content:"", error:false, }, }, //Computed data computed:{ //User's repository repo() { return `https://github.com/${this.user}/${this.user}` }, //Endpoint to use for computed metrics url() { const plugins = Object.entries(this.plugins.enabled) .flatMap(([key, value]) => key === "base" ? Object.entries(value).map(([key, value]) => [`base.${key}`, value]) : [[key, value]]) .filter(([key, value]) => /^base[.]\w+$/.test(key) ? !value : value) .map(([key, value]) => `${key}=${+value}`) const params = [...(this.templates.selected !== templates[0] ? [`template=${this.templates.selected}`] : []), ...plugins].join("&") return `${window.location.protocol}//${window.location.host}/${this.user}${params.length ? `?${params}` : ""}` }, }, //Methods methods:{ //Load and render image async load() { //Load template const template = this.templates.selected if (!this.templates.loaded[template]) { const {data:{image, style}} = await axios.get(`/placeholder.svg?template=${template}`) this.templates.loaded[template] = {image, style} } const {image = "", style = {}} = this.templates.loaded[this.templates.selected] || {} if (!image) return this.templates.placeholder = "#" //Proxifier const proxify = (target) => typeof target === "object" ? new Proxy(target, { get(target, property) { //Primitive conversion if (property === Symbol.toPrimitive) return () => "▇" //Iterables if (property === Symbol.iterator) return Reflect.get(target, property) //Plugins should not be proxified by default as they can be toggled by user if (/^plugins$/.test(property)) return Reflect.get(target, property) //Consider no errors on plugins if (/^error/.test(property)) return undefined //Proxify recursively return proxify(property in target ? Reflect.get(target, property) : {}) } }) : target //Placeholder data const data = { style, s(_, letter) { return letter === "y" ? "ies" : "s" }, base:this.plugins.enabled.base, meta:{version:"0.0.0", author:"lowlighter", placeholder:true}, user:proxify({name:`▇▇▇▇`, websiteUrl:`▇▇▇▇▇▇▇▇▇▇▇▇`}), computed:proxify({ avatar:"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mOcOnfpfwAGfgLYttYINwAAAABJRU5ErkJggg==", registration:"▇ years ago", calendar:new Array(14).fill({color:"#ebedf0"}), licenses:{favorite:`▇▇▇▇`}, plugins:Object.fromEntries(Object.entries(this.plugins.enabled).filter(([key, enabled]) => (key !== "base")&&(enabled)).map(([key]) => { return [key, proxify({ pagespeed:{scores:["Performance", "Accessibility", "Best Practices", "SEO"].map(title => ({title, score:NaN}))}, followup:{issues:{count:0}, pr:{count:0}}, habits:{indents:{style:`▇▇▇`}}, languages:{favorites:new Array(7).fill(null).map((_, x) => ({x, name:`▇▇▇▇`, color:"#ebedf0", value:1/(x+1)}))}, }[key]||{})] })), token:{scopes:[]}, }), } //Render placeholder this.templates.placeholder = this.serialize(ejs.render(image, data)) this.generated.content = "" }, //Generate metrics and flush cache async generate() { //Avoid requests spamming if (this.generated.pending) return this.generated.pending = true //Compute metrics try { await axios.get(`/action.flush?&token=${(await axios.get(`/action.flush?user=${this.user}`)).data.token}`) this.generated.content = this.serialize((await axios.get(this.url)).data) } catch { this.generated.error = true } finally { this.generated.pending = false } }, //Serialize svg serialize(svg) { return `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svg)))}` }, }, }) })()