diff --git a/docs/edit.css b/docs/edit.css index 85e0c81..7f7faa4 100644 --- a/docs/edit.css +++ b/docs/edit.css @@ -117,19 +117,20 @@ body.drag #content { outline: none; /* min-width: 180px; */ /* top: 0; */ - position: absolute; + /* position: absolute; */ padding: 0 1em; font-weight: bold; /* opacity:0.33; */ user-select: none; cursor: default; - margin-left: -1em; + /* margin-left: -1em; */ line-height: 2.5em; display: inline-block; - margin-top: -2.7em; + /* margin-top: -2.7em; */ z-index: 2000; float: left; + font-size: 16px; } #doc-title.open { @@ -480,6 +481,14 @@ div.menu-contents { color:var(--background-color) !important; } +#url-preview { + font-weight:normal; + max-width: 460px; + overflow:hidden; + text-overflow: ellipsis; + font-size: 13px; +} + .menu hr { border: none; background-color: transparent; diff --git a/docs/edit.html b/docs/edit.html index 418ba28..a41f4bd 100644 --- a/docs/edit.html +++ b/docs/edit.html @@ -36,16 +36,7 @@ -
-
- -
+
 itty bitty things
 can be conveyed in a link.
 type here – and then share!

 about itty bitty

@@ -60,7 +51,7 @@ diff --git a/docs/edit.js b/docs/edit.js index 26fc216..965af42 100644 --- a/docs/edit.js +++ b/docs/edit.js @@ -1,6 +1,8 @@ import * as bitty from './bitty.js'; +import * as bitty_menu from '/bitty-menu.js'; window.bitty = bitty; +window.el = bitty.el; var QS = document.querySelector.bind(document); var QSS = document.querySelectorAll.bind(document); @@ -87,7 +89,9 @@ window.onload = async function() { QS("#qrcode").onclick = makeQRCode; QS("#upload").onclick = upload; QS("#share").onclick = share; - if (!navigator.share) QS("#share").style.display = "none" + QS("#url-preview").onclick = () => {document.execCommand('selectAll',false,null)}; + + // if (!navigator.share) QS("#share").style.display = "none" QS("#twitter").onclick = tweetLink; QS("#copy").onclick = copyLink; QS("#preview").onclick = togglePreview; @@ -299,27 +303,34 @@ async function handleContentChange() { text = editor.innerHTML; } + console.log("text", text, rawHTML); if (text.trim().length) { let url = `data:text/html;charset=utf-8,${encodeURIComponent(text)}`; let durl = new bitty.DataURL(url) + if (metadata.params) { + console.log("parameters", metadata.params) + metadata.params.split(";").forEach(p => { + let ps = p.split('='); + durl.params[ps.shift()] = ps.pop() + }) + } if (metadata.password) { durl.params.cipher = "aes-gcm" durl.params.style = "default" durl.params._password = metadata.password; } + durl = await durl.compress(bitty.GZIP_MARKER); let ratio = durl.href.length / url.length; console.debug(`Compressed from ${url.length} to ${durl.href.length} bytes (${Math.round(ratio * 100)}%)`); - - - if (ratio <= 0.95) url = durl.href; + if (ratio >= 1.0) url = durl.href; if (rawHTML) { updateLink(url, metadata); - } else if (metadata.password) { + } else if (metadata.password || metadata.params) { updateLink(durl.href, metadata); } else { updateLink("?" + durl.data, metadata); @@ -366,12 +377,14 @@ function updateLink(url, metadata, push) { } var hash = location.hash; - if (true) { + if (false) { if (push || !hash || !hash.length) { window.history.pushState(null, null, bittyLink); } else { window.history.replaceState(null, null, bittyLink); } + } else { + document.getElementById("url-preview").innerText = bittyLink } var length = bittyLink.length; @@ -390,14 +403,17 @@ function updateLink(url, metadata, push) { } } -function share() { - navigator.share({ - title: 'itty.bitty', - url: bittyLink - }).then(() => { - console.log('Shared!'); - }) - .catch(console.error); +function share(e) { + let menu = new bitty_menu.Menu(e.target); + console.log("men", menu) + menu.show(); + // navigator.share({ + // title: 'itty.bitty', + // url: bittyLink + // }).then(() => { + // console.log('Shared!'); + // }) + // .catch(console.error); } function makeQRCode() { var url = diff --git a/functions/rasterize.js b/functions/rasterize.js deleted file mode 100644 index 7f44bad..0000000 --- a/functions/rasterize.js +++ /dev/null @@ -1,18 +0,0 @@ -const sharp = require("sharp") - - exports.handler = async function (event, context) { - console.log("event", event, context, event.rawQuery); - let data = event.rawQuery.replace(/\=/g,'') - let svg = atob(data) || decodeURIComponent(event.rawQuery); - if (!svg.startsWith("${svg}` - console.log("svg", svg) - const img = sharp(Buffer.from(svg)) - .resize(1200) - const jpeg = img.jpeg().toBuffer(); - return { - statusCode: 200, - headers: {"content-type": "image/jpeg"}, - isBase64Encoded: true, - body: (await jpeg).toString('base64') - }; - }; \ No newline at end of file diff --git a/netlify.toml b/netlify.toml index 292421d..473dad1 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,9 +1,3 @@ -[functions] - external_node_modules = [ - "sharp" - ] - directory = "functions/" - [[edge_functions]] path = "/*" function = "metadata" diff --git a/netlify/edge-functions/metadata.js b/netlify/edge-functions/metadata.js index d688840..2ed9c4d 100644 --- a/netlify/edge-functions/metadata.js +++ b/netlify/edge-functions/metadata.js @@ -11,6 +11,25 @@ function decodeURL(s) { function atou(b64) { return decodeURIComponent(escape(atob(b64))); } function utoa(data) { return btoa(unescape(encodeURIComponent(data))); } +// Shared SVG->PNG renderer: https://github.com/arfct/og-svg +const RENDER_ORIGIN = "https://og-svg.arfct.workers.dev"; + +// Builds a render URL from SVG markup. +// +// This replaces "/.netlify/functions/rasterize/" + svg, which never worked: +// rasterize.js read the query string, not the path, so every call 502'd. It +// also put unescaped markup straight into a URL path. +// +// base64url keeps the payload URL-safe with no percent-encoding, which matters +// because Cloudflare caps URLs at 16KB. +function renderUrl(svg) { + const payload = utoa(svg) + .replace(/\+/g, "-") + .replace(/\//g, "_") + .replace(/=+$/, ""); + return `${RENDER_ORIGIN}/png?s=${payload}`; +} + function pathToMetadata(path) { let components = path.substring(1).split("/"); let info = {title: decodePrettyComponent(components.shift())} @@ -56,7 +75,7 @@ export default async (request, context) => { if (info.i) { info.i = decodeURL(info.i) - if (!info.i.startsWith("http")) info.i = "/.netlify/functions/rasterize/" + info.i + if (!info.i.startsWith("http")) info.i = renderUrl(info.i) content.push(mProp("og:image", info.i)); if (info.iw) content.push(mProp("og:image:width", info.iw)); if (info.ih) content.push(mProp("og:image:width", info.ih)); diff --git a/package.json b/package.json index ab1ee23..0b79118 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,5 @@ { "dependencies": { - "brotli-wasm": "^1.1.0", - "sharp": "^0.31.3" + "brotli-wasm": "^1.1.0" } }