Download files
parent
dc1d993cca
commit
649ed6db6c
@ -0,0 +1,143 @@
|
|||||||
|
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()
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
html, body {
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background: navy;
|
||||||
|
margin: 10px;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.cyan {
|
||||||
|
background: cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.green {
|
||||||
|
background: lightgreen;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue