Compare commits

...

3 Commits

Author SHA1 Message Date
SArpnt fb8b1325be
move library code 2024-03-11 13:42:03 -04:00
SArpnt 40e1eccddd
move url code 2024-03-11 13:25:55 -04:00
SArpnt 2066466bec
url version 6 with base89 2024-03-11 12:51:29 -04:00
7 changed files with 349 additions and 247 deletions

View File

@ -20,16 +20,16 @@
'@codemirror/state': '^0.19.9',
'@codemirror/view': '^0.19.48',
'@jamshop/eleventy-plugin-esbuild': '^1.0.2',
'@prettier/plugin-pug': '^3.0.0',
//'@stdlib/constants-float32-eps': '^0.1.1',
fflate: '^0.8.1',
fflate: '^0.8.2',
'html-minifier': '^4.0.0',
minimatch: '^9.0.3',
'ts-essentials': '^9.4.1',
xxhash: '^0.3.0',
},
devDependencies: {
prettier: '^3.1.1',
typescript: '^5.3.3',
'@prettier/plugin-pug': '^3.0.0',
prettier: '^3.2.5',
typescript: '^5.4.2',
},
}

View File

@ -47,12 +47,9 @@ dependencies:
'@jamshop/eleventy-plugin-esbuild':
specifier: ^1.0.2
version: 1.0.2
'@prettier/plugin-pug':
specifier: ^3.0.0
version: 3.0.0(prettier@3.1.1)
fflate:
specifier: ^0.8.1
version: 0.8.1
specifier: ^0.8.2
version: 0.8.2
html-minifier:
specifier: ^4.0.0
version: 4.0.0
@ -61,18 +58,21 @@ dependencies:
version: 9.0.3
ts-essentials:
specifier: ^9.4.1
version: 9.4.1(typescript@5.3.3)
version: 9.4.1(typescript@5.4.2)
xxhash:
specifier: ^0.3.0
version: 0.3.0
devDependencies:
'@prettier/plugin-pug':
specifier: ^3.0.0
version: 3.0.0(prettier@3.2.5)
prettier:
specifier: ^3.1.1
version: 3.1.1
specifier: ^3.2.5
version: 3.2.5
typescript:
specifier: ^5.3.3
version: 5.3.3
specifier: ^5.4.2
version: 5.4.2
packages:
@ -86,13 +86,13 @@ packages:
hasBin: true
dependencies:
'@11ty/eleventy-utils': 1.0.2
chokidar: 3.5.3
chokidar: 3.6.0
debug: 4.3.4
dev-ip: 1.0.1
finalhandler: 1.2.0
mime: 3.0.0
minimist: 1.2.8
morphdom: 2.7.1
morphdom: 2.7.2
please-upgrade-node: 3.2.0
ssri: 8.0.1
ws: 8.16.0
@ -121,7 +121,7 @@ packages:
'@iarna/toml': 2.2.5
'@sindresorhus/slugify': 1.1.2
bcp-47-normalize: 1.1.1
chokidar: 3.5.3
chokidar: 3.6.0
cross-spawn: 7.0.3
debug: 4.3.4
dependency-graph: 0.11.0
@ -134,7 +134,7 @@ packages:
is-glob: 4.0.3
iso-639-1: 2.1.15
kleur: 4.1.5
liquidjs: 10.10.0
liquidjs: 10.10.1
luxon: 3.4.4
markdown-it: 13.0.2
micromatch: 4.0.5
@ -143,14 +143,14 @@ packages:
multimatch: 5.0.0
mustache: 4.2.0
normalize-path: 3.0.0
nunjucks: 3.2.4(chokidar@3.5.3)
nunjucks: 3.2.4(chokidar@3.6.0)
path-to-regexp: 6.2.1
please-upgrade-node: 3.2.0
posthtml: 0.16.6
posthtml-urls: 1.0.0
pug: 3.0.2
recursive-copy: 2.0.14
semver: 7.5.4
semver: 7.6.0
slugify: 1.6.6
transitivePeerDependencies:
- bufferutil
@ -173,16 +173,16 @@ packages:
engines: {node: '>=6.9.0'}
dev: false
/@babel/parser@7.23.6:
resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==}
/@babel/parser@7.24.0:
resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.23.6
'@babel/types': 7.24.0
dev: false
/@babel/types@7.23.6:
resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==}
/@babel/types@7.24.0:
resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-string-parser': 7.23.4
@ -250,7 +250,7 @@ packages:
'@codemirror/state': 0.19.9
'@codemirror/view': 0.19.48
'@lezer/common': 0.15.12
style-mod: 4.1.0
style-mod: 4.1.2
dev: false
/@codemirror/history@0.19.2:
@ -365,7 +365,7 @@ packages:
'@codemirror/rangeset': 0.19.9
'@codemirror/state': 0.19.9
'@codemirror/text': 0.19.6
style-mod: 4.1.0
style-mod: 4.1.2
w3c-keyname: 2.2.8
dev: false
@ -413,18 +413,18 @@ packages:
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.16.0
fastq: 1.17.1
dev: false
/@prettier/plugin-pug@3.0.0(prettier@3.1.1):
/@prettier/plugin-pug@3.0.0(prettier@3.2.5):
resolution: {integrity: sha512-ERMMvGSJK/7CTc8OT7W/dtlV43sytyNeiCWckN0DIFepqwXotU0+coKMv5Wx6IWSNj7ZSjdNGBAA1nMPi388xw==}
engines: {node: ^16.13.0 || >=18.0.0, npm: '>=7.10.0'}
peerDependencies:
prettier: ^3.0.0
dependencies:
prettier: 3.1.1
prettier: 3.2.5
pug-lexer: 5.0.1
dev: false
dev: true
/@sindresorhus/slugify@1.1.2:
resolution: {integrity: sha512-V9nR/W0Xd9TSGXpZ4iFUcFGhuOJtZX82Fzxj1YISlbSgKvIiNa7eLEZrT0vAraPOt++KHauIVNYgGRgjc13dXA==}
@ -454,7 +454,6 @@ packages:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: false
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@ -538,7 +537,7 @@ packages:
resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==}
engines: {node: '>= 10.0.0'}
dependencies:
'@babel/types': 7.23.6
'@babel/types': 7.24.0
dev: false
/balanced-match@1.0.2:
@ -589,13 +588,15 @@ packages:
fill-range: 7.0.1
dev: false
/call-bind@1.0.5:
resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
/call-bind@1.0.7:
resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==}
engines: {node: '>= 0.4'}
dependencies:
es-define-property: 1.0.0
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.2
set-function-length: 1.1.1
dev: false
get-intrinsic: 1.2.4
set-function-length: 1.2.2
/camel-case@3.0.0:
resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==}
@ -616,10 +617,9 @@ packages:
resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==}
dependencies:
is-regex: 1.1.4
dev: false
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
/chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
dependencies:
anymatch: 3.1.3
@ -672,8 +672,8 @@ packages:
/constantinople@4.0.1:
resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==}
dependencies:
'@babel/parser': 7.23.6
'@babel/types': 7.23.6
'@babel/parser': 7.24.0
'@babel/types': 7.24.0
dev: false
/crelt@1.0.6:
@ -712,14 +712,13 @@ packages:
ms: 2.1.2
dev: false
/define-data-property@1.1.1:
resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==}
/define-data-property@1.1.4:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.2.2
es-define-property: 1.0.0
es-errors: 1.3.0
gopd: 1.0.1
has-property-descriptors: 1.0.1
dev: false
/dependency-graph@0.11.0:
resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==}
@ -796,6 +795,16 @@ packages:
prr: 1.0.1
dev: false
/es-define-property@1.0.0:
resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==}
engines: {node: '>= 0.4'}
dependencies:
get-intrinsic: 1.2.4
/es-errors@1.3.0:
resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
engines: {node: '>= 0.4'}
/esbuild@0.7.22:
resolution: {integrity: sha512-B43SYg8LGWYTCv9Gs0RnuLNwjzpuWOoCaZHTWEDEf5AfrnuDMerPVMdCEu7xOdhFvQ+UqfP2MGU9lxEy0JzccA==}
hasBin: true
@ -840,14 +849,14 @@ packages:
micromatch: 4.0.5
dev: false
/fastq@1.16.0:
resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==}
/fastq@1.17.1:
resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
dependencies:
reusify: 1.0.4
dev: false
/fflate@0.8.1:
resolution: {integrity: sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==}
/fflate@0.8.2:
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
dev: false
/filelist@1.0.4:
@ -892,16 +901,16 @@ packages:
/function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
dev: false
/get-intrinsic@1.2.2:
resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==}
/get-intrinsic@1.2.4:
resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
engines: {node: '>= 0.4'}
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
has-proto: 1.0.1
has-proto: 1.0.3
has-symbols: 1.0.3
hasown: 2.0.0
dev: false
hasown: 2.0.2
/glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
@ -924,8 +933,7 @@ packages:
/gopd@1.0.1:
resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
dependencies:
get-intrinsic: 1.2.2
dev: false
get-intrinsic: 1.2.4
/graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@ -963,35 +971,30 @@ packages:
engines: {node: '>=8'}
dev: false
/has-property-descriptors@1.0.1:
resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
/has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
dependencies:
get-intrinsic: 1.2.2
dev: false
es-define-property: 1.0.0
/has-proto@1.0.1:
resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
/has-proto@1.0.3:
resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
engines: {node: '>= 0.4'}
dev: false
/has-symbols@1.0.3:
resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
engines: {node: '>= 0.4'}
dev: false
/has-tostringtag@1.0.0:
resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==}
/has-tostringtag@1.0.2:
resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
engines: {node: '>= 0.4'}
dependencies:
has-symbols: 1.0.3
dev: false
/hasown@2.0.0:
resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
/hasown@2.0.2:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
dependencies:
function-bind: 1.1.2
dev: false
/he@1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
@ -1058,7 +1061,7 @@ packages:
/is-core-module@2.13.1:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
hasown: 2.0.0
hasown: 2.0.2
dev: false
/is-decimal@1.0.4:
@ -1070,7 +1073,6 @@ packages:
dependencies:
acorn: 7.4.1
object-assign: 4.1.1
dev: false
/is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
@ -1106,9 +1108,8 @@ packages:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
engines: {node: '>= 0.4'}
dependencies:
call-bind: 1.0.5
has-tostringtag: 1.0.0
dev: false
call-bind: 1.0.7
has-tostringtag: 1.0.2
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@ -1170,8 +1171,8 @@ packages:
uc.micro: 1.0.6
dev: false
/liquidjs@10.10.0:
resolution: {integrity: sha512-f4gPvCq4uV4Fm5YezVUQoAMPmBMEuIE2LvgCnzyWoPRx+ZefH6b8DU2eb7znltRqATHF8zYvOsd5FD2z1spJgg==}
/liquidjs@10.10.1:
resolution: {integrity: sha512-h699VW79OLoshCTjFF02tmRCrd8t/E49LSIsjLwlg4k0TbMVjxsCRXVUEsURXbfKl3HUln2cShlDQCrSNm2YaA==}
engines: {node: '>=14'}
hasBin: true
dependencies:
@ -1288,8 +1289,8 @@ packages:
resolution: {integrity: sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==}
dev: false
/morphdom@2.7.1:
resolution: {integrity: sha512-LwrrjplMolniWtOGluKF1EHZ0y78Fa4sq7f/MXCydyNkDof+POf+ruCn+k08l7H7b/JISfRo8Zd0HazuqySY9w==}
/morphdom@2.7.2:
resolution: {integrity: sha512-Dqb/lHFyTi7SZpY0a5R4I/0Edo+iPMbaUexsHHsLAByyixCDiLHPHyVoKVmrpL0THcT7V9Cgev9y21TQYq6wQg==}
dev: false
/ms@2.0.0:
@ -1316,8 +1317,8 @@ packages:
hasBin: true
dev: false
/nan@2.18.0:
resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==}
/nan@2.19.0:
resolution: {integrity: sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==}
dev: false
/neo-async@2.6.2:
@ -1335,7 +1336,7 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/nunjucks@3.2.4(chokidar@3.5.3):
/nunjucks@3.2.4(chokidar@3.6.0):
resolution: {integrity: sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==}
engines: {node: '>= 6.9.0'}
hasBin: true
@ -1347,14 +1348,13 @@ packages:
dependencies:
a-sync-waterfall: 1.0.1
asap: 2.0.6
chokidar: 3.5.3
chokidar: 3.6.0
commander: 5.1.0
dev: false
/object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
dev: false
/on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
@ -1450,10 +1450,11 @@ packages:
posthtml-render: 3.0.0
dev: false
/prettier@3.1.1:
resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==}
/prettier@3.2.5:
resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==}
engines: {node: '>=14'}
hasBin: true
dev: true
/promise-each@2.2.0:
resolution: {integrity: sha512-67roqt1k3QDA41DZ8xi0V+rF3GoaMiX7QilbXu0vXimut+9RcKBNZ/t60xCRgcsihmNUsEjh48xLfNqOrKblUg==}
@ -1494,7 +1495,6 @@ packages:
/pug-error@2.0.0:
resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==}
dev: false
/pug-filters@4.0.0:
resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==}
@ -1512,7 +1512,6 @@ packages:
character-parser: 2.2.0
is-expression: 4.0.0
pug-error: 2.0.0
dev: false
/pug-linker@4.0.0:
resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==}
@ -1631,23 +1630,24 @@ packages:
resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
dev: false
/semver@7.5.4:
resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==}
/semver@7.6.0:
resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
engines: {node: '>=10'}
hasBin: true
dependencies:
lru-cache: 6.0.0
dev: false
/set-function-length@1.1.1:
resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==}
/set-function-length@1.2.2:
resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
engines: {node: '>= 0.4'}
dependencies:
define-data-property: 1.1.1
get-intrinsic: 1.2.2
define-data-property: 1.1.4
es-errors: 1.3.0
function-bind: 1.1.2
get-intrinsic: 1.2.4
gopd: 1.0.1
has-property-descriptors: 1.0.1
dev: false
has-property-descriptors: 1.0.2
/shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
@ -1697,8 +1697,8 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/style-mod@4.1.0:
resolution: {integrity: sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==}
/style-mod@4.1.2:
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
dev: false
/supports-color@7.2.0:
@ -1729,7 +1729,7 @@ packages:
resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==}
dev: false
/ts-essentials@9.4.1(typescript@5.3.3):
/ts-essentials@9.4.1(typescript@5.4.2):
resolution: {integrity: sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==}
peerDependencies:
typescript: '>=4.1.0'
@ -1737,11 +1737,11 @@ packages:
typescript:
optional: true
dependencies:
typescript: 5.3.3
typescript: 5.4.2
dev: false
/typescript@5.3.3:
resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
/typescript@5.4.2:
resolution: {integrity: sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==}
engines: {node: '>=14.17'}
hasBin: true
@ -1786,8 +1786,8 @@ packages:
resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}
engines: {node: '>= 10.0.0'}
dependencies:
'@babel/parser': 7.23.6
'@babel/types': 7.23.6
'@babel/parser': 7.24.0
'@babel/types': 7.24.0
assert-never: 1.2.1
babel-walk: 3.0.0-canary-5
dev: false
@ -1818,7 +1818,7 @@ packages:
engines: {node: '>=4.0.0'}
requiresBuild: true
dependencies:
nan: 2.18.0
nan: 2.19.0
dev: false
/yallist@4.0.0:

