From 22721aa2e3dd10241ac276eb0bf971488dff3f3b Mon Sep 17 00:00:00 2001 From: clfreville2 Date: Wed, 24 Jan 2024 21:21:31 +0100 Subject: [PATCH] Update to CodeMirror 6 --- package-lock.json | 225 +++++++++++++++--- package.json | 8 +- src/app/app.module.ts | 8 +- .../components/editor/editor.component.html | 34 +-- src/app/components/editor/editor.component.ts | 194 +++++---------- src/app/components/languages.ts | 49 ++++ src/main.ts | 3 - src/styles.scss | 3 - 8 files changed, 310 insertions(+), 214 deletions(-) create mode 100644 src/app/components/languages.ts diff --git a/package-lock.json b/package-lock.json index 49a7f13..b69ae85 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,12 +17,16 @@ "@angular/platform-browser": "^17.1.0", "@angular/platform-browser-dynamic": "^17.1.0", "@angular/router": "^17.1.0", - "@ctrl/ngx-codemirror": "^7.0.0", + "@codemirror/lang-cpp": "^6.0.2", + "@codemirror/lang-javascript": "^6.2.1", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.23.0", "@emailjs/browser": "^3.12.1", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", + "@sandkasten/codemirror6-editor": "^0.0.2", "ansi-to-html": "^0.7.2", - "codemirror": "^5.65.16", + "codemirror": "^6.0.1", "rxjs": "~7.8.1", "sse.js": "^2.2.0", "tslib": "^2.6.2", @@ -2262,6 +2266,105 @@ "node": ">=6.9.0" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz", + "integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.3.3.tgz", + "integrity": "sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-cpp": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-cpp/-/lang-cpp-6.0.2.tgz", + "integrity": "sha512-6oYEYUKHvrnacXxWxYa6t4puTlbN3dgV662BDfSH8+MfjQjVmP697/KYTDOqpxgerkvoNm7q5wlFMBeX8ZMocg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/cpp": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.1.tgz", + "integrity": "sha512-jlFOXTejVyiQCW3EQwvKH0m99bUYIw40oPmFjSX2VS78yzfe0HELZ+NEo9Yfo1MkGRpGlj3Gnu4rdxV1EnAs5A==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.0.tgz", + "integrity": "sha512-2vaNn9aPGCRFKWcHPFksctzJ8yS5p7YoaT+jHpc0UGKzNuAIx4qy6R5wiqbP+heEEdyaABA582mNqSHzSoYdmg==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.4.2.tgz", + "integrity": "sha512-wzRkluWb1ptPKdzlsrbwwjYCPLgzU6N88YBAmlZi8WFyuiEduSd05MnJYNogzyc8rPK7pj6m95ptUApc8sHKVA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.5.tgz", + "integrity": "sha512-PIEN3Ke1buPod2EHbJsoQwlbpkz30qGZKcnmH1eihq9+bPQx8gelauUwLYaY4vBOuBAuEhmpDLii4rj/uO0yMA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.0.tgz", + "integrity": "sha512-hm8XshYj5Fo30Bb922QX9hXB/bxOAVH+qaqHBzw5TKa72vOeslyGwd4X8M0c1dJ9JqxlaMceOQ8RsL9tC7gU0A==" + }, + "node_modules/@codemirror/view": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.23.0.tgz", + "integrity": "sha512-/51px9N4uW8NpuWkyUX+iam5+PM6io2fm+QmRnzwqBy5v/pwGg9T0kILFtYeum8hjuvENtgsGNKluOfqIICmeQ==", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2271,20 +2374,6 @@ "node": ">=0.1.90" } }, - "node_modules/@ctrl/ngx-codemirror": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@ctrl/ngx-codemirror/-/ngx-codemirror-7.0.0.tgz", - "integrity": "sha512-qvIWtSTw/8fdXDnofBTX6LmTW9646HhawG2+Qyagf1vH40jCy0ZbHnkC20UYOVpUX+QCd1e/PQpkvWQ/1iGFzQ==", - "dependencies": { - "@types/codemirror": "^5.60.7", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/core": ">=16.0.0-0", - "@angular/forms": ">=16.0.0-0", - "codemirror": "^5.65.9" - } - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -2864,6 +2953,47 @@ "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", "dev": true }, + "node_modules/@lezer/common": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.1.tgz", + "integrity": "sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==" + }, + "node_modules/@lezer/cpp": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/cpp/-/cpp-1.1.2.tgz", + "integrity": "sha512-macwKtyeUO0EW86r3xWQCzOV9/CF8imJLpJlPv3sDY57cPGeUZ8gXWOWNlJr52TVByMV3PayFQCA5SHEERDmVQ==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.0.tgz", + "integrity": "sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.13.tgz", + "integrity": "sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.14.tgz", + "integrity": "sha512-z5mY4LStlA3yL7aHT/rqgG614cfcvklS+8oFRFBYrs4YaWLJyKKM4+nN6KopToX0o9Hj6zmH6M5kinOYuy06ug==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@ljharb/through": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz", @@ -3323,6 +3453,20 @@ "win32" ] }, + "node_modules/@sandkasten/codemirror6-editor": { + "version": "0.0.2", + "resolved": "https://codefirst.iut.uca.fr/git/api/packages/sandkasten/npm/%40sandkasten%2Fcodemirror6-editor/-/0.0.2/codemirror6-editor-0.0.2.tgz", + "integrity": "sha512-hwqtIlIJFT1muFRqY66OC6qYtxj8XS0yG0SfDWh856CrZRcjSed5q4JBWROZqyPerc7L4PQiO3YmUnzR0YtCOA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^17.1.0", + "@angular/core": "^17.1.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.23.0" + } + }, "node_modules/@schematics/angular": { "version": "17.1.0", "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-17.1.0.tgz", @@ -3482,14 +3626,6 @@ "@types/node": "*" } }, - "node_modules/@types/codemirror": { - "version": "5.60.15", - "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz", - "integrity": "sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA==", - "dependencies": { - "@types/tern": "*" - } - }, "node_modules/@types/connect": { "version": "3.4.38", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", @@ -3547,7 +3683,8 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true }, "node_modules/@types/express": { "version": "4.17.21", @@ -3681,14 +3818,6 @@ "@types/node": "*" } }, - "node_modules/@types/tern": { - "version": "0.23.9", - "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz", - "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==", - "dependencies": { - "@types/estree": "*" - } - }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", @@ -4819,9 +4948,18 @@ } }, "node_modules/codemirror": { - "version": "5.65.16", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz", - "integrity": "sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg==" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } }, "node_modules/color-convert": { "version": "1.9.3", @@ -5127,6 +5265,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/critters": { "version": "0.0.20", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", @@ -10882,6 +11025,11 @@ "node": ">=6" } }, + "node_modules/style-mod": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz", + "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11514,6 +11662,11 @@ "node": ">=0.10.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/package.json b/package.json index e51187b..42484d5 100644 --- a/package.json +++ b/package.json @@ -19,12 +19,16 @@ "@angular/platform-browser": "^17.1.0", "@angular/platform-browser-dynamic": "^17.1.0", "@angular/router": "^17.1.0", - "@ctrl/ngx-codemirror": "^7.0.0", + "@codemirror/lang-cpp": "^6.0.2", + "@codemirror/lang-javascript": "^6.2.1", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.23.0", "@emailjs/browser": "^3.12.1", "@ngx-translate/core": "^15.0.0", "@ngx-translate/http-loader": "^8.0.0", + "@sandkasten/codemirror6-editor": "^0.0.2", "ansi-to-html": "^0.7.2", - "codemirror": "^5.65.16", + "codemirror": "^6.0.1", "rxjs": "~7.8.1", "sse.js": "^2.2.0", "tslib": "^2.6.2", diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2ed0287..4542326 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -17,7 +17,7 @@ import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-poli import { ReactiveFormsModule } from '@angular/forms'; import { FormsModule } from '@angular/forms'; -import { CodemirrorModule } from '@ctrl/ngx-codemirror'; +import { CodeMirrorComponent } from '@sandkasten/codemirror6-editor'; import { HttpClient, HttpClientModule } from '@angular/common/http'; import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; @@ -46,8 +46,7 @@ import { SafeHTMLPipe } from './safe-html.pipe'; AppRoutingModule, ReactiveFormsModule, FormsModule, - CodemirrorModule, - // Injection des HttpClient pour notre module de traduction + // Injection des HttpClient pour notre module de traduction HttpClientModule, // Initialisation du module de traduction TranslateModule.forRoot({ @@ -60,7 +59,8 @@ import { SafeHTMLPipe } from './safe-html.pipe'; deps: [HttpClient] }, defaultLanguage: 'fr' - }) + }), + CodeMirrorComponent ], providers: [TranslationService], bootstrap: [AppComponent] diff --git a/src/app/components/editor/editor.component.html b/src/app/components/editor/editor.component.html index 3945bba..fda73ff 100644 --- a/src/app/components/editor/editor.component.html +++ b/src/app/components/editor/editor.component.html @@ -1,35 +1,19 @@
- - + [extensions]="extensions" + >

 
   
