From e174b7ba4dc1f6e755d6142f0d26a3e6357be771 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Thu, 24 Nov 2022 18:55:21 -0500 Subject: make new mastodon share button Signed-off-by: Xe Iaso --- flake.nix | 21 +++++++- src/frontend/build.sh | 6 +++ src/frontend/deno.json | 8 ++++ src/frontend/import_map.json | 8 ++++ src/frontend/mastodon_share_button.tsx | 55 +++++++++++++++++++++ src/frontend/xeact/jsx-runtime.js | 16 +++++++ src/frontend/xeact/xeact.js | 88 ++++++++++++++++++++++++++++++++++ src/frontend/xeact/xeact.ts | 9 ++++ static/js/.gitignore | 1 + templates/blogpost.rs.html | 61 ++--------------------- 10 files changed, 215 insertions(+), 58 deletions(-) create mode 100755 src/frontend/build.sh create mode 100644 src/frontend/deno.json create mode 100644 src/frontend/import_map.json create mode 100644 src/frontend/mastodon_share_button.tsx create mode 100644 src/frontend/xeact/jsx-runtime.js create mode 100644 src/frontend/xeact/xeact.js create mode 100644 src/frontend/xeact/xeact.ts create mode 100644 static/js/.gitignore diff --git a/flake.nix b/flake.nix index 83c10df..4dcda34 100644 --- a/flake.nix +++ b/flake.nix @@ -54,6 +54,25 @@ ''; }; + frontend = pkgs.stdenv.mkDerivation { + pname = "xesite-frontend"; + inherit (bin) version; + src = ./src/frontend; + buildInputs = with pkgs; [ deno nodePackages.uglify-js ]; + + phases = "installPhase"; + + installPhase = '' + mkdir -p $out/static/js + mkdir -p .deno + export HOME=./.deno + + deno bundle --config $src/deno.json $src/mastodon_share_button.tsx ./mastodon_share_button.js + + uglifyjs ./mastodon_share_button.js -c -m > $out/static/js/mastodon_share_button.js + ''; + }; + static = pkgs.stdenv.mkDerivation { pname = "xesite-static"; inherit (bin) version; @@ -86,7 +105,7 @@ default = pkgs.symlinkJoin { name = "xesite-${bin.version}"; - paths = [ config posts static bin ]; + paths = [ config posts static bin frontend ]; }; docker = pkgs.dockerTools.buildLayeredImage { diff --git a/src/frontend/build.sh b/src/frontend/build.sh new file mode 100755 index 0000000..ad31763 --- /dev/null +++ b/src/frontend/build.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +set -e + +export RUST_LOG=info +deno bundle ./mastodon_share_button.tsx ../../static/js/mastodon_share_button.js diff --git a/src/frontend/deno.json b/src/frontend/deno.json new file mode 100644 index 0000000..b763d25 --- /dev/null +++ b/src/frontend/deno.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "jsxImportSource": "xeact", + "lib": ["esnext", "dom", "dom.iterable"] + }, + "importMap": "./import_map.json", +} diff --git a/src/frontend/import_map.json b/src/frontend/import_map.json new file mode 100644 index 0000000..20cfc64 --- /dev/null +++ b/src/frontend/import_map.json @@ -0,0 +1,8 @@ +{ + "imports": { + "xeact": "./xeact/xeact.ts", + "xeact/jsx-runtime": "./xeact/jsx-runtime.js", + "/": "./", + "./": "./" + } +} diff --git a/src/frontend/mastodon_share_button.tsx b/src/frontend/mastodon_share_button.tsx new file mode 100644 index 0000000..64164a7 --- /dev/null +++ b/src/frontend/mastodon_share_button.tsx @@ -0,0 +1,55 @@ +import { g, r, u, x } from "xeact"; + +r(() => { + const root = g("mastodon_share_button"); + + let defaultURL = localStorage["mastodon_instance"]; + + const title = document.querySelectorAll('meta[property="og:title"]')[0] + .getAttribute("content"); + let series = g("mastodon_share_series").innerText; + if (series != "") { + series = `#${series} `; + } + const tags = g("mastodon_share_tags"); + const articleURL = u(); + + const tootTemplate = `${title} + +${articleURL} + +${series}${tags.innerText}@cadey@pony.social`; + + const instanceBox = ( + + ); + const tootBox = ; + + const doShare = () => { + const instanceURL = instanceBox.value; + localStorage["mastodon_instance"] = instanceURL; + const text = tootBox.value; + const mastodon_url = u(instanceURL + "/share", { text }); + console.log({ text, mastodon_url }); + window.open(mastodon_url, "_blank"); + }; + + const shareButton = ; + + x(root); + + root.appendChild( +
+
+ Share on Mastodon + Instance URL (https://mastodon.example) +
+ {instanceBox} +
+ {tootBox} +
+ {shareButton} +
+
, + ); +}); diff --git a/src/frontend/xeact/jsx-runtime.js b/src/frontend/xeact/jsx-runtime.js new file mode 100644 index 0000000..58ccfaa --- /dev/null +++ b/src/frontend/xeact/jsx-runtime.js @@ -0,0 +1,16 @@ +import { h } from './xeact.ts'; + +/** + * Create a DOM element, assign the properties of `data` to it, and append all `data.children`. + * + * @type{function(string, Object=): HTMLElement} + */ +export const jsx = (tag, data) => { + let children = data.children; + delete data.children; + const result = h(tag, data, children); + result.classList.value = result.class; + return result; +}; +export const jsxs = jsx; +export const jsxDEV = jsx; diff --git a/src/frontend/xeact/xeact.js b/src/frontend/xeact/xeact.js new file mode 100644 index 0000000..7be9a1c --- /dev/null +++ b/src/frontend/xeact/xeact.js @@ -0,0 +1,88 @@ +/** + * Creates a DOM element, assigns the properties of `data` to it, and appends all `children`. + * + * @type{function(string|Function, Object=, Node|Array.=)} + */ +const h = (name, data = {}, children = []) => { + const result = typeof name == "function" ? name(data) : Object.assign(document.createElement(name), data); + if (!Array.isArray(children)) { + children = [children]; + } + result.append(...children); + return result; +}; + +/** + * Create a text node. + * + * Equivalent to `document.createTextNode(text)` + * + * @type{function(string): Text} + */ +const t = (text) => document.createTextNode(text); + +/** + * Remove all child nodes from a DOM element. + * + * @type{function(Node)} + */ +const x = (elem) => { + while (elem.lastChild) { + elem.removeChild(elem.lastChild); + } +}; + +/** + * Get all elements with the given ID. + * + * Equivalent to `document.getElementById(name)` + * + * @type{function(string): HTMLElement} + */ +const g = (name) => document.getElementById(name); + +/** + * Get all elements with the given class name. + * + * Equivalent to `document.getElementsByClassName(name)` + * + * @type{function(string): HTMLCollectionOf.} + */ +const c = (name) => document.getElementsByClassName(name); + +/** @type{function(string): HTMLCollectionOf.} */ +const n = (name) => document.getElementsByName(name); + +/** + * Get all elements matching the given HTML selector. + * + * Matches selectors with `document.querySelectorAll(selector)` + * + * @type{function(string): Array.} + */ +const s = (selector) => Array.from(document.querySelectorAll(selector)); + +/** + * Generate a relative URL from `url`, appending all key-value pairs from `params` as URL-encoded parameters. + * + * @type{function(string=, Object=): string} + */ +const u = (url = "", params = {}) => { + let result = new URL(url, window.location.href); + Object.entries(params).forEach((kv) => { + let [k, v] = kv; + result.searchParams.set(k, v); + }); + return result.toString(); +}; + +/** + * Takes a callback to run when all DOM content is loaded. + * + * Equivalent to `window.addEventListener('DOMContentLoaded', callback)` + * + * @type{function(function())} + */ +const r = (callback) => window.addEventListener('DOMContentLoaded', callback); + +export { h, t, x, g, c, n, u, s, r }; diff --git a/src/frontend/xeact/xeact.ts b/src/frontend/xeact/xeact.ts new file mode 100644 index 0000000..8974ec1 --- /dev/null +++ b/src/frontend/xeact/xeact.ts @@ -0,0 +1,9 @@ +export * from "./xeact.js"; + +declare global { + export namespace JSX { + interface IntrinsicElements { + [elemName: string]: any; + } + } +} diff --git a/static/js/.gitignore b/static/js/.gitignore new file mode 100644 index 0000000..4bf7e61 --- /dev/null +++ b/static/js/.gitignore @@ -0,0 +1 @@ +mastodon_share_button.js diff --git a/templates/blogpost.rs.html b/templates/blogpost.rs.html index b0e1965..985fca0 100644 --- a/templates/blogpost.rs.html +++ b/templates/blogpost.rs.html @@ -75,7 +75,10 @@ } - +
+ + +

This article was posted on @post.detri(). Facts and circumstances may have changed since publication. Please contact me before jumping to conclusions if something seems wrong or unclear.

@@ -103,60 +106,4 @@

The art for Cadey was drawn by ArtZora Studios.

- - @:footer_html() -- cgit v1.2.3