diff --git a/builder.js b/builder.js
index f0fc4f0..f46255c 100644
--- a/builder.js
+++ b/builder.js
@@ -1,8 +1,49 @@
-class Builder {
+const defaultHtml = `
+
+
+
+
+ macchiato.dev
+
+
+
+
+ ${ '<' + 'script type="module" src="/app.js"><' + '/script>' }
+
+
+
+`.trim()
+
+const defaultIntro = `
+
+window.Macchiato = {
+ modules: {},
+}
+
+`.trim()
+
+export class Builder {
constructor(files) {
this.files = files
}
+ buildStyle(file) {
+ const style = document.createElement('style')
+ style.textContent = file.data
+ return style.outerHTML
+ }
+
buildModule(file) {
const script = document.createElement('script')
script.setAttribute('type', 'module')
@@ -39,44 +80,74 @@ class Builder {
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 s => s
+ }
+ }
+
build() {
- const modules = this.files.map(file => {
- return this.buildModule(file)
+ const filesMap = Object.fromEntries(
+ this.files.map(
+ ({name, data}) => ([name, data])
+ )
+ )
+ const intro = this.buildModule({
+ name: '_intro.js',
+ data: (
+ '_intro.js' in filesMap ?
+ filesMap['_intro.js'] :
+ defaultIntro
+ ),
})
- return `
-
-
-
- Editor
-
-
-
-${'<'}script type="module">
-window.Macchiato = {modules: {}}
-${''}script>
-${modules.join("\n")}
-${'<'}script type="module">
-
-${''}script>
-
-
- `.trim()
+ const replace = this.buildReplace(filesMap)
+ const modules = this.files.filter(({name}) => (
+ name.endsWith('.js') &&
+ !name.startsWith('_')
+ )).map(file => (
+ this.buildModule({
+ ...file,
+ data: replace(file.data),
+ })
+ ))
+ 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
+ html = html.replace(
+ '<' + 'script type="module" src="/app.js"><' + '/script>',
+ () => {
+ replaced = true
+ return intro + "\n" + modules.join("\n")
+ }
+ )
+ if (!replaced) {
+ html += "\n" + intro + "\n" + modules.join("\n")
+ }
+ return html
}
}
\ No newline at end of file
diff --git a/editor-build.js b/editor-build.js
new file mode 100644
index 0000000..f98c140
--- /dev/null
+++ b/editor-build.js
@@ -0,0 +1,38 @@
+import { Builder } from "/loader/builder.js"
+
+export class EditorBuild {
+ deps = [
+ 'forms/button-group.js',
+ 'dialog/dialog.js',
+ 'menu/dropdown.js',
+ 'editor/file-group.js',
+ 'editor/file-view.js',
+ 'editor/text-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()
+ }
+}
\ No newline at end of file