Setup editor, remove tauri for now

This commit is contained in:
Chad Freeman 2024-08-15 17:29:13 -04:00
parent a27b94d916
commit 7afb5d8097
32 changed files with 319 additions and 3810 deletions

View file

@ -2,13 +2,16 @@
# planned for v1
- [ ] sprite manager
- [ ] level manager
- [ ] monaco editor
- [ ] **export project for sprig**
- [ ] ability to play project
- [ ] monaco code editor
- [ ] export project for sprig
- [ ] docs site
- [ ] typescript support (esbuild prob)
# planned for v2
- [ ] typescript support (esbuild prob)
- [ ] build project as a standalone `.html` file (maybe vite?)
- [ ] sprite manager
- [ ] level manager
- [ ] build project as a standalone `.html` file
- [ ] run on device
- [ ] downloadable version

BIN
bun.lockb

Binary file not shown.

View file

@ -1,5 +1,5 @@
{
"name": "sprig-rs",
"name": "sprigsy",
"version": "0.0.1",
"private": true,
"scripts": {
@ -17,6 +17,7 @@
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tailwindcss/typography": "^0.5.14",
"autoprefixer": "^10.4.20",
"babel-walk": "^3.0.0",
"prettier": "^3.1.1",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.6.5",
@ -24,12 +25,13 @@
"svelte-check": "^3.6.0",
"tailwindcss": "^3.4.9",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
"type": "module",
"dependencies": {
"vite": "^5.0.3",
"@babel/parser": "^7.25.3",
"@sveltejs/adapter-static": "^3.0.4",
"constrained-editor-plugin": "^1.3.0",
"monaco-editor": "^0.50.0",
"sprig": "^1.1.3",
"sveltekit-adapter-deno": "^0.12.1"
}
},
"type": "module"
}

View file

@ -1,3 +0,0 @@
# Generated by Cargo
# will have compiled files and executables
/target/