- + @for (language of languages; track language.name) { + + }
@@ -38,10 +22,6 @@
-
-

Chargement: {{ loadingProgress }}%

-
-
diff --git a/src/app/components/editor/editor.component.ts b/src/app/components/editor/editor.component.ts index 593b443..f3bee3a 100644 --- a/src/app/components/editor/editor.component.ts +++ b/src/app/components/editor/editor.component.ts @@ -1,96 +1,55 @@ -import { Component, OnInit } from "@angular/core"; -import { Router } from "@angular/router"; -import { CodeExecutionService } from "src/app/services/codeExecution.service"; -import "codemirror/mode/shell/shell.js"; -import "codemirror/mode/clike/clike.js"; -import Convert from 'ansi-to-html'; - - -// Exemple de code pour chaque langage autorisé -const codeDefaults = { - "text/typescript": `const component = { - name: "@exemple/Typescript", - author: "Sandkasten", - repo: "https://codefirst.iut.uca.fr/git/sandkasten/sandkasten-web.git" -}; -const hello: string = 'Bonjour ceci est un test de code en typescript';`, - "text/javascript": `const component = { - name: "@exemple/Javascript", - author: "Sandkasten", - repo: "https://codefirst.iut.uca.fr/git/sandkasten/sandkasten-web.git" -}; -const hello = 'Bonjour ceci est un test de code en javascript';`, - "text/x-c++src": `#include -using namespace std; -int main() { - cout << "Bonjour ceci est un test de code en c++" << endl; - return 0; -}`, - "text/x-csrc": `#include -int main() { - printf("Bonjour ceci est un test de code en c"); - return 0; -}`, - "text/x-sh": `#!/bin/bash -echo "Bonjour ceci est un test de code en shell"`, -}; - -// Langages autorisés -type AllowedLanguage = keyof typeof codeDefaults; +import { Component, ViewChild } from '@angular/core'; +import { CodeExecutionService } from 'src/app/services/codeExecution.service'; +import { basicSetup } from 'codemirror'; +import { Compartment, Extension } from '@codemirror/state'; +import { CodeMirrorComponent } from '@sandkasten/codemirror6-editor'; +import { LanguageDescription } from '@codemirror/language'; +import { CODE_DEFAULTS, LANGUAGES } from '../languages'; @Component({ selector: "app-editor", templateUrl: "./editor.component.html", styleUrls: ["./editor.component.scss"], }) -export class EditorComponent implements OnInit { - loadingProgress: number = 0; // Pour suivre la progression du chargement +export class EditorComponent { isLoaded: boolean = false; // Pour vérifier si le chargement est terminé + readonly languages: LanguageDescription[] = LANGUAGES; // Mode par défaut - mode: AllowedLanguage = "text/typescript"; - options = { - lineNumbers: true, - mode: this.mode, - }; - defaults = codeDefaults; + private _selectedLanguage = this.languages.find((lang) => lang.name === "JavaScript")!; + get selectedLanguage(): LanguageDescription { + return this._selectedLanguage; + } + set selectedLanguage(value: LanguageDescription) { + this._selectedLanguage = value; + if (value.name in CODE_DEFAULTS) { + this.editorContent = CODE_DEFAULTS[value.name as keyof typeof CODE_DEFAULTS]; + } + this.selectedLanguage.load().then((language) => { + this.codemirror.editor?.dispatch({ + effects: this.languageCompartment.reconfigure(language) + }); + }); + } // Contenu de l'éditeur que l'on passera au serveur - editorContent: string = this.defaults[this.mode as keyof typeof codeDefaults]; + editorContent: string = CODE_DEFAULTS[this.selectedLanguage.name as keyof typeof CODE_DEFAULTS]; resultContent: string = ""; // Message d'erreur errorMessage: string = ""; - constructor( - private router: Router, - private codeExecutionService: CodeExecutionService - ) {} - - ngOnInit(): void { - // Appel à changeMode pour mettre à jour le contenu de l'éditeur et le mode - this.changeMode(); - const convert = new Convert(); - - this.codeExecutionService.getResult().subscribe((result) => { - if (result.type !== 'exit') { - this.resultContent += convert.toHtml(result.text); - } - }); - } + @ViewChild(CodeMirrorComponent) private codemirror!: CodeMirrorComponent; - // Change le langage de l'éditeur - changeMode(): void { - this.options = { - ...this.options, - mode: this.mode, - }; - this.editorContent = this.defaults[this.mode as keyof typeof codeDefaults]; - } + private readonly languageCompartment = new Compartment(); + protected readonly extensions: Extension[] = [ + basicSetup, + this.languageCompartment.of(this.selectedLanguage.support!) + ]; - // Affiche le contenu de l'éditeur - handleChange($event: Event): void { - console.log("ngModelChange", $event); + constructor( + private codeExecutionService: CodeExecutionService + ) { } // Efface le contenu de l'éditeur @@ -98,77 +57,34 @@ export class EditorComponent implements OnInit { this.editorContent = ""; } - loadFromFile(event: any): void { - const file = event.target.files[0]; - if (file) { - const allowedExtensions = ["sh", "js", "ts", "cpp", "c"]; - const extension = file.name.split(".").pop()?.toLowerCase(); - - if (extension && allowedExtensions.includes(extension)) { - // Identifiez le mode en fonction de l'extension - const modeMap: Record = { - sh: "text/x-sh", - js: "text/javascript", - ts: "text/typescript", - cpp: "text/x-c++src", - c: "text/x-csrc", - }; - this.mode = modeMap[extension]; + onRunButtonClicked() { + // Le code à exécuter est le contenu de l'éditeur + const codeToExecute = this.editorContent; - // Mettez à jour le contenu de l'éditeur et le mode - this.changeMode(); + this.codeExecutionService.executeCode(codeToExecute, this.selectedLanguage.name); - const reader = new FileReader(); - reader.onload = (e) => { - this.editorContent = e.target?.result as string; - this.errorMessage = ""; // Réinitialisez le message d'erreur en cas de succès. - }; - reader.readAsText(file); - } else { - this.errorMessage = - "Unsupported file type. Please select a file with one of the following extensions: sh, js, ts, cpp, c"; - console.error(this.errorMessage); - } - } + this.resultContent = ''; } - saveToFile(): void { - const languageExtensionMap: Record = { - "text/x-sh": "sh", - "text/javascript": "js", - "text/typescript": "ts", - "text/x-c++src": "cpp", - "text/x-csrc": "c", - }; - - if (languageExtensionMap[this.mode]) { - const extension = languageExtensionMap[this.mode]; - if (this.editorContent.trim() === "") { - this.errorMessage = "Cannot save an empty file."; - console.error(this.errorMessage); - } else { - this.errorMessage = ""; // Réinitialisez le message d'erreur en cas de succès. - const blob = new Blob([this.editorContent], { type: "text/plain" }); - const a = document.createElement("a"); - a.href = window.URL.createObjectURL(blob); - a.download = `code.${extension}`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); + loadFromFile(event: Event) { + const file = (event.target as HTMLInputElement).files![0]; + for (const language of this.languages) { + if (language.extensions.some(ext => file.name.endsWith(`.${ext}`))) { + this.selectedLanguage = language; + return; } - } else { - this.errorMessage = - "Unsupported language. Please select one of the following languages: shell, javascript, typescript, c++, c"; - console.error(this.errorMessage); } + const extensions = this.languages.flatMap(lang => lang.extensions); + this.errorMessage = + `Unsupported language. Please select one of the following languages: ${extensions.join(', ')}.`; + console.error(this.errorMessage); } - onRunButtonClicked() { - // Le code à exécuter est le contenu de l'éditeur - const codeToExecute = this.editorContent; - - this.codeExecutionService.executeCode(codeToExecute, this.mode); - - this.resultContent = ''; + saveToFile() { + const blob = new Blob([this.editorContent], { type: 'text/plain' }); + const a = document.createElement('a'); + a.download = `code.${this.selectedLanguage.extensions![0]}`; + a.href = URL.createObjectURL(blob); + a.click(); } } diff --git a/src/app/components/languages.ts b/src/app/components/languages.ts new file mode 100644 index 0000000..abd7f0a --- /dev/null +++ b/src/app/components/languages.ts @@ -0,0 +1,49 @@ +import {LanguageDescription} from "@codemirror/language"; +import {javascript} from "@codemirror/lang-javascript"; + +export const CODE_DEFAULTS = { + 'C': /** @lang C */ `#include +int main() { + printf("Hello, World!\\n"); + return 0; +}`, + 'C++': /** @lang C++ */ `#include +int main() { + std::cout << "Hello, World!\\n"; + return 0; +}`, + 'JavaScript': /** @lang JS */ `console.log("Hello, World!");`, + 'TypeScript': /** @lang TS */ `console.log("Hello, World!");` +}; + +export const LANGUAGES = [ + LanguageDescription.of({ + name: 'C', + extensions: ['c', 'h', 'ino'], + load() { + return import("@codemirror/lang-cpp").then(m => m.cpp()) + } + }), + LanguageDescription.of({ + name: "C++", + alias: ['cpp'], + extensions: ['cpp', "c++", 'cc', 'cxx', 'hpp', "h++", 'hh', 'hxx'], + load() { + return import("@codemirror/lang-cpp").then(m => m.cpp()) + } + }), + LanguageDescription.of({ + name: 'JavaScript', + alias: ['ecmascript', 'js', 'node'], + extensions: ['js', 'mjs', 'cjs'], + support: javascript(), + }), + LanguageDescription.of({ + name: 'TypeScript', + alias: ['ts'], + extensions: ['ts'], + load() { + return import("@codemirror/lang-javascript").then(m => m.javascript({typescript: true})) + } + }), +]; diff --git a/src/main.ts b/src/main.ts index 01f6524..0a62114 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,3 @@ -import 'codemirror/mode/javascript/javascript'; -import 'codemirror/mode/markdown/markdown'; - import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; diff --git a/src/styles.scss b/src/styles.scss index e78eea3..1d0b411 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,6 +1,3 @@ -@import 'codemirror/lib/codemirror.css'; -@import 'codemirror/theme/material.css'; - //region Colors $color-purple: #605FFC; $color-white: #FFFFFF; -- 2.36.3