From b95c6a3de43121c061457039a4c926d5d34f2737 Mon Sep 17 00:00:00 2001
From: jsteuer <jan.steuer.htw@gmail.com>
Date: Mon, 16 Dec 2019 13:28:22 +0100
Subject: [PATCH] better docs, helpers namespace

---
 mathcoach-api.d.ts |   20 
 examples/README.md |    5 
 package-lock.json  |  213 ++++++---------
 tsconfig.json      |    3 
 src/index.ts       |   67 -----
 package.json       |   10 
 src/Helpers.ts     |  129 +++++++++
 CHANGELOG.md       |   13 +
 README.md          |  288 ++++++++++++++++-----
 9 files changed, 465 insertions(+), 283 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac44566..24e6a30 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,19 @@
 
 
 
+
+## [1.2.0] - 2019-12-16
+
+### Added
+-   Beispiele hinzugefügt
+-   Hilfsfunktion: `contextFileToExerciseFile` 
+### Changed
+-   Hilfsfunktionen sind nun im Namensraum `Helpers` untergebracht
+### Fixed
+-   Bessere Dokumentation   
+
+
+
 ## [1.1.0] - 2019-09-30
 
 ### Added
diff --git a/README.md b/README.md
index ecec13f..d7f97fd 100644
--- a/README.md
+++ b/README.md
@@ -1,117 +1,259 @@
- 
+
 # 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 