View File

@ -1,6 +1,6 @@
import { deflateSync, inflateSync } from "fflate";
import { f32ToRound10, isPlainObject, Song, SongMode } from "./common.ts";
import { f32ToRound10, isPlainObject, Song } from "./common.ts";
import { elements as elementsPromise } from "./dom.ts";
import { fromUrlData, setUrlData } from "./url/mod.ts";
const searchParams = new URLSearchParams(location.search);
@ -51,7 +51,7 @@ let elements = null; // TODO remove
import("./codemirror.ts").then(o => initCodemirror(o.default));
if (globalThis.loadLibrary !== false) {
import("./load-library.ts");
import("./library/load.ts");
}
handleWindowResize(true);
@ -60,7 +60,7 @@ let elements = null; // TODO remove
loadSettings();
let urlData: Song | undefined;
if (window.location.hash && globalThis.useUrlData !== false) {
urlData = await getUrlData();
urlData = await fromUrlData(window.location.hash);
}
setSong(urlData, false);
updateCounterValue();
@ -121,8 +121,8 @@ function handleMessage(e) {
}
}
if (data.updateUrl) {
setUrlData();
if (data.updateUrl && globalThis.useUrlData !== false) {
setUrlData(getSong());
}
if (data.errorMessage !== undefined) {
@ -246,135 +246,6 @@ function setCodeEditorText(value: string) {
}
}
// see smallmode text file
const smallmode_table = {
Bytebeat: 0b00000111,
"Signed Bytebeat": 0b00000110,
Floatbeat: 0b00011100,
Funcbeat: 0b11111100,
} as const;
async function concatUint8Arrays(uint8arrays) {
const blob = new Blob(uint8arrays);
const buffer = await blob.arrayBuffer();
return new Uint8Array(buffer);
}
// handmade, not very effective. not using it right now
//const deflateDictionary5 = new TextEncoder().encode(
// Object.getOwnPropertyNames(Math).join("(t*") +
// Object.getOwnPropertyNames(Math).join("(t+") +
// Object.getOwnPropertyNames(Math).join("(PI*") +
// Object.getOwnPropertyNames(Math).join("(t*=") +
// "int(t/=)**int(t//t--t++t**t&&!(t||t]??=0,\n\n]||=.00x=x=>(),(+=this.globalThis.window.5*random()*=\"[t>>='[t>>=`[t>>t,\".charCodeAt(t,'.charCodeAt(t,`.charCodeAt(t;i++);i++);return Math.alse-(function(){for(i=0;i<(a,b)=>(",
//);
async function getUrlData(): Promise<Song | undefined> {
const hash = window.location.hash;
const v = hash[1];
try {
if (v === "5") {
// #5
// add "00" to shift over float bytes and set first 4 bits to 0
const rateMode = Uint8Array.from(
atob("00" + hash.substring(2, 8)),
// @ts-ignore
c => c.charCodeAt(),
);
const compressedCode = Uint8Array.from(
atob(hash.substring(8)),
// @ts-ignore
c => c.charCodeAt(),
);
// this may be useful for extra properties without a new url version
/*
if (rateMode[1] >= 76) {
// number >= 2**25
}
*/
const dataview = new DataView(rateMode.buffer);
const sampleRate = dataview.getFloat32(1);
if (sampleRate >= 2 ** 24) {
console.error("Couldn't load data from url: invalid samplerate");
return;
}
const maybe_mode = Object.entries(smallmode_table).find(x => x[1] === rateMode[5]);
if (maybe_mode === undefined) {
console.error("Couldn't load data from url: invalid mode");
return;
}
const mode = maybe_mode[0] as SongMode;
const code = new TextDecoder().decode(inflateSync(compressedCode,
// a dictionary can be added later without breaking compatibility
));
return { code, sampleRate, mode };
} else if (v === "v") {
// #v4, #v3b64
const dataString = atob(hash.substring(hash[2] === "4" ? 3 : 6));
// @ts-ignore
const dataBuffer = Uint8Array.from(
dataString,
// @ts-ignore
c => c.charCodeAt(),
);
const songDataString = new TextDecoder().decode(inflateSync(dataBuffer));
let { code, sampleRate, mode } = JSON.parse(songDataString);
code = code + "";
sampleRate = Math.fround(sampleRate ?? 8000);
mode = mode ?? "Bytebeat";
if (sampleRate < 2 || sampleRate >= 2 ** 24) {
console.error("Couldn't load data from url: invalid samplerate");
return;
}
// @ts-ignore
if (smallmode_table[mode] === undefined) {
console.error("Couldn't load data from url: invalid mode");
return;
}
return { code, sampleRate, mode };
} else {
console.error("Unrecognized url data");
return;
}
} catch (err) {
console.error("Couldn't load data from url:", err);
return;
}
}
async function setUrlData() {
if (globalThis.useUrlData !== false) {
const { code, mode, sampleRate } = getSong();
const smallmode = smallmode_table[mode];
const compressedCode = deflateSync(new TextEncoder().encode(code), {
level: 8,
});
const buffer = new ArrayBuffer(6 + compressedCode.length);
const dataview = new DataView(buffer);
dataview.setFloat32(1, sampleRate);
dataview.setUint8(5, smallmode);
const dataArray = new Uint8Array(buffer);
dataArray.set(compressedCode, 6);
const dataString = dataArray.reduce((a, b) => a + String.fromCharCode(b), "");
const base64 = btoa(dataString).substring(2).replaceAll("=", "");
window.location.hash = `#5${base64}`;
}
}
function refreshCode() {
if (audioWorklet) {
audioWorklet.port.postMessage({ code: getCodeEditorText().trim() });
@ -736,7 +607,9 @@ function setByteSample(value, send = true, clear = false) {
function setPlaybackMode(playbackMode) {
if (audioWorklet) {
songData.mode = playbackMode;
setUrlData();
if (globalThis.useUrlData !== false) {
setUrlData(getSong());
}
audioWorklet.port.postMessage({ songData });
}
}

View File

@ -1,5 +1,5 @@
import { DeepReadonly } from "ts-essentials";
import { SongMode, SmallSongMode } from "common.ts";
import { SongMode, SmallSongMode } from "../common.ts";
type RemixedEntry = Readonly<{

View File

@ -1,5 +1,5 @@
import { library, Entry, EntryBase, InlineEntry, FileEntry } from "./library.ts";
import { setSong } from "./bytebeat.js";
import { setSong } from "../bytebeat.js";
function stripEntryToSong(entry: Entry) {

96
src/url/base89.ts Normal file
View File

@ -0,0 +1,96 @@
// TODO everything here is extremely poorly optimized
// into and from iterate over bits at every step, they should go over full bytes at some point
// should probably benchmark the website
const tochar =
"!#$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_abcdefghijklmnopqrstuvwxyz{|}~";
const fromchar = Object.fromEntries(Object.entries(tochar).map(([i, v]) => [v, BigInt(i)]));
// go through 123 bits at a time, into 19 character chunks
// bitIndex from 0 to 7 to trim bits off the input data
// least amount of bits that requires a base 89 string of a specific length
const lbl = Array(20)
.fill(undefined)
.map((v, i) => i && (89n ** BigInt(i - 1)).toString(2).length);
function into89(data: Uint8Array, bitIndex = 0): string {
let coded = "";
while (true) {
//const byteIndex = bitIndex >> 3;
//const bitOffset = bitIndex & 7;
let bigint = 0n;
for (let i = 0; i < 123; i++) {
if (bitIndex >> 3 < data.length) {
bigint += BigInt(!!(data[bitIndex >> 3] & (1 << (bitIndex & 7)))) << BigInt(i);
bitIndex++;
} else {
//bigint = BigInt.asUintN(123, bigint << BigInt(bitOffset));
// TODO length often wrong, i gave up on it for now
/*
for (const bits of lbl.slice(1).map(x => x - 1)) {
if (bits >= i) {
return coded;
}
coded += tochar[Number(bigint % 89n)];
bigint /= 89n;
}
// unreachable
*/
while (bigint) {
coded += tochar[Number(bigint % 89n)];
bigint /= 89n;
}
return coded;
}
}
//bigint = BigInt.asUintN(123, bigint << BigInt(bitOffset));
for (let j = 0; j < 19; j++) {
coded += tochar[Number(bigint % 89n)];
bigint /= 89n;
}
}
}
function from89(coded: string, bitIndex = 0/*, byteUp = true*/): Uint8Array {
// all this code is PROBABLY correct but i'm not sure because into89 length is wrong anyways
//const chunkCount = Math.max(Math.ceil(coded.length / 19) - 1, 0);
//const chunkRem = coded.length - chunkCount * 19;
//const lbla = lbl[chunkRem];
//const bitrem = byteUp ? (lbla + 7 & ~7) - (bitIndex & 7) : lbla;
//const bits = chunkCount * 123 + bitrem;
const bits = Math.ceil(coded.length / 19) * 123; // always too long but that's good for now
const data = new Uint8Array(((bits + bitIndex + 7) >> 3));
let currentByte = 0;
if (coded.length) {
const chunks = (coded.match(/.{1,19}/g) as RegExpMatchArray);
for (const chunk of chunks) {
let bigint = 0n;
for (const letter of chunk.split("").reverse()) {
bigint *= 89n;
bigint += fromchar[letter];
}
for (let i = 123; i; i--) {
let bit = Number(bigint & 1n);
currentByte |= bit << (bitIndex & 7);
if ((bitIndex & 7) === 7) {
data[bitIndex >> 3] = currentByte;
currentByte = 0;
}
bitIndex++;
if (bitIndex === bits) {
if ((bitIndex & 7) !== 0) {
data[bitIndex >> 3] = currentByte;
}
return data;
}
bigint >>= 1n;
}
}
}
return data;
}
export { into89, from89 };

133
src/url/mod.ts Normal file
View File

@ -0,0 +1,133 @@
import { deflateSync, inflateSync } from "fflate";
import { into89, from89 } from "./base89.ts";
import { Song, SongMode } from "../common.ts";
// see smallmode text file
const smallmode_table = {
Bytebeat: 0b00000111,
"Signed Bytebeat": 0b00000110,
Floatbeat: 0b00011100,
Funcbeat: 0b11111100,
} as const;
// handmade, not very effective. not using it right now
//const deflateDictionary5 = new TextEncoder().encode(
// Object.getOwnPropertyNames(Math).join("(t*") +
// Object.getOwnPropertyNames(Math).join("(t+") +
// Object.getOwnPropertyNames(Math).join("(PI*") +
// Object.getOwnPropertyNames(Math).join("(t*=") +
// "int(t/=)**int(t//t--t++t**t&&!(t||t]??=0,\n\n]||=.00x=x=>(),(+=this.globalThis.window.5*random()*=\"[t>>='[t>>=`[t>>t,\".charCodeAt(t,'.charCodeAt(t,`.charCodeAt(t;i++);i++);return Math.alse-(function(){for(i=0;i<(a,b)=>(",
//);
async function fromUrlData(hash: string): Promise<Song | undefined> {
const v = hash[1];
try {
if (v === "6" || v === "5") {
// #6, #5
let data: Uint8Array;
let compressedCode;
if (v === "6") {
data = from89(hash.substring(2), 12);
data[1] = data[1] >> 4 | 0x40;
compressedCode = data.subarray(6);
} else {
// add "00" to shift over float bytes and set first 4 bits to 0100
data = Uint8Array.from(
atob("00" + hash.substring(2, 8)),
// @ts-ignore
c => c.charCodeAt(),
);
compressedCode = Uint8Array.from(
atob(hash.substring(8)),
// @ts-ignore
c => c.charCodeAt(),
);
}
// this may be useful for extra properties without a new url version
/*
if (rateMode[1] >= 76) {
// number >= 2**25
}
*/
const dataview = new DataView(data.buffer);
const sampleRate = dataview.getFloat32(1);
if (sampleRate >= 2 ** 24) {
console.error("Couldn't load data from url: invalid samplerate");
return;
}
const maybe_mode = Object.entries(smallmode_table).find(x => x[1] === data[5]);
if (maybe_mode === undefined) {
console.error("Couldn't load data from url: invalid mode");
return;
}
const mode = maybe_mode[0] as SongMode;
const code = new TextDecoder().decode(inflateSync(compressedCode,
// a dictionary can be added later without breaking compatibility
));
return { code, sampleRate, mode };
} else if (v === "v") {
// #v4, #v3b64
const dataString = atob(hash.substring(hash[2] === "4" ? 3 : 6));
// @ts-ignore
const dataBuffer = Uint8Array.from(
dataString,
// @ts-ignore
c => c.charCodeAt(),
);
const songDataString = new TextDecoder().decode(inflateSync(dataBuffer));
let { code, sampleRate, mode } = JSON.parse(songDataString);
code = code + "";
sampleRate = Math.fround(sampleRate ?? 8000);
mode = mode ?? "Bytebeat";
if (sampleRate < 2 || sampleRate >= 2 ** 24) {
console.error("Couldn't load data from url: invalid samplerate");
return;
}
// @ts-ignore
if (smallmode_table[mode] === undefined) {
console.error("Couldn't load data from url: invalid mode");
return;
}
return { code, sampleRate, mode };
} else {
console.error("Unrecognized url data");
return;
}
} catch (err) {
console.error("Couldn't load data from url:", err);
return;
}
}
async function setUrlData({ code, mode, sampleRate }: Song) {
const smallmode = smallmode_table[mode];
const compressedCode = deflateSync(new TextEncoder().encode(code), {
level: 8,
});
const buffer = new ArrayBuffer(5 + compressedCode.length);
const dataview = new DataView(buffer);
dataview.setFloat32(0, sampleRate);
dataview.setUint8(4, smallmode);
const dataArray = new Uint8Array(buffer);
dataArray.set(compressedCode, 5);
dataArray[0] <<= 4;
const base89 = into89(dataArray, 4);
window.location.hash = `#6${base89}`;
}
export { fromUrlData, setUrlData };