export const BOOKMARKS_PARAM = 'bookmarks'
async function pipe(bytes, stream) {
const out = new Blob([bytes]).stream().pipeThrough(stream)
return new Uint8Array(await new Response(out).arrayBuffer())
}
function toBase64url(bytes) {
let bin = ''
for (const b of bytes) bin += String.fromCharCode(b)
return btoa(bin).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
}
function fromBase64url(s) {
const bin = atob(s.replace(/-/g, '+').replace(/_/g, '/'))
return Uint8Array.from(bin, c => c.charCodeAt(0))
}
export async function encodeBookmarkIds(ids) {
const bytes = new TextEncoder().encode(ids.join('\n'))
return toBase64url(await pipe(bytes, new CompressionStream('deflate-raw')))
}
export async function decodeBookmarkIds(param) {
try {
const bytes = await pipe(fromBase64url(param), new DecompressionStream('deflate-raw'))
const ids = new TextDecoder().decode(bytes).split('\n').filter(id => /^https?:\/\/\S+$/.test(id))
return ids.length > 0 ? [...new Set(ids)] : null
} catch {
return null
}
}
export async function bookmarkLink(ids, origin) {
const url = new URL('/', origin)
url.searchParams.set(BOOKMARKS_PARAM, await encodeBookmarkIds(ids))
return url.href
}