extract and fix html exporter
This commit is contained in:
parent
cc71c91bd7
commit
ff83f1e5f2
@ -44,11 +44,11 @@ export class Gamelib {
|
|||||||
}
|
}
|
||||||
}, 16);
|
}, 16);
|
||||||
|
|
||||||
if (this.codeStopper.isStopped()) {
|
if (this.codeStopper?.isStopped()) {
|
||||||
clearInterval(loopInterval);
|
clearInterval(loopInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codeStopper.addListener(() => {
|
this.codeStopper?.addListener(() => {
|
||||||
clearInterval(loopInterval);
|
clearInterval(loopInterval);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
71
src/html_exporter.js
Normal file
71
src/html_exporter.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { minifyJs } from "./utils.js";
|
||||||
|
|
||||||
|
export class HtmlExporter {
|
||||||
|
constructor(spriteProvider) {
|
||||||
|
this.spriteProvider = spriteProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
async export(projectName, code) {
|
||||||
|
const js = code
|
||||||
|
.split("\n")
|
||||||
|
.map((line) => " ".repeat(12) + line).join("\n");
|
||||||
|
|
||||||
|
let lib = await (await fetch("./src/gamelib.js")).text();
|
||||||
|
lib = minifyJs(lib);
|
||||||
|
|
||||||
|
const sprites = this.spriteProvider.getAll();
|
||||||
|
|
||||||
|
const html = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="generator" content="karlkoder playground">
|
||||||
|
<title>${projectName}</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"gamelib": "data:text/javascript,${encodeURIComponent(lib)}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
import { Gamelib } from "gamelib";
|
||||||
|
|
||||||
|
const sprites = ${JSON.stringify(sprites)}
|
||||||
|
|
||||||
|
class SpriteProvider {
|
||||||
|
url(name) {
|
||||||
|
return sprites[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const gamelib = new Gamelib(console, null, new SpriteProvider(), document.querySelector('canvas'));
|
||||||
|
|
||||||
|
window.karlkoder = {
|
||||||
|
lib() {
|
||||||
|
return gamelib;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<script type="module">
|
||||||
|
${js}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas width="480" height="360"></canvas>
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
}
|
73
src/index.js
73
src/index.js
@ -12,6 +12,8 @@ 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 } from "./utils.js";
|
||||||
|
import { HtmlExporter } from "./html_exporter.js";
|
||||||
|
|
||||||
const playgroundConsole = new PlaygroundConsole(
|
const playgroundConsole = new PlaygroundConsole(
|
||||||
document.querySelector("#console-code"),
|
document.querySelector("#console-code"),
|
||||||
@ -26,6 +28,8 @@ const spriteEditor = new SpriteEditor(document.querySelector("#sprite-editor-con
|
|||||||
|
|
||||||
new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, codeRunner);
|
new ConsoleInput(document.querySelector("#console-input"), playgroundConsole, codeRunner);
|
||||||
|
|
||||||
|
const htmlExporter = new HtmlExporter(spriteProvider);
|
||||||
|
|
||||||
const gamelib = new Gamelib(
|
const gamelib = new Gamelib(
|
||||||
playgroundConsole,
|
playgroundConsole,
|
||||||
codeStopper,
|
codeStopper,
|
||||||
@ -122,32 +126,6 @@ runButton.onclick = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function downloadFile(content, extension, mime) {
|
|
||||||
const filename = prompt("Filename?");
|
|
||||||
if (filename === null) return;
|
|
||||||
|
|
||||||
const blob = new Blob([content], { type: mime });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
const element = document.createElement("a");
|
|
||||||
|
|
||||||
element.href = url;
|
|
||||||
element.download = filename.endsWith(extension) ? filename : filename + extension;
|
|
||||||
element.style.display = "none";
|
|
||||||
|
|
||||||
document.body.appendChild(element);
|
|
||||||
|
|
||||||
element.click();
|
|
||||||
|
|
||||||
document.body.removeChild(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
function minifyJs(code) {
|
|
||||||
return code
|
|
||||||
.replace(/[\s\n]+/g, " ")
|
|
||||||
.replace(/;\s+/g, ";");
|
|
||||||
}
|
|
||||||
|
|
||||||
saveButton.onclick = () => {
|
saveButton.onclick = () => {
|
||||||
if (saveButton.classList.contains("active")) {
|
if (saveButton.classList.contains("active")) {
|
||||||
saveButton.classList.remove("active");
|
saveButton.classList.remove("active");
|
||||||
@ -164,48 +142,9 @@ saveJsButton.onclick = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
saveHtmlButton.onclick = async () => {
|
saveHtmlButton.onclick = async () => {
|
||||||
const js = editor.getValue()
|
const html = await htmlExporter.export(projectName.value, editor.getValue());
|
||||||
.split("\n")
|
|
||||||
.map((line) => " ".repeat(12) + line).join("\n");
|
|
||||||
let lib = await (await fetch("./js/lib.js")).text();
|
|
||||||
lib = minifyJs(lib);
|
|
||||||
|
|
||||||
const html = `
|
downloadFile(html, ".html", "text/html");
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="generator" content="karlkoder playground">
|
|
||||||
<title>Game</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
An iterable object such as an Array, having ArrayBuffers, TypedArrays, DataViews, Blobs, strings, or a mix of any of such elements, that will be put inside the Blob. Strings should be well-formed Unicode, and lone surrogates are sanitized using the same algorithm as String.prototype.toWellFormed().
|
|
||||||
</style>
|
|
||||||
<script type="importmap">
|
|
||||||
{
|
|
||||||
"imports": {
|
|
||||||
"lib": "data:text/javascript,${encodeURIComponent(lib)}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="module">
|
|
||||||
${js}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<canvas width="480" height="360"></canvas>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
|
|
||||||
downloadTextFile(html, ".html", "text/html");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function saveKarlKoder() {
|
function saveKarlKoder() {
|
||||||
|
@ -14,4 +14,14 @@ export class SpriteProvider {
|
|||||||
}
|
}
|
||||||
return `data:${sprite.mime};base64,${sprite.bytes.toBase64()}`;
|
return `data:${sprite.mime};base64,${sprite.bytes.toBase64()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAll() {
|
||||||
|
const result = {};
|
||||||
|
|
||||||
|
for (const sprite of this.sprites) {
|
||||||
|
result[sprite.name] = this.url(sprite.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
25
src/utils.js
Normal file
25
src/utils.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export function downloadFile(content, extension, mime) {
|
||||||
|
const filename = prompt("Filename?");
|
||||||
|
if (filename === null) return;
|
||||||
|
|
||||||
|
const blob = new Blob([content], { type: mime });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
const element = document.createElement("a");
|
||||||
|
|
||||||
|
element.href = url;
|
||||||
|
element.download = filename.endsWith(extension) ? filename : filename + extension;
|
||||||
|
element.style.display = "none";
|
||||||
|
|
||||||
|
document.body.appendChild(element);
|
||||||
|
|
||||||
|
element.click();
|
||||||
|
|
||||||
|
document.body.removeChild(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function minifyJs(code) {
|
||||||
|
return code
|
||||||
|
.replace(/[\s\n]+/g, " ")
|
||||||
|
.replace(/;\s+/g, ";");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user