Compare commits

..

No commits in common. 'pages' and 'main' have entirely different histories.
pages ... main

@ -1,3 +1,3 @@
# loader # loader
loader: builds content to load in a frame and set up sandbox and CSP loader: loads content in a frame and sets up sandbox and CSP

@ -1,49 +1,8 @@
const defaultHtml = ` class Builder {
<!doctype html>
<html>
<head>
<title>macchiato.dev</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<style type="text/css">
html, body {
margin: 0;
padding: 0;
}
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
</style>
</head>
<body>
${ '<' + 'script type="module" src="/app.js"><' + '/script>' }
</body>
</html>
`.trim()
const defaultIntro = `
window.Macchiato = {
modules: {},
}
`.trim()
export class Builder {
constructor(files) { constructor(files) {
this.files = files this.files = files
} }
buildStyle(file) {
const style = document.createElement('style')
style.textContent = file.data
return style.outerHTML
}
buildModule(file) { buildModule(file) {
const script = document.createElement('script') const script = document.createElement('script')
script.setAttribute('type', 'module') script.setAttribute('type', 'module')
@ -61,7 +20,7 @@ export class Builder {
return `// append: ${s}\n${match}` return `// append: ${s}\n${match}`
} }
).replaceAll( ).replaceAll(
/^\s*import\s+(\{[^}]+\})\s+from\s+("[^"]+")/gms, /^\s*import\s+(\{[^}]+\})\s+from\s+("[^"]+"|')/gms,
(match, p1, p2) => { (match, p1, p2) => {
const vars = p1.replaceAll(' as ', ': ') const vars = p1.replaceAll(' as ', ': ')
const importPath = p2.slice(1, -1) const importPath = p2.slice(1, -1)
@ -80,81 +39,44 @@ export class Builder {
return script.outerHTML return script.outerHTML
} }
buildReplace(filesMap) {
if ('_replace.js' in filesMap) {
const rSrc = filesMap['_replace.js']
return new Function(
rSrc.match(/\((\w+)\)/)[1],
rSrc.slice(
rSrc.indexOf('{') + 1,
rSrc.lastIndexOf('}')
)
)
} else {
return ({data}) => data
}
}
build() { build() {
const filesMap = Object.fromEntries( const modules = this.files.map(file => {
this.files.map( return this.buildModule(file)
({name, data}) => ([name, data])
)
)
const replace = this.buildReplace(filesMap)
const intro = this.buildModule({
name: '_intro.js',
data: replace({
name: '_intro.js',
data: (
'_intro.js' in filesMap ?
filesMap['_intro.js'] :
defaultIntro
),
files: this.files,
})
}) })
const modules = this.files.filter(({name}) => ( return `
name.endsWith('.js') && <!doctype html>
!name.startsWith('_') <html>
)).map(file => ( <head>
this.buildModule({ <title>Editor</title>
...file, <style>
data: replace({ html, body, iframe {
...file, margin: 0;
files: this.files, padding: 0;
}), width: 100%;
}) height: 100%;
))
const styles = this.files.filter(({name}) => (
name.endsWith('.css')
)).map(file => (
this.buildStyle(file)
))
let html = (
'index.html' in filesMap ?
filesMap['index.html'] :
defaultHtml
)
let replaced = false
html = html.replace(/\s*<\/head>/, match => {
replaced = true
return styles.join("\n") + "\n" + match
})
if (!replaced) {
html = styles.join("\n") + "\n" + html
} }
replaced = false iframe {
html = html.replace( border: none;
'<' + 'script type="module" src="/app.js"><' + '/script>', display: block;
() => {
replaced = true
return intro + "\n" + modules.join("\n")
} }
) html {
if (!replaced) { box-sizing: border-box;
html += "\n" + intro + "\n" + modules.join("\n") }
*, *:before, *:after {
box-sizing: inherit;
} }
return html </style>
</head>
<body>
${'<'}script type="module">
window.Macchiato = {modules: {}}
${'</'}script>
${modules.join("\n")}
${'<'}script type="module">
${'</'}script>
</body>
</html>
`.trim()
} }
} }

@ -1,40 +0,0 @@
import { Builder } from "/loader/builder.js"
export class EditorBuild {
deps = [
'forms/button-group.js',
'dialog/dialog.js',
'menu/dropdown.js',
'editor/header.js',
'editor/file-group.js',
'editor/file-view.js',
'editor/text-edit.js',
'editor/code-edit.js',
'loader/builder.js',
'editor/app.js',
]
constructor() {
this.files = undefined
}
async loadFiles() {
const files = []
for (const name of this.deps) {
const resp = await fetch(name)
files.push({
name,
data: await resp.text(),
})
}
this.files = files
}
async build() {
if (this.files === undefined) {
await this.loadFiles()
}
const builder = new Builder(this.files)
return builder.build()
}
}
Loading…
Cancel
Save