+Grundlegende Idee ist, dass ein externes Werkzeug nahtlos in die MathCoach IDE integriert werden 
+kann. Bestimmte Dateien werden anhand ihrer Dateiendung mit dem Werkzeug verknüpft, sodass der
+Benutzer das passende Werkzeug durch einen einfache Klick im Dateie-Explorer starten kann. Diese 
+Datei wird im folgenden Kontext-Datei genannt und soll dazu dienen das interene Datenmodell (also
+alle Informationen, die der Benutzer im Editor angibt) zu speichern. Das gespeicherte Datenmodell kann 
+zu einem späteren Zeitpunkt wieder geladen werden. Weiterhin kann das Werkzeug aus dem internen 
+Datenmodell eine MathCoach-Aufgabe (Groovy-Datei) generieren. Weitere Funktionalitäten - beispielsweise 
+das Starten der generierten Aufgabe in der Aufgaben-Vorschau der IDE - sind ebenfalls für den 
+Werkzeugentwickler verfügbar.
+
+Das Realisieren von Werkzeugen auf diese Art und Weise hat zahlreiche Vorteile:
+-   Werkzeuge werden einheitliche und benutzerfreundlich zur Verfügung gestellt
+-   Grundlegende Funktionalitäten (Anlegen von Dateien, Navigieren im Dateisystem) werden bereits 
+    durch die IDE bereitgestellt. So können Werkzeug-Entwickler ihren Fokus auf das Werkzeug legen.
+-   Die IDE kann gefährliche Situationen (z.B. das Überschreiben von Dateien) abfangen
+    und den Benutzer entscheiden lassen, wie fortgefahren werden soll.
+
+
+
+## Entwicklung externer Werkzeuge
+
+Externe Werkzeuge laufen ausschließlich im Webbrowser des Benutzers - es muss also
+auf `HTML`, `JavaScript` und `CSS` gesetzt werden. Außerdem muss das Werkzeug unter 
+der Domain des jeweiligen MathCoach-Servers erreichbar sein. Zur Entwicklungszeit legt man das Werkzeug 
+dazu im www-Verzeichnis ab. Die von der IDE bereitgestellte `ide-lib.js` Bibliothek 
+muss eingebunden werden. 
+
+    <script src="/mathcoach/ui/ide/ide-lib.js"/> 
+
+Dabei darf der MathCoach-Server **nicht** fest in die URL eincodiert werden. Andernfalls
+kann es zu Problemen kommen, wenn das Werkzeug auf unterschiedlichen Server bereitgestellt 
+wird. Bei korrekter Verwendung steht die IDE API nun durch die globale Varialbe `MC` zur 
+Verfügung - [Dokumentation der IDE API](./interfaces/mathcoach.api.html).
+
+> **Hinweis**: Es steht **ausschließlich** die API, welche über die globale Variable `MC`
+> definiert ist, zur Verfügung! Hilfsfunktionen wie `Helpers.enableOfflineUsageIfNecessary()` 
+> sind grundsätzlich nicht verfügbar und müssen vom Werkzeugentwickler eingebunden 
+> werden - siehe "Hilfunktionen für Werkzeug-Entwickler" weiter unten.
+
+> **Hinweis**: Erst, wenn das Werkzeug in die IDE integriert und aus dieser heraus
+> gestartet wurde, kann die IDE API verwendet werden! Soll das Werkzeug auch ohne die 
+> IDE nutzbar sein (z.B. zum Testen), muss dies bei der Implementierung berücksichtigt
+> werden. Konnte die `ide-lib.js` nicht eingebunden werden (weil das Werkzeug ohne IDE 
+> gestartet wurde - darum darf auch kein Server fest eincodiert werden), steht die 
+> globale Variable `MC` nicht zur Verfügung (`typeof MC === "undefined"`). Hier kann das 
+> Werkezug eine Fallunterscheidung treffen und beispielsweise eine eigene Implementierung 
+> über die globale Variable `MC` bereitstellen. Siehe auch `Helpers.enableOfflineUsageIfNecessary()` 
+> weiter unten.
+
+
+
+### 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 oder die IDE (aus
+welchen Gründen auch immer) nicht einsatzbereit ist.
+
+    if(typeof MC === "undefined"){
+        // Hinweis: Hier kann die IDE API nachgebildet werden,
+        // sodass das Werkzeug auch "Offline" funktioniert. 
+        // Also: MC = { isReady: async () => true, ...}
+        throw new Error("IDE Lib nicht eingebunden"); // TODO: show error to user
+    }
+    const isReady = await MC.isReady();
+    if(!isReady){
+        throw new Error("Die MathCoach-API ist nicht einsatzbereit."); // TODO: show error to user
+    }
+    ...
+
+Von nun an kann die IDE API vollständig genutzt werden. Zunächst sollte die Kontext-Datei (die 
+Datei, mit der das Werkzeug gestartet wurde) geladen werden.
+
+Ist der Inhalt der Kontext-Datei leer, wurde die Datei neu angelegt und zum ersten mal geöffnet.
+Nun soll das Werkzeug:
+-   Sich initialisieren. Es ist sinnvoll, dass das Werkzeug mit einem beispielhaften
+    Datenmodell inititalisiert wird.
+-   Das interne Datenmodell in die Kontext-Datei schreiben 
+-   Die zugehörige Aufgabe generieren. Siehe auch `contextFileToExerciseFile` weiter unten.
+
+Andernfalls kann das zuvor gespeichertes Datenmodell aus der Kontext-Datei in den 
+Editor geladen werden. Anschließend sollte die generierten Aufgaben in der Vorschau gestartet werden, sodass der 
+Benutzer besser abschätzen kann, wie sich Änderungen im Werkzeug auf die Aufgabe auswirken.
+
+
+    let contextFile = await MC.ide.getContextFile(); // Datei, mit der der Editor gestartet wurde
+    let contextFileContent = await MC.ide.fs.readFile(contextFile);
+    let contextFileIsEmpty = contextFileContent === "";
+
+    let exerciseFile = contextFileToExerciseFile(contextFile);
+
+    if(contextFileIsEmpty){
+        // TODO: Datenmodell anlegen (Idealerweise mit beispielhaften Inhalt)
+        // TODO: Datenmodell in Kontext-Datei schreiben, z.B. mit JSON.stringify(...)
+        let dataModelAsString = JSON.stringify({/* TODO */});
+        await MC.ide.fs.writeFile(contextFile, dataModelAsString);
+        // TODO: Aufgabe generieren
+        let generatedExerciseCode = "startup { print('Hallo Welt!') }"; 
+        await MC.ide.fs.writeFile(exerciseFile, generatedExerciseCode);
+    }else{
+        // TODO: Datenmodell laden, z.B. mit JSON.parse(contextFileContent)
+        // TODO: (Aufgabe neu generieren)
+        // TODO: init application based on your data model
+    }
+
+    // Aufgabe anzeigen
+    await MC.ide.navigator.navigateToExercise(exerciseFile);
+
+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 wird generiert und die Vorschau zu dieser navigiert
+
+  
+
+### Hilfsunktionen für Werkzeug-Entwickler
+
+[Dokumentation der Hilfsfunktionen](./modules/helpers.html)
+
+Dieses Paket beinhaltet zusätzlich Hilfsfunktionen für Werkzeug-Entwickler. Diese sind aktuell
+in `TypeScript` implementiert und können bei Bedarf auch zukünftig als ES6-JavaScript 
+bereitgestellt werden. Zum Einbinden der Funktionen wird demzufolge ein Build-System 
+vorausgesetzt. Keine der Hilfsfunktionen wird durch die `ide-lib.js` ausgeliefert!
+
+Beispielsweise werden diese wie folgt eingebunden und genutzt:
+
+    import { Helpers } from "@mathcoach/ide-api";
+    Helpers.enableOfflineUsageIfNecessary()
  
 
-## Entwicklung externer Werkzeuge 
+> **Hinweis**: Hilfunktionen ohne Build-System bereitzustellen gestaltet sich schwierig und
+> bringt große Nachteile mit sich:
+> - Als reine JavaScript-Datei - platziert auf einem Server - ist die die 
+>   Offline-Fähigkeit (siehe `Helpers.enableOfflineUsageIfNecessary()`) von Werkzeugen nicht 
+>   gewährleistet. 
+> - Werden Dateien oder Code-Ausschnitte von Hand kopiert, muss der Werkzeug-Entwickler sich
+>   um das Aktualisieren kümmern. 
+> 
+> Ein möglicher Kompromiss wäre die Hilsfunktionen als reine JavaScript-Datei (ES5 oder ES6) 
+> bereitzustellen und eine Kopie mit dem Werkezug auszuliefern. Der aktuelle Ansatz bettet 
+> Hilfsfunktionen durch den Build-Prozess in das Werkzeug ein.
 
