-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from WhyPenguins/splashkit-online-documentation
Create Documentation for SplashKit Online
- Loading branch information
Showing
6 changed files
with
1,254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
...cumentation/splashkit-online/code-documentation/classes/ExecutionEnvironment.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
--- | ||
title: ExecutionEnvironment - Code Documentation | ||
description: An explanation of what ExecutionEnvironment is, its methods, members, and events. | ||
--- | ||
|
||
[_executionEnvironment.js_](https://github.com/thoth-tech/SplashkitOnline/blob/main/Browser_IDE/executionEnvironment.js) | ||
|
||
ExecutionEnvironment is a class designed to abstract out running the user's code, and also handle | ||
the environment itself (such as resetting variables, preloading files, etc). It contains functions | ||
to 'compile' user code, run the main program, reset itself, and create directories/files inside the | ||
environment. | ||
|
||
The actual implementation can be found inside `executionEnvironment.js`. Upon creation, it creates | ||
an iFrame (which can be thought of as a page inside the page) - and this is where all the user's | ||
code will be run. | ||
|
||
## Why create an iFrame? | ||
|
||
The iFrame it creates is sandboxed so that it cannot access anything inside the main page. This is | ||
important, since while we can likely trust code the user writes themselves, we cannot trust code | ||
they may receive from other people. If we ran the code the user writes directly inside the main | ||
page, it could access and manipulate the IDE itself, along with accessing cookies and other things | ||
it shouldn't have access to. By running it inside the iFrame, we can be sure it can't access | ||
anything it shouldn't. | ||
|
||
It also makes it clear which files are part of the project (since those exist outside the iFrame), | ||
and which parts are only transient, such as logs (that only exist inside the iFrame and are | ||
destroyed on reloads). It means user code can not permanently overwrite resources. | ||
|
||
Additionally, it gives us a way to completely reset the environment the code is running in, as we | ||
can destroy and recreate the iFrame without having to reload the main page itself. | ||
|
||
To communicate with the iFrame, we can only send and receive messages, which also limits the number | ||
of potential escape routes from the iFrame. | ||
|
||
## Members | ||
|
||
- `hasRunOnce` - has the program been run yet? Is reset with `resetEnvironment()` | ||
- `executionStatus` - current status of the program, can be: | ||
- `ExecutionStatus.Unstarted` | ||
- `ExecutionStatus.Running` | ||
- `ExecutionStatus.Paused` | ||
|
||
## Methods | ||
|
||
- `constructor(container)` - takes a container element to load the iFrame inside. | ||
|
||
### Initializing user's code | ||
|
||
- `runCodeBlock(block, source)` - takes a code block (which has the block name `block`, and the | ||
source code `source`, syntax checks it, and if it passes, sends the code to the iFrame via a | ||
message. | ||
- `runCodeBlocks(blocks)` - takes an array of dictionaries with the keys {name, code}, and calls | ||
`runCodeBlock` for each one. | ||
|
||
### Running user's code | ||
|
||
- `runProgram()` - sends a message to the iFrame to run the user's `main` (if it exists). | ||
- `pauseProgram()` - sends a message to pause the user's program - returns a `promise`, that | ||
resolves once the program pauses, or fails after 2 seconds. | ||
- `continueProgram()` - sends a message to continue the user's program (if it has been paused) | ||
- `stopProgram()` - sends a message to stop the user's program completely - returns a `promise`, | ||
that resolves once the program stops, or fails after 2 seconds. | ||
|
||
### Handling the environment | ||
|
||
- `resetEnvironment()` - completely resets the environment, by destroying and recreating the iFrame. | ||
All files inside the environment will also be lost. | ||
- `cleanEnvironment()` - Does a 'best-efforts' attempt to tidy the environment, such as removing | ||
user created global variables. Much faster than `resetEnvironment()`, and does not reset the file | ||
system. | ||
|
||
### Filesystem | ||
|
||
- `mkdir(path)` - sends a message to create a directory at `path` | ||
- `writeFile(path, data)` - sends a message to write `data` to a file `path`, creating it if it does | ||
not exist | ||
|
||
## Events | ||
|
||
The events can be listened to by attaching with `addEventListener(event, callback)` | ||
|
||
- `initialized` - the ExecutionEnvironment is setup and ready to execute code. | ||
- `error` - an error has occurred in user code. Members: | ||
- `message` - the error message | ||
- `line` - the line number of the error | ||
- `block` - the name of the code block the error occurred in. | ||
- `programStarted` - the program has started running | ||
- `programStopped` - the program has stopped running | ||
- `programPaused` - the program has paused | ||
- `programContinued` - the program has resumed running | ||
- `onMovePath` - A file or directory has been moved. Members: | ||
- `oldPath` - the original path | ||
- `newPath` - the path it was moved to | ||
- `onMakeDirectory` - A directory has been made. Members: | ||
- `path` - the path to the new directory | ||
- `onDeletePath` - A file or directory has been deleted. Members: - `path` - the path to the | ||
file/directory | ||
- `onOpenFile` - A file has been opened, possibly for reading or writing. Members: | ||
- `path` - the path to the file |
100 changes: 100 additions & 0 deletions
100
...t/documentation/splashkit-online/code-documentation/classes/IDBStoredProject.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
--- | ||
title: IDBStoredProject - Code Documentation | ||
description: An explanation of what IDBStoredProject is, its methods, members, and events. | ||
--- | ||
|
||
[_IDBStoredProject.js_](https://github.com/thoth-tech/SplashkitOnline/blob/main/Browser_IDE/IDBStoredProject.js) | ||
|
||
IDBStoredProject is a class that handles saving/loading the user's project within the browser | ||
itself. It uses | ||
[IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) storage, | ||
which allows it to store large amounts of data in a simplified database structure. | ||
|
||
It stores a single project inside a single database, creating a new one for each project. It has | ||
functions to read and write files to a virtual filesystem saved inside the database (for storing | ||
user code, and uploaded resources like sprites and sounds). It also has an area for config, and | ||
keeps track of its lastWriteTime inside there. | ||
|
||
## Database layout | ||
|
||
There are two tables: | ||
|
||
- `project` - contains information about the project, such as the last write time. Simple key-value, | ||
with the key's name being 'category'. | ||
- `files` - stores all the user's files and directories. Each entry contains the following: | ||
- `nodeID` - a numerical identifier for the node (file/directory), automatically increments. | ||
- `name` - name of the file/directory | ||
- `type` - either `"FILE"` or `"DIR"` - file or directory | ||
- `data` - the file's contents - a binary blob of data. Or `null` if it's a directory. | ||
- `parent` - the `nodeID` of the parent of the file/directory (what directory is it inside). -1 | ||
means it is inside the root directory. | ||
|
||
## Members | ||
|
||
- `initializer` - a function that can be called to initialize the database - performs the equivalent | ||
of `skm new` | ||
- `projectName` - the name of the project (and therefore database) it is currently attached to. | ||
`null` if detached. | ||
- `lastKnownWriteTime` - the last time the project was written to within this tab. | ||
|
||
## Methods | ||
|
||
- `constructor(initializer)` - takes an initializer function, used when initializing a project's | ||
database for the first time. | ||
- `attachToProject(storeName)` - attaches it to a project with the name `storeName`. Initializes the | ||
database, and emits an `attached` event. | ||
- `detachFromProject()` - detaches itself from the project, resets its internal state and emits a | ||
`detached` event. | ||
- `deleteProject(storeName)` - deletes the project named `storeName`, and returns a promise which | ||
resolves once the database is truly deleted. | ||
- `checkForWriteConflicts()` - checks the `lastKnownWriteTime` against the actual `lastWriteTime` | ||
inside the database - if they conflict in a way that suggests another tab has written to the | ||
database, throws a `timeConflict` event. | ||
- `access(func)` - a bit of a special function. This function is the only entry point to | ||
reading/writing to the IDBStoredProject. It takes a function, which it will call, passing in a new | ||
object (internally a `__IDBStoredProjectRW`), which has many more methods for reading/writing. | ||
This is done, so that the opening/closing of the database can be wrapped around the user function, | ||
without them having to handle it manually (and potentially leave open connections causing issues | ||
later on). Here's an example of usage: | ||
|
||
```javascript | ||
let storedProject = new StoredProject(...) | ||
... | ||
// we get passed a new object, which we called "project", and can use it to get the lastWriteTime. | ||
// this is all performed asynchronously, so we need to "await" it to get the result | ||
let storedTime = await storedProject.access((project)=>project.getLastWriteTime()); | ||
// in non-lambda syntax | ||
let storedTime = await storedProject.access(function(project){ return project.getLastWriteTime()}); | ||
``` | ||
|
||
**The following functions are ones accessible from inside the callback to `access` only** | ||
|
||
- `getLastWriteTime()` - get the last write time. | ||
- `updateLastWriteTime(time = null)` - set the last write time - defaults to the current time | ||
(stored in unix time) | ||
- `mkdir(path)` - make a directory at path, does nothing if it already exists. Emits | ||
`onMakeDirectory` event. | ||
- `writeFile(path, data)` - overwrites the data inside the file at `path` with `data` - creates the | ||
file if it doesn't exist. Emits `onOpenFile` event. Also emits `onWriteToFile` event. | ||
- `rename(oldPath, newPath)` - moves a file/directory to a new path and/or name. Emits `onMovePath` | ||
event. | ||
- `readFile(path)` - reads a file at `path` and returns the data inside. Returns `null` if the file | ||
doesn't exist. | ||
- `getFileTree()` - returns a complete tree of the file system, in a structure digestible by the | ||
`TreeView`. | ||
|
||
## Events | ||
|
||
The events can be listened to by attaching with `addEventListener(event, callback)` | ||
|
||
- `attached` - Is attached and can be used. | ||
- `detached` - Has been detached. | ||
- `onMovePath` - A file or directory has been moved. Members: | ||
- `oldPath` - the original path | ||
- `newPath` - the path it was moved to | ||
- `onMakeDirectory` - A directory has been made. Members: | ||
- `path` - the path to the new directory | ||
- `onDeletePath` - A file or directory has been deleted. Members: | ||
- `path` - the path to the file/directory | ||
- `onOpenFile` - A file has been opened, possibly for reading or writing. Members: | ||
- `path` - the path to the file |
83 changes: 83 additions & 0 deletions
83
...splashkit/documentation/splashkit-online/code-documentation/classes/TreeView.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
--- | ||
title: TreeView - Code Documentation | ||
description: An explanation of what TreeView is, its methods, members, and events. | ||
--- | ||
|
||
[_treeview.js_](https://github.com/thoth-tech/SplashkitOnline/blob/main/Browser_IDE/treeview.js) | ||
|
||
TreeView is a class used for displaying and updating a tree view, designed specifically around | ||
file/directory manipulation. It allows viewing multiple filesystems at once in an overlapping | ||
fashion (important since we have the files in the user's project that will be saved/loaded, and also | ||
the live files inside the ExecutionEnvironment, which may be different). It allows files/folders to | ||
be dragged around and organized, and folders to have a button on the side for uploading new files. | ||
|
||
The way it is intended to be used, is to make it listen to events from the target filesystems (such | ||
as file moves/deletes), and update itself accordingly. When it is interacted with by the user, it | ||
will emit its own events - these events should be listened to, and the target filesystem updated | ||
accordingly. It should then look like this : | ||
|
||
1. A file is created in the target filesystem and an event is emitted | ||
2. The TreeView reacts to this event and creates a node in its tree with the same name. | ||
3. The user now drags that node to inside another node (directory), and the TreeView emits an event. | ||
Note that it does _not_ change itself here. The node inside the tree has not actually moved yet. | ||
4. A function is called back from this event, that then tells the target filesystem to move the | ||
file. | ||
5. The target filesystem moves the file, and an event is emitted. | ||
6. The TreeView reacts to this event, and moves the node to inside the directory. | ||
|
||
See how the TreeView never updates itself - it relies on an event coming _back_ from the target | ||
filesystem. This means that if the target filesystem fails to do the operation for whatever reason, | ||
the TreeView also remains in the same state, meaning the two remain synchronized effectively. | ||
|
||
See example usage of it inside `fileview.js` | ||
([here](https://github.com/thoth-tech/SplashkitOnline/blob/main/Browser_IDE/fileview.js)), where it | ||
is attached to both the `IDBStoredProject` filesystem, and also the filesystem inside the | ||
`ExecutionEnvironment`. | ||
|
||
### Limitations | ||
|
||
Currently there is no way to delete files/folders, or rename files/folders in the interface itself. | ||
This shouldn't be hard to add, however. | ||
|
||
## Members | ||
|
||
None publicly available. | ||
|
||
## Methods | ||
|
||
- `constructor(container, FSes)` - takes a container to place the TreeView's elements into, and a | ||
list of FSes, which are the filesystems it will support. An example list looks like this | ||
`{"persistent":"node-persistent", "transient":"node-transient"}`, key-value pairs where the key is | ||
the filesystems name, and the value is a css style to apply to nodes inside this filesystem. | ||
- `moveNode(oldPath, newPath, index = -1, FS)` - moves a node to a new path and/or name. Allows one | ||
to set the index the node will appear at, and also which filesystem(s) (a list) the move occurred | ||
in. | ||
- `deleteNode(path, FS)` - deletes a node from a set of filesystem(s) (a list) | ||
- `addDirectory(path, FS)` - make a directory at path, does nothing if it already exists. Allows one | ||
to set which filesystem(s) (a list) the directory add occurred in. | ||
- `addFile(path, data)` - make a file at path, does nothing if it already exists. Allows one to set | ||
which filesystem(s) (a list) the file was added in. | ||
- `reset(path)` - Deletes all nodes. | ||
- `populatefileView(files, FS)` - Populates the tree with a list of files in a particular structure | ||
(the same one `IDBStoredProject.getFileTree()` returns). Allows one to set which filesystem(s) (a | ||
list) the directory add occurred in. | ||
|
||
## Events | ||
|
||
The events can be listened to by attaching with `addEventListener(event, callback)` | ||
|
||
- `nodeMoveRequest` - A file or directory has been moved. Members: | ||
- `treeView` - the TreeView object | ||
- `oldPath` - the original path | ||
- `newPath` - the path it was moved to | ||
- `FS` - the filesystem(s) the change occurred in. | ||
- `accept` - a function that can be called to announce that the change was successful - | ||
**currently unused**. | ||
- `folderUploadRequest` - The 'add file' button was clicked on on a directory. Members: | ||
- `treeView` - the TreeView object | ||
- `path` - path to the directory | ||
- `FS` - the filesystem(s) the directory exists in. | ||
- `nodeDoubleClick` - A file node has been double clicked. Members: | ||
- `treeView` - the TreeView object | ||
- `path` - path to the file | ||
- `FS` - the filesystem(s) the directory exists in. |
Oops, something went wrong.