add function for extracting files from editor
This commit is contained in:
parent
05cdc423fc
commit
d04f61752d
|
@ -29,7 +29,8 @@
|
|||
"shiki": "^1.7.0",
|
||||
"starlight-links-validator": "^0.7.1",
|
||||
"tm-themes": "^1.4.3",
|
||||
"typescript": "^5.4.5"
|
||||
"typescript": "^5.4.5",
|
||||
"use-immer": "^0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sass": "^1.77.6"
|
||||
|
|
|
@ -65,6 +65,9 @@ dependencies:
|
|||
typescript:
|
||||
specifier: ^5.4.5
|
||||
version: 5.4.5
|
||||
use-immer:
|
||||
specifier: ^0.10.0
|
||||
version: 0.10.0(immer@10.1.1)(react@18.3.1)
|
||||
|
||||
devDependencies:
|
||||
sass:
|
||||
|
@ -3278,6 +3281,10 @@ packages:
|
|||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||
dev: false
|
||||
|
||||
/immer@10.1.1:
|
||||
resolution: {integrity: sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==}
|
||||
dev: false
|
||||
|
||||
/immutable@4.3.6:
|
||||
resolution: {integrity: sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==}
|
||||
|
||||
|
@ -5490,6 +5497,16 @@ packages:
|
|||
picocolors: 1.0.1
|
||||
dev: false
|
||||
|
||||
/use-immer@0.10.0(immer@10.1.1)(react@18.3.1):
|
||||
resolution: {integrity: sha512-/eVwNR4TG9Tm/dd+aHYLLaI0FLfYKlkTqKMkn78Ah/EYVzWd/zJIgpkdoFEKbhQJOGo8XN7/mWrTx0exp1c+Ug==}
|
||||
peerDependencies:
|
||||
immer: '>=8.0.0'
|
||||
react: ^16.8.0 || ^17.0.1 || ^18.0.0
|
||||
dependencies:
|
||||
immer: 10.1.1
|
||||
react: 18.3.1
|
||||
dev: false
|
||||
|
||||
/util-deprecate@1.0.2:
|
||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
dev: false
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { useMonaco, type Monaco } from "@monaco-editor/react";
|
||||
import FileView from "./playground/FileView";
|
||||
import Editor from "./playground/Editor";
|
||||
import { useImmer, type ImmerHook, type Updater } from "use-immer";
|
||||
|
||||
import "@styles/playground.scss";
|
||||
|
||||
import mainFileContent from "@assets/playground/main.shu?raw";
|
||||
import packTomlContent from "@assets/playground/pack.toml?raw";
|
||||
|
||||
import FileView from "./playground/FileView";
|
||||
import Editor from "./playground/Editor";
|
||||
import Header from "./playground/Header";
|
||||
|
||||
export type File = {
|
||||
|
@ -21,7 +21,7 @@ export type Directory = {
|
|||
export type SetState<T> = React.Dispatch<React.SetStateAction<T>>;
|
||||
|
||||
export default function Playground() {
|
||||
const rootDir: Directory = {
|
||||
const [rootDir, updateRootDir] = useImmer({
|
||||
dirs: {
|
||||
src: {
|
||||
files: {
|
||||
|
@ -46,15 +46,29 @@ export default function Playground() {
|
|||
language: "toml",
|
||||
},
|
||||
},
|
||||
};
|
||||
} as Directory);
|
||||
|
||||
const [fileName, setFileName] = useState("src/main.shu");
|
||||
const file = getFile(rootDir, fileName)!;
|
||||
|
||||
const onBuild: () => void = () => {
|
||||
if (monaco) {
|
||||
console.log(getFiles(monaco));
|
||||
} else {
|
||||
console.error("monaco has not loaded");
|
||||
}
|
||||
};
|
||||
const onZip: () => void = () => {
|
||||
if (monaco) {
|
||||
loadFile(monaco, updateRootDir, {content: "zip"}, "dist/pack.zip");
|
||||
} else {
|
||||
console.error("onZip not set");}
|
||||
};
|
||||
|
||||
const monaco = useMonaco();
|
||||
useEffect(() => {
|
||||
if (monaco) {
|
||||
loadFiles(monaco, rootDir);
|
||||
loadFiles(monaco, updateRootDir, rootDir);
|
||||
}
|
||||
}, [monaco]);
|
||||
|
||||
|
@ -68,7 +82,7 @@ export default function Playground() {
|
|||
marginTop: "0.5cm",
|
||||
}}
|
||||
>
|
||||
<Header />
|
||||
<Header onBuild={onBuild} onZip={onZip} />
|
||||
<FileView
|
||||
className="file-view"
|
||||
root={rootDir}
|
||||
|
@ -81,6 +95,38 @@ export default function Playground() {
|
|||
);
|
||||
}
|
||||
|
||||
function getFiles(monaco: Monaco): Directory {
|
||||
const files: Directory = {};
|
||||
|
||||
for (const model of monaco.editor.getModels()) {
|
||||
const parts = model.uri.path.slice(1).split("/");
|
||||
const name = parts.pop()!;
|
||||
|
||||
let dir = files;
|
||||
for (const part of parts) {
|
||||
if (!dir.dirs) {
|
||||
dir.dirs = {};
|
||||
}
|
||||
if (!dir.dirs[part]) {
|
||||
dir.dirs[part] = {};
|
||||
}
|
||||
|
||||
dir = dir.dirs[part].files ?? {};
|
||||
}
|
||||
|
||||
if (!dir.files) {
|
||||
dir.files = {};
|
||||
}
|
||||
|
||||
dir.files[name] = {
|
||||
content: model.getValue(),
|
||||
language: model.getLanguageId(),
|
||||
};
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
function getFile(root: Directory, path: string): File | null {
|
||||
if (path.includes("/")) {
|
||||
let dir = root;
|
||||
|
@ -101,19 +147,46 @@ function getFile(root: Directory, path: string): File | null {
|
|||
return root.files?.[path] ?? null;
|
||||
}
|
||||
|
||||
function loadFiles(monaco: Monaco, dir: Directory, prefix = "") {
|
||||
function loadFiles(monaco: Monaco, updater: Updater<Directory>, dir: Directory, prefix = "") {
|
||||
for (const [name, d] of Object.entries(dir.dirs ?? {})) {
|
||||
loadFiles(monaco, d, prefix + name + "/");
|
||||
loadFiles(monaco, updater, d, prefix + name + "/");
|
||||
updater(dir => {
|
||||
let current = dir;
|
||||
for(const part of [...prefix.split("/").filter(s => s !== ""), name]) {
|
||||
if (!current.dirs) {
|
||||
current.dirs = {};
|
||||
}
|
||||
current = current.dirs[part];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const [name, file] of Object.entries(dir.files ?? {})) {
|
||||
loadFile(monaco, file, prefix + name);
|
||||
loadFile(monaco, updater, file, prefix + name);
|
||||
}
|
||||
}
|
||||
|
||||
function loadFile(monaco: Monaco, file: File, name: string) {
|
||||
function loadFile(monaco: Monaco, updater: Updater<Directory>, file: File, name: string) {
|
||||
const uri = monaco.Uri.parse(name);
|
||||
if (!monaco.editor.getModel(uri)) {
|
||||
monaco.editor.createModel(file.content, file.language, uri);
|
||||
}
|
||||
updater(dir => {
|
||||
let current = dir;
|
||||
const parts = name.split("/").filter(s => s !== "");
|
||||
const last = parts.pop()!;
|
||||
for(const part of parts) {
|
||||
console.log(part);
|
||||
if (!current.dirs) {
|
||||
current.dirs = {};
|
||||
}
|
||||
current = current.dirs[part];
|
||||
}
|
||||
if (!current.files) {
|
||||
current.files = {};
|
||||
}
|
||||
current.files[last] = file;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
import SplitButton from "./SplitButton";
|
||||
|
||||
export default function Header() {
|
||||
const clickBuild = () => {
|
||||
console.log("build");
|
||||
}
|
||||
const clickZip = () => {
|
||||
console.log("zip");
|
||||
}
|
||||
export default function Header({onBuild, onZip}: {onBuild: () => void; onZip: () => void;}){
|
||||
|
||||
return (
|
||||
<header style={{
|
||||
|
@ -15,7 +9,7 @@ export default function Header() {
|
|||
marginBottom: "0.5cm",
|
||||
}}>
|
||||
<h1 id="_top">Playground</h1>
|
||||
<SplitButton onClick={clickBuild} options={[["Download zip", clickZip]]}>Build</SplitButton>
|
||||
<SplitButton onClick={onBuild} options={[["Download zip", onZip]]}>Build</SplitButton>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue