diff --git a/components/file-group-page.js b/components/file-group-page.js index 03bd4e2..dab9dcf 100644 --- a/components/file-group-page.js +++ b/components/file-group-page.js @@ -23,22 +23,29 @@ html {
${'<'}script type="module"> - let frame = undefined +let frame = undefined addEventListener('message', event => { - let isNew = false - const d = event.data - if (Array.isArray(d) && d[0] === 'srcdoc') { - isNew = frame === undefined - if (isNew) { - frame = document.createElement('iframe') - frame.sandbox = "allow-scripts allow-top-navigation" + const isChild = ( + frame !== undefined && event.source == frame.contentWindow + ) + if (isChild) { + parent.postMessage(event.data, '*') + } else { + let isNew = false + const d = event.data + if (Array.isArray(d) && d[0] === 'srcdoc') { + isNew = frame === undefined + if (isNew) { + frame = document.createElement('iframe') + frame.sandbox = "allow-scripts allow-top-navigation" + } + frame.srcdoc = d[1] + if (isNew) { + document.body.appendChild(frame) + } + } else if (frame !== undefined) { + frame.contentWindow.postMessage(event.data, '*') } - frame.srcdoc = d[1] - } else if (frame !== undefined) { - frame.postMessage(event.data) - } - if (isNew) { - document.body.appendChild(frame) } }) ${''}script> @@ -81,10 +88,16 @@ export class FileGroupPage extends HTMLElement { this.initEditFrame() this.initViewFrame() this.editing = this.editing + addEventListener('message', this.handleMessage) + } + + disconnectedCallback() { + removeEventListener('message', this.handleMessage) } initEditFrame() { const frame = document.createElement('iframe') + frame.classList.add('edit') if (this.csp !== undefined) { frame.sandbox = "allow-same-origin allow-scripts allow-top-navigation" const url = new URL( @@ -100,12 +113,16 @@ export class FileGroupPage extends HTMLElement { frame.addEventListener('load', () => { this.displayEdit() }) + frame.addEventListener('message', message => { + this.handleEditMessage(message) + }) this.editFrame = frame this.shadowRoot.append(frame) } initViewFrame() { const frame = document.createElement('iframe') + frame.classList.add('view') if (this.csp !== undefined) { frame.sandbox = "allow-same-origin allow-scripts allow-top-navigation" const url = new URL( @@ -125,22 +142,50 @@ export class FileGroupPage extends HTMLElement { this.shadowRoot.append(frame) } - displayView() { - let doc = 'view here' + displayView(doc) { const msg = ['srcdoc', doc] this.viewFrame.contentWindow.postMessage( msg, '*' ) } - displayEdit() { - let doc = 'edit here' + async displayEdit() { + const doc = await this.editorBuild.build() const msg = ['srcdoc', doc] - this.viewFrame.contentWindow.postMessage( + this.editFrame.contentWindow.postMessage( msg, '*' ) } + handleMessage = event => { + const editWin = this.editFrame?.contentWindow + const viewWin = this.viewFrame?.contentWindow + if (editWin && event.source == editWin) { + this.handleEditMessage(event) + } else if (viewWin && event.source == viewWin) { + this.handleViewMessage(event) + } + } + + async handleViewMessage(event) { + } + + async handleEditMessage(event) { + if (Array.isArray(event.data)) { + if (event.data[0] === 'ready') { + this.editFrame.contentWindow.postMessage( + ['doc', this.body], '*' + ) + } else if (event.data[0] === 'html') { + const html = event.data[1] + this.displayView(html) + } else if (event.data[0] === 'save') { + const doc = event.data[1] + this.body = doc + } + } + } + set body(value) { try { localStorage.setItem(this.path, value) @@ -168,6 +213,11 @@ export class FileGroupPage extends HTMLElement { } else { classes.add('viewing') classes.remove('editing') + if (this.editFrame) { + this.editFrame.contentWindow.postMessage( + ['request-html'], '*' + ) + } } } } diff --git a/components/header.js b/components/header.js index 088a30f..04ff05e 100644 --- a/components/header.js +++ b/components/header.js @@ -28,6 +28,9 @@ export class Header extends HTMLElement { cancel: 'Cancel', alreadyExists: 'There is already a page with that name.', createPage: 'Create Page', + htmlCss: 'HTML/CSS', + singleFile: 'Single File', + newPage: 'New Page', } textEs = { @@ -40,6 +43,9 @@ export class Header extends HTMLElement { cancel: 'Cancelar', alreadyExists: 'Ya existe una página con ese nombre.', createPage: 'Crear Página', + htmlCss: 'HTML/CSS', + singleFile: 'Archivo único', + newPage: 'Nueva Página', } constructor() { @@ -310,6 +316,22 @@ export class Header extends HTMLElement { input.value = '/' input.style.minWidth = '300px' dialog.bodyEl.appendChild(input) + const select = document.createElement('select') + const options = ['htmlCss', 'singleFile'] + select.append(...options.map(value => { + const el = document.createElement('option') + el.value = value + el.innerText = this.text[value] + return el + })) + select.value = 'htmlCss' + input.addEventListener('input', e => { + const ext = e.target.value.match(/\.\w+$/) + select.value = ext ? 'singleFile' : 'htmlCss' + }) + select.style.marginTop = '10px' + select.style.marginBottom = '10px' + dialog.bodyEl.appendChild(select) let errorEl const bGroup = document.createElement( 'm-forms-button-group' @@ -328,7 +350,24 @@ export class Header extends HTMLElement { } return } - localStorage.setItem(newPath, '') + const value = ( + select.value === 'singleFile' ? + '' : + JSON.stringify({ + type: 'm-file-group', + files: [ + { + "name": "index.html", + "data": `