From 45b99ababc6496ebf7c8387ece77b5c9044139b1 Mon Sep 17 00:00:00 2001 From: Nicholas Jitkoff Date: Tue, 6 Jun 2023 21:05:48 +0200 Subject: [PATCH] Update contact --- docs/index.js | 2 +- docs/js/util.js | 18 ++++- docs/render/contact.css | 38 ++++++++-- docs/render/contact.html | 28 +++++++ docs/render/contact.js | 159 ++++++++++++++++++++++++++++++++------- 5 files changed, 207 insertions(+), 38 deletions(-) create mode 100644 docs/render/contact.html diff --git a/docs/index.js b/docs/index.js index 59ca7d4..a65ed12 100644 --- a/docs/index.js +++ b/docs/index.js @@ -97,7 +97,7 @@ "text/canvas+javascript": {script:"canvas"}, "text/javascript": {script:"script"}, // "text/vcard": {script:"/render/contact.html"}, - "mecard": {script:"contact"}, + "mecard": {script:"/render/contact.html"}, "application/bitsy": {script:"/render/bitsy.html", sandbox:"bitsy"}, "c": {script:"color"}, "e": {rewrite: "data:text/html;cipher=aes;format=gz;base64,"}, diff --git a/docs/js/util.js b/docs/js/util.js index aa05dab..c60aa0c 100644 --- a/docs/js/util.js +++ b/docs/js/util.js @@ -1,4 +1,4 @@ -const m = (selector, ...args) => { +const el = (selector, ...args) => { var attrs = (args[0] && typeof args[0] === 'object' && !Array.isArray(args[0]) && !(args[0] instanceof HTMLElement)) ? args.shift() : {}; let classes = selector.split("."); @@ -16,7 +16,11 @@ const m = (selector, ...args) => { let dataProp = prop.substring(5).replace(/-([a-z])/g, function(g) { return g[1].toUpperCase(); }); node.dataset[dataProp] = attrs[prop]; } else { - node[prop] = attrs[prop]; + if (typeof attrs[prop] === 'function' || prop == "className") { + node[prop] = attrs[prop]; + } else { + node.setAttribute(prop, attrs[prop]); + } } } } @@ -30,6 +34,12 @@ const m = (selector, ...args) => { return node; }; +el.trust = function (html) { + if (!html?.length) return undefined; + var template = document.createElement('template'); + template.innerHTML = html; + return Array.from(template.content.childNodes); +} - -const el = m; \ No newline at end of file +const m = el; +window.el = el; diff --git a/docs/render/contact.css b/docs/render/contact.css index f71def6..dc05309 100644 --- a/docs/render/contact.css +++ b/docs/render/contact.css @@ -52,13 +52,25 @@ body { overflow:hidden; } +.firstGroup { + display:flex; + flex-direction: column; + width:320px; +} + +@media only screen and (min-width: 640px) { + .contact { + flex-direction: row; + width:640px; + } +} .header { flex: 1 1 auto; padding-top:1em; display:flex; flex-direction: column; - padding: 24px 8px; + padding: 24px 8px 8px 0px; } .content { @@ -68,6 +80,7 @@ body { img.profile { aspect-ratio: 1.0; background-color:rgba(0,0,0, 0.025); + width:100%; } /* .header img { @@ -83,9 +96,11 @@ img.profile { .icon { order:-1; padding: 6px 0; - margin-right:32px; + margin-right:0; align-self: flex-start; height: 8px; + min-width:24px; + height:24px; } .icon img { @@ -104,18 +119,31 @@ img.profile { align-items: center; background:white; } + +.header div.row { + padding: 0 0px; + margin: 8px 16px 0 16px; + order:1; + background-color:transparent +} + +div.row a { +padding: 8px; +color:black; +} + .field { flex: 1 1 auto; overflow:hidden; text-overflow: ellipsis; white-space: pre-wrap; padding:4px 0; -} - -.icon svg { + padding-left:16px; } +.icon svg {width: 24px;height: 24px;} + a, h1, div.memo, .header div { padding: 0 24px; margin:0; diff --git a/docs/render/contact.html b/docs/render/contact.html new file mode 100644 index 0000000..49d9710 --- /dev/null +++ b/docs/render/contact.html @@ -0,0 +1,28 @@ + + + + +
+ + + + + + + + + + + + + +
+ + + + + diff --git a/docs/render/contact.js b/docs/render/contact.js index 86aa64f..1aaf49d 100644 --- a/docs/render/contact.js +++ b/docs/render/contact.js @@ -2,8 +2,8 @@ let script = window.script; let fieldIcons = { bday: '', - tel: '', - text: '', + call: '', + tel: '', url: '', adr: '', email: '', @@ -13,29 +13,80 @@ let fieldIcons = { } let siteIcons = { - "twitter.com": "twitter", - "facebook.com": "facebook", - "instagram.com": "instagram", - "linkedin.com": "linkedin", - "youtube.com": "youtube", - "tiktok.com": "tiktok", - "snapchat.com": "snapchat", - "pinterest.com": "pinterest", - "tumblr.com": "tumblr", - "reddit.com": "reddit", - "github.com": "github", - "medium.com": "medium", - "twitch.tv": "twitch", + "twitter.com": {icon: "twitter", reformat:(a) => a.replace(/twitter.com\/(.*)/, "@$1")}, + "facebook.com": {icon: "facebook"}, + "instagram.com": {icon: "instagram", reformat:(a) => a.replace(/instagram.com\/(.*)/, "@$1")}, + "linkedin.com": {icon: "linkedin"}, + "youtube.com": {icon: "youtube"}, + "tiktok.com": {icon: "tiktok"}, + "snapchat.com": {icon: "snapchat"}, + "pinterest.com": {icon: "pinterest"}, + "tumblr.com": {icon: "tumblr"}, + "reddit.com": {icon: "reddit"}, + "github.com": {icon: "github", reformat:(a) => a.replace(/github.com\/(.*)/, "@$1")}, + "medium.com": {icon: "medium"}, + "twitch.tv": {icon: "twitch"}, } +let spriteString = ` + + + + + + + + + + + + + + + + + + + + + + +` +// +var template = document.createElement('template'); +template.innerHTML = spriteString; +console.log(template.content.firstChild); +let groups = Array.from(template.content.querySelector("svg .Symbols").children); +let sprite = el("svg", {xmlns:"http://www.w3.org/2000/svg"}, + el("defs", {},groups.map( + (group,i) => el("symbol", {viewBox: 24 * i + " 0 24 24", id:"icon-" + group.getAttribute("class")}, group) + ) + )) + +console.log("sprite", sprite); +// document.body.appendChild(sprite); + function share() { parent.postMessage({share:{}}, "*"); } +function vcardVersion(data) { + if (data.vcard) return data.vcard; + + return `BEGIN:VCARD +VERSION:3.0 +N:NAME +END:VCARD` +} + function formatBday(date) { const year = date.slice(0, 4); const month = date.slice(4, 6) - 1; // months are zero-indexed in JavaScript @@ -45,7 +96,8 @@ function formatBday(date) { } function render() { - document.documentElement.appendChild(el("base", {target:"_top"})) + document.head.appendChild(el("base", {target:"_top"})) + document.head.appendChild(el("meta", {name:"viewport", content:"width=device-width, initial-scale=1.0"})) let vcard = params.body.match(/BEGIN:VCARD/); if (vcard) { let data = parse(params.body) @@ -76,6 +128,7 @@ function render() { if (key == 'color') { document.body.style.backgroundColor = value; } else if (key == 'n') { + value = value.split(",").reverse().join(" "); headingElements.push(el("h1", {}, value)) } else if (key == 'img') { imgElement = (el("img.profile", {src:value})); @@ -89,17 +142,55 @@ function render() { value = value.replace(/https?:\/\/(www.)?/, "") } + if (key == "bday") { + value = formatBday(value) + } + + if (key == "tel") { + let actionrow = el("div.row." + key, {target:"top", href}, + el("a.icon", {href:"facetime:" + value}, el.trust(fieldIcons["vid"])), + el("a.icon", {href:"tel:" + value}, el.trust(fieldIcons["call"])), + + el("a.icon", {href:"add:" + value}, el.trust(fieldIcons["add"])), + ) + headingElements.push(actionrow) + } + if (key == "nickname") { return; } + if (!fieldIcons[key]) { headingElements.push(el("div", value)); } else { - let img = el.trust(fieldIcons[key]); + let icon = el("div.icon", el.trust(fieldIcons[key])) + if (key == "url") { - img = el("img", {src:"https://www.google.com/s2/favicons?sz=48&domain=" + href}); - } + let override = siteIcons[new URL(href).hostname]; + + if (override) { + let site = "#icon-" + override.icon; + if (override.reformat) value = override.reformat(value); + console.log(override.reformat, value) + icon.innerHTML = `