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 = `