From 540981ccef6048d429cd68e0ce004ef77d1f245e Mon Sep 17 00:00:00 2001 From: Mats Larsen Date: Fri, 24 Jun 2022 13:14:32 +0100 Subject: [PATCH] Port lib/languages.js to TypeScript (#3740) --- README.md | 2 +- docs/AddingALanguage.md | 2 +- lib/base-compiler.ts | 5 +- lib/handlers/route-api.js | 2 +- lib/{languages.js => languages.ts} | 616 +++++++++++++++++------------ static/main.js | 2 +- static/panes/compiler.js | 16 +- test/unfurl-tests.js | 3 + types/languages.interfaces.ts | 69 +++- 9 files changed, 435 insertions(+), 282 deletions(-) rename lib/{languages.js => languages.ts} (70%) diff --git a/README.md b/README.md index 618ff53dd..55b27ce96 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ important you can quickly and easily get running. Currently, **Compiler Explorer variable or `make` parameter). Running with `make EXTRA_ARGS='--language LANG'` will allow you to load `LANG` exclusively, where `LANG` is one for the -language ids/aliases defined in `lib/languages.js`. For example, to only run **Compiler Explorer** with C++ support, +language ids/aliases defined in `lib/languages.ts`. For example, to only run **Compiler Explorer** with C++ support, you'd run `make EXTRA_ARGS='--language c++'`. The `Makefile` will automatically install all the third party libraries needed to run; using `npm` to install server-side and client side components. diff --git a/docs/AddingALanguage.md b/docs/AddingALanguage.md index 9e44ffe14..6881ec696 100644 --- a/docs/AddingALanguage.md +++ b/docs/AddingALanguage.md @@ -2,7 +2,7 @@ If you want to add a new language to the site, you should follow this steps: -- Add the new language to the exported `languages` variable in `lib/languages.js`: +- Add the new language to the exported `languages` variable in `lib/languages.ts`: - The syntax is as follows: diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts index 1689eac81..17824ca53 100644 --- a/lib/base-compiler.ts +++ b/lib/base-compiler.ts @@ -37,6 +37,7 @@ import { } from '../types/compilation/compilation.interfaces'; import {UnprocessedExecResult} from '../types/execution/execution.interfaces'; import {ParseFilters} from '../types/features/filters.interfaces'; +import {Language} from '../types/languages.interfaces'; import {Library, LibraryVersion, SelectedLibraryVersion} from '../types/libraries/libraries.interfaces'; import {ResultLine} from '../types/resultline/resultline.interfaces'; @@ -50,7 +51,7 @@ import * as exec from './exec'; import {getExternalParserByKey} from './external-parsers'; import {ExternalParserBase} from './external-parsers/base'; import {InstructionSets} from './instructionsets'; -import {CELanguage, languages} from './languages'; +import {languages} from './languages'; import {LlvmAstParser} from './llvm-ast'; import {LlvmIrParser} from './llvm-ir'; import * as compilerOptInfo from './llvm-opt-transformer'; @@ -64,7 +65,7 @@ import * as utils from './utils'; export class BaseCompiler { public compiler: any; - public lang: CELanguage; + public lang: Language; protected compileFilename: string; protected env: any; protected compilerProps: (key: string, defaultValue?: string) => string; diff --git a/lib/handlers/route-api.js b/lib/handlers/route-api.js index 106061a51..01d3dd743 100644 --- a/lib/handlers/route-api.js +++ b/lib/handlers/route-api.js @@ -186,7 +186,7 @@ export class RouteAPI { filterCode(req, code, lang) { let lines = code.split('\n'); - if (lang.previewFilter) { + if (lang.previewFilter !== null) { lines = lines.filter(line => !lang.previewFilter.test(line)); } return lines.map(line => this.escapeLine(req, line)).join('\n'); diff --git a/lib/languages.js b/lib/languages.ts similarity index 70% rename from lib/languages.js rename to lib/languages.ts index c8c3b484f..53bac98de 100644 --- a/lib/languages.js +++ b/lib/languages.ts @@ -27,239 +27,21 @@ import path from 'path'; import fs from 'fs-extra'; import _ from 'underscore'; -/*** - * TODO: Use the types/languages once available - * Language object type - * - * @typedef {Object} CELanguage - * @property {string} id - Id of language. Added programmatically based on CELanguages key - * @property {string} name - UI display name of the language - * @property {string} monaco - Monaco Editor language ID (Selects which language Monaco will use to highlight the code) - * @property {string[]} extensions - Usual extensions associated with the language. First one is used as file input etx - * @property {string[]} alias - Different ways in which we can also refer to this language - * @property {string} [formatter] - Format API name to use (See https://godbolt.org/api/formats) - * @property {boolean} supportsExecute - Whether there's at least 1 compiler in this language that supportsExecute - */ +import {LanguageKey, Language} from '../types/languages.interfaces'; -/*** - * Currently supported languages on Compiler Explorer - * - * @typedef {Object.} CELanguages - */ +type DefKeys = 'name' | 'monaco' | 'extensions' | 'alias' | 'previewFilter' | 'formatter' | 'logoUrl' | 'logoUrlDark'; +type LanguageDefinition = Pick; -/*** - * Current supported languages - * @type {CELanguages} - */ -export const languages = { +const definitions: Record = { 'c++': { name: 'C++', monaco: 'cppp', extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c', '.cc', '.ixx'], alias: ['gcc', 'cpp'], - previewFilter: /^\s*#include/, + logoUrl: 'c++.svg', + logoUrlDark: null, formatter: 'clangformat', - logoUrl: 'c++.svg', - }, - llvm: { - name: 'LLVM IR', - monaco: 'llvm-ir', - extensions: ['.ll'], - alias: [], - logoUrl: 'llvm.png', - }, - mlir: { - name: 'MLIR', - monaco: 'mlir', - extensions: ['.mlir'], - alias: [], - logoUrl: 'mlir.svg', - monacoDisassembly: 'mlir', - }, - cppx: { - name: 'Cppx', - monaco: 'cppp', - extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], - alias: [], previewFilter: /^\s*#include/, - logoUrl: 'c++.svg', - }, - cppx_gold: { - name: 'Cppx-Gold', - monaco: 'cppx-gold', - extensions: ['.usyntax', '.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], - alias: [], - logoUrl: 'c++.svg', // TODO: Find a better alternative - }, - cppx_blue: { - name: 'Cppx-Blue', - monaco: 'cppx-blue', - extensions: ['.blue', '.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], - alias: [], - logoUrl: 'c++.svg', // TODO: Find a better alternative - }, - c: { - name: 'C', - monaco: 'nc', - extensions: ['.c', '.h'], - alias: [], - previewFilter: /^\s*#include/, - logoUrl: 'c.svg', - }, - openclc: { - name: 'OpenCL C', - monaco: 'openclc', - extensions: ['.cl', '.ocl'], - alias: [], - logoUrl: 'opencl.svg', - logoUrlDark: 'opencl-dark.svg', - }, - cpp_for_opencl: { - name: 'C++ for OpenCL', - monaco: 'cpp-for-opencl', - extensions: ['.clcpp', '.cl', '.ocl'], - alias: [], - logoUrl: 'opencl.svg', // TODO: Find a better alternative - logoUrlDark: 'opencl-dark.svg', - }, - rust: { - name: 'Rust', - monaco: 'rust', - extensions: ['.rs'], - alias: [], - formatter: 'rustfmt', - logoUrl: 'rust.svg', - logoUrlDark: 'rust-dark.svg', - }, - d: { - name: 'D', - monaco: 'd', - extensions: ['.d'], - alias: [], - logoUrl: 'd.svg', - }, - erlang: { - name: 'Erlang', - monaco: 'erlang', - extensions: ['.erl', '.hrl'], - alias: [], - logoUrl: 'erlang.svg', - }, - go: { - name: 'Go', - monaco: 'go', - extensions: ['.go'], - alias: [], - logoUrl: 'go.svg', - }, - ispc: { - name: 'ispc', - monaco: 'ispc', - extensions: ['.ispc'], - alias: [], - logoUrl: 'ispc.png', - }, - haskell: { - name: 'Haskell', - monaco: 'haskell', - extensions: ['.hs', '.haskell'], - alias: [], - logoUrl: 'haskell.png', - }, - java: { - name: 'Java', - monaco: 'java', - extensions: ['.java'], - alias: [], - logoUrl: 'java.svg', - }, - kotlin: { - name: 'Kotlin', - monaco: 'kotlin', - extensions: ['.kt'], - alias: [], - logoUrl: 'kotlin.png', - }, - scala: { - name: 'Scala', - monaco: 'scala', - extensions: ['.scala'], - alias: [], - logoUrl: 'scala.png', - }, - ocaml: { - name: 'OCaml', - monaco: 'ocaml', - extensions: ['.ml', '.mli'], - alias: [], - logoUrl: 'ocaml.svg', - }, - python: { - name: 'Python', - monaco: 'python', - extensions: ['.py'], - alias: [], - logoUrl: 'python.svg', - }, - swift: { - name: 'Swift', - monaco: 'swift', - extensions: ['.swift'], - alias: [], - logoUrl: 'swift.svg', - }, - pascal: { - name: 'Pascal', - monaco: 'pascal', - extensions: ['.pas', '.dpr'], - alias: [], - logoUrl: 'pascal.svg', // TODO: Find a better alternative - logoUrlDark: 'pascal-dark.svg', - }, - fortran: { - id: 'fortran', - name: 'Fortran', - monaco: 'fortran', - extensions: ['.f90', '.F90', '.f95', '.F95', '.f'], - alias: [], - logoUrl: 'fortran.svg', - }, - assembly: { - name: 'Assembly', - monaco: 'asm', - extensions: ['.asm', '.6502'], - alias: ['asm'], - logoUrl: 'assembly.png', // TODO: Find a better alternative - }, - analysis: { - name: 'Analysis', - monaco: 'asm', - extensions: ['.asm'], // maybe add more? Change to a unique one? - alias: ['tool', 'tools'], - logoUrl: 'analysis.png', // TODO: Find a better alternative - }, - cuda: { - name: 'CUDA C++', - monaco: 'cuda', - extensions: ['.cu'], - alias: ['nvcc'], - monacoDisassembly: 'ptx', - logoUrl: 'cuda.svg', - logoUrlDark: 'cuda-dark.svg', - }, - zig: { - name: 'Zig', - monaco: 'zig', - extensions: ['.zig'], - alias: [], - logoUrl: 'zig.svg', - }, - clean: { - name: 'Clean', - monaco: 'clean', - extensions: ['.icl'], - alias: [], - logoUrl: 'clean.svg', // TODO: Find a better alternative }, ada: { name: 'Ada', @@ -268,21 +50,38 @@ export const languages = { alias: [], logoUrl: 'ada.svg', logoUrlDark: 'ada-dark.svg', + formatter: null, + previewFilter: null, }, - nim: { - name: 'Nim', - monaco: 'nim', - extensions: ['.nim'], - alias: [], - logoUrl: 'nim.svg', + analysis: { + name: 'Analysis', + monaco: 'asm', + extensions: ['.asm'], // maybe add more? Change to a unique one? + alias: ['tool', 'tools'], + logoUrl: 'analysis.png', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, + previewFilter: null, }, - crystal: { - name: 'Crystal', - monaco: 'crystal', - extensions: ['.cr'], + assembly: { + name: 'Assembly', + monaco: 'asm', + extensions: ['.asm', '.6502'], + alias: ['asm'], + logoUrl: 'assembly.png', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + c: { + name: 'C', + monaco: 'nc', + extensions: ['.c', '.h'], alias: [], - logoUrl: 'crystal.svg', - logoUrlDark: 'crystal-dark.svg', + logoUrl: 'c.svg', + logoUrlDark: null, + formatter: 'clangformat', + previewFilter: /^\s*#include/, }, circle: { name: 'C++ (Circle)', @@ -291,14 +90,18 @@ export const languages = { alias: [], previewFilter: /^\s*#include/, logoUrl: 'c++.svg', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, }, - ruby: { - name: 'Ruby', - monaco: 'ruby', - extensions: ['.rb'], + clean: { + name: 'Clean', + monaco: 'clean', + extensions: ['.icl'], alias: [], - monacoDisassembly: 'asmruby', - logoUrl: 'ruby.svg', + logoUrl: 'clean.svg', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, + previewFilter: null, }, cmake: { name: 'CMake', @@ -306,6 +109,69 @@ export const languages = { extensions: ['.txt'], alias: [], logoUrl: 'cmake.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + cpp_for_opencl: { + name: 'C++ for OpenCL', + monaco: 'cpp-for-opencl', + extensions: ['.clcpp', '.cl', '.ocl'], + alias: [], + logoUrl: 'opencl.svg', // TODO: Find a better alternative + logoUrlDark: 'opencl-dark.svg', + formatter: null, + previewFilter: null, + }, + mlir: { + name: 'MLIR', + monaco: 'mlir', + extensions: ['.mlir'], + alias: [], + logoUrl: 'mlir.svg', + formatter: null, + logoUrlDark: null, + previewFilter: null, + }, + cppx: { + name: 'Cppx', + monaco: 'cppp', + extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], + alias: [], + logoUrl: 'c++.svg', + logoUrlDark: null, + formatter: null, + previewFilter: /^\s*#include/, + }, + cppx_blue: { + name: 'Cppx-Blue', + monaco: 'cppx-blue', + extensions: ['.blue', '.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], + alias: [], + logoUrl: 'c++.svg', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + cppx_gold: { + name: 'Cppx-Gold', + monaco: 'cppx-gold', + extensions: ['.usyntax', '.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'], + alias: [], + logoUrl: 'c++.svg', // TODO: Find a better alternative + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + crystal: { + name: 'Crystal', + monaco: 'crystal', + extensions: ['.cr'], + alias: [], + logoUrl: 'crystal.svg', + logoUrlDark: 'crystal-dark.svg', + formatter: null, + previewFilter: null, }, csharp: { name: 'C#', @@ -313,6 +179,59 @@ export const languages = { extensions: ['.cs'], alias: [], logoUrl: 'dotnet.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + cuda: { + name: 'CUDA C++', + monaco: 'cuda', + extensions: ['.cu'], + alias: ['nvcc'], + logoUrl: 'cuda.svg', + logoUrlDark: 'cuda-dark.svg', + formatter: null, + previewFilter: null, + }, + d: { + name: 'D', + monaco: 'd', + extensions: ['.d'], + alias: [], + logoUrl: 'd.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + dart: { + name: 'Dart', + monaco: 'dart', + extensions: ['.dart'], + alias: [], + logoUrl: 'dart.svg', + logoUrlDark: null, + formatter: 'dartformat', + previewFilter: null, + }, + erlang: { + name: 'Erlang', + monaco: 'erlang', + extensions: ['.erl', '.hrl'], + alias: [], + logoUrl: 'erlang.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + fortran: { + name: 'Fortran', + monaco: 'fortran', + extensions: ['.f90', '.F90', '.f95', '.F95', '.f'], + alias: [], + logoUrl: 'fortran.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, fsharp: { name: 'F#', @@ -320,28 +239,149 @@ export const languages = { extensions: ['.fs'], alias: [], logoUrl: 'fsharp.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, - vb: { - name: 'Visual Basic', - monaco: 'vb', - extensions: ['.vb'], + go: { + name: 'Go', + monaco: 'go', + extensions: ['.go'], alias: [], - logoUrl: 'dotnet.svg', + logoUrl: 'go.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, - dart: { - name: 'Dart', - monaco: 'dart', - extensions: ['.dart'], + haskell: { + name: 'Haskell', + monaco: 'haskell', + extensions: ['.hs', '.haskell'], alias: [], - formatter: 'dartformat', - logoUrl: 'dart.svg', + logoUrl: 'haskell.png', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, - typescript: { - name: 'TypeScript Native', - monaco: 'typescript', - extensions: ['.ts', '.d.ts'], + ispc: { + name: 'ispc', + monaco: 'ispc', + extensions: ['.ispc'], alias: [], - logoUrl: 'ts.svg', + logoUrl: 'ispc.png', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + java: { + name: 'Java', + monaco: 'java', + extensions: ['.java'], + alias: [], + logoUrl: 'java.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + kotlin: { + name: 'Kotlin', + monaco: 'kotlin', + extensions: ['.kt'], + alias: [], + logoUrl: 'kotlin.png', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + llvm: { + name: 'LLVM IR', + monaco: 'llvm-ir', + extensions: ['.ll'], + alias: [], + logoUrl: 'llvm.png', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + nim: { + name: 'Nim', + monaco: 'nim', + extensions: ['.nim'], + alias: [], + logoUrl: 'nim.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + ocaml: { + name: 'OCaml', + monaco: 'ocaml', + extensions: ['.ml', '.mli'], + alias: [], + logoUrl: 'ocaml.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + openclc: { + name: 'OpenCL C', + monaco: 'openclc', + extensions: ['.cl', '.ocl'], + alias: [], + logoUrl: 'opencl.svg', + logoUrlDark: 'opencl-dark.svg', + formatter: null, + previewFilter: null, + }, + pascal: { + name: 'Pascal', + monaco: 'pascal', + extensions: ['.pas', '.dpr'], + alias: [], + logoUrl: 'pascal.svg', // TODO: Find a better alternative + logoUrlDark: 'pascal-dark.svg', + formatter: null, + previewFilter: null, + }, + python: { + name: 'Python', + monaco: 'python', + extensions: ['.py'], + alias: [], + logoUrl: 'python.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + ruby: { + name: 'Ruby', + monaco: 'ruby', + extensions: ['.rb'], + alias: [], + logoUrl: 'ruby.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + rust: { + name: 'Rust', + monaco: 'rust', + extensions: ['.rs'], + alias: [], + logoUrl: 'rust.svg', + logoUrlDark: 'rust-dark.svg', + formatter: 'rustfmt', + previewFilter: null, + }, + scala: { + name: 'Scala', + monaco: 'scala', + extensions: ['.scala'], + alias: [], + logoUrl: 'scala.png', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, solidity: { name: 'Solidity', @@ -349,15 +389,65 @@ export const languages = { extensions: ['.sol'], alias: [], logoUrl: 'solidity.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + swift: { + name: 'Swift', + monaco: 'swift', + extensions: ['.swift'], + alias: [], + logoUrl: 'swift.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + typescript: { + name: 'TypeScript Native', + monaco: 'typescript', + extensions: ['.ts', '.d.ts'], + alias: [], + logoUrl: 'ts.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + vb: { + name: 'Visual Basic', + monaco: 'vb', + extensions: ['.vb'], + alias: [], + logoUrl: 'dotnet.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, + }, + zig: { + name: 'Zig', + monaco: 'zig', + extensions: ['.zig'], + alias: [], + logoUrl: 'zig.svg', + logoUrlDark: null, + formatter: null, + previewFilter: null, }, }; -_.each(languages, (lang, key) => { - lang.id = key; - lang.supportsExecute = false; +export const languages: Record = _.mapObject(definitions, (lang, key) => { + let example: string; try { - lang.example = fs.readFileSync(path.join('examples', lang.id, 'default' + lang.extensions[0]), 'utf8'); + example = fs.readFileSync(path.join('examples', key, 'default' + lang.extensions[0]), 'utf8'); } catch (error) { - lang.example = 'Oops, something went wrong and we could not get the default code for this language.'; + example = 'Oops, something went wrong and we could not get the default code for this language.'; } + + const def: Language = { + ...lang, + id: key as LanguageKey, + supportsExecute: false, + example, + }; + return def; }); diff --git a/static/main.js b/static/main.js index 27dbbdc91..798d8d1ae 100644 --- a/static/main.js +++ b/static/main.js @@ -464,7 +464,7 @@ function setupLanguageLogos(languages) { function (lang) { try { lang.logoData = logos('./' + lang.logoUrl); - if (lang.logoUrlDark) { + if (lang.logoUrlDark !== null) { lang.logoDataDark = logos('./' + lang.logoUrlDark); } } catch (ignored) { diff --git a/static/panes/compiler.js b/static/panes/compiler.js index 13d4f6c31..56215d3e3 100644 --- a/static/panes/compiler.js +++ b/static/panes/compiler.js @@ -128,9 +128,19 @@ function Compiler(hub, container, state) { this.initButtons(state); var monacoDisassembly = 'asm'; - if (languages[this.currentLangId] && languages[this.currentLangId].monacoDisassembly) { - // TODO: If languages[this.currentLangId] is not valid, something went wrong. Find out what - monacoDisassembly = languages[this.currentLangId].monacoDisassembly; + // Bandaid fix to not have to include monacoDisassembly everywhere in languages.js + if (languages[this.currentLangId]) { + switch (languages[this.currentLangId].id) { + case 'cuda': + monacoDisassembly = 'ptx'; + break; + case 'ruby': + monacoDisassembly = 'asmruby'; + break; + case 'mlir': + monacoDisassembly = 'mlir'; + break; + } } this.outputEditor = monaco.editor.create( diff --git a/test/unfurl-tests.js b/test/unfurl-tests.js index 1bf2eee4a..9c2045072 100644 --- a/test/unfurl-tests.js +++ b/test/unfurl-tests.js @@ -62,6 +62,7 @@ describe('Basic unfurls', () => { languages: { 'c++': { name: 'C++', + previewFilter: null, }, }, compilers: [], @@ -90,6 +91,7 @@ describe('Basic unfurls', () => { languages: { 'c++': { name: 'C++', + previewFilter: null, }, }, compilers: [], @@ -119,6 +121,7 @@ describe('Basic unfurls', () => { languages: { 'c++': { name: 'C++', + previewFilter: null, }, }, compilers: [], diff --git a/types/languages.interfaces.ts b/types/languages.interfaces.ts index a0446a487..591900467 100644 --- a/types/languages.interfaces.ts +++ b/types/languages.interfaces.ts @@ -22,19 +22,68 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -export type Language = { - // ID of language. Added programmatically based on CELanguages key - id: string; - // UI display name of the language +export type LanguageKey = + | 'mlir' + | 'c++' + | 'llvm' + | 'cppx' + | 'cppx_gold' + | 'cppx_blue' + | 'c' + | 'openclc' + | 'cpp_for_opencl' + | 'rust' + | 'd' + | 'erlang' + | 'go' + | 'ispc' + | 'haskell' + | 'java' + | 'kotlin' + | 'scala' + | 'ocaml' + | 'python' + | 'swift' + | 'pascal' + | 'fortran' + | 'assembly' + | 'analysis' + | 'cuda' + | 'zig' + | 'clean' + | 'ada' + | 'nim' + | 'crystal' + | 'circle' + | 'ruby' + | 'cmake' + | 'csharp' + | 'fsharp' + | 'vb' + | 'dart' + | 'typescript' + | 'solidity'; + +export interface Language { + /** Id of language. Added programmatically based on CELanguages key */ + id: LanguageKey; + /** UI display name of the language */ name: string; - // Monaco Editor language ID (Selects which language Monaco will use to highlight the code) + /** Monaco Editor language ID (Selects which language Monaco will use to highlight the code) */ monaco: string; - // Usual extensions associated with the language. First one is used as file input etx - extensions: string[]; - // Different ways in which we can also refer to this language + /** Usual extensions associated with the language. First one is used as file input extension */ + extensions: [string, ...string[]]; + /** Different ways in which we can also refer to this language */ alias: string[]; - // Format API name to use (See https://godbolt.org/api/formats) + /** Format API name to use (See https://godbolt.org/api/formats) */ formatter: string | null; - // Whether there's at least 1 compiler in this language that supportsExecute + /** Whether there's at least 1 compiler in this language that supportsExecute */ supportsExecute: boolean | null; + /** Path in /views/resources/logos to the logo of the language */ + logoUrl: string; + /** Path in /views/resources/logos to the logo of the language for dark mode use */ + logoUrlDark: string | null; + /** Example code to show in the language's editor */ + example: string; + previewFilter: RegExp | null; };