diff --git a/docs/index.js b/docs/index.js index 1ea5a2f..59ca7d4 100644 --- a/docs/index.js +++ b/docs/index.js @@ -96,6 +96,8 @@ "application/ld+json": {script:"/render/recipe.html"}, "text/canvas+javascript": {script:"canvas"}, "text/javascript": {script:"script"}, + // "text/vcard": {script:"/render/contact.html"}, + "mecard": {script:"contact"}, "application/bitsy": {script:"/render/bitsy.html", sandbox:"bitsy"}, "c": {script:"color"}, "e": {rewrite: "data:text/html;cipher=aes;format=gz;base64,"}, @@ -356,7 +358,8 @@ let scheme = fragment.substring(0,colon); type = scheme; - let renderer = renderers[scheme]; + let renderer = renderers[scheme.toLowerCase()]; + if (renderer) { return renderContentWithScript({renderer, title, info, body:fragment, url:fragment}); } diff --git a/docs/js/nosleep.js b/docs/js/nosleep.js index 9b49362..2b3c10d 100644 --- a/docs/js/nosleep.js +++ b/docs/js/nosleep.js @@ -56,7 +56,6 @@ window.addEventListener("click", function enable() { video.append(source) // Play it as a result of user interaction - console.log("video", video) video.play() activate() }) diff --git a/docs/js/util.js b/docs/js/util.js index 393fac2..aa05dab 100644 --- a/docs/js/util.js +++ b/docs/js/util.js @@ -29,4 +29,7 @@ const m = (selector, ...args) => { args.forEach(append); return node; -}; \ No newline at end of file +}; + + +const el = m; \ No newline at end of file diff --git a/docs/render/contact.css b/docs/render/contact.css new file mode 100644 index 0000000..fe1f070 --- /dev/null +++ b/docs/render/contact.css @@ -0,0 +1,91 @@ +* { + font-family: -apple-system, BlinkMacSystemFont, sans-serif; +} + +:root { + --shadow-color: 0deg 0% 63%; + --shadow-elevation-low: + 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.34), + 0px 0.8px 0.9px -1.2px hsl(var(--shadow-color) / 0.34), + 0px 1.9px 2.1px -2.5px hsl(var(--shadow-color) / 0.34); + --shadow-elevation-medium: + 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.36), + 0px 1.5px 1.7px -0.8px hsl(var(--shadow-color) / 0.36), + 0px 3.8px 4.3px -1.7px hsl(var(--shadow-color) / 0.36), + -0.1px 9.4px 10.6px -2.5px hsl(var(--shadow-color) / 0.36); + --shadow-elevation-high: + 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.34), + 0px 2.7px 3px -0.4px hsl(var(--shadow-color) / 0.34), + 0px 5.1px 5.7px -0.7px hsl(var(--shadow-color) / 0.34), + -0.1px 8.4px 9.5px -1.1px hsl(var(--shadow-color) / 0.34), + -0.1px 13.4px 15.1px -1.4px hsl(var(--shadow-color) / 0.34), + -0.2px 20.9px 23.5px -1.8px hsl(var(--shadow-color) / 0.34), + -0.2px 31.8px 35.8px -2.1px hsl(var(--shadow-color) / 0.34), + -0.4px 46.8px 52.7px -2.5px hsl(var(--shadow-color) / 0.34); +} + +body { + color:#16161d; + background-color: #eeeeef; + display:flex; + justify-content:center; + align-items: center; + min-height:100vh; +} + +.contact { + background-color: white; + width:320px; + height:518px; + box-shadow: var(--shadow-elevation-medium); + margin-bottom:20vh; + padding-top:24px; + border-radius:3px; + display:flex; + flex-direction: column; + justify-content: space-between; + padding:8px 0; +} + + +.header { + flex: 1 1 auto; +} + + + +.icon { + order:1; + padding: 12px 0; +} + +.row { + display:flex; + text-decoration:none; + color:black; + flex-direction: row; + border-top:1px solid #eee; + min-height:48px; + align-items: center; +} +.field { + flex: 1 1 auto; +} + +.icon svg { + +} + +a, h1, div.memo { + padding: 0 12px; + margin:0; +} + +h1 { + font-weight:normal; + font-size:24px; +} + +.contact a:hover { + background-color: #eee; +} \ No newline at end of file diff --git a/docs/render/contact.js b/docs/render/contact.js new file mode 100644 index 0000000..03f571c --- /dev/null +++ b/docs/render/contact.js @@ -0,0 +1,116 @@ +let script = window.script; + +let icon = { + bday: '', + tel: '', + text: '', + url: '', + adr: '', + email: '', + note: '', + add: '', + vid: '', +} + + + + + +function share() { + parent.postMessage({share:{}}, "*"); +} + +function render() { + document.documentElement.appendChild(el("base", {target:"_top"})) + let vcard = params.body.match(/BEGIN:VCARD/); + if (vcard) { + let data = parse(params.body) + console.log(data, params.body.split("\n")); + document.body.appendChild( + el("div.contact", {}, + el("h1.header", {}, data.fn), + data.email.forEach(email => el("div.email", {}, email.value.pop())), + data.tel.forEach(tel => el("div.tel", {}, tel.value.pop())), + // array.map(line => el("div.line", {}, line)), + ) + ) + } else if (params.body.match(/MECARD:/)){ + let lines = decodeURIComponent(params.body.substring(7)).trim().replace(/\\n/g, "\n").replace(/\\:/g, "\:").split(";"); + let mecard = {} + lines.forEach(line => { + let parts = line.split(":"); + mecard[parts.shift().toLowerCase()] = [parts.join(":")]; + }) + + document.body.appendChild( + el("div.contact", {}, + el("div.header", {}, + el("h1", {}, mecard.n), + ), + mecard.tel.map(tel => el("a.row.tel", {href:"tel:" + tel}, + el("div.icon", {innerHTML:icon.tel}), el("div.field", {}, tel))), + mecard.email.map(email => el("a.row.email", {target:"top", href:"mailto:" + email}, + el("div.icon", {innerHTML:icon.email}), el("div.field", {}, email))), + mecard.adr.map(adr => el("a.row.adr", {href:"https://address.fyi/" + adr}, + el("div.icon", {innerHTML:icon.adr}), el("div.field", {}, adr))), + mecard.bday.map(bday => el("a.row.bday", {href:"https://address.fyi/" + bday}, + el("div.icon", {innerHTML:icon.bday}), el("div.field", {}, bday))), + mecard.url.map(url => el("a.row.url", {href:url}, + el("div.icon", {innerHTML:icon.url}), el("div.field", {}, url.replace(/https?:\/\//, "")))), + mecard.memo.map(memo => el("div.row.memo", {}, el("div.field", {}, memo))), + + ) + ) + console.log("mecard", lines, mecard); + } + +} + +var path = script.substring(0, script.lastIndexOf(".")); +var cssURL = path + ".css"; +Promise.all([ + loadSyle(cssURL) +]).then(render); + +function parse(input) { + var Re1 = /^(version|fn|title|org):(.+)$/i; + var Re2 = /^([^:;]+);([^:]+):(.+)$/; + var ReKey = /item\d{1,2}\./; + var fields = {}; + + input.split(/\r\n|\r|\n/).forEach(function (line) { + var results, key; + + if (Re1.test(line)) { + results = line.match(Re1); + key = results[1].toLowerCase(); + fields[key] = results[2]; + } else if (Re2.test(line)) { + results = line.match(Re2); + key = results[1].replace(ReKey, '').toLowerCase(); + + var meta = {}; + results[2].split(';') + .map(function (p, i) { + var match = p.match(/([a-z]+)=(.*)/i); + if (match) { + return [match[1], match[2]]; + } else { + return ["TYPE" + (i === 0 ? "" : i), p]; + } + }) + .forEach(function (p) { + meta[p[0]] = p[1]; + }); + + if (!fields[key]) fields[key] = []; + + fields[key].push({ + meta: meta, + value: results[3].split(';') + }) + } + }); + + return fields; +};