diff options
| author | Xe Iaso <me@xeiaso.net> | 2023-04-01 17:54:07 -0400 |
|---|---|---|
| committer | Xe Iaso <me@xeiaso.net> | 2023-04-01 17:54:07 -0400 |
| commit | 06070a820f5a92c2671242b044cec5f6b3dacff5 (patch) | |
| tree | 257be786bee080c0eb76941df827680eec9912f0 /src | |
| parent | c78d291679a0b054e20ad35784dd5a8f9238f0a9 (diff) | |
| download | xesite-06070a820f5a92c2671242b044cec5f6b3dacff5.tar.xz xesite-06070a820f5a92c2671242b044cec5f6b3dacff5.zip | |
build javascript files with esbuild
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'src')
| -rw-r--r-- | src/frontend/.gitignore | 1 | ||||
| -rwxr-xr-x | src/frontend/build.sh | 1 | ||||
| -rw-r--r-- | src/frontend/build.ts | 25 | ||||
| -rw-r--r-- | src/frontend/components/ConvSnippet.tsx | 56 | ||||
| -rw-r--r-- | src/frontend/components/MastodonShareButton.tsx | 76 | ||||
| -rw-r--r-- | src/frontend/components/WASITerm.tsx | 83 | ||||
| -rw-r--r-- | src/frontend/deno.lock | 32 | ||||
| -rw-r--r-- | src/frontend/deps.ts | 10 | ||||
| -rw-r--r-- | src/frontend/import_map.json | 9 | ||||
| -rw-r--r-- | src/frontend/mastodon_share_button.tsx | 64 | ||||
| -rw-r--r-- | src/frontend/state.js | 5 | ||||
| -rw-r--r-- | src/frontend/wasiterm.tsx | 53 | ||||
| -rw-r--r-- | src/tmpl/blog.rs | 11 |
13 files changed, 273 insertions, 153 deletions
diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore new file mode 100644 index 0000000..5f98501 --- /dev/null +++ b/src/frontend/.gitignore @@ -0,0 +1 @@ +dist/*.js diff --git a/src/frontend/build.sh b/src/frontend/build.sh index 33577ae..ef3fed1 100755 --- a/src/frontend/build.sh +++ b/src/frontend/build.sh @@ -9,4 +9,3 @@ set -e export RUST_LOG=info denobuild ./mastodon_share_button.tsx ../../static/js/mastodon_share_button.js -denobuild ./wasiterm.tsx ../../static/js/wasiterm.js diff --git a/src/frontend/build.ts b/src/frontend/build.ts new file mode 100644 index 0000000..70c8b2b --- /dev/null +++ b/src/frontend/build.ts @@ -0,0 +1,25 @@ +import * as esbuild from "@esbuild"; +import { denoPlugin } from "@esbuild/deno"; + +const result = await esbuild.build({ + plugins: [denoPlugin({ + importMapURL: new URL("./import_map.json", import.meta.url), + })], + entryPoints: [ + "./components/ConvSnippet.tsx", + "./components/MastodonShareButton.tsx", + "./components/WASITerm.tsx", + ], + outdir: Deno.env.get("WRITE_TO") + ? Deno.env.get("WRITE_TO") + : "../../static/xeact", + bundle: true, + splitting: true, + format: "esm", + //minifyWhitespace: true, + inject: ["xeact"], + jsxFactory: "h", +}); +console.log(result.outputFiles); + +esbuild.stop(); diff --git a/src/frontend/components/ConvSnippet.tsx b/src/frontend/components/ConvSnippet.tsx index 02b2121..375ed9a 100644 --- a/src/frontend/components/ConvSnippet.tsx +++ b/src/frontend/components/ConvSnippet.tsx @@ -1,27 +1,43 @@ +// @jsxImportSource xeact +// @jsxRuntime automatic + export interface ConvSnippetProps { - name: string; - mood: string; - children: HTMLElement[]; + name: string; + mood: string; + children: HTMLElement[]; } -const ConvSnippet = ({name, mood, children}: ConvSnippetProps) => { - const nameLower = name.toLowerCase(); - name = name.replace(" ", "_"); +const ConvSnippet = ({ name, mood, children }: ConvSnippetProps) => { + const nameLower = name.toLowerCase(); + name = name.replace(" ", "_"); - return ( - <div className="conversation"> - <div className="conversation-standalone"> - <picture> - <source type="image/avif" srcset={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.avif`} /> - <source type="image/webp" srcset={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.webp`} /> - <img style="max-height:4.5rem" alt={`${name} is ${mood}`} loading="lazy" src={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.png`} /> - </picture> - </div> - <div className="conversation-chat"> - <<a href={`/characters#${nameLower}`}><b>{name}</b></a>> {children} - </div> - </div> - ); + return ( + <div className="conversation"> + <div className="conversation-standalone"> + <picture> + <source + type="image/avif" + srcset={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.avif`} + /> + <source + type="image/webp" + srcset={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.webp`} + /> + <img + style="max-height:4.5rem" + alt={`${name} is ${mood}`} + loading="lazy" + src={`https://cdn.xeiaso.net/file/christine-static/stickers/${nameLower}/${mood}.png`} + /> + </picture> + </div> + <div className="conversation-chat"> + <<a href={`/characters#${nameLower}`}> + <b>{name}</b> + </a>> {children} + </div> + </div> + ); }; export default ConvSnippet; diff --git a/src/frontend/components/MastodonShareButton.tsx b/src/frontend/components/MastodonShareButton.tsx new file mode 100644 index 0000000..03fe596 --- /dev/null +++ b/src/frontend/components/MastodonShareButton.tsx @@ -0,0 +1,76 @@ +// @jsxImportSource xeact +// @jsxRuntime automatic + +import { u } from "xeact"; + +export interface MastodonShareButtonProps { + title: string; + url: string; + series?: string; + tags: string; +} + +export default function MastodonShareButton( + { title, url = u(), series, tags }: MastodonShareButtonProps, +) { + let defaultURL = localStorage["mastodon_instance"]; + + if (defaultURL == undefined) { + defaultURL = ""; + } + + const tootTemplate = `${title} + +${url} + +${series ? "#" + series + " " : ""}${ + tags ? tags.map((x) => "#" + x).join(" ") : "" + } @cadey@pony.social`; + + const instanceBox = ( + <input + type="text" + placeholder="https://pony.social" + value={defaultURL} + /> + ); + const tootBox = ( + <textarea rows={6} cols={40}> + {tootTemplate} + </textarea> + ); + + return ( + <div> + <details> + <summary>Share on Mastodon</summary> + <span>{"Instance URL (https://mastodon.example)"}</span> + <br /> + {instanceBox} + <br /> + {tootBox} + <br /> + <button + onClick={() => { + let instanceURL = instanceBox.value; + + if (!instanceURL.startsWith("https://")) { + instanceURL = `https://${instanceURL}`; + } + + localStorage["mastodon_instance"] = instanceURL; + const text = tootBox.value; + const mastodonURL = u(instanceURL + "/share", { + text, + visibility: "public", + }); + console.log({ text, mastodonURL }); + window.open(mastodonURL, "_blank"); + }} + > + Share + </button> + </details> + </div> + ); +} diff --git a/src/frontend/components/WASITerm.tsx b/src/frontend/components/WASITerm.tsx new file mode 100644 index 0000000..5f7e7f9 --- /dev/null +++ b/src/frontend/components/WASITerm.tsx @@ -0,0 +1,83 @@ +// @jsxImportSource xeact +// @jsxRuntime automatic + +import { t, x } from "xeact"; +import Terminal from "@xterm"; +import * as fitAdd from "@xterm/addon-fit"; +import { Fd, File, PreopenDirectory, WASI } from "@bjorn3/browser_wasi_shim"; + +class XtermStdio extends Fd { + term: Terminal; + + constructor(term: Terminal) { + super(); + this.term = term; + } + + fd_write(view8: Uint8Array, iovs: any) { + let nwritten = 0; + for (let iovec of iovs) { + console.log( + iovec.buf_len, + iovec.buf_len, + view8.slice(iovec.buf, iovec.buf + iovec.buf_len), + ); + let buffer = view8.slice(iovec.buf, iovec.buf + iovec.buf_len); + this.term.write(buffer); + nwritten += iovec.buf_len; + } + return { ret: 0, nwritten }; + } +} + +const loadExternalFile = async (path: string) => { + return new File(await (await (await fetch(path)).blob()).arrayBuffer()); +}; + +export interface WASITermProps { + href: string; + env: string[]; + args: string[]; +} + +export default function WASITerm({ href, env, args }: WASITermProps) { + const root = <div style="max-width:80ch;max-height:20ch"></div>; + + const term = new Terminal({ + convertEol: true, + fontFamily: "Iosevka Curly Iaso", + }); + + const fit = new fitAdd.default(); + term.loadAddon(fit); + fit.fit(); + + return ( + <div> + {root} + <button + onClick={async () => { + term.writeln(`\x1B[93mfetching ${href}...\x1B[0m`); + const wasm = await WebAssembly.compileStreaming(fetch(href)); + term.writeln("\x1B[93mdone, instantiating\x1B[0m"); + + const fds = [ + new XtermStdio(term), + new XtermStdio(term), + new XtermStdio(term), + new PreopenDirectory("/tmp", {}), + ]; + + let wasi = new WASI(args, env, fds); + term.clear(); + // let inst = await WebAssembly.instantiate(wasm, { + // "wasi_snapshot_preview1": wasi.wasiImport, + // }); + // wasi.start(inst); + }} + > + Run + </button> + </div> + ); +} diff --git a/src/frontend/deno.lock b/src/frontend/deno.lock index 01f35a5..8c5f04b 100644 --- a/src/frontend/deno.lock +++ b/src/frontend/deno.lock @@ -1,9 +1,35 @@ { "version": "2", "remote": { - "https://deno.land/x/wasm@v1.2.2/pkg/wasmer_wasi_js.d.ts": "0e202696f693f922ed63e1f372dd7b4641ce587d357fcf32de3d09cb48785867", - "https://deno.land/x/wasm@v1.2.2/pkg/wasmer_wasi_js.js": "33c58765ded371211b754157955a7ab1d2de921a9c8fee8748112d25605726dd", - "https://deno.land/x/wasm@v1.2.2/wasi.ts": "4fde34f8fa8c52af06adcc241f1b18fabf2df0d8b1f1b62d05e70377688a8fcb", + "https://deno.land/std@0.156.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74", + "https://deno.land/std@0.156.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49", + "https://deno.land/std@0.156.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3", + "https://deno.land/std@0.156.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09", + "https://deno.land/std@0.156.0/path/_util.ts": "d16be2a16e1204b65f9d0dfc54a9bc472cafe5f4a190b3c8471ec2016ccd1677", + "https://deno.land/std@0.156.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633", + "https://deno.land/std@0.156.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee", + "https://deno.land/std@0.156.0/path/mod.ts": "56fec03ad0ebd61b6ab39ddb9b0ddb4c4a5c9f2f4f632e09dd37ec9ebfd722ac", + "https://deno.land/std@0.156.0/path/posix.ts": "c1f7afe274290ea0b51da07ee205653b2964bd74909a82deb07b69a6cc383aaa", + "https://deno.land/std@0.156.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9", + "https://deno.land/std@0.156.0/path/win32.ts": "bd7549042e37879c68ff2f8576a25950abbfca1d696d41d82c7bca0b7e6f452c", + "https://deno.land/x/denoflate@1.2.1/mod.ts": "f5628e44b80b3d80ed525afa2ba0f12408e3849db817d47a883b801f9ce69dd6", + "https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4", + "https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d", + "https://deno.land/x/esbuild@v0.15.10/mod.d.ts": "12e96a8d05c8e2c5638aa9cb09f24222134d437abb2f3f52de0156adb2270719", + "https://deno.land/x/esbuild@v0.15.10/mod.js": "b6076f05f58057025ce0eddb404a4da3b7a0e3768c53f6c87959c8c32240e9cd", + "https://deno.land/x/esbuild@v0.17.13/mod.d.ts": "dc279a3a46f084484453e617c0cabcd5b8bd1920c0e562e4ea02dfc828c8f968", + "https://deno.land/x/esbuild@v0.17.13/mod.js": "99302be2ce2a11eecd7a0764d970e2a0aa1c2d38d5ffcbb041d360a124c9aabc", + "https://deno.land/x/esbuild_deno_loader@0.6.0/deps.ts": "fe86f62cb954edc2580868cdc3292d4446f22cd2c4eedbf8ee26513fdf74e343", + "https://deno.land/x/esbuild_deno_loader@0.6.0/mod.ts": "5d8a429b26c70f9fd522a8629e751f3bdf63680da473e537bc420d552ee3bf0b", + "https://deno.land/x/esbuild_deno_loader@0.6.0/src/deno.ts": "0e83ccabbe2b004389288e38df2031b79eb347df2d139fce9394d8e88a11f259", + "https://deno.land/x/esbuild_deno_loader@0.6.0/src/native_loader.ts": "343854a566cf510cf25144f7c09fc0c1097780a31830305142a075d12bb697ba", + "https://deno.land/x/esbuild_deno_loader@0.6.0/src/portable_loader.ts": "35b6c526eed8c2c781a3256b23c30aa7cce69c0ef1d583c15528663287ba18a3", + "https://deno.land/x/esbuild_deno_loader@0.6.0/src/shared.ts": "b64749cd8c0f6252a11498bd8758ef1220003e46b2c9b68e16da63fd7e92b13a", + "https://deno.land/x/importmap@0.2.1/_util.ts": "ada9a9618b537e6c0316c048a898352396c882b9f2de38aba18fd3f2950ede89", + "https://deno.land/x/importmap@0.2.1/mod.ts": "ae3d1cd7eabd18c01a4960d57db471126b020f23b37ef14e1359bbb949227ade", + "https://esm.sh/v113/@bjorn3/browser_wasi_shim@0.2.7/es2022/browser_wasi_shim.mjs": "0d06fb9add2a2e53d8c52e3e5c3b5aa2115fe3ee651021d3ae1fff150a662e4e", + "https://esm.sh/v113/xterm-addon-fit@0.7.0/es2022/xterm-addon-fit.mjs": "131a41086e2e41272da58fac19e128029fb0d363103ae5f68bb71c8b7beadcf9", + "https://esm.sh/v113/xterm@5.1.0/es2022/xterm.mjs": "e0697e20cbe92d2177abe9fb744457df5c0f89f77a8e8ce7e9515b7d60f5cb57", "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/jsx-runtime.js": "a8e0e04c44bbc80bb0a8c59e1d3ee338dd799e25e89792cadb67f00bf4f6ceca", "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.js": "4b943b147cddd20b514b0cf85c68438e585712e809d8da4283ee5f0b8ac1ab8d", "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.ts": "b6def4bebff19548539f4708cff028cd1fd7abdf6bfd7b3cd8dd5025b97d676e" diff --git a/src/frontend/deps.ts b/src/frontend/deps.ts deleted file mode 100644 index f19e9ae..0000000 --- a/src/frontend/deps.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as wasi from "https://deno.land/x/wasm@v1.2.2/wasi.ts"; -//import * as xterm from "https://esm.sh/xterm@5.0.0?pin=v102"; - -import * as xeact from "xeact"; - -export { - wasi, - xeact, - //xterm -}; diff --git a/src/frontend/import_map.json b/src/frontend/import_map.json index 9e87d14..5794405 100644 --- a/src/frontend/import_map.json +++ b/src/frontend/import_map.json @@ -1,8 +1,15 @@ { "imports": { + "@bjorn3/browser_wasi_shim": "https://esm.sh/v113/@bjorn3/browser_wasi_shim@0.2.7/es2022/browser_wasi_shim.mjs", + "@xterm": "https://esm.sh/v113/xterm@5.1.0/es2022/xterm.mjs", + "@xterm/addon-fit": "https://esm.sh/v113/xterm-addon-fit@0.7.0/es2022/xterm-addon-fit.mjs", + + "@esbuild": "https://deno.land/x/esbuild@v0.17.13/mod.js", + "@esbuild/deno": "https://deno.land/x/esbuild_deno_loader@0.6.0/mod.ts", + "xeact": "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/xeact.ts", "xeact/jsx-runtime": "https://xena.greedo.xeserv.us/pkg/xeact/v0.69.71/jsx-runtime.js", - "/": "./", + "@/": "./", "./": "./" } } diff --git a/src/frontend/mastodon_share_button.tsx b/src/frontend/mastodon_share_button.tsx deleted file mode 100644 index 744570f..0000000 --- a/src/frontend/mastodon_share_button.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { g, r, u, x } from "xeact"; - -r(() => { - const root = g("mastodon_share_button"); - - let defaultURL = localStorage["mastodon_instance"]; - - if (defaultURL == undefined) { - defaultURL = ""; - } - - 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 = ( - <input type="text" placeholder="https://pony.social" value={defaultURL} /> - ); - const tootBox = <textarea rows={6} cols={40}>{tootTemplate}</textarea>; - - const doShare = () => { - let instanceURL = instanceBox.value; - - if (!instanceURL.startsWith("https://")) { - instanceURL = `https://${instanceURL}`; - } - - localStorage["mastodon_instance"] = instanceURL; - const text = tootBox.value; - const mastodonURL = u(instanceURL + "/share", { text, visibility: "public" }); - console.log({ text, mastodonURL }); - window.open(mastodonURL, "_blank"); - }; - - const shareButton = <button onclick={doShare}>Share</button>; - - x(root); - - root.appendChild( - <div> - <details> - <summary>Share on Mastodon</summary> - <span>Instance URL (https://mastodon.example)</span> - <br /> - {instanceBox} - <br /> - {tootBox} - <br /> - {shareButton} - </details> - </div>, - ); -}); diff --git a/src/frontend/state.js b/src/frontend/state.js new file mode 100644 index 0000000..195fd24 --- /dev/null +++ b/src/frontend/state.js @@ -0,0 +1,5 @@ +export const useState = (value = undefined) => { + return [() => value, (x) => { + value = x; + }]; +}; diff --git a/src/frontend/wasiterm.tsx b/src/frontend/wasiterm.tsx deleted file mode 100644 index a9b0ea5..0000000 --- a/src/frontend/wasiterm.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { wasi as wasiMod, xeact, /*xterm*/ } from "./deps.ts"; - -const { x, t } = xeact; -//const { Terminal } = xterm; -const { WASI } = wasiMod; - -const init = async (rootElem: Element, wasmURL: string) => { - //const termElem = <div></div>; - const termElem = <code></code>; - - //const term = new Terminal(); - //term.open(termElem); - - const runProgram = async () => { - await wasiMod.init(new URL("https://cdn.xeiaso.net/file/christine-static/wasm/5410143de81b20061e9750d1cf80aceef56d2938ab949e30dd7b13fa699307ad.wasm")); - - //term.writeln(`loading ${wasmURL}`); - termElem.appendChild(t(`loading ${wasmURL}`)); - - const wasi = new WASI({ - env: { - "HOSTNAME": "pyra", - }, - }) - - const moduleBytes = fetch(wasmURL); - const module = await WebAssembly.compileStreaming(moduleBytes); - await wasi.instantiate(module, {}); - //term.writeln("executing"); - termElem.appendChild(t("executing")); - let exitCode = wasi.start(); - let stdout = wasi.getStdoutString(); - console.log(`${stdout}\n\n(exit code: ${exitCode})`); - //term.writeln(`${stdout}\n\n(exit code: ${exitCode})`); - termElem.appendChild(t(`${stdout}\n\n(exit code: ${exitCode})`)); - }; - - const runButton = <button onclick={runProgram}>Run</button>; - - const root = <div> - <link rel="stylesheet" href="https://cdn.xeiaso.net/file/christine-static/wasm/xterm/xterm-a36f07105014cc9220cae423d97c30d1a59fdb0230da8e53bb74bb0faade4310.css" type="text/css" /> - {runButton} - <pre>{termElem}</pre> - </div>; - - x(rootElem); - rootElem.appendChild(root); - - //term.writeln(`loading ${wasmURL}`); - //term.writeln(`${stdout}\n\n(exit code: ${exitCode})`); -} - -export { init }; diff --git a/src/tmpl/blog.rs b/src/tmpl/blog.rs index f940db4..18d66e7 100644 --- a/src/tmpl/blog.rs +++ b/src/tmpl/blog.rs @@ -1,6 +1,7 @@ use super::{base, nag}; use crate::post::{schemaorg::Article, Post}; use maud::{html, Markup, PreEscaped}; +use xesite_templates::xeact_component; fn post_metadata(post: &Post) -> Markup { let art: Article = post.into(); @@ -28,11 +29,19 @@ fn post_metadata(post: &Post) -> Markup { } fn share_button(post: &Post) -> Markup { + return xeact_component("MastodonShareButton", serde_json::json!({ + "title": post.front_matter.title, + "series": post.front_matter.series, + "tags": post.front_matter.tags.as_ref().unwrap_or(&Vec::new()) + })); +} + +fn share_button_old(post: &Post) -> Markup { html! { div # mastodon_share_button {} div # mastodon_share_series style="display:none" {(post.front_matter.series.as_ref().unwrap_or(&"".to_string()))} div # mastodon_share_tags style="display:none" {@for tag in post.front_matter.tags.as_ref().unwrap_or(&Vec::new()) {"#" (tag) " "}} - script r#type="module" src="/static/js/mastodon_share_button.js" {} + script type="module" src="/static/js/mastodon_share_button.js" {} } } |
