Update to CodeMirror 6 (#7)
continuous-integration/drone/push Build is passing Details

Update the editor to CodeMirror, using a [custom package](https://codefirst.iut.uca.fr/git/sandkasten/components/src/branch/main/projects/codemirror6-editor). All the Angular integration parts happen in this dedicated package, and the editor configuration is done here.

Language selection has been refactored to dynamically import on the fly the appropriate CodeMirror modes (now called extensions).

Co-authored-by: clfreville2 <clement.freville2@etu.uca.fr>
Reviewed-on: #7
Reviewed-by: Colin FRIZOT <colin.frizot@etu.uca.fr>
Reviewed-by: Bastien OLLIER <bastien.ollier@noreply.codefirst.iut.uca.fr>
Reviewed-by: Hugo PRADIER <hugo.pradier2@etu.uca.fr>
Reviewed-by: Matis MAZINGUE <matis.mazingue@etu.uca.fr>
error-extensions-editor
Clément FRÉVILLE 1 year ago
parent d41629abd0
commit af989fc165

225
package-lock.json generated

@ -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",

@ -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",

@ -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,7 +46,6 @@ import { SafeHTMLPipe } from './safe-html.pipe';
AppRoutingModule,
ReactiveFormsModule,
FormsModule,
CodemirrorModule,
// Injection des HttpClient pour notre module de traduction
HttpClientModule,
// Initialisation du module de traduction
@ -60,7 +59,8 @@ import { SafeHTMLPipe } from './safe-html.pipe';
deps: [HttpClient]
},
defaultLanguage: 'fr'
})
}),
CodeMirrorComponent
],
providers: [TranslationService],
bootstrap: [AppComponent]

@ -1,35 +1,19 @@
<div>
<div>
<ngx-codemirror
[options]="{
theme: 'material',
lineNumbers: true,
lineWrapping: true,
mode: mode,
autofocus: true
}"
<codemirror6-editor
[(ngModel)]="editorContent"
[autoFocus]="true"
>
</ngx-codemirror>
[extensions]="extensions"
></codemirror6-editor>
</div>
<pre [innerHTML]="resultContent | safeHTML"></pre>
<div>
<label for="language">Langage de programmation</label>
<select
id="language"
name="language"
[(ngModel)]="mode"
(ngModelChange)="changeMode()">
<option value="text/typescript" selected>TypeScript</option>
<option value="text/javascript">JavaScript</option>
<option value="text/x-csrc">C</option>
<option value="text/x-c++src">C++</option>
<option value="text/x-sh">Shell</option>
<select id="language" [(ngModel)]="selectedLanguage">
@for (language of languages; track language.name) {
<option [ngValue]="language">{{ language.name }}</option>
}
</select>
</div>
@ -38,10 +22,6 @@
</div>
<button (click)="onRunButtonClicked()" [disabled]="isLoaded">Lancer</button>
<div *ngIf="!isLoaded">
<p>Chargement: {{ loadingProgress }}%</p>
<div class="loading-bar" [style.width.%]="loadingProgress"></div>
</div>
<div>
<label for="fileInput">Charger à partir d'un fichier</label>

@ -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 <iostream>
using namespace std;
int main() {
cout << "Bonjour ceci est un test de code en c++" << endl;
return 0;
}`,
"text/x-csrc": `#include <stdio.h>
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<string, AllowedLanguage> = {
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<AllowedLanguage, string> = {
"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 {
}
const extensions = this.languages.flatMap(lang => lang.extensions);
this.errorMessage =
"Unsupported language. Please select one of the following languages: shell, javascript, typescript, c++, c";
`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();
}
}

@ -0,0 +1,49 @@
import {LanguageDescription} from "@codemirror/language";
import {javascript} from "@codemirror/lang-javascript";
export const CODE_DEFAULTS = {
'C': /** @lang C */ `#include <stdio.h>
int main() {
printf("Hello, World!\\n");
return 0;
}`,
'C++': /** @lang C++ */ `#include <iostream>
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}))
}
}),
];

@ -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';

@ -1,6 +1,3 @@
@import 'codemirror/lib/codemirror.css';
@import 'codemirror/theme/material.css';
//region Colors
$color-purple: #605FFC;
$color-white: #FFFFFF;

Loading…
Cancel
Save