--   Externe Werkzeuge müssen unter der Domain von MathCoach erreichbar sein. Zur Entwicklungszeit legt
-    man das Werkzeug dazu im www-Verzeichnis ab.
--   Die von der IDE bereitgestellte Bibliothek muss eingebunden werden 
-
-        <script src="/mathcoach/ui/ide/ide-lib.js"/>
-
--   Von nun an steht die hier definierte 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`)
 
 ### Beispiele
-Im Verzeichnis `./examples/` finden sich Beispiele für externe Werkzeuge. 
+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.
-
-    import { enableOfflineUsageIfNecessary } from "@mathcoach/ide-api";
-    let offline: boolean = enableOfflineUsageIfNecessary();
-
-
-### Kleinere Werkzeuge
-Für kleiner Werkzeuge bietet es sich an im WWW-Verzeichnis zu entwickeln  (z.B. 
+### Entwicklung kleinerer 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
-Editieren der `tool.js`-Datei zur Verfügung. Da es sich um eine JavaScript-Datei handelt, 
-ist keine Typsicherheit gegeben. Das Werkzeug muss lokal in die IDE integriert werden, siehe 
+Editieren der `tool.js`-Datei zur Verfügung. Da es sich um eine JavaScript-Datei handelt,
+ist keine Typsicherheit gegeben. Das Werkzeug muss lokal in die IDE integriert werden, siehe
 weiter unten.
 
 ![Demo](media/usage_tool_developer.gif)
 
-### Größere Werkzeuge
-Für größere Werkzeuge sollte ein Build-System wie [webpack](https://webpack.js.org/) 
-oder [PARCEL](https://parceljs.org/) in Kombination mit 
-[TypeScript](https://www.typescriptlang.org/) verwendet werden. Das Werkzeug muss nach dem
-Build-Prozess in das WWW-Verzeichnis kopiert und ebenfalls lokal in die IDE integriert werden, siehe
-weiter unten.
+### Entwicklung größerer Werkzeuge
+Für größere Werkzeuge sollten etablierte Entwicklungswerkzeuge verwendet werden, beispielsweise:
+- [npm](https://nodejs.org/en/) um externe Bibliotheken (u.A. dieses Paket) einzubinden
+- [webpack](https://webpack.js.org/) oder [Parcel](https://parceljs.org/) als Build-System um den Quellcode des Werkzeuges zu "bündeln"
+- [TypeScript](https://www.typescriptlang.org/) zum typsischeren Programmieren (und/oder Dateien zu ES6 oder ES5 konformen JavaScript umzuformen)
+- [Git](https://git-scm.com/) zur Versionierung des Quellcodes
+- [Visual Studio Code](https://code.visualstudio.com/) als Entwicklungsumgebung
+- Unit Tests
+
+Das "gebündelte" Werkzeug muss nach dem Build-Prozess in das WWW-Verzeichnis kopiert und ebenfalls 
+lokal in die IDE integriert werden, siehe weiter unten.
 
 
-Die MathCoach-API kann auch als npm-Package eingebunden werden, sodass eine typsichere 
-und komfortable Entwicklung (z.B. mit Visual Studio Code) möglich ist. Hierzu muss 
+#### MathCoach-API als npm-Package einbinden
+
+Die MathCoach-API kann auch als npm-Package eingebunden werden, sodass eine typsichere
+und komfortable Entwicklung (z.B. mit Visual Studio Code) möglich ist. Außerdem wird es 
+möglich die angebotenen [Hilfsfunktionen](./modules/helpers.html) zu einzubinden. Hierzu muss
 die `package.json` des Werkzeug-Projektes wie folgt ergänzt werden:
 
     {
         ...
         "devDependencies": {
-            "@mathcoach/ide-api": "git+https://newton.htwsaar.de/gitblit/r/mathcoach/mathcoach-ide-api.git#1.1.0" 
+            "@mathcoach/ide-api": "git+https://newton.htwsaar.de/gitblit/r/mathcoach/mathcoach-ide-api.git#1.2.0"
         },
         ...
     }
+ 
 
-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):
+Wie man der Git-Repo URL ansieht, werden Git-Tags verwendet um eine Versionierung 
+[(Semantic Versioning)](https://semver.org/lang/de/) der API zu erreichen. Lässt man die Versionierung weg, 
+wird die aktuellste Version verwendet. (Siehe Gitblit um verfügbare Versionen einzusehen)
+ 
+
+
+ 
+#### Typdefinition auch ohne Build-System nutzen
+Beim Arbeiten mit Visual Studio Code kann man auch ohne Einsatz weiterer Entwicklungswerkzeuge 
+und Build-Systeme von der Typdefinition der IDE API profitieren. Hierzu muss ein spezielles Kommentar 
+an den Anfang der JavaScript-Datei platziert werden (Pfad 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/)
-der API zu erreichen. Lässt man die Versionierung weg, wird die 
-aktuellste Version verwendet. (Siehe Gitblit um verfügbare Versionen
-einzusehen)
+Dies sorgt dafür, dass Visual Studio Code Autovervollständigung samt Dokumentation der 
+IDE API anbieten kann. Nachteilig ist, dass die `mathcoach-api.d.ts` dazu heruntergeladen
+werden muss.
 
-
-Zertifikat von Newton hinzufügen, damit npm auf das Repository zugreifen kann.
+#### Zertifikat-Problem beheben
+Falls es Probleme mit dem HTW Zertifikat gibt, muss das Zertifikat von Newton ggf. von
+Hand hinzugefügt werden. Nur so kann npm auf das Git-Repository zugreifen und den 
+Inhalt automatisch herunterladen.
 
     cd /usr/local/share/ca-certificates/
     sudo mkdir newton.htwsaar.de
-    
+
     sudo cp path/to/newton.htwsaar.de.crt /usr/local/share/ca-certificates/newton.htwsaar.de/
-    
-    sudo chown 755 /usr/local/share/ca-certificates/newton.htwsaar.de 
+
+    sudo chown 755 /usr/local/share/ca-certificates/newton.htwsaar.de
     sudo chown 644 /usr/local/share/ca-certificates/newton.htwsaar.de/newton.htwsaar.de.crt
     sudo update-ca-certificates
 
 
-    
+
 ## Werkzeuge in die IDE integrieren
 Damit die IDE das Werkzeug integrieren kann, muss eine Werkzeug-Deklaration registriert werden. Zur
-Entwicklungszeit kann der Werkzeug-Entwickler dies lokal vornehmen. Anschließend können verknüpfte 
-Dateien mit dem Werkzeug geöffnet werden und erstellt werden (siehe Kontext-Menüs im IDE-Explorer).  
-Eine Freischaltung des Werkzeugs für alle Autoren erfolgt durch einen Administrator. 
+Entwicklungszeit kann der Werkzeug-Entwickler dies lokal vornehmen. Anschließend können verknüpfte
+Dateien mit dem Werkzeug geöffnet werden und erstellt werden (siehe Kontext-Menüs im IDE-Explorer).
+Eine Freischaltung des Werkzeugs für alle Autoren erfolgt durch einen Administrator.
 
-### Lokal (Nur für den Entwickler des Werkzeugs) 
-In der IDE muss eine Werkzeug-Deklaration angelegt werden, dazu muss die Datei `ide-settings.json` editiert werden:  
+### Lokal (Nur für den Entwickler des Werkzeugs)
+In der IDE muss eine Werkzeug-Deklaration angelegt werden, dazu muss die Datei `ide-settings.json` editiert werden:
 
     {
         ...
-        "editor.external.declarations": [ 
+        "editor.external.declarations": [
             {
-                "displayName": "Dummy",                          
-                "entry": "/mathcoach/www/YOURNAME/tool.html",   
-                "description": "...",                            
-                "developer": "...",                              
-                "extension": "ext"                             
+                "displayName": "Dummy",
+                "entry": "/mathcoach/www/YOURNAME/tool.html",
+                "description": "...",
+                "developer": "...",
+                "extension": "fib.json"
             }
             ...
-        ], 
+        ],
         ...
-    } 
+    }
 
 | Schlüssel | Beschreibung  | Beispiel  |
 |---------------|---|---|
@@ -124,30 +266,32 @@
 
 
 ### Global (Für alle Autoren)
--   Das Werkzeug samt Werkzeug-Deklaration muss als `.zip`-Datei an einen Administrator übergeben werden
+-   Das Werkzeug samt Werkzeug-Deklaration muss an einen Administrator übergeben werden
 -   Der Administrator schaltet das Werkzeug nach einer kurzen Prüfung (Keine Konflikte mit anderen
     Dateierweiterung, usw) frei. Beim nächsten Release von MathCoach ist das Werkzeug dann für alle
     Autoren verfügbar.
- 
 
 
- 
+
+
 ## Infos zu diesem Repository
 
     .
     ├── CHANGELOG.md                // Dokumentation von Änderungen der API
     ├── examples                    // Beispiele
-    │   ├── ... 
+    │   ├── ...
+    │   └── ...
+    ├── media                       // Grafiken
     │   └── ...
     ├── src                         // Hilfsfunktionen für Werkzeugentwickler
     │   ├── index.ts                // Einstiegspunkt
     │   └── ...
-    ├── mathcoach-api.d.ts          // Definition der API
-    ├── package.json                
+    ├── mathcoach-api.d.ts          // Typ-Definition der API
+    ├── package.json
     ├── package-lock.json
     ├── README.md
     └── tsconfig.json
-    
+
 
 ### Dokumentation erzeugen
 
diff --git a/examples/README.md b/examples/README.md
index 1eaaf85..5c6a0a3 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -1,6 +1,3 @@
 # Beispiele
 -   `example-ide`: 
-    Entwickeln eines externen Werkzeuges in der MathCoach-IDE
--   `example-vscode-advanced`: 
-    Entwickeln eines externen Werkzeuges mit VSCode, Typescript und 
-    Parcel als Build-System
\ No newline at end of file
+    Entwickeln eines externen Werkzeuges in der MathCoach-IDE 
\ No newline at end of file
diff --git a/mathcoach-api.d.ts b/mathcoach-api.d.ts
index b5ed739..bb80ace 100644
--- a/mathcoach-api.d.ts
+++ b/mathcoach-api.d.ts
@@ -1,4 +1,3 @@
-
 /**
  * Wenn die Bibliothek zur Erweiterung der IDE eingebunden (`ide-lib.js`) wurde,
  * steht diese globale Variable mit Zugang zur öffentlichen Schnittstelle
@@ -9,14 +8,17 @@
 /**
  * Der MathCoach-Namensraum ist die Sammelstelle für alle öffentlichen Schnittstellen.
  * Somit können auch externe Module (z.B. grafische Editoren) typsicher erstellt werden.
+ * 
  * Als Einstiegspunkt dient das interface `MathCoach.Api` - eine Implementierung dieser Schnittstelle
  * wird von der IDE (siehe `ide-lib.js`) bereitgestellt und kann über die globale Variable 
  * `MC` zugegriffen werden. 
  */
 declare namespace MathCoach {
 
-    /**
-     * Einstiegspunkt zur MathCoach API Schnittstelle 
+    /** 
+     * Als Einstiegspunkt dient das interface `MathCoach.Api` - eine Implementierung dieser Schnittstelle
+     * wird von der IDE (siehe `ide-lib.js`) bereitgestellt und kann über die globale Variable 
+     * `MC` zugegriffen werden. 
      */
     interface Api {
         /**
@@ -55,7 +57,7 @@
     */
     interface IdeApi {
         /**
-         * Name des aktuellen Benutzers.
+         * Gibt den Namen des aktuellen Benutzers zurück, der mit dem Werkzeug arbeitet.
          * 
          * Anwendungsbeisipiel:
          * 
@@ -64,7 +66,7 @@
          */
         getUserName(): Promise<string>;
         /**
-         * Verweis auf die Datei, mit der das Entwicklerwerkzeug gestartet wurde. 
+         * Gibt den Verweis auf die Datei zurück, mit der das Entwicklerwerkzeug gestartet wurde. 
          * 
          * Anwendungsbeispiel:
          * 
@@ -73,16 +75,16 @@
          */
         getContextFile(): Promise<File>;
         /**
-         * Schnittstelle zum Dateisystem
+         * Einstiegspunkt der Dateisystem-Schnittstelle (z.B. um Dateien zu lesen und zu schreiben)
          */
         readonly fs: FileSystemApi;
         /**
-         * Schnittstelle zur Vorschau
+         * Einstiegspunkt der Vorschau-Schnittstelle (z.B. um generierte Aufgaben zu starten)
          */
         readonly navigator: NavigatorApi;
     }
     /**
-     * Schnittstelle zur Navigations-Vorschau
+     * Schnittstelle zur Navigation der Vorschau
      */
     interface NavigatorApi {
         /**
@@ -101,7 +103,7 @@
         /**
          * Navigiert die Vorschau zu einer MathCoach-Aufgabe.
          * Hinweis: Die Datei muss im `vfs`-Teil des Dateisystems liegen und
-         * eine ausführbar sein (z.B. eine groovy-Datei).
+         * eine ausführbare MathCoach-Aufgabe sein (z.B. eine groovy-Datei).
          * 
          * Anwendungsbeispiel:
          *      
diff --git a/package-lock.json b/package-lock.json
index 4635441..cde9d93 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,79 +4,19 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
-    "@types/events": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
-      "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
-      "dev": true
-    },
-    "@types/fs-extra": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.1.0.tgz",
-      "integrity": "sha512-AInn5+UBFIK9FK5xc9yP5e3TQSPNNgjHByqYcj9g5elVBnDQcQL7PlO1CIRy2gWlbwK7UPYqi7vRvFA44dCmYQ==",
-      "dev": true,
-      "requires": {
-        "@types/node": "*"
-      }
-    },
-    "@types/glob": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
-      "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
-      "dev": true,
-      "requires": {
-        "@types/events": "*",
-        "@types/minimatch": "*",
-        "@types/node": "*"
-      }
-    },
-    "@types/handlebars": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.1.0.tgz",
-      "integrity": "sha512-gq9YweFKNNB1uFK71eRqsd4niVkXrxHugqWFQkeLRJvGjnxsLr16bYtcsG4tOFwmYi0Bax+wCkbf1reUfdl4kA==",
-      "dev": true,
-      "requires": {
-        "handlebars": "*"
-      }
-    },
-    "@types/highlight.js": {
-      "version": "9.12.3",
-      "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz",
-      "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==",
-      "dev": true
-    },
-    "@types/lodash": {
-      "version": "4.14.135",
-      "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.135.tgz",
-      "integrity": "sha512-Ed+tSZ9qM1oYpi5kzdsBuOzcAIn1wDW+e8TFJ50IMJMlSopGdJgKAbhHzN6h1E1OfjlGOr2JepzEWtg9NIfoNg==",
-      "dev": true
-    },
-    "@types/marked": {
-      "version": "0.4.2",
-      "resolved": "https://registry.npmjs.org/@types/marked/-/marked-0.4.2.tgz",
-      "integrity": "sha512-cDB930/7MbzaGF6U3IwSQp6XBru8xWajF5PV2YZZeV8DyiliTuld11afVztGI9+yJZ29il5E+NpGA6ooV/Cjkg==",
-      "dev": true
-    },
     "@types/minimatch": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
       "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
       "dev": true
     },
-    "@types/node": {
-      "version": "12.0.10",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.0.10.tgz",
-      "integrity": "sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==",
-      "dev": true
-    },
-    "@types/shelljs": {
-      "version": "0.8.5",
-      "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.5.tgz",
-      "integrity": "sha512-bZgjwIWu9gHCjirKJoOlLzGi5N0QgZ5t7EXEuoqyWCHTuSddURXo3FOBYDyRPNOWzZ6NbkLvZnVkn483Y/tvcQ==",
+    "backbone": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.4.0.tgz",
+      "integrity": "sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==",
       "dev": true,
       "requires": {
-        "@types/glob": "*",
-        "@types/node": "*"
+        "underscore": ">=1.8.3"
       }
     },
     "balanced-match": {
@@ -96,9 +36,9 @@
       }
     },
     "commander": {
-      "version": "2.20.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
-      "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+      "version": "2.20.3",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
       "dev": true,
       "optional": true
     },
@@ -109,12 +49,12 @@
       "dev": true
     },
     "fs-extra": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
-      "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+      "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
       "dev": true,
       "requires": {
-        "graceful-fs": "^4.1.2",
+        "graceful-fs": "^4.2.0",
         "jsonfile": "^4.0.0",
         "universalify": "^0.1.0"
       }
@@ -126,9 +66,9 @@
       "dev": true
     },
     "glob": {
-      "version": "7.1.4",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz",
-      "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==",
+      "version": "7.1.6",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
       "dev": true,
       "requires": {
         "fs.realpath": "^1.0.0",
@@ -140,15 +80,15 @@
       }
     },
     "graceful-fs": {
-      "version": "4.1.15",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
-      "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
       "dev": true
     },
     "handlebars": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz",
-      "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==",
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+      "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
       "dev": true,
       "requires": {
         "neo-async": "^2.6.0",
@@ -158,10 +98,13 @@
       }
     },
     "highlight.js": {
-      "version": "9.15.8",
-      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.8.tgz",
-      "integrity": "sha512-RrapkKQWwE+wKdF73VsOa2RQdIoO3mxwJ4P8mhbI6KYJUraUHRKM5w5zQQKXNk0xNL4UVRdulV9SBJcmzJNzVA==",
-      "dev": true
+      "version": "9.17.1",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.17.1.tgz",
+      "integrity": "sha512-TA2/doAur5Ol8+iM3Ov7qy3jYcr/QiJ2eDTdRF4dfbjG7AaaB99J5G+zSl11ljbl6cIcahgPY6SKb3sC3EJ0fw==",
+      "dev": true,
+      "requires": {
+        "handlebars": "^4.5.3"
+      }
     },
     "inflight": {
       "version": "1.0.6",
@@ -185,6 +128,12 @@
       "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==",
       "dev": true
     },
+    "jquery": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
+      "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==",
+      "dev": true
+    },
     "jsonfile": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
@@ -195,15 +144,21 @@
       }
     },
     "lodash": {
-      "version": "4.17.11",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+      "dev": true
+    },
+    "lunr": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz",
+      "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==",
       "dev": true
     },
     "marked": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/marked/-/marked-0.4.0.tgz",
-      "integrity": "sha512-tMsdNBgOsrUophCAFQl0XPe6Zqk/uy9gnue+jIIKhykO51hxyu6uNx7zBPy0+y/WKYVZZMspV9YeXLNdKk+iYw==",
+      "version": "0.7.0",
+      "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz",
+      "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==",
       "dev": true
     },
     "minimatch": {
@@ -274,18 +229,18 @@
       }
     },
     "resolve": {
-      "version": "1.11.1",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
-      "integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==",
+      "version": "1.13.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz",
+      "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==",
       "dev": true,
       "requires": {
         "path-parse": "^1.0.6"
       }
     },
     "rimraf": {
-      "version": "2.6.3",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz",
+      "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==",
       "dev": true,
       "requires": {
         "glob": "^7.1.3"
@@ -309,53 +264,59 @@
       "dev": true
     },
     "typedoc": {
-      "version": "0.14.2",
-      "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.14.2.tgz",
-      "integrity": "sha512-aEbgJXV8/KqaVhcedT7xG6d2r+mOvB5ep3eIz1KuB5sc4fDYXcepEEMdU7XSqLFO5hVPu0nllHi1QxX2h/QlpQ==",
+      "version": "0.15.5",
+      "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.15.5.tgz",
+      "integrity": "sha512-AKXLtOUCLRlSTyfXQHYp3LFPy6RiFLnxnKS5z1jwQsYXmCPbHWuhmfgS264Es2hPMZjzvHqk/ZQDzCBpb49u6w==",
       "dev": true,
       "requires": {
-        "@types/fs-extra": "^5.0.3",
-        "@types/handlebars": "^4.0.38",
-        "@types/highlight.js": "^9.12.3",
-        "@types/lodash": "^4.14.110",
-        "@types/marked": "^0.4.0",
         "@types/minimatch": "3.0.3",
-        "@types/shelljs": "^0.8.0",
-        "fs-extra": "^7.0.0",
-        "handlebars": "^4.0.6",
-        "highlight.js": "^9.13.1",
-        "lodash": "^4.17.10",
-        "marked": "^0.4.0",
+        "fs-extra": "^8.1.0",
+        "handlebars": "^4.5.3",
+        "highlight.js": "^9.17.1",
+        "lodash": "^4.17.15",
+        "marked": "^0.7.0",
         "minimatch": "^3.0.0",
-        "progress": "^2.0.0",
-        "shelljs": "^0.8.2",
-        "typedoc-default-themes": "^0.5.0",
-        "typescript": "3.2.x"
+        "progress": "^2.0.3",
+        "shelljs": "^0.8.3",
+        "typedoc-default-themes": "^0.6.2",
+        "typescript": "3.7.x"
       }
     },
     "typedoc-default-themes": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz",
-      "integrity": "sha1-bcJDPnjti+qOiHo6zeLzF4W9Yic=",
-      "dev": true
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.6.2.tgz",
+      "integrity": "sha512-+O+1aHjVIpDLsbkIDkZSNu+kutqmg7WdzahT+4KwBC/95mUgAb0xkbwdPpEJEpRX0ov1UJoCmvEPb1/VHxnTuw==",
+      "dev": true,
+      "requires": {
+        "backbone": "^1.4.0",
+        "jquery": "^3.4.1",
+        "lunr": "^2.3.8",
+        "underscore": "^1.9.1"
+      }
     },
     "typescript": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz",
-      "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==",
+      "version": "3.7.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz",
+      "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==",
       "dev": true
     },
     "uglify-js": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
-      "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.7.2.tgz",
+      "integrity": "sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA==",
       "dev": true,
       "optional": true,
       "requires": {
-        "commander": "~2.20.0",
+        "commander": "~2.20.3",
         "source-map": "~0.6.1"
       }
     },
+    "underscore": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
+      "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==",
+      "dev": true
+    },
     "universalify": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
diff --git a/package.json b/package.json
index 254f69c..3432d0e 100644
--- a/package.json
+++ b/package.json
@@ -1,20 +1,20 @@
 {
   "name": "@mathcoach/ide-api",
   "version": "1.1.0",
-  "description": "API zur MathCoach IDE", 
+  "description": "API zur MathCoach IDE",
   "main": "./src/index.ts",
   "directories": {
     "example": "examples"
   },
   "devDependencies": {
-    "rimraf": "^2.6.3",
-    "typedoc": "^0.14.2"
+    "rimraf": "^3.0.0",
+    "typedoc": "^0.15.5"
   },
   "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-docs": "typedoc mathcoach-api.d.ts src/ --out docs/ --mode file --hideGenerator --theme minimal --includeDeclarations --excludeExternals --media ./media"
   },
   "author": "jsteuer",
   "license": ""
-}
\ No newline at end of file
+}
diff --git a/src/Helpers.ts b/src/Helpers.ts
new file mode 100644
index 0000000..3ec398c
--- /dev/null
+++ b/src/Helpers.ts
@@ -0,0 +1,129 @@
+/// <reference path="../mathcoach-api.d.ts"/>
+
+/**
+ * Hilfsfunktionen für Werkzeug-Entwickler. Diese werden nicht durch die `ide-lib.js` 
+ * ausgeliefert!
+ */
+export namespace Helpers {
+    /**
+     * Bildet die MathCoach API nach, sodass diese auch Offline (ohne IDE) 
+     * verfügbar ist.
+     * 
+     * Das Dateisystem wird durch den LocalStorage des Browsers implementiert.
+     * Einige Features der IDE (beispielsweise der Navigator) sind nicht verfügbar 
+     * und führen keine Aktionen durch. Alle Aktionen werden in der Browser-Console
+     * geloggt.
+     * 
+     * **Hinweis**: Wenn die echte MathCoach-API der IDE verfügbar ist, hat der Aufruf 
+     * dieser Funktion keinen Seiteneffekt.
+     * 
+     * Anwendungsbeispiel 
+     * 
+     *      import { Helpers } from "@mathcoach/ide-api";
+     *      Helpers.enableOfflineUsageIfNecessary();
+     * 
+     * 
+     * @param contextFileExtension Datei-Erweiterung der Kontext-Datei (Das Werkzeug soll 
+     * jedoch unabhängig von der Endung arbeiten können)
+     * @returns Gibt `true` zurück, wenn die Offline-Funktionalität aktiviert 
+     * wurde, andernfalls `false`
+     */
+    export function enableOfflineUsageIfNecessary(contextFileExtension: string = "dummy.json"): boolean {
+
+        const fileIdentifier = (file: MathCoach.File) => `mock-file://${file.owner}@${file.part}/${file.path}`;
+        const traceMethod = (method: string, args?: any[]) => console.log(["[MC MOCK API]", " ", method, "(", (args ? args : [""]).join(","), ")"].join(""));
+
+        class MockAPI implements MathCoach.Api {
+
+            public ide: MathCoach.IdeApi = {
+                async getContextFile(): Promise<MathCoach.File> {
+                    traceMethod("MC.ide.getContextFile");
+                    return {
+                        owner: "jdoe",
+                        path: `/file.${contextFileExtension}`,
+                        part: "vfs"
+                    }
+                },
+                async getUserName(): Promise<string> {
+                    traceMethod("MC.ide.getUserName");
+                    return "jdoe"
+                },
+                fs: {
+                    async readFile(file: MathCoach.File) {
+                        traceMethod("MC.ide.fs.readFile", [JSON.stringify(file)]);
+                        return localStorage.getItem(fileIdentifier(file)) || "";
+                    },
+                    async writeFile(file: MathCoach.File, text: string) {
+                        traceMethod("MC.ide.fs.writeFile", [JSON.stringify(file), JSON.stringify(`...${text.length} chars...`)]);
+                        return localStorage.setItem(fileIdentifier(file), text);
+                    }
+                },
+                navigator: {
+                    async navigateTo(link: string, forceOpen?: boolean) {
+                        traceMethod("MC.ide.navigator.navigateTo", [JSON.stringify(link), JSON.stringify(forceOpen ? true : false)]);
+                    },
+                    async navigateToExercise(file: MathCoach.File, forceOpen?: boolean) {
+                        traceMethod("MC.ide.navigator.navigateToExercise", [JSON.stringify(file), JSON.stringify(forceOpen ? true : false)]);
+                    }
+                }
+            };
+            public async isReady(): Promise<boolean> {
+                traceMethod("MC.isReady()");
+                return true;
+            }
+        }
+        if (typeof MC === "undefined") {
+            console.warn("you are offline - offline api is used");
+            (window as any).MC = new MockAPI(); // fake the MathCoach-API
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+
+
+    /**
+     * Bildet die Kontext-Datei auf eine Aufgaben-Datei mit selben Namen ab.
+     * 
+     * Ein Werkzeug speichert sein Datenmodell in der sogenannten Kontext-Datei. Soll 
+     * eine MathCoach-Aufgabe generiert werden, ist es sinnvoll, wenn die Aufgaben-Datei
+     * den selben Namen wie die Kontext-Datei trägt (natürlich mit anderer Dateiendung).
+     * 
+     * Beispielsweise wird eine Dateireferenz mit dem Pfad `"/path/to/myExercise.mcq.json"` 
+     * auf eine Dateireferenz mit dem Pfad `"/path/to/myExercise.groovy"` abgebildet.
+     * 
+     * Anwendungsbeispiel
+     * 
+     *      import { Helpers } from "@mathcoach/ide-api";
+     *      const contextFile: MathCoach.File = await MC.ide.getContextFile();
+     *      const exerciseFile: MathCoach.File = Helpers.contextFileToExerciseFile(contextFile);
+     */
+    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;
+    }
+
+
+
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 3d8644f..4afae24 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,66 +1 @@
-/// <reference path="../mathcoach-api.d.ts"/>
-
-/**
- * Offline MathCoach-API falls notwendig bereitstellen. Dabei wird das Dateisystem durch den
- * LocalStorage des Browsers implementiert - einige Features der IDE (beispielsweise 
- * der Navigator) sind nicht verfügbar und führen keine Aktionen durch. 
- * 
- * **Hinweis**: Wenn die echte MathCoach-API der IDE verfügbar ist, hat der Aufruf 
- * dieser Funktion keinen Seiteneffekt.
- * 
- * @param contextFileExtension Datei-Erweiterung der Kontext-Datei
- * 
- */
-export function enableOfflineUsageIfNecessary(contextFileExtension: string = "dummy.json"): boolean {
-
-    const fileIdentifier = (file: MathCoach.File) => `mock-file://${file.owner}@${file.part}/${file.path}`;
-    const traceMethod = (method: string, args?: any[]) => console.log(["[MC MOCK API]", " ", method, "(", (args ? args : [""]).join(","), ")"].join(""));
-
-    class MockAPI implements MathCoach.Api {
-
-        public ide: MathCoach.IdeApi = {
-            async getContextFile(): Promise<MathCoach.File> {
-                traceMethod("MC.ide.getContextFile");
-                return {
-                    owner: "jdoe",
-                    path: `/file.${contextFileExtension}`,
-                    part: "vfs"
-                }
-            },
-            async getUserName(): Promise<string> {
-                traceMethod("MC.ide.getUserName");
-                return "jdoe"
-            },
-            fs: {
-                async readFile(file: MathCoach.File) {
-                    traceMethod("MC.ide.fs.readFile", [JSON.stringify(file)]);
-                    return localStorage.getItem(fileIdentifier(file)) || "";
-                },
-                async writeFile(file: MathCoach.File, text: string) {
-                    traceMethod("MC.ide.fs.writeFile", [JSON.stringify(file), JSON.stringify(`...${text.length} chars...`)]);
-                    return localStorage.setItem(fileIdentifier(file), text);
-                }
-            },
-            navigator: {
-                async navigateTo(link: string, forceOpen?: boolean) {
-                    traceMethod("MC.ide.navigator.navigateTo", [JSON.stringify(link), JSON.stringify(forceOpen ? true : false)]);
-                },
-                async navigateToExercise(file: MathCoach.File, forceOpen?: boolean) {
-                    traceMethod("MC.ide.navigator.navigateToExercise", [JSON.stringify(file), JSON.stringify(forceOpen ? true : false)]);
-                }
-            }
-        };
-        public async isReady(): Promise<boolean> {
-            traceMethod("MC.isReady()");
-            return true;
-        }
-    }
-    if (typeof MC === "undefined") {
-        console.warn("you are offline - offline api is used");
-        (window as any).MC = new MockAPI(); // fake the MathCoach-API
-        return true;
-    } else {
-        return false;
-    }
-}
-
+export * from "./Helpers"
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index e1b03ff..ca8ced6 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,7 +3,8 @@
     "module": "commonjs",
     "target": "es5",
     "declaration": true,
-    "outDir": "./dist"
+    "outDir": "./dist",
+    "lib": ["DOM","ES2016"]
   },
   "include": [
     "src/**/*"

--
Gitblit v1.10.0-SNAPSHOT