create project save handler, fix html export again
This commit is contained in:
parent
2b87a57d43
commit
bf9a06cadf
@ -8,6 +8,7 @@ export class AssetEditor {
|
|||||||
this.toggleButton = rootEl.querySelector("#toggle-asset-editor-button");
|
this.toggleButton = rootEl.querySelector("#toggle-asset-editor-button");
|
||||||
this.container = rootEl;
|
this.container = rootEl;
|
||||||
this.previewedName = null;
|
this.previewedName = null;
|
||||||
|
this.changeEventHandlers = [];
|
||||||
|
|
||||||
if (localStorage.getItem("asset-editor-expanded")) {
|
if (localStorage.getItem("asset-editor-expanded")) {
|
||||||
this.editor.style.display = "block";
|
this.editor.style.display = "block";
|
||||||
@ -32,6 +33,16 @@ export class AssetEditor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addChangeListener(callback) {
|
||||||
|
this.changeEventHandlers.push(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#emitChange() {
|
||||||
|
for (const handler of this.changeEventHandlers) {
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getAssets() {
|
getAssets() {
|
||||||
return this.store.getAll();
|
return this.store.getAll();
|
||||||
}
|
}
|
||||||
@ -43,6 +54,7 @@ export class AssetEditor {
|
|||||||
await this.addAsset({ name: asset.name, file: asset.file });
|
await this.addAsset({ name: asset.name, file: asset.file });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.#emitChange();
|
||||||
this.renderList();
|
this.renderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,12 +88,14 @@ export class AssetEditor {
|
|||||||
async addAsset({ name, file }) {
|
async addAsset({ name, file }) {
|
||||||
await this.store.add(name, file);
|
await this.store.add(name, file);
|
||||||
|
|
||||||
|
this.#emitChange();
|
||||||
this.renderList();
|
this.renderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAsset(name) {
|
async deleteAsset(name) {
|
||||||
await this.store.delete(name);
|
await this.store.delete(name);
|
||||||
|
|
||||||
|
this.#emitChange();
|
||||||
this.renderList();
|
this.renderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export class HtmlExporter {
|
|||||||
<title>${projectName}</title>
|
<title>${projectName}</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
background-color: black;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -49,7 +50,7 @@ export class HtmlExporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const gamelib = new Gamelib(console, null, new AssetProvider(), document.querySelector('canvas'));
|
const gamelib = new Gamelib(console, new AssetProvider(), document.querySelector('canvas'));
|
||||||
|
|
||||||
window.karlkoder = {
|
window.karlkoder = {
|
||||||
lib() {
|
lib() {
|
||||||
|
68
src/index.js
68
src/index.js
@ -6,13 +6,10 @@ import { CodeRunner } from "./code_runner.js";
|
|||||||
import { AssetEditor } from "./asset_editor.js";
|
import { AssetEditor } from "./asset_editor.js";
|
||||||
import { AssetProvider } from "./asset_provider.js";
|
import { AssetProvider } from "./asset_provider.js";
|
||||||
import { Gamelib } from "./gamelib.js";
|
import { Gamelib } from "./gamelib.js";
|
||||||
import { KarlkoderCodec } from "./karlkoder_codec.js";
|
|
||||||
import { promptUpload } from "./prompt_upload.js";
|
|
||||||
import { GamelibCompleter } from "./gamelib_completer.js";
|
import { GamelibCompleter } from "./gamelib_completer.js";
|
||||||
import { TextCompleter } from "./text_completer.js";
|
import { TextCompleter } from "./text_completer.js";
|
||||||
import { ConsoleInput } from "./console_input.js";
|
import { ConsoleInput } from "./console_input.js";
|
||||||
import { downloadFile, slugify } from "./utils.js";
|
import { ProjectSaveHandler } from "./project_save_handler.js";
|
||||||
import { HtmlExporter } from "./html_exporter.js";
|
|
||||||
|
|
||||||
const editor = ace.edit("editor");
|
const editor = ace.edit("editor");
|
||||||
editor.setTheme("ace/theme/gruvbox");
|
editor.setTheme("ace/theme/gruvbox");
|
||||||
@ -43,8 +40,6 @@ const assetProvider = new AssetProvider();
|
|||||||
|
|
||||||
const assetEditor = new AssetEditor(document.querySelector("#asset-editor-container"), []);
|
const assetEditor = new AssetEditor(document.querySelector("#asset-editor-container"), []);
|
||||||
|
|
||||||
const htmlExporter = new HtmlExporter(assetProvider);
|
|
||||||
|
|
||||||
const gamelib = new Gamelib(
|
const gamelib = new Gamelib(
|
||||||
playgroundConsole.getAdapter(),
|
playgroundConsole.getAdapter(),
|
||||||
assetProvider,
|
assetProvider,
|
||||||
@ -68,6 +63,8 @@ const saveButton = document.querySelector("#save-button");
|
|||||||
const loadButton = document.querySelector("#load-button");
|
const loadButton = document.querySelector("#load-button");
|
||||||
const exportButton = document.querySelector("#export-button");
|
const exportButton = document.querySelector("#export-button");
|
||||||
|
|
||||||
|
const projectSaveHandler = new ProjectSaveHandler(editor, assetEditor, assetProvider, projectName);
|
||||||
|
|
||||||
const sessionSaveDebounce = new Debounce(1000);
|
const sessionSaveDebounce = new Debounce(1000);
|
||||||
editor.addEventListener("change", () => {
|
editor.addEventListener("change", () => {
|
||||||
sessionSaveDebounce.run(() => {
|
sessionSaveDebounce.run(() => {
|
||||||
@ -83,41 +80,6 @@ projectName.onchange = () => {
|
|||||||
sessionStorage.setItem("project-name", projectName.value);
|
sessionStorage.setItem("project-name", projectName.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
loadButton.onclick = async () => {
|
|
||||||
const files = await promptUpload(".karlkode", false);
|
|
||||||
if (files.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (files.length > 1) {
|
|
||||||
throw new Error(
|
|
||||||
`unreachable: something went wrong ! files.length > 1 : files.length = ${files.length}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const items = KarlkoderCodec.de(
|
|
||||||
await fetch(URL.createObjectURL(files[0])).then((x) => x.bytes()),
|
|
||||||
);
|
|
||||||
const assets = items
|
|
||||||
.filter((x) => x.tag === "asset")
|
|
||||||
.map((x) => {
|
|
||||||
delete x.tag;
|
|
||||||
return x;
|
|
||||||
});
|
|
||||||
const code = items.find((x) => x.tag === "code");
|
|
||||||
delete code.tag;
|
|
||||||
|
|
||||||
assetEditor.importAssets(
|
|
||||||
assets.map(({ name, mime, content }) => {
|
|
||||||
const file = new File([content], name, { type: mime });
|
|
||||||
|
|
||||||
return { name, file };
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
projectName.value = code.name;
|
|
||||||
const dec = new TextDecoder();
|
|
||||||
editor.setValue(dec.decode(code.content));
|
|
||||||
};
|
|
||||||
|
|
||||||
runButton.onclick = async () => {
|
runButton.onclick = async () => {
|
||||||
const code = editor.getValue();
|
const code = editor.getValue();
|
||||||
|
|
||||||
@ -139,29 +101,21 @@ runButton.onclick = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
exportButton.onclick = async () => {
|
exportButton.onclick = async () => {
|
||||||
const html = await htmlExporter.export(projectName.value, editor.getValue());
|
projectSaveHandler.exportProject();
|
||||||
|
|
||||||
downloadFile(slugify(projectName.value) || "project", html, ".html", "text/html");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function saveKarlKoder() {
|
loadButton.onclick = () => {
|
||||||
downloadFile(
|
projectSaveHandler.loadFromFile();
|
||||||
slugify(projectName.value) || "project",
|
};
|
||||||
await KarlkoderCodec.en(
|
|
||||||
projectName.value,
|
|
||||||
editor.getValue(),
|
|
||||||
await assetEditor.getAssets(),
|
|
||||||
),
|
|
||||||
".karlkode",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
saveButton.onclick = () => saveKarlKoder();
|
saveButton.onclick = () => {
|
||||||
|
projectSaveHandler.saveFile();
|
||||||
|
};
|
||||||
|
|
||||||
addEventListener("keydown", (ev) => {
|
addEventListener("keydown", (ev) => {
|
||||||
if (ev.ctrlKey && ev.key === "s") {
|
if (ev.ctrlKey && ev.key === "s") {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
saveKarlKoder();
|
projectSaveHandler.saveFile();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
19
src/utils.js
19
src/utils.js
@ -1,9 +1,4 @@
|
|||||||
export function downloadFile(name, content, extension, mime) {
|
export function downloadFile(filename, content, extension, mime) {
|
||||||
const filename = prompt("Filename?", name);
|
|
||||||
if (!filename) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const blob = new Blob([content], { type: mime });
|
const blob = new Blob([content], { type: mime });
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
@ -29,6 +24,14 @@ export function slugify(text) {
|
|||||||
|
|
||||||
export function minifyJs(code) {
|
export function minifyJs(code) {
|
||||||
return code
|
return code
|
||||||
.replace(/[\s\n]+/g, " ")
|
.split("\n")
|
||||||
.replace(/;\s+/g, ";");
|
.map((line) =>
|
||||||
|
line
|
||||||
|
.replace(/\/\/.+$/, "")
|
||||||
|
.replace(/\) \{/, "){")
|
||||||
|
.replace(/ = /g, "=")
|
||||||
|
.trim()
|
||||||
|
)
|
||||||
|
.filter((line) => line.length > 0)
|
||||||
|
.join("\n");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user