uses brotli and base64url for link sharing

This commit is contained in:
eefano
2025-07-03 22:49:32 +02:00
parent caf6686d01
commit 9107d0bd3e
5 changed files with 81 additions and 3 deletions
+41 -1
View File
@@ -777,6 +777,12 @@ importers:
astro:
specifier: ^5.1.9
version: 5.1.9(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(rollup@2.79.2)(terser@5.37.0)(typescript@5.7.3)(yaml@2.7.0)
base64url-universal:
specifier: ^2.0.0
version: 2.0.0
brotli-wasm:
specifier: ^3.0.1
version: 3.0.1
claviature:
specifier: ^0.1.0
version: 0.1.0
@@ -819,6 +825,9 @@ importers:
tailwindcss:
specifier: ^3.4.17
version: 3.4.17
vite-plugin-wasm:
specifier: ^3.4.1
version: 3.4.1(vite@6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0))
worker-timers:
specifier: ^8.0.13
version: 8.0.13
@@ -3206,6 +3215,14 @@ packages:
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
base64url-universal@2.0.0:
resolution: {integrity: sha512-6Hpg7EBf3t148C3+fMzjf+CHnADVDafWzlJUXAqqqbm4MKNXbsoPdOkWeRTjNlkYG7TpyjIpRO1Gk0SnsFD1rw==}
engines: {node: '>=14'}
base64url@3.0.1:
resolution: {integrity: sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==}
engines: {node: '>=6.0.0'}
before-after-hook@2.2.3:
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
@@ -3237,6 +3254,10 @@ packages:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
brotli-wasm@3.0.1:
resolution: {integrity: sha512-U3K72/JAi3jITpdhZBqzSUq+DUY697tLxOuFXB+FpAE/Ug+5C3VZrv4uA674EUZHxNAuQ9wETXNqQkxZD6oL4A==}
engines: {node: '>=v18.0.0'}
browserslist@4.24.4:
resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -5714,6 +5735,7 @@ packages:
node-domexception@1.0.0:
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
engines: {node: '>=10.5.0'}
deprecated: Use your platform's native DOMException instead
node-fetch-native@1.6.6:
resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==}
@@ -7453,6 +7475,11 @@ packages:
'@vite-pwa/assets-generator':
optional: true
vite-plugin-wasm@3.4.1:
resolution: {integrity: sha512-ja3nSo2UCkVeitltJGkS3pfQHAanHv/DqGatdI39ja6McgABlpsZ5hVgl6wuR8Qx5etY3T5qgDQhOWzc5RReZA==}
peerDependencies:
vite: ^2 || ^3 || ^4 || ^5 || ^6
vite@6.0.11:
resolution: {integrity: sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@@ -7657,6 +7684,7 @@ packages:
workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
workbox-navigation-preload@7.0.0:
resolution: {integrity: sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==}
@@ -10797,6 +10825,12 @@ snapshots:
base64-js@1.5.1: {}
base64url-universal@2.0.0:
dependencies:
base64url: 3.0.1
base64url@3.0.1: {}
before-after-hook@2.2.3: {}
bin-links@4.0.4:
@@ -10840,6 +10874,8 @@ snapshots:
dependencies:
fill-range: 7.1.1
brotli-wasm@3.0.1: {}
browserslist@4.24.4:
dependencies:
caniuse-lite: 1.0.30001695
@@ -12762,7 +12798,7 @@ snapshots:
jake@10.9.2:
dependencies:
async: 3.2.6
chalk: 4.1.0
chalk: 4.1.2
filelist: 1.0.4
minimatch: 3.1.2
@@ -15894,6 +15930,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
vite-plugin-wasm@3.4.1(vite@6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0)):
dependencies:
vite: 6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0)
vite@6.0.11(@types/node@22.10.10)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(yaml@2.7.0):
dependencies:
esbuild: 0.24.2
+5 -1
View File
@@ -6,6 +6,7 @@ import rehypeSlug from 'rehype-slug';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeUrls from 'rehype-urls';
import bundleAudioWorkletPlugin from 'vite-plugin-bundle-audioworklet';
import wasm from 'vite-plugin-wasm';
import tailwind from '@astrojs/tailwind';
import AstroPWA from '@vite-pwa/astro';
@@ -135,7 +136,10 @@ export default defineConfig({
site,
base,
vite: {
plugins: [bundleAudioWorkletPlugin()],
optimizeDeps: {
exclude: ["brotli-wasm", "brotli-wasm/pkg.bundler/brotli_wasm_bg.wasm"],
},
plugins: [bundleAudioWorkletPlugin(),wasm()],
ssr: {
// Example: Force a broken package to skip SSR processing, if needed
// external: ['fraction.js'], // https://github.com/infusion/Fraction.js/issues/51
+3
View File
@@ -54,6 +54,8 @@
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"astro": "^5.1.9",
"base64url-universal": "^2.0.0",
"brotli-wasm": "^3.0.1",
"claviature": "^0.1.0",
"date-fns": "^4.1.0",
"hs2js": "0.1.0",
@@ -68,6 +70,7 @@
"rehype-urls": "^1.2.0",
"remark-toc": "^9.0.0",
"tailwindcss": "^3.4.17",
"vite-plugin-wasm": "^3.4.1",
"worker-timers": "^8.0.13"
},
"devDependencies": {
+15 -1
View File
@@ -35,6 +35,10 @@ import { getRandomTune, initCode, loadModules, shareCode } from './util.mjs';
import './Repl.css';
import { setInterval, clearInterval } from 'worker-timers';
import { getMetadata } from '../metadata_parser';
import brotliPromise from 'brotli-wasm';
import { encode as base64urlencode } from 'base64url-universal';
const brotli = await brotliPromise; // Import is async in browsers due to wasm requirements!
const { latestCode, maxPolyphony, audioDeviceName, multiChannelOrbits } = settingsMap.get();
let modulesLoading, presets, drawContext, clearCanvas, audioReady;
@@ -99,7 +103,17 @@ export function useReplContext() {
window.parent?.postMessage(code);
setLatestCode(code);
window.location.hash = '#' + code2hash(code);
//window.location.hash = '#' + code2hash(code);
// Compress the script with brotli and encode it with base64url
const encoded = new TextEncoder().encode(code);
//console.log('encoded',encoded);
const brotlized = brotli.compress(encoded, { mode: 1, quality: 11 });
//console.log('brotlized',brotlized);
const baseurled = base64urlencode(brotlized);
//console.log('baseurled',baseurled);
window.location.hash = '#~' + baseurled;
setDocumentTitle(code);
const viewingPatternData = getViewingPatternData();
setVersionDefaultsFrom(code);
+17
View File
@@ -8,6 +8,10 @@ import { createClient } from '@supabase/supabase-js';
import { nanoid } from 'nanoid';
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
import { $featuredPatterns /* , loadDBPatterns */ } from '@src/user_pattern_utils.mjs';
import brotliPromise from 'brotli-wasm';
import { decode as base64urldecode } from 'base64url-universal';
const brotli = await brotliPromise; // Import is async in browsers due to wasm requirements!
// Create a single supabase client for interacting with your database
export const supabase = createClient(
@@ -27,6 +31,19 @@ export async function initCode() {
const hash = initialUrl.split('?')[1]?.split('#')?.[0]?.split('&')[0];
const codeParam = window.location.href.split('#')[1] || '';
if (codeParam) {
if (codeParam[0] === '~')
{
// Encoded using base64url and Compressed by brotli
const baseurled = codeParam.substring(1);
//console.log('baseurled', baseurled);
const brotlized = base64urldecode(baseurled);
//console.log('brotlized', brotlized);
const encoded = brotli.decompress(brotlized);
//console.log('encoded', encoded);
const decoded = new TextDecoder().decode(encoded);
//console.log('decoded', decoded);
return decoded;
}
// looking like https://strudel.cc/#ImMzIGUzIg%3D%3D (hash length depends on code length)
return hash2code(codeParam);
} else if (hash) {