function log(message, cls = 'cyan') { const el = document.createElement('pre') el.classList.add(cls) el.innerText = message document.body.append(el) } class App { jApiBaseUrl = 'https://data.jsdelivr.com/v1/' jCdnBaseUrl = 'https://cdn.jsdelivr.net/npm/' scripts = { '@rollup/browser': { version: '3.20.4', path: 'dist/rollup.browser.js', sha: 'sha256-GgOznxZmgghx1a7CH09B+VmDKtziPO5tAnC5gC+/5Kw=', }, } topLevelDeps = [ "@codemirror/autocomplete", "@codemirror/commands", "@codemirror/language", "@codemirror/lint", "@codemirror/search", "@codemirror/state", "@codemirror/view", "@codemirror/lang-javascript", ] constructor() { this.downloads = [] this.run().catch(e => { log(`${e}`) }) } checkOk(resp) { if (!resp.ok) { throw new Error(`HTTP request failed: ${resp.status}`) } } async loadDep(dep) { this.scripts[dep] = {} const dataResp = await fetch( this.jApiBaseUrl + `packages/npm/${dep}/resolved`, { headers: { 'User-Agent': 'https://codeberg.org/macchiato', }, }, ) this.checkOk(dataResp) const {version} = await dataResp.json() this.scripts[dep].version = version const pkgResp = await fetch( this.jCdnBaseUrl + `${dep}@${version}/package.json` ) this.checkOk(pkgResp) log(dep) const pkg = await pkgResp.json() this.scripts[dep].path = ( pkg.module ?? pkg.main ) this.downloads.push(this.getScript(dep)) const deps = Object.keys( pkg.dependencies || {} ).filter(dep => !(dep in this.scripts)) await Promise.allSettled(deps.map(dep => ( this.loadDep(dep) ))) } async checkIntegrity(resp, name, script) { const blob = await resp.blob() const ab = await blob.arrayBuffer() const hash = await crypto.subtle.digest( "SHA-256", ab ) const checkValue = 'sha256-' + btoa( String.fromCharCode( ...new Uint8Array(hash) ) ) if (checkValue !== script.sha) { throw new Error( 'failed integrity check: ' + `${checkValue} !== ${script.sha}` ) } return ab } async getScript(name) { log('[downloading] ' + name, 'green') const script = this.scripts[name] if (script.text) { return script.text } const url = ( this.jCdnBaseUrl + `${name}@${script.version}/${script.path}` ) const resp = await fetch(url) this.checkOk(resp) if (script.sha) { const ab = await this.checkIntegrity( resp, name, script ) script.text = new TextDecoder().decode(ab) } else { script.text = await resp.text script.sha = resp.integrity } log('[downloaded] ' + url, 'green') return script.text } async loadScript(name) { const text = await this.getScript(name) const s = document.createElement('script') s.text = text document.head.append(s) } async run() { await Promise.allSettled( this.topLevelDeps.map(dep => ( this.loadDep(dep) )) ) await Promise.allSettled(this.downloads) //await this.loadScript('@rollup/browser') //const { rollup } = window.rollup //output.value = `${typeof rollup}` } } new App()