tmp
jsteuer
2019-12-11 73b20b5cc3f198a027c7ee9480d6051f2c095c99
tmp
4 files modified
122 ■■■■■ changed files
README.md 86 ●●●● patch | view | raw | blame | history
package.json 5 ●●●●● patch | view | raw | blame | history
src/index.ts 29 ●●●●● patch | view | raw | blame | history
tsconfig.json 2 ●●● patch | view | raw | blame | history
README.md
@@ -2,13 +2,19 @@
# MathCoach IDE API
In diesem Paket ([Das Gitblit Repository findet sich hier](https://newton.htwsaar.de/gitblit/summary/mathcoach!mathcoach-ide-api.git)) 
ist die öffentliche Schnittstelle zur MathCoach Entwicklungsumgebung (IDE)
definiert. Mithilfe dieser Schnittstelle können externe Werkzeuge (z.B. Editoren) erstellt werden.
Für den Anwender stehen diese Werkzeuge dann komfortabel - in die IDE integriert - zur Verfügung.
ist die öffentliche Schnittstelle zur MathCoach Entwicklungsumgebung (IDE) definiert. Mithilfe
dieser Schnittstelle können externe Werkzeuge (z.B. Editoren) erstellt werden. Ziel ist, dass
diese Werkzeuge für den Anwender komfortable - in die IDE integriert -zur Verfügung gestellt werden
können. Darüber hinaus werden als Ergänzung einige Hilfsfunktionen zum Bau von Werkzeugen angeboten.
![Demo](media/usage_author.gif)
*Beispielhafte Anwendung: Eine Datei wird angelegt und einem Demo-Editor geöffnet. Dieser generiert eine
Groovy-Aufgabe*
 
## Idee
TODO: Grafik (IDE, Werkzeug, Dateien, JSON, usw)
## Entwicklung externer Werkzeuge 
-   Externe Werkzeuge müssen unter der Domain von MathCoach erreichbar sein. Zur Entwicklungszeit legt
@@ -17,17 +23,17 @@
        <script src="/mathcoach/ui/ide/ide-lib.js"/>
-   Von nun an steht die hier definierte API durch die globale Variable `MC` zur Verfügung.
-   Von nun an steht die IDE API durch die globale Variable `MC` zur Verfügung.
-   **Hinweis**: Erst, wenn das Werkzeug in die IDE integriert und aus dieser heraus 
    gestartet wurde, kann die API verwendet werden! (Hinweis: durch nachbilden der API kann
    eine Nutzung ohne IDE ermöglicht werden, siehe `enableOfflineUsageIfNecessary`)
    gestartet wurde, kann die API verwendet werden! Durch nachbilden der API kann
    eine Nutzung ohne IDE ermöglicht werden, siehe `enableOfflineUsageIfNecessary`.
### Empfohlenes Vorgehen
Damit externe Werkzeuge ein einheitliches Verhalten aufweisen, sollte wie folgt vorgegangen werden.
 
Als erstes muss sichergestellt werden, dass die MathCoach IDE API auch verfügbar ist. Dies ist beispielsweise
nicht der Fall, wenn das Werkzeug ohne die IDE gestartet wurde (und nicht offline-fähig ist) oder diee IDE (aus
nicht der Fall, wenn das Werkzeug ohne die IDE gestartet wurde (und nicht offline-fähig ist) oder die IDE (aus
welchen Gründen auch immer) nicht einsatzbereit ist.
    if(typeof MC !== "undefined"){
@@ -44,7 +50,7 @@
Ist der Inhalt der Kontext-Datei leer, wurde das Werkzeug vermutlich zum ersten mal gestartet das Werkzeug:
-   Sich initialisieren (z.B. mit einem leeren oder beispielhaften internem Datenmodell)
-   Das interne Datenmodell in die Kontext-Datei schreiben 
-   Die zugehörige Aufgabe generieren. Siehe auch `createExerciseFile` weiter unten.
-   Die zugehörige Aufgabe generieren. Siehe auch `contextFileToExerciseFile` weiter unten.
    
Andernfalls kann das zuvor gespeichertes Datenmodell in den Editor geladen werden.
@@ -56,13 +62,13 @@
    let contextFileContent = await MC.ide.fs.readFile(contextFile);
    let contextFileIsEmpty = contextFileContent === "";
 
    let exerciseFile = createExerciseFile(contextFile);
    let exerciseFile = contextFileToExerciseFile(contextFile);
    if(contextFileIsEmpty){ 
        // TODO: init application with new data model (maybe with example contents)
        // write serialized model to context file, e.g. using JSON.stringify(...)
        let dataModelAsString = JSON.stringify({/* TODO */});  
        await MC.ide.fs.writeFile(file, dataModelAsString);
        await MC.ide.fs.writeFile(contextFile, dataModelAsString);
        // generate exercise 
        let generatedExerciseCode = "startup { print('Hallo Welt!') }"; // TODO
        await MC.ide.fs.writeFile(exerciseFile, generatedExerciseCode);  
@@ -77,39 +83,27 @@
Jedes Werkzeug sollte über eine "Speichern"-Funktion verfügen, mit der der Benutzer:
- Das interne Datenmodell in die Kontext-Datei speichert (sodass es später wieder geladen werden kann)
- Die zugehörige Aufgabe generiert
- Die Vorschau zur generierten Aufgabe navigiert
- Die zugehörige Aufgabe wird generiert und die Vorschau zu dieser navigiert
### Aufgaben-Datei generieren
Die generierte Aufgabe soll wie die Kontext-Datei benannt sein, sodass diese vom Benutzer schnell
zugeordnet werden können. Beispielsweise soll ein Werkzeug, welches mit der
Kontext-Datei `/path/to/myExercise.mcq.json` gestartet wird die Aufgabe `/path/to/myExercise.groovy`
erzeugen.
    /**
    * Kontext-Datei (z.B. "/path/to/myExercise.mcq.json") auf
    * Aufgaben-Datei (z.B. "/path/to/myExercise.groovy") abbilden.
    */
    export function createExerciseFile(contextFile: MathCoach.File): MathCoach.File {
        let file: MathCoach.File = {
            part: contextFile.part,
            owner: contextFile.owner,
            path: contextFile.path.split(".")[0] + ".groovy"
        };
        return file;
    }
### Beispiele
Im Verzeichnis `./examples/` finden sich Beispiele für externe Werkzeuge.
### Hilfunktionen für Werkzeug-Entwickler
Dieses Paket beinhaltet zusätzlich Hilfsfunktionen für Werkzeug-Entwickler. Beispielsweise kann
ein Werkzeug ohne IDE-Anbindung genutzt werden, indem die API nachgebildet wird - aktuell auf
Basis des LocalStorage des Browsers. Dies ist besonders während der Entwicklung nützlich.
Dieses Paket beinhaltet zusätzlich Hilfsfunktionen für Werkzeug-Entwickler.
-   **Aufgaben-Datei ableiten**: Die generierte Aufgabe soll wie die Kontext-Datei benannt sein,
    sodass diese vom Benutzer schnell zugeordnet werden können. Beispielsweise soll ein Werkzeug,
    welches mit der Kontext-Datei `/path/to/myExercise.mcq.json` gestartet wird, die
    Aufgabe `/path/to/myExercise.groovy` erzeugen.
        import { contextFileToExerciseFile } from "@mathcoach/ide-api";
        let contextFile = await MC.ide.getContextFile()
        let exerciseFile = contextFileToExerciseFile(contextFile);
-   **Standalone-Werkzeuge**: Werkzeuge können ohne IDE-Anbindung entwickelt und getestet
    werden. Dazu wird die IDE API nachgebildet - aktuell auf Basis des `LocalStorage` des
    Browsers.
    import { enableOfflineUsageIfNecessary } from "@mathcoach/ide-api";
    let offline: boolean = enableOfflineUsageIfNecessary();
@@ -117,6 +111,9 @@
    // now use the IDE API
### Beispiele
Im Verzeichnis `./examples/` finden sich Beispiele für externe Werkzeuge.
### Kleinere Werkzeuge
Für kleiner Werkzeuge bietet es sich an im WWW-Verzeichnis zu entwickeln  (z.B. 
`myTool/tool.html` und `myTool/tool.js`). Die MathCoach-IDE stellt Autovervollständigung beim
@@ -146,11 +143,6 @@
        ...
    }
Bei Verwendung einer Entwicklungsumgebung wie Visual Studio Code kann die Typdefinition der
API auch für JavaScript eingebunden werden. Hierfür ist ggf. ein spezielles Kommentar am Anfang
der Datei notwendig (Pfad falls nötig anpassen):
    /// <reference path="../node_modules/@mathcoach/ide-api/mathcoach-api.d.ts"/>
Wie man der Git-Repo URL ansieht, werden Git-Tags verwendet um eine 
Versionierung [(Semantic Versioning)](https://semver.org/lang/de/)
@@ -158,6 +150,12 @@
aktuellste Version verwendet. (Siehe Gitblit um verfügbare Versionen
einzusehen)
Bei Verwendung einer Entwicklungsumgebung wie Visual Studio Code kann die Typdefinition der
API auch für JavaScript eingebunden werden. Hierfür ist ggf. ein spezielles Kommentar am Anfang
der Datei notwendig (Pfad falls nötig anpassen):
    /// <reference path="../node_modules/@mathcoach/ide-api/mathcoach-api.d.ts"/>
Zertifikat von Newton hinzufügen, damit npm auf das Repository zugreifen kann.
package.json
@@ -12,8 +12,9 @@
  },
  "scripts": {
    "clean": "rimraf dist/ && rimraf docs/",
    "build": "npm run clean  && npm run build-docs",
    "build-docs": "typedoc mathcoach-api.d.ts --out docs/ --mode file --theme minimal --includeDeclarations --excludeExternals --media ./media"
    "build": "npm run clean  && npm run build-docs && npm run build-utils",
    "build-utils": "tsc",
    "build-docs": "typedoc mathcoach-api.d.ts src/ --out docs/ --mode file --theme minimal --includeDeclarations --excludeExternals --media ./media"
  },
  "author": "jsteuer",
  "license": ""
src/index.ts
@@ -64,3 +64,32 @@
    }
}
/**
 * Kontext-Datei auf Aufgaben-Datei abbilden.
 * Beispiel: "/path/to/myExercise.mcq.json" zu "/path/to/myExercise.groovy"
 */
export function contextFileToExerciseFile(contextFile: MathCoach.File): MathCoach.File {
    if (contextFile) {
        if (!contextFile.owner || !(typeof contextFile.owner === "string") || !(contextFile.owner.trim() === "")) {
            throw new Error("Context file has no valid 'owner' property.");
        }
        if (!contextFile.part || !(typeof contextFile.part === "string")) {
            if (contextFile.part !== "vfs" && contextFile.part !== "www") {
                throw new Error("Context file has no valid 'part' property. Allowed values are 'vfs' and 'www'.");
            }
        }
        if (!contextFile.path || !(typeof contextFile.path === "string") || !(contextFile.owner.trim().startsWith("/"))) {
            throw new Error("Context file has no valid 'path' property.");
        }
    } else {
        throw new Error("No context file object given.")
    }
    let file: MathCoach.File = {
        part: contextFile.part,
        owner: contextFile.owner,
        path: contextFile.path.split(".")[0] + ".groovy"
    };
    return file;
}
tsconfig.json
@@ -1,6 +1,6 @@
{
  "compilerOptions": {
    "module": "commonjs",
    "module": "es6",
    "target": "es5",
    "declaration": true,
    "outDir": "./dist"