UNPKG

sweetpea

Version:

Signal and Web Component Enhanced Web Apps

208 lines (167 loc) 6 kB
import EventEmitter from 'event-emitter'; export default Inheritance => class Project extends Inheritance { project = { name: 'Untitled', file: 'untitled.txt', } generateCode(){ const lines = []; lines.push(` // URGENT: this should be a zip or tar file. import actors from 'sweetpea-company'; const stage = new Stage(); `.split('\n').map(i=>i.trim()).join('\n')) const meta = this.project; const data = this.dehydrate(); function omit(o, ...keys){ return Object.fromEntries(Object.entries(o).filter(e=>!keys.includes(e[0]))); } function str(input) { return JSON.stringify(input) } function className(str) { return str .split(/[^a-z0-1)]/i) // Split by spaces .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize first letter .join(''); // Join without spaces } function toInstanceName(str) { const word = className(str); return word.charAt(0).toLowerCase() + word.slice(1); } function toPropertyName(str) { const word = className(str); return word.charAt(0).toLowerCase() + word.slice(1); } let counter = 0; for (const actorObject of data) { delete actorObject.x; delete actorObject.y; if(actorObject.type == 'super'){ const name = actorObject.type; const type = actorObject.worker; const properties = omit(actorObject, 'type', 'id', 'worker'); const instanceName = toInstanceName(`${name}${counter}`); lines.push(`const ${instanceName} = new ${className(name)}(stage);`) for (const property in properties) { const value = properties[property] lines.push(`${instanceName}.${toPropertyName(property)} = ${str(value)}`) } lines.push(`await ${instanceName}.worker(${str(type)});`) }else{ const name = actorObject.type; const type = actorObject.type; const properties = omit(actorObject, 'type', 'id'); const instanceName = toInstanceName(`${name}${counter}`); lines.push(`const ${instanceName} = new ${className(type)}(stage);`) for (const property in properties) { const value = properties[property] lines.push(`${instanceName}.${toPropertyName(property)} = ${str(value)}`) } } lines.push('') counter++; } lines.push(` stage.director.emit('start'); // TODO: nonitor CTRL-C, setup HTTP, daemonize, setup browser extenion, etc. `.split('\n').map(i=>i.trim()).join('\n')) console.log(lines.join('\n')); this.downloadDialogue('code.js', lines.join('\n')); } dehydrate(){ const response = []; for (const child of this.getStage().children) { console.log(child); // Do something with each child element const obj = {}; obj.type = child.tagName.toLowerCase().split('-')[1]; const attributes = Object.fromEntries(Array.from(child.attributes).map(attr => [attr.name, attr.value])); Object.assign(obj, attributes); response.push(obj); } return response; } // Convert to HTML rehydrate(rawData){ return rawData; } blank(){ this.getStage().replaceChildren(); } open(){ this.host.shadowRoot.getElementById('fileInput').click(); this.host.shadowRoot.getElementById('fileInput').addEventListener('change', async (event) => { const file = event.target.files[0]; if (file) { const contents = await file.text(); const {meta, data} = JSON.parse(contents) // console.log({meta, data}); this.getStage().replaceChildren(); // Clear Stage for (const actorObject of data) { const actorElement = document.createElement(`${VPL_ELEMENT_PREFIX}-${actorObject.type}`); delete actorObject.type; for (const [attributeName, attributeValue] of Object.entries(actorObject)) { actorElement.setAttribute(attributeName, attributeValue); } console.log(actorElement); this.getStage().appendChild(actorElement); } this.project = meta; } }); } save(){ const str = JSON.stringify({ meta: this.project, data: this.dehydrate(), }, null, 2) this.downloadDialogue(this.project.file, str); } saveAs(){ } downloadDialogue(name, str){ const blob = new Blob([str], { type: 'text/plain' }); // Create a URL for the Blob const url = URL.createObjectURL(blob); // Get the iframe element const iframe = this.host.shadowRoot.getElementById('downloadIframe'); // Set the iframe's source to the Blob URL iframe.src = url; // Optionally, revoke the Blob URL after a short delay setTimeout(() => { URL.revokeObjectURL(url); }, 100); // Trigger download by creating a temporary link (optional for browsers) const link = document.createElement('a'); link.href = url; link.download = name; // Specify the filename link.click(); } // formatHTML(htmlString) { // // Use a regular expression to split at tag boundaries // const lines = htmlString.split(/(?=<)|(?<=>)/g); // const formattedHTML = []; // let indentLevel = 0; // const indentSize = ' '; // // lines.forEach(line => { // line = line.trim(); // if (line.startsWith('</')) { // // Closing tag; decrement indent level first // indentLevel--; // } // // if (line) { // // Add current line with the current level of indentation // formattedHTML.push(`${indentSize.repeat(indentLevel)}${line}`); // } // // if (line.startsWith('<') && !line.startsWith('</') && !line.endsWith('/>')) { // // Opening tag; increment indent level after use // indentLevel++; // } // }); // // return formattedHTML.join('\n'); // } }