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.  +*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.  -### 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