3689
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,26 +0,0 @@
[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.60"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.5.3", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.7.0", features = [] }
[features]
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.
# DO NOT REMOVE!!
custom-protocol = [ "tauri/custom-protocol" ]

View file

@ -1,3 +0,0 @@
fn main() {
tauri_build::build()
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

View file

@ -1,8 +0,0 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
tauri::Builder::default()
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View file

@ -1,65 +0,0 @@
{
"build": {
"beforeBuildCommand": "bun run build",
"beforeDevCommand": "bun run dev",
"devPath": "http://localhost:5173",
"distDir": "../buid"
},
"package": {
"productName": "sprigsy",
"version": "0.1.0"
},
"tauri": {
"allowlist": {
"all": false
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "com.tauri.dev",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "Sprigsy Editor",
"width": 800
}
]
}
}

View file

@ -1,3 +1,7 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
body, html {
}

191
src/lib/Editor.svelte Normal file
View file

@ -0,0 +1,191 @@
<script lang="ts">
import { onMount } from 'svelte';
import * as monaco from 'monaco-editor';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';
import {} from 'sprig/web';
import { constrainedEditor } from 'constrained-editor-plugin';
import { parse } from '@babel/parser';
let editorContainer: HTMLDivElement;
let editor: import('monaco-editor').editor.IStandaloneCodeEditor;
// const monaco = await import ('monaco-editor')
// Initial code inside the function
function debounce<A, T = void>(func: (this: T, ...args: A[]) => any, timeout = 300) {
let timer: number;
return function (this: T, ...args: A[]) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, timeout);
};
}
let code = `console.log('Hello sprig!');`;
onMount(async () => {
globalThis.process = {};
globalThis.process.env = {};
const { recursive } = await import('babel-walk');
await addGlobalTypes();
setupEditor();
self.MonacoEnvironment = {
getWorker: function (_: any, label: string) {
return new tsWorker();
}
};
// Function to add global types
async function addGlobalTypes() {
const sprigTypeDef = (await import('./editorcontext/sprig.d.ts?raw')).default;
monaco.languages.typescript.typescriptDefaults.addExtraLib(
sprigTypeDef,
'context/sprig.d.ts'
);
const globalTypeDef = (await import('./editorcontext/global.d.ts?raw')).default;
monaco.languages.typescript.typescriptDefaults.addExtraLib(
globalTypeDef,
'context/global.d.ts'
);
// IMPLEMENT ONCE v2 IS DONE!
// const sprigsyTypeDef = (await import('./editorcontext/sprigsy.d.ts?raw')).default;
// monaco.languages.typescript.typescriptDefaults.addExtraLib(
// sprigsyTypeDef,
// 'context/sprigsy.d.ts'
// );
}
const disallowedIdentifiers = ['window', 'globalThis'];
type ASTState = {
disallowedWarnings: { identifier: string; loc: [number, number, number, number] }[];
};
const ASTWalker = recursive<ASTState>({
Identifier(node, state, c) {
console;
if (disallowedIdentifiers.includes(node.name)) {
state.disallowedWarnings.push({
identifier: node.name,
loc: [
node.loc?.start?.line!,
node.loc?.start?.column!,
node.loc?.end?.line!,
node.loc?.end?.column!
]
});
}
}
});
const checkBabel = debounce(() => {
console.log('checking for uhh');
const ast = parse(editor.getValue(), {
plugins: ['typescript']
});
const state: ASTState = { disallowedWarnings: [] };
ASTWalker(ast, state);
console.log(state);
state.disallowedWarnings.forEach((v) => {
monaco.editor.setModelMarkers(editor.getModel()!, editor.getId(), [
{
message: `'${v.identifier}' is not allowed.`,
severity: monaco.MarkerSeverity.Error,
startLineNumber: v.loc[0],
startColumn: v.loc[1]+1,
endLineNumber: v.loc[2],
endColumn: v.loc[3]+1
}
]);
});
});
// Function to set up the editor
function setupEditor() {
editor = monaco.editor.create(editorContainer, {
value: `function game(api: sprig.FullSprigAPI): void {
${code}
}`,
language: 'typescript',
automaticLayout: true,
scrollBeyondLastLine: false,
theme: 'vs-dark'
});
const model = editor.getModel()!;
// Mark function declaration and closing brace as read-only
// editor.createDecorationsCollection(
// [
// {
// range: new monaco.Range(1, 1, 1, 28),
// options: {
// className: 'read-only',
// isWholeLine: true
// }
// },
// {
// range: new monaco.Range(
// model.getLineCount(),
// 1,
// model.getLineCount(),
// model.getLineMaxColumn(model.getLineCount())
// ),
// options: {
// className: 'read-only',
// isWholeLine: true
// }
// }
// ]
// );
// Disable editing in read-only regions
// editor.onDidChangeModelContent((event) => {
// event.changes.forEach((change) => {
// const { range } = change;
// if (
// (range.startLineNumber === 1 && range.endLineNumber === 1) ||
// (range.startLineNumber === model.getLineCount() &&
// range.endLineNumber === model.getLineCount())
// ) {
// editor.executeEdits('revert-read-only', [
// {
// range: new monaco.Range(
// range.startLineNumber,
// range.startColumn,
// range.endLineNumber,
// range.endColumn
// ),
// text: '',
// forceMoveMarkers: true
// }
// ]);
// }
// });
// });
const constrainedInstance = constrainedEditor(monaco);
constrainedInstance.initializeIn(editor);
constrainedInstance.addRestrictionsTo(model, [
{
range: [2, 1, 2, code.length + 2], // Range of Function definition
allowMultiline: true,
label: 'funcDefinition'
}
]);
editor.onDidChangeModelContent((event) => {
console.log(event.changes);
console.log(model.getValueInEditableRanges());
checkBabel();
});
}
return () => {
if (editor) {
editor.dispose();
}
};
});
</script>
<div bind:this={editorContainer} class="editor-container"></div>
<style>
.editor-container {
height: 100vh;
width: 100%;
}
</style>

10
src/lib/editorcontext/global.d.ts vendored Normal file
View file

@ -0,0 +1,10 @@
import "./sprig"
declare global {
var setTimeout: sprig.FullSprigAPI['setTimeout'];
var setInterval: sprig.FullSprigAPI['setInterval'];
var clearTimeout: sprig.FullSprigAPI['clearTimeout'];
var clearInterval: sprig.FullSprigAPI['clearInterval'];
var tones: typeof sprig['tones']
}

75
src/lib/editorcontext/sprig.d.ts vendored Normal file
View file

@ -0,0 +1,75 @@
declare namespace sprig {
export declare const VALID_INPUTS: readonly ["w", "s", "a", "d", "i", "j", "k", "l"];
export type InputKey = typeof VALID_INPUTS[number];
export interface AddTextOptions {
x?: number;
y?: number;
color?: string;
}
export declare class SpriteType {
type: string;
x: number;
y: number;
readonly dx: number;
readonly dy: number;
remove(): void;
}
export type Rgba = [number, number, number, number];
export interface TextElement {
x: number;
y: number;
color: Rgba;
content: string;
}
export interface GameState {
legend: [string, string][];
texts: TextElement[];
dimensions: {
width: number;
height: number;
};
sprites: SpriteType[];
solids: string[];
pushable: Record<string, string[]>;
background: string | null;
}
export interface PlayTuneRes {
end(): void;
isPlaying(): boolean;
}
// export declare const tones: Record<string, number>;
// export declare const instruments: readonly ["sine", "triangle", "square", "sawtooth"];
export type InstrumentType = typeof instruments[number];
// export declare const instrumentKey: Record<string, InstrumentType>;
// export declare const reverseInstrumentKey: Record<"sine" | "triangle" | "square" | "sawtooth", string>;
export type Tune = [number, ...(InstrumentType | number | string)[]][];
export interface FullSprigAPI {
map(template: TemplateStringsArray, ...params: string[]): string;
bitmap(template: TemplateStringsArray, ...params: string[]): string;
color(template: TemplateStringsArray, ...params: string[]): string;
tune(template: TemplateStringsArray, ...params: string[]): string;
setMap(string: string): void;
addText(str: string, opts?: AddTextOptions): void;
clearText(): void;
addSprite(x: number, y: number, type: string): void;
getGrid(): SpriteType[][];
getTile(x: number, y: number): SpriteType[];
tilesWith(...matchingTypes: string[]): SpriteType[][];
clearTile(x: number, y: number): void;
setSolids(types: string[]): void;
setPushables(map: Record<string, string[]>): void;
setBackground(type: string): void;
getFirst(type: string): SpriteType | undefined;
getAll(type: string): SpriteType[];
width(): number;
height(): number;
setLegend(...bitmaps: [string, string][]): void;
onInput(key: InputKey, fn: () => void): void;
afterInput(fn: () => void): void;
playTune(text: string, n?: number): PlayTuneRes;
setTimeout(fn: TimerHandler, ms: number): number;
setInterval(fn: TimerHandler, ms: number): number;
clearTimeout(id: number): void;
clearInterval(id: number): void;
}
}

11
src/lib/editorcontext/sprigsy.d.ts vendored Normal file
View file

@ -0,0 +1,11 @@
/**
* API for sprigsy
* this is provided because your project has sprigsy v2 enabeled
*/
declare namespace sprigsy {
/**
* Retrieve a sprite key for the sprite name
* @param name Sprite name
*/
function spriteKeyFor(name: string): string
}

View file

@ -1 +1,2 @@
export const prerender = true;
export const ssr = false

View file

@ -1,2 +1,8 @@
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<script>
import Editor from "$lib/Editor.svelte";
</script>
<div class="">
<Editor />
</div>