diff --git a/.agents/skills/livecodes/language-support/references/languages.md b/.agents/skills/livecodes/language-support/references/languages.md
index 66a48dcb2f..1fa694624d 100644
--- a/.agents/skills/livecodes/language-support/references/languages.md
+++ b/.agents/skills/livecodes/language-support/references/languages.md
@@ -123,6 +123,7 @@ Enabled via `processors` config:
| C++ (Wasm) | `cpp-wasm`, `clang`, `wasm.cpp` | Clang WASM |
| Objective-C | `objc-wasm`, `objc`, `wasm.m` | Clang WASM |
| Objective-C++ | `objcpp-wasm`, `objcpp`, `wasm.mm` | Clang WASM |
+| COBOL (Wasm) | `cobol-wasm`, `cobol`, `cob`, `cbl`, `cpy`, `gnucobol`, `wasm.cobol` | GnuCOBOL (COBOL -> WASM) |
| Java | `java` | Java runtime |
| C# | `csharp-wasm`, `cs`, `cs-wasm`, `wasm.cs` | C# WASM |
| Blazor (Wasm) | `blazor-wasm`, `blazor`, `razor`, `razor-wasm`, `wasm.razor` | Razor components rendered by Blazor (WASM) |
diff --git a/README.md b/README.md
index 8cc8a1d294..08af338fb2 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ A [feature-rich](https://livecodes.io/docs/features/), open-source, **client-sid
[](https://www.npmjs.com/package/livecodes)
[](https://www.npmjs.com/package/livecodes)
[](https://www.jsdelivr.com/package/npm/livecodes)
-[](https://livecodes.io/docs/languages/)
+[](https://livecodes.io/docs/languages/)
[](https://livecodes.io/docs/)
[](https://livecodes.io/docs/llms.txt)
[](https://livecodes.io/docs/llms-full.txt)
diff --git a/docs/docs/languages/cobol-wasm.mdx b/docs/docs/languages/cobol-wasm.mdx
new file mode 100644
index 0000000000..cfb79696ef
--- /dev/null
+++ b/docs/docs/languages/cobol-wasm.mdx
@@ -0,0 +1,156 @@
+# COBOL (Wasm)
+
+COBOL is a compiled, imperative programming language designed for business data processing.
+
+COBOL in LiveCodes is compiled to WebAssembly by the real [GnuCOBOL](https://gnucobol.sourceforge.io/)
+compiler and run in the browser, with no server. The toolchain translates COBOL to C, compiles that
+with Clang, links `libcob`, and runs the resulting WebAssembly module.
+
+## Usage
+
+Demo:
+
+import LiveCodes from '../../src/components/LiveCodes.tsx';
+
+export const cobolConfig = {
+ activeEditor: 'script',
+ script: {
+ language: 'cobol-wasm',
+ content: `IDENTIFICATION DIVISION.
+PROGRAM-ID. HELLO-WORLD.
+PROCEDURE DIVISION.
+ DISPLAY "Hello, World!".
+ STOP RUN.`,
+ },
+ mode: 'simple',
+ editor: 'auto',
+ tools: {
+ status: 'full',
+ },
+};
+
+
+
+### Communication with JavaScript
+
+The program runs in the context of the result page. A few helpers are available in the browser global
+`livecodes.cobol` object:
+
+- `livecodes.cobol.input`: the standard input passed to the program.
+- `livecodes.cobol.loaded`: a promise that resolves when the compiler has downloaded and the program
+ has run, and rejects if the toolchain fails to load. Other helpers should be used after it resolves.
+- `livecodes.cobol.output`: the program's output (stdout and stderr combined).
+- `livecodes.cobol.error`: the compiler diagnostics, if the code failed to compile.
+- `livecodes.cobol.exitCode`: the exit code of the program.
+- `livecodes.cobol.run`: compiles and runs the code again with new input, returning a promise that
+ resolves with `output`, `error` and `exitCode`.
+
+Example:
+
+
+
+```cobol
+IDENTIFICATION DIVISION.
+PROGRAM-ID. HELLO-WORLD.
+PROCEDURE DIVISION.
+ DISPLAY "Hello, World!".
+ STOP RUN.
+```
+
+`ACCEPT` reads from the **stdin** pane, in the same way as the other console languages:
+
+```cobol
+IDENTIFICATION DIVISION.
+PROGRAM-ID. GREET.
+DATA DIVISION.
+WORKING-STORAGE SECTION.
+01 WS-NAME PIC X(20).
+PROCEDURE DIVISION.
+ ACCEPT WS-NAME
+ DISPLAY "Hello, " WS-NAME
+ STOP RUN.
+```
+
+## Language Info
+
+### Name
+
+`cobol-wasm`
+
+### Aliases / Extensions
+
+`cobol`, `cob`, `cbl`, `cpy`, `gnucobol`, `wasm.cobol`
+
+### Editor
+
+`script`
+
+## Compiler
+
+[GnuCOBOL](https://gnucobol.sourceforge.io/) 3.2 compiled to WebAssembly, with Clang and LLD for the
+generated C.
+
+### Custom Settings
+
+The GnuCOBOL compiler can be configured through the `customSettings` object, under the `cobol-wasm`
+key. The following options are supported:
+
+- `sourceFormat`: the COBOL source format, `free` (the default) or `fixed`.
+- `compileArgs`: extra GnuCOBOL (`cobc`) flags.
+- `cCompileArgs`: extra Clang flags for the generated C.
+- `args`: the program's command-line arguments.
+- `fileName`: the name the source is compiled under (`main.cob` by default).
+
+Example:
+
+```js
+const config = {
+ activeEditor: 'script',
+ script: {
+ language: 'cobol-wasm',
+ content: '...',
+ },
+ customSettings: {
+ 'cobol-wasm': {
+ sourceFormat: 'fixed',
+ },
+ },
+};
+```
+
+## Code Formatting
+
+Not currently supported.
+
+## Live Reload
+
+By default, new code changes are sent to the result page for re-evaluation without a full page reload. This behavior can be disabled by adding the code comment `*> __livecodes_reload__` to the COBOL code, which forces a full page reload.
+
+This comment can be added in the [`hiddenContent` property of the editor](../configuration/configuration-object.mdx#markup) for embedded playgrounds.
+
+## Example Usage
+
+```cobol
+IDENTIFICATION DIVISION.
+PROGRAM-ID. INVOICE.
+DATA DIVISION.
+WORKING-STORAGE SECTION.
+01 WS-RATE PIC 9(3)V99 VALUE 25.50.
+01 WS-HOURS PIC 9(3) VALUE 40.
+01 WS-PAY PIC 9(5)V99.
+PROCEDURE DIVISION.
+ COMPUTE WS-PAY = WS-RATE * WS-HOURS
+ DISPLAY "Rate: " WS-RATE
+ DISPLAY "Pay: " WS-PAY
+ STOP RUN.
+```
+
+## Starter Template
+
+https://livecodes.io/?template=cobol-wasm
+
+## Links
+
+- [GnuCOBOL](https://gnucobol.sourceforge.io/)
+- [Learn X in Y minutes, where X=COBOL](https://learnxinyminutes.com/docs/cobol/)
+- [@live-codes/cobol-wasm](https://www.npmjs.com/package/@live-codes/cobol-wasm)
diff --git a/docs/src/components/LanguageSliders.tsx b/docs/src/components/LanguageSliders.tsx
index e87b4a218b..393d686d37 100644
--- a/docs/src/components/LanguageSliders.tsx
+++ b/docs/src/components/LanguageSliders.tsx
@@ -92,6 +92,7 @@ export default function Sliders() {
{ name: 'cpp-wasm', title: 'C++ (Wasm)' },
{ name: 'objc-wasm', title: 'Objective-C (Wasm)' },
{ name: 'objcpp-wasm', title: 'Objective-C++ (Wasm)' },
+ { name: 'cobol-wasm', title: 'COBOL (Wasm)' },
{ name: 'fortran', title: 'Fortran' },
{ name: 'rust-wasm', title: 'Rust (Wasm)' },
{ name: 'swift-wasm', title: 'Swift (Wasm)' },
diff --git a/docs/src/components/TemplateList.tsx b/docs/src/components/TemplateList.tsx
index 16e56b01d9..9703d55ab2 100644
--- a/docs/src/components/TemplateList.tsx
+++ b/docs/src/components/TemplateList.tsx
@@ -48,6 +48,7 @@ const templates = [
{ name: 'php-wasm', title: 'PHP (Wasm) Starter', thumbnail: 'php.svg' },
{ name: 'cpp', title: 'C++ Starter', thumbnail: 'cpp.svg' },
{ name: 'c-wasm', title: 'C (Wasm) Starter', thumbnail: 'c.svg' },
+ { name: 'cobol-wasm', title: 'COBOL Starter', thumbnail: 'cobol.svg' },
{ name: 'fortran-wasm', title: 'Fortran Starter', thumbnail: 'fortran.svg' },
{ name: 'cpp-wasm', title: 'C++ (Wasm) Starter', thumbnail: 'cpp.svg' },
{ name: 'objc-wasm', title: 'Objective-C (Wasm) Starter', thumbnail: 'objective-c.svg' },
diff --git a/functions/vendors/templates.js b/functions/vendors/templates.js
index 347939811e..9834c0e64d 100644
--- a/functions/vendors/templates.js
+++ b/functions/vendors/templates.js
@@ -50,6 +50,7 @@ export const starterTemplates = {
"c-wasm": "C (Wasm) Starter",
"cpp-wasm": "C++ (Wasm) Starter",
"objc-wasm": "Objective-C (Wasm) Starter",
+ "cobol-wasm": "COBOL Starter",
"fortran-wasm": "Fortran Starter",
"rust-wasm": "Rust (Wasm) Starter",
"swift-wasm": "Swift (Wasm) Starter",
diff --git a/scripts/build.js b/scripts/build.js
index 81a0f32183..cc79d610e3 100644
--- a/scripts/build.js
+++ b/scripts/build.js
@@ -229,6 +229,7 @@ const iifeBuild = () =>
'languages/cpp/lang-cpp-script.ts',
'languages/clang-wasm/lang-clang-wasm-script.ts',
'languages/fortran-wasm/lang-fortran-wasm-script.ts',
+ 'languages/cobol-wasm/lang-cobol-wasm-script.ts',
'languages/go-wasm/lang-go-wasm-script.ts',
'languages/csharp-wasm/lang-csharp-wasm-script.ts',
'languages/fanak/lang-fanak-script.ts',
diff --git a/server/php/inc/starter-templates.json b/server/php/inc/starter-templates.json
index cfa96c36b4..63b164e539 100644
--- a/server/php/inc/starter-templates.json
+++ b/server/php/inc/starter-templates.json
@@ -50,6 +50,7 @@
"c-wasm": "C (Wasm) Starter",
"cpp-wasm": "C++ (Wasm) Starter",
"objc-wasm": "Objective-C (Wasm) Starter",
+ "cobol-wasm": "COBOL Starter",
"fortran-wasm": "Fortran Starter",
"rust-wasm": "Rust (Wasm) Starter",
"swift-wasm": "Swift (Wasm) Starter",
diff --git a/src/livecodes/UI/command-menu-actions.ts b/src/livecodes/UI/command-menu-actions.ts
index d03bd476f2..a088cf673c 100644
--- a/src/livecodes/UI/command-menu-actions.ts
+++ b/src/livecodes/UI/command-menu-actions.ts
@@ -306,6 +306,7 @@ export const getCommandMenuActions = ({
'c-wasm',
'cpp-wasm',
'objc-wasm',
+ 'cobol-wasm',
'fortran-wasm',
'rust-wasm',
'swift-wasm',
diff --git a/src/livecodes/assets/templates/cobol.svg b/src/livecodes/assets/templates/cobol.svg
new file mode 100644
index 0000000000..e37313d773
--- /dev/null
+++ b/src/livecodes/assets/templates/cobol.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/livecodes/html/language-info.html b/src/livecodes/html/language-info.html
index f9f9713781..843afed019 100644
--- a/src/livecodes/html/language-info.html
+++ b/src/livecodes/html/language-info.html
@@ -423,6 +423,36 @@
CLJS (self-hosted)
+
+ COBOL (Wasm)
+
+ COBOL compiled to WebAssembly by the real
+
GnuCOBOL compiler,
+ running entirely in the browser.
+
+
+
CoffeeScript
Unfancy JavaScript.
diff --git a/src/livecodes/i18n/locales/ar/language-info.lokalise.json b/src/livecodes/i18n/locales/ar/language-info.lokalise.json
index 74d4ff58b6..9cffd85e61 100644
--- a/src/livecodes/i18n/locales/ar/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ar/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " الموقع الرسمي لـ ClojureScript الموقع الرسمي لـ Clojure مستودع Cherry تعلم X في Y دقائق، حيث X=clojure وثائق LiveCodes تحميل القالب الأولي "
},
+ "cobol-wasm.desc": {
+ "translation": "يتم تجميع COBOL الحديثة إلى WebAssembly بواسطة GnuCOBOL، وتعمل بالكامل داخل المتصفح."
+ },
+ "cobol-wasm.link": {
+ "translation": " الموقع الرسمي لـ GnuCOBOL تعلم X في Y دقيقة، حيث X = COBOL وثائق LiveCodes تحميل قالب البدء "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "جافاسكريبت بسيطة."
},
diff --git a/src/livecodes/i18n/locales/ar/language-info.ts b/src/livecodes/i18n/locales/ar/language-info.ts
index 0da8da1c90..a2838d9ca6 100644
--- a/src/livecodes/i18n/locales/ar/language-info.ts
+++ b/src/livecodes/i18n/locales/ar/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript هو مترجم لـ <1>Clojure1> يستهدف JavaScript. <2>2>في LiveCodes، يعمل في المتصفح باستخدام <3>Cherry3>.',
link: '<1> <2>الموقع الرسمي لـ ClojureScript2> 1> <3> <4>الموقع الرسمي لـ Clojure4> 3> <5> <6>مستودع Cherry6> 5> <7> <8>تعلم X في Y دقائق، حيث X=clojure8> 7> <9> <10>وثائق LiveCodes10> 9> <11> <12>تحميل القالب الأولي12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'يتم تجميع COBOL الحديثة إلى WebAssembly بواسطة <1>GnuCOBOL1>، وتعمل بالكامل داخل المتصفح.',
+ link: '<1> <2>الموقع الرسمي لـ GnuCOBOL2> 1> <3> <4>تعلم X في Y دقيقة، حيث X = COBOL4> 3> <5> <6>وثائق LiveCodes6> 5> <7> <8>تحميل قالب البدء8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'جافاسكريبت بسيطة.',
link: '<1> <2>الموقع الرسمي لـ CoffeeScript2> 1> <3> <4>تعلم X في Y دقائق، حيث X=coffeescript4> 3> <5> <6>تحميل القالب الأولي6> 5>',
diff --git a/src/livecodes/i18n/locales/ar/translation.lokalise.json b/src/livecodes/i18n/locales/ar/translation.lokalise.json
index a42cef5d1f..b59238f279 100644
--- a/src/livecodes/i18n/locales/ar/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ar/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "قالب ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "قالب COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "قالب CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/ar/translation.ts b/src/livecodes/i18n/locales/ar/translation.ts
index 62b9a1866a..b192d9ce38 100644
--- a/src/livecodes/i18n/locales/ar/translation.ts
+++ b/src/livecodes/i18n/locales/ar/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'قالب Clio',
'cljs-selfhosted': 'قالب CLJS (مستضاف ذاتيًا)',
clojurescript: 'قالب ClojureScript (Cherry)',
+ 'cobol-wasm': 'قالب COBOL',
coffeescript: 'قالب CoffeeScript',
commonlisp: 'قالب Common Lisp',
cpp: 'قالب C++',
diff --git a/src/livecodes/i18n/locales/bn/language-info.lokalise.json b/src/livecodes/i18n/locales/bn/language-info.lokalise.json
index 2209c6b338..637743f6a3 100644
--- a/src/livecodes/i18n/locales/bn/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/bn/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript অফিসিয়াল ওয়েবসাইট Clojure অফিসিয়াল ওয়েবসাইট Cherry রেপো Y মিনিটে X শিখুন, যেখানে X=clojure LiveCodes ডকুমেন্টেশন স্টার্টার টেমপ্লেট লোড করুন "
},
+ "cobol-wasm.desc": {
+ "translation": "আধুনিক COBOL GnuCOBOL দ্বারা WebAssembly-তে কম্পাইল করা হয় এবং সম্পূর্ণভাবে ব্রাউজারে চলে।"
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL অফিসিয়াল ওয়েবসাইট Y মিনিটে X শিখুন, যেখানে X=COBOL লাইভকোডস ডকুমেন্টেশন স্টার্টার টেমপ্লেট লোড করুন "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "সাধারণ JavaScript।"
},
diff --git a/src/livecodes/i18n/locales/bn/language-info.ts b/src/livecodes/i18n/locales/bn/language-info.ts
index e343eb9c07..29ab84cefd 100644
--- a/src/livecodes/i18n/locales/bn/language-info.ts
+++ b/src/livecodes/i18n/locales/bn/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript হলো <1>Clojure1>-এর জন্য একটি কম্পাইলার যা JavaScript লক্ষ্য করে। <2>2>LiveCodes-এ, এটি <3>Cherry3> ব্যবহার করে ব্রাউজারে চলে',
link: '<1> <2>ClojureScript অফিসিয়াল ওয়েবসাইট2> 1> <3> <4>Clojure অফিসিয়াল ওয়েবসাইট4> 3> <5> <6>Cherry রেপো6> 5> <7> <8>Y মিনিটে X শিখুন, যেখানে X=clojure8> 7> <9> <10>LiveCodes ডকুমেন্টেশন10> 9> <11> <12>স্টার্টার টেমপ্লেট লোড করুন12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'আধুনিক COBOL <1>GnuCOBOL1> দ্বারা WebAssembly-তে কম্পাইল করা হয় এবং সম্পূর্ণভাবে ব্রাউজারে চলে।',
+ link: '<1> <2>GnuCOBOL অফিসিয়াল ওয়েবসাইট2> 1> <3> <4>Y মিনিটে X শিখুন, যেখানে X=COBOL4> 3> <5> <6>লাইভকোডস ডকুমেন্টেশন6> 5> <7> <8>স্টার্টার টেমপ্লেট লোড করুন8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'সাধারণ JavaScript।',
link: '<1> <2>CoffeeScript অফিসিয়াল ওয়েবসাইট2> 1> <3> <4>Y মিনিটে X শিখুন, যেখানে X=coffeescript4> 3> <5> <6>স্টার্টার টেমপ্লেট লোড করুন6> 5>',
diff --git a/src/livecodes/i18n/locales/bn/translation.lokalise.json b/src/livecodes/i18n/locales/bn/translation.lokalise.json
index 04e292fb20..b42e2be2b0 100644
--- a/src/livecodes/i18n/locales/bn/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/bn/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry) স্টার্টার"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL স্টার্টার"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript স্টার্টার"
},
diff --git a/src/livecodes/i18n/locales/bn/translation.ts b/src/livecodes/i18n/locales/bn/translation.ts
index b903338c21..d562058e1c 100644
--- a/src/livecodes/i18n/locales/bn/translation.ts
+++ b/src/livecodes/i18n/locales/bn/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'Clio স্টার্টার',
'cljs-selfhosted': 'CLJS (স্ব-হোস্টেড) স্টার্টার',
clojurescript: 'ClojureScript (Cherry) স্টার্টার',
+ 'cobol-wasm': 'COBOL স্টার্টার',
coffeescript: 'CoffeeScript স্টার্টার',
commonlisp: 'Common Lisp স্টার্টার',
cpp: 'C++ স্টার্টার',
diff --git a/src/livecodes/i18n/locales/de/language-info.lokalise.json b/src/livecodes/i18n/locales/de/language-info.lokalise.json
index e76c371e75..0f40d74b57 100644
--- a/src/livecodes/i18n/locales/de/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/de/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript offizielle Website Clojure offizielle Website Cherry Repository Lerne X in Y Minuten, wobei X=clojure LiveCodes Dokumentation Starter-Vorlage laden "
},
+ "cobol-wasm.desc": {
+ "translation": "Modernes COBOL wird von GnuCOBOL nach WebAssembly kompiliert und läuft vollständig im Browser."
+ },
+ "cobol-wasm.link": {
+ "translation": " Offizielle Website von GnuCOBOL Lerne X in Y Minuten, wobei X = COBOL LiveCodes-Dokumentation Startervorlage laden "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "Schnörkelloses JavaScript."
},
diff --git a/src/livecodes/i18n/locales/de/language-info.ts b/src/livecodes/i18n/locales/de/language-info.ts
index a4adf884fb..c23d622d5d 100644
--- a/src/livecodes/i18n/locales/de/language-info.ts
+++ b/src/livecodes/i18n/locales/de/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript ist ein Compiler für <1>Clojure1>, der auf JavaScript abzielt. <2>2>In LiveCodes läuft es im Browser mit <3>Cherry3>.',
link: '<1> <2>ClojureScript offizielle Website2> 1> <3> <4>Clojure offizielle Website4> 3> <5> <6>Cherry Repository6> 5> <7> <8>Lerne X in Y Minuten, wobei X=clojure8> 7> <9> <10>LiveCodes Dokumentation10> 9> <11> <12>Starter-Vorlage laden12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'Modernes COBOL wird von <1>GnuCOBOL1> nach WebAssembly kompiliert und läuft vollständig im Browser.',
+ link: '<1> <2>Offizielle Website von GnuCOBOL2> 1> <3> <4>Lerne X in Y Minuten, wobei X = COBOL4> 3> <5> <6>LiveCodes-Dokumentation6> 5> <7> <8>Startervorlage laden8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'Schnörkelloses JavaScript.',
link: '<1> <2>CoffeeScript offizielle Website2> 1> <3> <4>Lerne X in Y Minuten, wobei X=coffeescript4> 3> <5> <6>Starter-Vorlage laden6> 5>',
diff --git a/src/livecodes/i18n/locales/de/translation.lokalise.json b/src/livecodes/i18n/locales/de/translation.lokalise.json
index 914ba2de33..77dcad0c02 100644
--- a/src/livecodes/i18n/locales/de/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/de/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry)-Starter"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL-Starter"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript-Starter"
},
diff --git a/src/livecodes/i18n/locales/de/translation.ts b/src/livecodes/i18n/locales/de/translation.ts
index 915f79adf4..70dda525df 100644
--- a/src/livecodes/i18n/locales/de/translation.ts
+++ b/src/livecodes/i18n/locales/de/translation.ts
@@ -992,6 +992,7 @@ const translation: I18nTranslation = {
clio: 'Clio-Starter',
'cljs-selfhosted': 'CLJS (selbst gehostet)-Starter',
clojurescript: 'ClojureScript (Cherry)-Starter',
+ 'cobol-wasm': 'COBOL-Starter',
coffeescript: 'CoffeeScript-Starter',
commonlisp: 'Common Lisp-Starter',
cpp: 'C++-Starter',
diff --git a/src/livecodes/i18n/locales/en/language-info.lokalise.json b/src/livecodes/i18n/locales/en/language-info.lokalise.json
index 987aaaa837..3aa9b19a7c 100644
--- a/src/livecodes/i18n/locales/en/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/en/language-info.lokalise.json
@@ -180,6 +180,18 @@
"notes": "### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n",
"translation": " ClojureScript official website Clojure official website Cherry repo Learn X in Y minutes, where X=clojure LiveCodes Documentations Load starter template "
},
+ "cobol-wasm.desc": {
+ "notes": "### ###\n\n\n",
+ "translation": "COBOL compiled to WebAssembly by the real GnuCOBOL compiler, running entirely in the browser."
+ },
+ "cobol-wasm.link": {
+ "notes": "### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n### ###\n\n\n",
+ "translation": " GnuCOBOL official website Learn X in Y minutes, where X=COBOL LiveCodes Documentation Load starter template "
+ },
+ "cobol-wasm.name": {
+ "notes": "",
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"notes": "",
"translation": "Unfancy JavaScript."
diff --git a/src/livecodes/i18n/locales/en/language-info.ts b/src/livecodes/i18n/locales/en/language-info.ts
index 0dc6d293bf..d1fd6417bd 100644
--- a/src/livecodes/i18n/locales/en/language-info.ts
+++ b/src/livecodes/i18n/locales/en/language-info.ts
@@ -87,6 +87,11 @@ const languageInfo = {
desc: 'ClojureScript is a compiler for <1>Clojure1> that targets JavaScript. <2>2>In LiveCodes, it runs in the browser using <3>Cherry3>',
link: '<1> <2>ClojureScript official website2> 1> <3> <4>Clojure official website4> 3> <5> <6>Cherry repo6> 5> <7> <8>Learn X in Y minutes, where X=clojure8> 7> <9> <10>LiveCodes Documentations10> 9> <11> <12>Load starter template12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL compiled to WebAssembly by the real <1>GnuCOBOL1> compiler, running entirely in the browser.',
+ link: '<1> <2>GnuCOBOL official website2> 1> <3> <4>Learn X in Y minutes, where X=COBOL4> 3> <5> <6>LiveCodes Documentation6> 5> <7> <8>Load starter template8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'Unfancy JavaScript.',
link: '<1> <2>CoffeeScript official website2> 1> <3> <4>Learn X in Y minutes, where X=coffeescript4> 3> <5> <6>Load starter template6> 5>',
diff --git a/src/livecodes/i18n/locales/en/translation.lokalise.json b/src/livecodes/i18n/locales/en/translation.lokalise.json
index e6f2d89824..d8d8ceb184 100644
--- a/src/livecodes/i18n/locales/en/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/en/translation.lokalise.json
@@ -2604,6 +2604,10 @@
"notes": "",
"translation": "ClojureScript (Cherry) Starter"
},
+ "templates.starter.cobol-wasm": {
+ "notes": "",
+ "translation": "COBOL Starter"
+ },
"templates.starter.coffeescript": {
"notes": "",
"translation": "CoffeeScript Starter"
diff --git a/src/livecodes/i18n/locales/en/translation.ts b/src/livecodes/i18n/locales/en/translation.ts
index 89958f0bde..ab7866dad1 100644
--- a/src/livecodes/i18n/locales/en/translation.ts
+++ b/src/livecodes/i18n/locales/en/translation.ts
@@ -997,6 +997,7 @@ const translation = {
clio: 'Clio Starter',
'cljs-selfhosted': 'CLJS (self-hosted) Starter',
clojurescript: 'ClojureScript (Cherry) Starter',
+ 'cobol-wasm': 'COBOL Starter',
coffeescript: 'CoffeeScript Starter',
commonlisp: 'Common Lisp Starter',
cpp: 'C++ Starter',
diff --git a/src/livecodes/i18n/locales/es/language-info.lokalise.json b/src/livecodes/i18n/locales/es/language-info.lokalise.json
index c4f43924b7..7b059552a3 100644
--- a/src/livecodes/i18n/locales/es/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/es/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Sitio web oficial de ClojureScript Sitio web oficial de Clojure Repositorio de Cherry Aprende X en Y minutos, donde X=clojure Documentación de LiveCodes Cargar plantilla inicial "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL moderno compilado a WebAssembly por GnuCOBOL, ejecutándose íntegramente en el navegador."
+ },
+ "cobol-wasm.link": {
+ "translation": " Página web oficial de GnuCOBOL Aprende X en Y minutos, donde X = COBOL Documentación de LiveCodes Cargar plantilla de inicio "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript sin complicaciones."
},
diff --git a/src/livecodes/i18n/locales/es/language-info.ts b/src/livecodes/i18n/locales/es/language-info.ts
index 1d3a0c5190..f4fe59abc5 100644
--- a/src/livecodes/i18n/locales/es/language-info.ts
+++ b/src/livecodes/i18n/locales/es/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript es un compilador para <1>Clojure1> que tiene como objetivo JavaScript. <2>2>En LiveCodes, se ejecuta en el navegador usando <3>Cherry3>.',
link: '<1> <2>Sitio web oficial de ClojureScript2> 1> <3> <4>Sitio web oficial de Clojure4> 3> <5> <6>Repositorio de Cherry6> 5> <7> <8>Aprende X en Y minutos, donde X=clojure8> 7> <9> <10>Documentación de LiveCodes10> 9> <11> <12>Cargar plantilla inicial12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL moderno compilado a WebAssembly por <1>GnuCOBOL1>, ejecutándose íntegramente en el navegador.',
+ link: '<1> <2>Página web oficial de GnuCOBOL2> 1> <3> <4>Aprende X en Y minutos, donde X = COBOL4> 3> <5> <6>Documentación de LiveCodes6> 5> <7> <8>Cargar plantilla de inicio8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript sin complicaciones.',
link: '<1> <2>Sitio web oficial de CoffeeScript2> 1> <3> <4>Aprende X en Y minutos, donde X=coffeescript4> 3> <5> <6>Cargar plantilla inicial6> 5>',
diff --git a/src/livecodes/i18n/locales/es/translation.lokalise.json b/src/livecodes/i18n/locales/es/translation.lokalise.json
index 29545a4464..7f94058ecc 100644
--- a/src/livecodes/i18n/locales/es/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/es/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Inicio ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Inicio COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Inicio CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/es/translation.ts b/src/livecodes/i18n/locales/es/translation.ts
index 97cabf6951..8c67cb6395 100644
--- a/src/livecodes/i18n/locales/es/translation.ts
+++ b/src/livecodes/i18n/locales/es/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'Inicio Clio',
'cljs-selfhosted': 'Inicio CLJS (autoalojado)',
clojurescript: 'Inicio ClojureScript (Cherry)',
+ 'cobol-wasm': 'Inicio COBOL',
coffeescript: 'Inicio CoffeeScript',
commonlisp: 'Inicio Common Lisp',
cpp: 'Inicio C++',
diff --git a/src/livecodes/i18n/locales/fa/language-info.lokalise.json b/src/livecodes/i18n/locales/fa/language-info.lokalise.json
index a64e8cd3c7..472c93c427 100644
--- a/src/livecodes/i18n/locales/fa/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/fa/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " وبسایت رسمی ClojureScript وبسایت رسمی Clojure مخزن Cherry یادگیری X در Y دقیقه، جایی که X=clojure مستندات LiveCodes بارگذاری قالب شروع کننده "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL مدرن توسط GnuCOBOL به WebAssembly کامپایل میشود و کاملاً در مرورگر اجرا میشود."
+ },
+ "cobol-wasm.link": {
+ "translation": " وبسایت رسمی GnuCOBOL یادگیری X در Y دقیقه، که X=COBOL مستندات لایوکدز بارگذاری قالب شروع "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "جاوااسکریپت ساده."
},
diff --git a/src/livecodes/i18n/locales/fa/language-info.ts b/src/livecodes/i18n/locales/fa/language-info.ts
index dea2e9dc89..277ffd09f0 100644
--- a/src/livecodes/i18n/locales/fa/language-info.ts
+++ b/src/livecodes/i18n/locales/fa/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript یک کامپایلر برای <1>Clojure1> است که JavaScript را هدف قرار میدهد. <2>2>در LiveCodes، با استفاده از <3>Cherry3> در مرورگر اجرا میشود',
link: '<1> <2>وبسایت رسمی ClojureScript2> 1> <3> <4>وبسایت رسمی Clojure4> 3> <5> <6>مخزن Cherry6> 5> <7> <8>یادگیری X در Y دقیقه، جایی که X=clojure8> 7> <9> <10>مستندات LiveCodes10> 9> <11> <12>بارگذاری قالب شروع کننده12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL مدرن توسط <1>GnuCOBOL1> به WebAssembly کامپایل میشود و کاملاً در مرورگر اجرا میشود.',
+ link: '<1> <2>وبسایت رسمی GnuCOBOL2> 1> <3> <4>یادگیری X در Y دقیقه، که X=COBOL4> 3> <5> <6>مستندات لایوکدز6> 5> <7> <8>بارگذاری قالب شروع8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'جاوااسکریپت ساده.',
link: '<1> <2>وبسایت رسمی CoffeeScript2> 1> <3> <4>یادگیری X در Y دقیقه، جایی که X=coffeescript4> 3> <5> <6>بارگذاری قالب شروع کننده6> 5>',
diff --git a/src/livecodes/i18n/locales/fa/translation.lokalise.json b/src/livecodes/i18n/locales/fa/translation.lokalise.json
index 344ad63c46..dc2bede4fd 100644
--- a/src/livecodes/i18n/locales/fa/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/fa/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "شروع کننده ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "شروع کننده COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "شروع کننده CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/fa/translation.ts b/src/livecodes/i18n/locales/fa/translation.ts
index f51ed44098..b59ac5b97e 100644
--- a/src/livecodes/i18n/locales/fa/translation.ts
+++ b/src/livecodes/i18n/locales/fa/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'شروع کننده Clio',
'cljs-selfhosted': 'شروع کننده CLJS (خودمیزبان)',
clojurescript: 'شروع کننده ClojureScript (Cherry)',
+ 'cobol-wasm': 'شروع کننده COBOL',
coffeescript: 'شروع کننده CoffeeScript',
commonlisp: 'شروع کننده Common Lisp',
cpp: 'شروع کننده C++',
diff --git a/src/livecodes/i18n/locales/fr/language-info.lokalise.json b/src/livecodes/i18n/locales/fr/language-info.lokalise.json
index 140c8026a2..a570fd3ec0 100644
--- a/src/livecodes/i18n/locales/fr/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/fr/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Site officiel de ClojureScript Site officiel de Clojure Dépôt Cherry Apprenez X en Y minutes, où X=clojure Documentations LiveCodes Charger le modèle de démarrage "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL moderne compilé en WebAssembly par GnuCOBOL, s'exécutant entièrement dans le navigateur."
+ },
+ "cobol-wasm.link": {
+ "translation": " Site officiel de GnuCOBOL Apprenez X en Y minutes, où X = COBOL Documentation LiveCodes Charger un modèle de démarrage "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript sans fioritures."
},
diff --git a/src/livecodes/i18n/locales/fr/language-info.ts b/src/livecodes/i18n/locales/fr/language-info.ts
index e9328b4798..5dbe8b80bf 100644
--- a/src/livecodes/i18n/locales/fr/language-info.ts
+++ b/src/livecodes/i18n/locales/fr/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: "ClojureScript est un compilateur pour <1>Clojure1> qui cible JavaScript. <2>2>Dans LiveCodes, il s'exécute dans le navigateur en utilisant <3>Cherry3>.",
link: '<1> <2>Site officiel de ClojureScript2> 1> <3> <4>Site officiel de Clojure4> 3> <5> <6>Dépôt Cherry6> 5> <7> <8>Apprenez X en Y minutes, où X=clojure8> 7> <9> <10>Documentations LiveCodes10> 9> <11> <12>Charger le modèle de démarrage12> 11>',
},
+ 'cobol-wasm': {
+ desc: "COBOL moderne compilé en WebAssembly par <1>GnuCOBOL1>, s'exécutant entièrement dans le navigateur.",
+ link: '<1> <2>Site officiel de GnuCOBOL2> 1> <3> <4>Apprenez X en Y minutes, où X = COBOL4> 3> <5> <6>Documentation LiveCodes6> 5> <7> <8>Charger un modèle de démarrage8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript sans fioritures.',
link: '<1> <2>Site officiel de CoffeeScript2> 1> <3> <4>Apprenez X en Y minutes, où X=coffeescript4> 3> <5> <6>Charger le modèle de démarrage6> 5>',
diff --git a/src/livecodes/i18n/locales/fr/translation.lokalise.json b/src/livecodes/i18n/locales/fr/translation.lokalise.json
index 4135e48ffd..8c6f6ee8cf 100644
--- a/src/livecodes/i18n/locales/fr/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/fr/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Démarrage ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Démarrage COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Démarrage CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/fr/translation.ts b/src/livecodes/i18n/locales/fr/translation.ts
index 6d083ee2b2..e4b42bf928 100644
--- a/src/livecodes/i18n/locales/fr/translation.ts
+++ b/src/livecodes/i18n/locales/fr/translation.ts
@@ -992,6 +992,7 @@ const translation: I18nTranslation = {
clio: 'Démarrage Clio',
'cljs-selfhosted': 'Démarrage CLJS (auto-hébergé)',
clojurescript: 'Démarrage ClojureScript (Cherry)',
+ 'cobol-wasm': 'Démarrage COBOL',
coffeescript: 'Démarrage CoffeeScript',
commonlisp: 'Démarrage Common Lisp',
cpp: 'Démarrage C++',
diff --git a/src/livecodes/i18n/locales/hi/language-info.lokalise.json b/src/livecodes/i18n/locales/hi/language-info.lokalise.json
index f280849b4d..6130a1afa4 100644
--- a/src/livecodes/i18n/locales/hi/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/hi/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript आधिकारिक वेबसाइट Clojure आधिकारिक वेबसाइट Cherry रेपो X को Y मिनटों में सीखें, जहां X=clojure LiveCodes दस्तावेज़ीकरण स्टार्टर टेम्पलेट लोड करें "
},
+ "cobol-wasm.desc": {
+ "translation": "आधुनिक COBOL को GnuCOBOL द्वारा WebAssembly में संकलित किया जाता है, जो पूरी तरह से ब्राउज़र में चलता है।"
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL आधिकारिक वेबसाइट Y मिनट में X सीखें, जहाँ X=COBOL लाइवकोड्स दस्तावेज़ीकरण स्टार्टर टेम्पलेट लोड करें "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "सरल जावास्क्रिप्ट।"
},
diff --git a/src/livecodes/i18n/locales/hi/language-info.ts b/src/livecodes/i18n/locales/hi/language-info.ts
index 2f6cb47781..6378e336ef 100644
--- a/src/livecodes/i18n/locales/hi/language-info.ts
+++ b/src/livecodes/i18n/locales/hi/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript <1>Clojure1> के लिए एक कंपाइलर है जो JavaScript को लक्षित करता है। <2>2>LiveCodes में, यह ब्राउज़र में <3>Cherry3> का उपयोग करके चलता है।',
link: '<1> <2>ClojureScript आधिकारिक वेबसाइट2> 1> <3> <4>Clojure आधिकारिक वेबसाइट4> 3> <5> <6>Cherry रेपो6> 5> <7> <8>X को Y मिनटों में सीखें, जहां X=clojure8> 7> <9> <10>LiveCodes दस्तावेज़ीकरण10> 9> <11> <12>स्टार्टर टेम्पलेट लोड करें12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'आधुनिक COBOL को <1>GnuCOBOL1> द्वारा WebAssembly में संकलित किया जाता है, जो पूरी तरह से ब्राउज़र में चलता है।',
+ link: '<1> <2>GnuCOBOL आधिकारिक वेबसाइट2> 1> <3> <4>Y मिनट में X सीखें, जहाँ X=COBOL4> 3> <5> <6>लाइवकोड्स दस्तावेज़ीकरण6> 5> <7> <8>स्टार्टर टेम्पलेट लोड करें8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'सरल जावास्क्रिप्ट।',
link: '<1> <2>CoffeeScript आधिकारिक वेबसाइट2> 1> <3> <4>X को Y मिनटों में सीखें, जहां X=coffeescript4> 3> <5> <6>स्टार्टर टेम्पलेट लोड करें6> 5>',
diff --git a/src/livecodes/i18n/locales/hi/translation.lokalise.json b/src/livecodes/i18n/locales/hi/translation.lokalise.json
index c05ad0a63e..50ddbb6bda 100644
--- a/src/livecodes/i18n/locales/hi/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/hi/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry) स्टार्टर"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL स्टार्टर"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript स्टार्टर"
},
diff --git a/src/livecodes/i18n/locales/hi/translation.ts b/src/livecodes/i18n/locales/hi/translation.ts
index 2120fab325..6e55916bee 100644
--- a/src/livecodes/i18n/locales/hi/translation.ts
+++ b/src/livecodes/i18n/locales/hi/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'Clio स्टार्टर',
'cljs-selfhosted': 'CLJS (स्व-होस्टेड) स्टार्टर',
clojurescript: 'ClojureScript (Cherry) स्टार्टर',
+ 'cobol-wasm': 'COBOL स्टार्टर',
coffeescript: 'CoffeeScript स्टार्टर',
commonlisp: 'Common Lisp स्टार्टर',
cpp: 'C++ स्टार्टर',
diff --git a/src/livecodes/i18n/locales/hu/language-info.lokalise.json b/src/livecodes/i18n/locales/hu/language-info.lokalise.json
index 84eac14e02..2fae13696f 100644
--- a/src/livecodes/i18n/locales/hu/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/hu/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript hivatalos weboldal Clojure hivatalos weboldal Cherry repo Tanulj X-et Y perc alatt, ahol X=clojure LiveCodes dokumentáció Kezdő sablon betöltése "
},
+ "cobol-wasm.desc": {
+ "translation": "A modern COBOL a GnuCOBOL segítségével WebAssembly-re fordul, és teljes egészében a böngészőben fut."
+ },
+ "cobol-wasm.link": {
+ "translation": " Az GnuCOBOL hivatalos weboldala Tanulj meg X-et Y perc alatt, ahol X=COBOL LiveCodes dokumentáció Indító sablon betöltése "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "Egyszerű JavaScript."
},
diff --git a/src/livecodes/i18n/locales/hu/language-info.ts b/src/livecodes/i18n/locales/hu/language-info.ts
index 6e8d4606e2..3ecf913ae5 100644
--- a/src/livecodes/i18n/locales/hu/language-info.ts
+++ b/src/livecodes/i18n/locales/hu/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'A ClojureScript egy <1>Clojure1> fordító, amely JavaScript-et céloz meg. <2>2>A LiveCodes-ben a böngészőben fut a <3>Cherry3> segítségével',
link: '<1> <2>ClojureScript hivatalos weboldal2> 1> <3> <4>Clojure hivatalos weboldal4> 3> <5> <6>Cherry repo6> 5> <7> <8>Tanulj X-et Y perc alatt, ahol X=clojure8> 7> <9> <10>LiveCodes dokumentáció10> 9> <11> <12>Kezdő sablon betöltése12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'A modern COBOL a <1>GnuCOBOL1> segítségével WebAssembly-re fordul, és teljes egészében a böngészőben fut.',
+ link: '<1> <2>Az GnuCOBOL hivatalos weboldala2> 1> <3> <4>Tanulj meg X-et Y perc alatt, ahol X=COBOL4> 3> <5> <6>LiveCodes dokumentáció6> 5> <7> <8>Indító sablon betöltése8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'Egyszerű JavaScript.',
link: '<1> <2>CoffeeScript hivatalos weboldal2> 1> <3> <4>Tanulj X-et Y perc alatt, ahol X=coffeescript4> 3> <5> <6>Kezdő sablon betöltése6> 5>',
diff --git a/src/livecodes/i18n/locales/hu/translation.lokalise.json b/src/livecodes/i18n/locales/hu/translation.lokalise.json
index f46a2869c1..5ad93207f0 100644
--- a/src/livecodes/i18n/locales/hu/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/hu/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry) kezdő"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL kezdő"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript kezdő"
},
diff --git a/src/livecodes/i18n/locales/hu/translation.ts b/src/livecodes/i18n/locales/hu/translation.ts
index dcb1301048..8c614f588b 100644
--- a/src/livecodes/i18n/locales/hu/translation.ts
+++ b/src/livecodes/i18n/locales/hu/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Clio kezdő',
'cljs-selfhosted': 'CLJS (saját üzemeltetésű) kezdő',
clojurescript: 'ClojureScript (Cherry) kezdő',
+ 'cobol-wasm': 'COBOL kezdő',
coffeescript: 'CoffeeScript kezdő',
commonlisp: 'Common Lisp kezdő',
cpp: 'C++ kezdő',
diff --git a/src/livecodes/i18n/locales/id/language-info.lokalise.json b/src/livecodes/i18n/locales/id/language-info.lokalise.json
index c5a075af70..7c8be50542 100644
--- a/src/livecodes/i18n/locales/id/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/id/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Situs web resmi ClojureScript Situs web resmi Clojure Repo Cherry Pelajari X dalam Y menit, dengan X=clojure Dokumentasi LiveCodes Muat template pemula "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL modern dikompilasi ke WebAssembly oleh GnuCOBOL, berjalan sepenuhnya di dalam browser."
+ },
+ "cobol-wasm.link": {
+ "translation": " Situs web resmi GnuCOBOL Belajar X dalam Y menit, di mana X = COBOL Dokumentasi LiveCodes Muat templat awal "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript yang sederhana."
},
diff --git a/src/livecodes/i18n/locales/id/language-info.ts b/src/livecodes/i18n/locales/id/language-info.ts
index 9a24feb09e..bc6d0467e7 100644
--- a/src/livecodes/i18n/locales/id/language-info.ts
+++ b/src/livecodes/i18n/locales/id/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript adalah kompiler untuk <1>Clojure1> yang menargetkan JavaScript. <2>2>Di LiveCodes, berjalan di browser menggunakan <3>Cherry3>',
link: '<1> <2>Situs web resmi ClojureScript2> 1> <3> <4>Situs web resmi Clojure4> 3> <5> <6>Repo Cherry6> 5> <7> <8>Pelajari X dalam Y menit, dengan X=clojure8> 7> <9> <10>Dokumentasi LiveCodes10> 9> <11> <12>Muat template pemula12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL modern dikompilasi ke WebAssembly oleh <1>GnuCOBOL1>, berjalan sepenuhnya di dalam browser.',
+ link: '<1> <2>Situs web resmi GnuCOBOL2> 1> <3> <4>Belajar X dalam Y menit, di mana X = COBOL4> 3> <5> <6>Dokumentasi LiveCodes6> 5> <7> <8>Muat templat awal8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript yang sederhana.',
link: '<1> <2>Situs web resmi CoffeeScript2> 1> <3> <4>Pelajari X dalam Y menit, dengan X=coffeescript4> 3> <5> <6>Muat template pemula6> 5>',
diff --git a/src/livecodes/i18n/locales/id/translation.lokalise.json b/src/livecodes/i18n/locales/id/translation.lokalise.json
index 6d0aa7c2be..66df0cffab 100644
--- a/src/livecodes/i18n/locales/id/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/id/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Pemula ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Pemula COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Pemula CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/id/translation.ts b/src/livecodes/i18n/locales/id/translation.ts
index ad70da0152..71bad67074 100644
--- a/src/livecodes/i18n/locales/id/translation.ts
+++ b/src/livecodes/i18n/locales/id/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'Pemula Clio',
'cljs-selfhosted': 'Pemula CLJS (swa-hosting)',
clojurescript: 'Pemula ClojureScript (Cherry)',
+ 'cobol-wasm': 'Pemula COBOL',
coffeescript: 'Pemula CoffeeScript',
commonlisp: 'Pemula Common Lisp',
cpp: 'Pemula C++',
diff --git a/src/livecodes/i18n/locales/it/language-info.lokalise.json b/src/livecodes/i18n/locales/it/language-info.lokalise.json
index 34bba3d623..6bd459e148 100644
--- a/src/livecodes/i18n/locales/it/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/it/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Sito ufficiale di ClojureScript Sito ufficiale di Clojure Repository di Cherry Impara X in Y minuti, dove X=clojure Documentazione di LiveCodes Carica il modello di partenza "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL moderno compilato in WebAssembly da GnuCOBOL, eseguito interamente nel browser."
+ },
+ "cobol-wasm.link": {
+ "translation": " Sito web ufficiale di GnuCOBOL Impara X in Y minuti, dove X = COBOL Documentazione di LiveCodes Carica il modello di avvio "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript senza fronzoli."
},
diff --git a/src/livecodes/i18n/locales/it/language-info.ts b/src/livecodes/i18n/locales/it/language-info.ts
index 09bad4dc6b..a894e3c498 100644
--- a/src/livecodes/i18n/locales/it/language-info.ts
+++ b/src/livecodes/i18n/locales/it/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript è un compilatore per <1>Clojure1> che ha come target JavaScript. <2>2>In LiveCodes, funziona nel browser utilizzando <3>Cherry3>.',
link: '<1> <2>Sito ufficiale di ClojureScript2> 1> <3> <4>Sito ufficiale di Clojure4> 3> <5> <6>Repository di Cherry6> 5> <7> <8>Impara X in Y minuti, dove X=clojure8> 7> <9> <10>Documentazione di LiveCodes10> 9> <11> <12>Carica il modello di partenza12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL moderno compilato in WebAssembly da <1>GnuCOBOL1>, eseguito interamente nel browser.',
+ link: '<1> <2>Sito web ufficiale di GnuCOBOL2> 1> <3> <4>Impara X in Y minuti, dove X = COBOL4> 3> <5> <6>Documentazione di LiveCodes6> 5> <7> <8>Carica il modello di avvio8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript senza fronzoli.',
link: '<1> <2>Sito ufficiale di CoffeeScript2> 1> <3> <4>Impara X in Y minuti, dove X=coffeescript4> 3> <5> <6>Carica il modello di partenza6> 5>',
diff --git a/src/livecodes/i18n/locales/it/translation.lokalise.json b/src/livecodes/i18n/locales/it/translation.lokalise.json
index 816e747b3a..df72eb124c 100644
--- a/src/livecodes/i18n/locales/it/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/it/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Starter ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Starter COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Starter CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/it/translation.ts b/src/livecodes/i18n/locales/it/translation.ts
index 00d5a12ec9..d06368db46 100644
--- a/src/livecodes/i18n/locales/it/translation.ts
+++ b/src/livecodes/i18n/locales/it/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Starter Clio',
'cljs-selfhosted': 'Starter CLJS (self-hosted)',
clojurescript: 'Starter ClojureScript (Cherry)',
+ 'cobol-wasm': 'Starter COBOL',
coffeescript: 'Starter CoffeeScript',
commonlisp: 'Starter Common Lisp',
cpp: 'Starter C++',
diff --git a/src/livecodes/i18n/locales/ja/language-info.lokalise.json b/src/livecodes/i18n/locales/ja/language-info.lokalise.json
index 1b50161e6a..003af91a09 100644
--- a/src/livecodes/i18n/locales/ja/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ja/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript 公式ウェブサイト Clojure 公式ウェブサイト Cherry リポジトリ X分でYを学ぶ、X=clojure LiveCodes ドキュメント スターターテンプレートを読み込む "
},
+ "cobol-wasm.desc": {
+ "translation": "モダンな COBOL は GnuCOBOL によって WebAssembly にコンパイルされ、ブラウザ内で完全に実行されます。"
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL 公式サイト 「Y分でXを学ぶ」(X=COBOL) LiveCodes ドキュメント スターターテンプレートを読み込む "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "飾り気のない JavaScript。"
},
diff --git a/src/livecodes/i18n/locales/ja/language-info.ts b/src/livecodes/i18n/locales/ja/language-info.ts
index eb625fdb27..3035393447 100644
--- a/src/livecodes/i18n/locales/ja/language-info.ts
+++ b/src/livecodes/i18n/locales/ja/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript は JavaScript をターゲットとする<1>Clojure1>のコンパイラです。<2>2>LiveCodes では、<3>Cherry3>を使用してブラウザで実行されます。',
link: '<1> <2>ClojureScript 公式ウェブサイト2> 1> <3> <4>Clojure 公式ウェブサイト4> 3> <5> <6>Cherry リポジトリ6> 5> <7> <8>X分でYを学ぶ、X=clojure8> 7> <9> <10>LiveCodes ドキュメント10> 9> <11> <12>スターターテンプレートを読み込む12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'モダンな COBOL は <1>GnuCOBOL1> によって WebAssembly にコンパイルされ、ブラウザ内で完全に実行されます。',
+ link: '<1> <2>GnuCOBOL 公式サイト2> 1> <3> <4>「Y分でXを学ぶ」(X=COBOL)4> 3> <5> <6>LiveCodes ドキュメント6> 5> <7> <8>スターターテンプレートを読み込む8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: '飾り気のない JavaScript。',
link: '<1> <2>CoffeeScript 公式ウェブサイト2> 1> <3> <4>X分でYを学ぶ、X=coffeescript4> 3> <5> <6>スターターテンプレートを読み込む6> 5>',
diff --git a/src/livecodes/i18n/locales/ja/translation.lokalise.json b/src/livecodes/i18n/locales/ja/translation.lokalise.json
index 43ae4dbe59..6c8c6c8989 100644
--- a/src/livecodes/i18n/locales/ja/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ja/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry)スターター"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOLスターター"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScriptスターター"
},
diff --git a/src/livecodes/i18n/locales/ja/translation.ts b/src/livecodes/i18n/locales/ja/translation.ts
index 152287864c..1683c8e497 100644
--- a/src/livecodes/i18n/locales/ja/translation.ts
+++ b/src/livecodes/i18n/locales/ja/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Clioスターター',
'cljs-selfhosted': 'CLJS (セルフホスト)スターター',
clojurescript: 'ClojureScript (Cherry)スターター',
+ 'cobol-wasm': 'COBOLスターター',
coffeescript: 'CoffeeScriptスターター',
commonlisp: 'Common Lispスターター',
cpp: 'C++スターター',
diff --git a/src/livecodes/i18n/locales/nl/language-info.lokalise.json b/src/livecodes/i18n/locales/nl/language-info.lokalise.json
index 1f5f1f62f6..475696dba9 100644
--- a/src/livecodes/i18n/locales/nl/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/nl/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript officiële website Clojure officiële website Cherry repo Leer X in Y minuten, waarbij X=clojure LiveCodes Documentatie Startsjabloon laden "
},
+ "cobol-wasm.desc": {
+ "translation": "Moderne COBOL wordt door GnuCOBOL gecompileerd naar WebAssembly en draait volledig in de browser."
+ },
+ "cobol-wasm.link": {
+ "translation": " Officiële website van GnuCOBOL Leer X in Y minuten, waarbij X = COBOL LiveCodes-documentatie Starterssjabloon laden "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript zonder poespas."
},
diff --git a/src/livecodes/i18n/locales/nl/language-info.ts b/src/livecodes/i18n/locales/nl/language-info.ts
index e1f714ea1c..164da152f1 100644
--- a/src/livecodes/i18n/locales/nl/language-info.ts
+++ b/src/livecodes/i18n/locales/nl/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript is een compiler voor <1>Clojure1> die zich richt op JavaScript. <2>2>In LiveCodes draait het in de browser met <3>Cherry3>',
link: '<1> <2>ClojureScript officiële website2> 1> <3> <4>Clojure officiële website4> 3> <5> <6>Cherry repo6> 5> <7> <8>Leer X in Y minuten, waarbij X=clojure8> 7> <9> <10>LiveCodes Documentatie10> 9> <11> <12>Startsjabloon laden12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'Moderne COBOL wordt door <1>GnuCOBOL1> gecompileerd naar WebAssembly en draait volledig in de browser.',
+ link: '<1> <2>Officiële website van GnuCOBOL2> 1> <3> <4>Leer X in Y minuten, waarbij X = COBOL4> 3> <5> <6>LiveCodes-documentatie6> 5> <7> <8>Starterssjabloon laden8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript zonder poespas.',
link: '<1> <2>CoffeeScript officiële website2> 1> <3> <4>Leer X in Y minuten, waarbij X=coffeescript4> 3> <5> <6>Startsjabloon laden6> 5>',
diff --git a/src/livecodes/i18n/locales/nl/translation.lokalise.json b/src/livecodes/i18n/locales/nl/translation.lokalise.json
index 1a2cf5bea2..6d15d7fad6 100644
--- a/src/livecodes/i18n/locales/nl/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/nl/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry)-starter"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL-starter"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript-starter"
},
diff --git a/src/livecodes/i18n/locales/nl/translation.ts b/src/livecodes/i18n/locales/nl/translation.ts
index 7aac8a6a1a..7e9b636c88 100644
--- a/src/livecodes/i18n/locales/nl/translation.ts
+++ b/src/livecodes/i18n/locales/nl/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Clio-starter',
'cljs-selfhosted': 'CLJS (zelfgehost)-starter',
clojurescript: 'ClojureScript (Cherry)-starter',
+ 'cobol-wasm': 'COBOL-starter',
coffeescript: 'CoffeeScript-starter',
commonlisp: 'Common Lisp-starter',
cpp: 'C++-starter',
diff --git a/src/livecodes/i18n/locales/pt/language-info.lokalise.json b/src/livecodes/i18n/locales/pt/language-info.lokalise.json
index 32cd91fd32..e2bf2819f5 100644
--- a/src/livecodes/i18n/locales/pt/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/pt/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Site oficial do ClojureScript Site oficial do Clojure Repositório do Cherry Aprenda X em Y minutos, onde X=clojure Documentação do LiveCodes Carregar modelo inicial "
},
+ "cobol-wasm.desc": {
+ "translation": "COBOL moderno compilado para WebAssembly pelo GnuCOBOL, executado na íntegra no navegador."
+ },
+ "cobol-wasm.link": {
+ "translation": " Site oficial do GnuCOBOL Aprenda X em Y minutos, onde X = COBOL Documentação do LiveCodes Carregar modelo inicial "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "JavaScript sem frescura."
},
diff --git a/src/livecodes/i18n/locales/pt/language-info.ts b/src/livecodes/i18n/locales/pt/language-info.ts
index a79cf64a9c..1e542fb8ba 100644
--- a/src/livecodes/i18n/locales/pt/language-info.ts
+++ b/src/livecodes/i18n/locales/pt/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript é um compilador para <1>Clojure1> que tem como alvo JavaScript. <2>2>No LiveCodes, ele é executado no navegador usando <3>Cherry3>.',
link: '<1> <2>Site oficial do ClojureScript2> 1> <3> <4>Site oficial do Clojure4> 3> <5> <6>Repositório do Cherry6> 5> <7> <8>Aprenda X em Y minutos, onde X=clojure8> 7> <9> <10>Documentação do LiveCodes10> 9> <11> <12>Carregar modelo inicial12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'COBOL moderno compilado para WebAssembly pelo <1>GnuCOBOL1>, executado na íntegra no navegador.',
+ link: '<1> <2>Site oficial do GnuCOBOL2> 1> <3> <4>Aprenda X em Y minutos, onde X = COBOL4> 3> <5> <6>Documentação do LiveCodes6> 5> <7> <8>Carregar modelo inicial8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'JavaScript sem frescura.',
link: '<1> <2>Site oficial do CoffeeScript2> 1> <3> <4>Aprenda X em Y minutos, onde X=coffeescript4> 3> <5> <6>Carregar modelo inicial6> 5>',
diff --git a/src/livecodes/i18n/locales/pt/translation.lokalise.json b/src/livecodes/i18n/locales/pt/translation.lokalise.json
index 9240d000f2..aa8debfe63 100644
--- a/src/livecodes/i18n/locales/pt/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/pt/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Iniciante ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Iniciante COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Iniciante CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/pt/translation.ts b/src/livecodes/i18n/locales/pt/translation.ts
index e068a9419b..1bc08b3c99 100644
--- a/src/livecodes/i18n/locales/pt/translation.ts
+++ b/src/livecodes/i18n/locales/pt/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Iniciante Clio',
'cljs-selfhosted': 'Iniciante CLJS (auto-hospedado)',
clojurescript: 'Iniciante ClojureScript (Cherry)',
+ 'cobol-wasm': 'Iniciante COBOL',
coffeescript: 'Iniciante CoffeeScript',
commonlisp: 'Iniciante Common Lisp',
cpp: 'Iniciante C++',
diff --git a/src/livecodes/i18n/locales/ru/language-info.lokalise.json b/src/livecodes/i18n/locales/ru/language-info.lokalise.json
index 36f603eb61..065ac297a6 100644
--- a/src/livecodes/i18n/locales/ru/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ru/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " Официальный сайт ClojureScript Официальный сайт Clojure Репозиторий Cherry Изучите X за Y минут, где X=clojure Документация LiveCodes Загрузить стартовый шаблон "
},
+ "cobol-wasm.desc": {
+ "translation": "Современный COBOL компилируется в WebAssembly с помощью GnuCOBOL и полностью выполняется в браузере."
+ },
+ "cobol-wasm.link": {
+ "translation": " Официальный сайт GnuCOBOL «Изучите X за Y минут», где X = COBOL Документация LiveCodes Загрузить стартовый шаблон "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "Непретенциозный JavaScript."
},
diff --git a/src/livecodes/i18n/locales/ru/language-info.ts b/src/livecodes/i18n/locales/ru/language-info.ts
index b40fa609d1..7d53b29f06 100644
--- a/src/livecodes/i18n/locales/ru/language-info.ts
+++ b/src/livecodes/i18n/locales/ru/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript - это компилятор для <1>Clojure1>, который нацелен на JavaScript. <2>2>В LiveCodes он работает в браузере с использованием <3>Cherry3>.',
link: '<1> <2>Официальный сайт ClojureScript2> 1> <3> <4>Официальный сайт Clojure4> 3> <5> <6>Репозиторий Cherry6> 5> <7> <8>Изучите X за Y минут, где X=clojure8> 7> <9> <10>Документация LiveCodes10> 9> <11> <12>Загрузить стартовый шаблон12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'Современный COBOL компилируется в WebAssembly с помощью <1>GnuCOBOL1> и полностью выполняется в браузере.',
+ link: '<1> <2>Официальный сайт GnuCOBOL2> 1> <3> <4>«Изучите X за Y минут», где X = COBOL4> 3> <5> <6>Документация LiveCodes6> 5> <7> <8>Загрузить стартовый шаблон8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'Непретенциозный JavaScript.',
link: '<1> <2>Официальный сайт CoffeeScript2> 1> <3> <4>Изучите X за Y минут, где X=coffeescript4> 3> <5> <6>Загрузить стартовый шаблон6> 5>',
diff --git a/src/livecodes/i18n/locales/ru/translation.lokalise.json b/src/livecodes/i18n/locales/ru/translation.lokalise.json
index 4a0004d386..5778dcbf95 100644
--- a/src/livecodes/i18n/locales/ru/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ru/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "Стартер ClojureScript (Cherry)"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "Стартер COBOL"
+ },
"templates.starter.coffeescript": {
"translation": "Стартер CoffeeScript"
},
diff --git a/src/livecodes/i18n/locales/ru/translation.ts b/src/livecodes/i18n/locales/ru/translation.ts
index 0073f09164..a66e97ded6 100644
--- a/src/livecodes/i18n/locales/ru/translation.ts
+++ b/src/livecodes/i18n/locales/ru/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'Стартер Clio',
'cljs-selfhosted': 'Стартер CLJS (самостоятельный хостинг)',
clojurescript: 'Стартер ClojureScript (Cherry)',
+ 'cobol-wasm': 'Стартер COBOL',
coffeescript: 'Стартер CoffeeScript',
commonlisp: 'Стартер Common Lisp',
cpp: 'Стартер C++',
diff --git a/src/livecodes/i18n/locales/tr/language-info.lokalise.json b/src/livecodes/i18n/locales/tr/language-info.lokalise.json
index 935c311b93..c24dda41e7 100644
--- a/src/livecodes/i18n/locales/tr/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/tr/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript resmi web sitesi Clojure resmi web sitesi Cherry repo'su Y Dakikada X Öğrenin, X=clojure LiveCodes Dokümantasyonu Başlangıç şablonunu yükle "
},
+ "cobol-wasm.desc": {
+ "translation": "Modern COBOL, GnuCOBOL tarafından WebAssembly’ye derlenir ve tamamen tarayıcı içinde çalışır."
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL resmi web sitesi Y dakikada X'i öğrenin, burada X=COBOL LiveCodes Belgeleri Başlangıç şablonunu yükle "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "Sade JavaScript."
},
diff --git a/src/livecodes/i18n/locales/tr/language-info.ts b/src/livecodes/i18n/locales/tr/language-info.ts
index aac52ba913..d5d18f7de6 100644
--- a/src/livecodes/i18n/locales/tr/language-info.ts
+++ b/src/livecodes/i18n/locales/tr/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: "ClojureScript, JavaScript'i hedefleyen bir <1>Clojure1> derleyicisidir. <2>2>LiveCodes'ta, tarayıcıda <3>Cherry3> kullanarak çalışır.",
link: "<1> <2>ClojureScript resmi web sitesi2> 1> <3> <4>Clojure resmi web sitesi4> 3> <5> <6>Cherry repo'su6> 5> <7> <8>Y Dakikada X Öğrenin, X=clojure8> 7> <9> <10>LiveCodes Dokümantasyonu10> 9> <11> <12>Başlangıç şablonunu yükle12> 11>",
},
+ 'cobol-wasm': {
+ desc: 'Modern COBOL, <1>GnuCOBOL1> tarafından WebAssembly’ye derlenir ve tamamen tarayıcı içinde çalışır.',
+ link: "<1> <2>GnuCOBOL resmi web sitesi2> 1> <3> <4>Y dakikada X'i öğrenin, burada X=COBOL4> 3> <5> <6>LiveCodes Belgeleri6> 5> <7> <8>Başlangıç şablonunu yükle8> 7>",
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'Sade JavaScript.',
link: '<1> <2>CoffeeScript resmi web sitesi2> 1> <3> <4>Y Dakikada X Öğrenin, X=coffeescript4> 3> <5> <6>Başlangıç şablonunu yükle6> 5>',
diff --git a/src/livecodes/i18n/locales/tr/translation.lokalise.json b/src/livecodes/i18n/locales/tr/translation.lokalise.json
index 9d8bcbdd5d..c1fd9a1e2e 100644
--- a/src/livecodes/i18n/locales/tr/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/tr/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry) Başlangıç"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL Başlangıç"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript Başlangıç"
},
diff --git a/src/livecodes/i18n/locales/tr/translation.ts b/src/livecodes/i18n/locales/tr/translation.ts
index 3cc5c451b0..e0d07f1935 100644
--- a/src/livecodes/i18n/locales/tr/translation.ts
+++ b/src/livecodes/i18n/locales/tr/translation.ts
@@ -991,6 +991,7 @@ const translation: I18nTranslation = {
clio: 'Clio Başlangıç',
'cljs-selfhosted': 'CLJS (kendi sunucunda) Başlangıç',
clojurescript: 'ClojureScript (Cherry) Başlangıç',
+ 'cobol-wasm': 'COBOL Başlangıç',
coffeescript: 'CoffeeScript Başlangıç',
commonlisp: 'Common Lisp Başlangıç',
cpp: 'C++ Başlangıç',
diff --git a/src/livecodes/i18n/locales/ur/language-info.lokalise.json b/src/livecodes/i18n/locales/ur/language-info.lokalise.json
index 4c7705337a..5edc90fd8f 100644
--- a/src/livecodes/i18n/locales/ur/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ur/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " کلوجر اسکرپٹ کی سرکاری ویب سائٹ کلوجر کی سرکاری ویب سائٹ چیری ریپوزٹری X کو Y منٹ میں سیکھیں، جہاں X=کلوجر لائیو کوڈز دستاویزات ابتدائی سانچہ لوڈ کریں "
},
+ "cobol-wasm.desc": {
+ "translation": "جدید COBOL GnuCOBOL کے ذریعے WebAssembly میں مرتب کیا جاتا ہے، جو مکمل طور پر براؤزر میں چلتا ہے۔"
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL آفیشل ویب سائٹ Y منٹ میں X سیکھیں، جہاں X=COBOL لائیو کوڈز دستاویزات اسٹارٹر ٹیمپلیٹ لوڈ کریں "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "سادہ جاوا اسکرپٹ۔"
},
diff --git a/src/livecodes/i18n/locales/ur/language-info.ts b/src/livecodes/i18n/locales/ur/language-info.ts
index 84355149fa..ed2b461a39 100644
--- a/src/livecodes/i18n/locales/ur/language-info.ts
+++ b/src/livecodes/i18n/locales/ur/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'کلوجر اسکرپٹ <1>کلوجر1> کے لیے ایک کمپائلر ہے جو جاوا اسکرپٹ کو ہدف بناتا ہے۔ <2>2>لائیو کوڈز میں، یہ براؤزر میں <3>چیری3> کا استعمال کرتے ہوئے چلتا ہے۔',
link: '<1> <2>کلوجر اسکرپٹ کی سرکاری ویب سائٹ2> 1> <3> <4>کلوجر کی سرکاری ویب سائٹ4> 3> <5> <6>چیری ریپوزٹری6> 5> <7> <8>X کو Y منٹ میں سیکھیں، جہاں X=کلوجر8> 7> <9> <10>لائیو کوڈز دستاویزات10> 9> <11> <12>ابتدائی سانچہ لوڈ کریں12> 11>',
},
+ 'cobol-wasm': {
+ desc: 'جدید COBOL <1>GnuCOBOL1> کے ذریعے WebAssembly میں مرتب کیا جاتا ہے، جو مکمل طور پر براؤزر میں چلتا ہے۔',
+ link: '<1> <2>GnuCOBOL آفیشل ویب سائٹ2> 1> <3> <4>Y منٹ میں X سیکھیں، جہاں X=COBOL4> 3> <5> <6>لائیو کوڈز دستاویزات6> 5> <7> <8>اسٹارٹر ٹیمپلیٹ لوڈ کریں8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: 'سادہ جاوا اسکرپٹ۔',
link: '<1> <2>کافی اسکرپٹ کی سرکاری ویب سائٹ2> 1> <3> <4>X کو Y منٹ میں سیکھیں، جہاں X=کافی اسکرپٹ4> 3> <5> <6>ابتدائی سانچہ لوڈ کریں6> 5>',
diff --git a/src/livecodes/i18n/locales/ur/translation.lokalise.json b/src/livecodes/i18n/locales/ur/translation.lokalise.json
index 6abab68d77..18f444566e 100644
--- a/src/livecodes/i18n/locales/ur/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ur/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "کلوجر اسکرپٹ (Cherry) شروعاتی"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL شروعاتی"
+ },
"templates.starter.coffeescript": {
"translation": "کافی اسکرپٹ شروعاتی"
},
diff --git a/src/livecodes/i18n/locales/ur/translation.ts b/src/livecodes/i18n/locales/ur/translation.ts
index 592a0d7d93..98147ee70a 100644
--- a/src/livecodes/i18n/locales/ur/translation.ts
+++ b/src/livecodes/i18n/locales/ur/translation.ts
@@ -990,6 +990,7 @@ const translation: I18nTranslation = {
clio: 'کلیو شروعاتی',
'cljs-selfhosted': 'سی ایل جے ایس (خود میزبان) شروعاتی',
clojurescript: 'کلوجر اسکرپٹ (Cherry) شروعاتی',
+ 'cobol-wasm': 'COBOL شروعاتی',
coffeescript: 'کافی اسکرپٹ شروعاتی',
commonlisp: 'کامن لسپ شروعاتی',
cpp: 'سی++ شروعاتی',
diff --git a/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json b/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json
index cb11cf9eb3..6030018064 100644
--- a/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json
@@ -135,6 +135,15 @@
"clojurescript.link": {
"translation": " ClojureScript 官方网站 Clojure 官方网站 Cherry 仓库 在 Y 分钟内学习 X,其中 X=clojure LiveCodes 文档 加载启动模板 "
},
+ "cobol-wasm.desc": {
+ "translation": "现代 COBOL 由 GnuCOBOL 编译为 WebAssembly,完全在浏览器中运行。"
+ },
+ "cobol-wasm.link": {
+ "translation": " GnuCOBOL 官方网站 《Y分钟学会X》,其中X=COBOL LiveCodes 文档 加载入门模板 "
+ },
+ "cobol-wasm.name": {
+ "translation": "COBOL (Wasm)"
+ },
"coffeescript.desc": {
"translation": "不花哨的 JavaScript。"
},
diff --git a/src/livecodes/i18n/locales/zh-CN/language-info.ts b/src/livecodes/i18n/locales/zh-CN/language-info.ts
index 400ddd621a..eff5c264d1 100644
--- a/src/livecodes/i18n/locales/zh-CN/language-info.ts
+++ b/src/livecodes/i18n/locales/zh-CN/language-info.ts
@@ -80,6 +80,11 @@ const languageInfo: I18nLangInfoTranslation = {
desc: 'ClojureScript 是 <1>Clojure1> 到 JavaScript 的编译器。<2>2>在 LiveCodes 中,它使用 <3>Cherry3> 在浏览器中运行。',
link: '<1> <2>ClojureScript 官方网站2> 1> <3> <4>Clojure 官方网站4> 3> <5> <6>Cherry 仓库6> 5> <7> <8>在 Y 分钟内学习 X,其中 X=clojure8> 7> <9> <10>LiveCodes 文档10> 9> <11> <12>加载启动模板12> 11>',
},
+ 'cobol-wasm': {
+ desc: '现代 COBOL 由 <1>GnuCOBOL1> 编译为 WebAssembly,完全在浏览器中运行。',
+ link: '<1> <2>GnuCOBOL 官方网站2> 1> <3> <4>《Y分钟学会X》,其中X=COBOL4> 3> <5> <6>LiveCodes 文档6> 5> <7> <8>加载入门模板8> 7>',
+ name: 'COBOL (Wasm)',
+ },
coffeescript: {
desc: '不花哨的 JavaScript。',
link: '<1> <2>CoffeeScript 官方网站2> 1> <3> <4>在 Y 分钟内学习 X,其中 X=CoffeeScript4> 3> <5> <6>加载启动模板6> 5>',
diff --git a/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json b/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
index 360d3eb3dc..2fb10a92c1 100644
--- a/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
@@ -1953,6 +1953,9 @@
"templates.starter.clojurescript": {
"translation": "ClojureScript (Cherry) 启动模板"
},
+ "templates.starter.cobol-wasm": {
+ "translation": "COBOL 启动模板"
+ },
"templates.starter.coffeescript": {
"translation": "CoffeeScript 启动模板"
},
diff --git a/src/livecodes/i18n/locales/zh-CN/translation.ts b/src/livecodes/i18n/locales/zh-CN/translation.ts
index 759aa9540b..740a43b357 100644
--- a/src/livecodes/i18n/locales/zh-CN/translation.ts
+++ b/src/livecodes/i18n/locales/zh-CN/translation.ts
@@ -988,6 +988,7 @@ const translation: I18nTranslation = {
clio: 'Clio 启动模板',
'cljs-selfhosted': 'CLJS(自托管)启动模板',
clojurescript: 'ClojureScript (Cherry) 启动模板',
+ 'cobol-wasm': 'COBOL 启动模板',
coffeescript: 'CoffeeScript 启动模板',
commonlisp: 'Common Lisp 启动模板',
cpp: 'C++ 启动模板',
diff --git a/src/livecodes/languages/ada-wasm/lang-ada-wasm-script.ts b/src/livecodes/languages/ada-wasm/lang-ada-wasm-script.ts
index 58d7190c31..0d814c1d16 100644
--- a/src/livecodes/languages/ada-wasm/lang-ada-wasm-script.ts
+++ b/src/livecodes/languages/ada-wasm/lang-ada-wasm-script.ts
@@ -1,6 +1,7 @@
/* eslint-disable no-console */
-import { createWorkerFromContent, getErrorMessage } from '../../utils/utils';
+import { getErrorMessage } from '../../utils/utils';
import { adaWasmBaseUrl } from '../../vendors';
+import { createWorkerRunner, type Runner } from '../worker-runner';
// Ada is compiled and run by HAC (@live-codes/ada-wasm), a single self-contained
// WebAssembly bundle. It runs inside a dedicated worker so a non-terminating
@@ -24,12 +25,6 @@ interface RunResult {
exitCode: number | null;
}
-interface Runner {
- ensureReady: () => Promise;
- run: (code: string, input: string) => Promise;
- destroy: () => void;
-}
-
interface AdaWasmApi {
ready: boolean;
failed: boolean;
@@ -39,7 +34,7 @@ interface AdaWasmApi {
exitCode: number | null;
loaded: Promise;
init: Promise | null;
- runner?: Runner;
+ runner?: Runner;
run: (input?: string) => Promise;
}
@@ -103,83 +98,6 @@ getRuntime().then(
);
`;
-interface Pending {
- resolve: (result: WorkerRunResult) => void;
- reject: (error: Error) => void;
-}
-
-const createRunner = (): Runner => {
- let worker: Worker | null = null;
- let ready: Promise | null = null;
- let settleReady: ((error?: Error) => void) | null = null;
- let pending: Record = {};
- let nextId = 1;
-
- const failAll = (error: Error) => {
- for (const id of Object.keys(pending)) {
- pending[Number(id)].reject(error);
- }
- pending = {};
- };
-
- const teardown = (error?: Error) => {
- worker?.terminate();
- worker = null;
- ready = null;
- settleReady?.(error);
- settleReady = null;
- if (error) failAll(error);
- };
-
- const onMessage = (event: MessageEvent) => {
- const message = event.data ?? {};
- if (message.type === 'ready') {
- settleReady?.();
- settleReady = null;
- return;
- }
- if (message.type === 'error') {
- // The runtime failed to load (network, or the browser is unsupported).
- teardown(new Error(message.message));
- return;
- }
- const request = pending[message.id];
- if (!request) return;
- delete pending[message.id];
- if (message.error != null) {
- request.reject(new Error(message.error));
- } else {
- request.resolve(message.result);
- }
- };
-
- const spawn = () => {
- ready = new Promise((resolve, reject) => {
- settleReady = (error?: Error) => (error ? reject(error) : resolve());
- });
- worker = createWorkerFromContent(getWorkerSrc());
- worker.onmessage = onMessage;
- worker.onerror = (event) => teardown(new Error(`The Ada worker crashed: ${event.message}`));
- };
-
- const ensureReady = async () => {
- if (!ready) spawn();
- await ready;
- };
-
- const run = (code: string, input: string) =>
- ensureReady().then(
- () =>
- new Promise((resolve, reject) => {
- const id = nextId++;
- pending[id] = { resolve, reject };
- worker?.postMessage({ id, code, input });
- }),
- );
-
- return { ensureReady, run, destroy: () => teardown() };
-};
-
const setResult = (
input: string,
output: string | null,
@@ -207,7 +125,7 @@ adaWasm.ready = false;
adaWasm.failed = false;
/** Start (once) loading the runtime in a worker, showing the loading indicator. */
-const ensureLoaded = (runner: Runner): Promise => {
+const ensureLoaded = (runner: Runner): Promise => {
let init = adaWasm.init;
if (!init) {
adaWasm.failed = false;
@@ -258,7 +176,8 @@ adaWasm.run = async (input?: string) => {
});
if (!code.trim()) return setResult(stdin, null, null, 0);
- const runner = (adaWasm.runner = adaWasm.runner || createRunner());
+ const runner = (adaWasm.runner =
+ adaWasm.runner || createWorkerRunner({ getWorkerSrc, label: 'Ada' }));
try {
await ensureLoaded(runner);
diff --git a/src/livecodes/languages/assembly-wasm/lang-assembly-wasm-script.ts b/src/livecodes/languages/assembly-wasm/lang-assembly-wasm-script.ts
index 0b1d063490..b2b031da86 100644
--- a/src/livecodes/languages/assembly-wasm/lang-assembly-wasm-script.ts
+++ b/src/livecodes/languages/assembly-wasm/lang-assembly-wasm-script.ts
@@ -1,11 +1,12 @@
/* eslint-disable no-console */
-import { createWorkerFromContent, getErrorMessage } from '../../utils/utils';
+import { getErrorMessage } from '../../utils/utils';
import {
assemblyWasmBaseUrl,
keystoneJsUrl,
keystoneJsWasmUrl,
unicornJsX86Url,
} from '../../vendors';
+import { createWorkerRunner, type Runner } from '../worker-runner';
// x86-64 assembly is assembled and executed by @live-codes/assembly-wasm, which loads
// Keystone (the assembler) and Unicorn (the CPU emulator) as separate WebAssembly
@@ -20,12 +21,6 @@ const SCRIPT_TYPE = 'text/assembly';
const BOOT_TIMEOUT_MS = 2 * 60_000;
-interface WorkerRunResult {
- output: string;
- errors: string[];
- exitCode: number | null;
-}
-
interface RunResult {
input: string;
output: string | null;
@@ -33,12 +28,6 @@ interface RunResult {
exitCode: number | null;
}
-interface Runner {
- ensureReady: () => Promise;
- run: (code: string, input: string) => Promise;
- destroy: () => void;
-}
-
interface AssemblyWasmApi {
ready: boolean;
failed: boolean;
@@ -118,85 +107,6 @@ getCompiler().then(
);
`;
-interface Pending {
- resolve: (result: WorkerRunResult) => void;
- reject: (error: Error) => void;
-}
-
-const createRunner = (): Runner => {
- let worker: Worker | null = null;
- let ready: Promise | null = null;
- let settleReady: ((error?: Error) => void) | null = null;
- let pending: Record = {};
- let nextId = 1;
-
- const failAll = (error: Error) => {
- for (const id of Object.keys(pending)) {
- pending[Number(id)].reject(error);
- }
- pending = {};
- };
-
- const teardown = (error?: Error) => {
- worker?.terminate();
- worker = null;
- ready = null;
- settleReady?.(error);
- settleReady = null;
- if (error) failAll(error);
- };
-
- const onMessage = (event: MessageEvent) => {
- const message = event.data ?? {};
- if (message.type === 'ready') {
- settleReady?.();
- settleReady = null;
- return;
- }
- if (message.type === 'error') {
- // The runtime failed to load (network, or the browser is unsupported).
- teardown(new Error(message.message));
- return;
- }
- const request = pending[message.id];
- if (!request) return;
- delete pending[message.id];
- if (message.error != null) {
- request.reject(new Error(message.error));
- } else {
- request.resolve(message.result);
- }
- };
-
- const spawn = () => {
- ready = new Promise((resolve, reject) => {
- settleReady = (error?: Error) => (error ? reject(error) : resolve());
- });
- worker = createWorkerFromContent(getWorkerSrc());
- worker.onmessage = onMessage;
- worker.onerror = (event) =>
- teardown(new Error(`The Assembly worker crashed: ${event.message}`));
- };
-
- /** Spawn the worker if needed and resolve once the runtime has loaded. */
- const ensureReady = async () => {
- if (!ready) spawn();
- await ready;
- };
-
- const run = (code: string, input: string) =>
- ensureReady().then(
- () =>
- new Promise((resolve, reject) => {
- const id = nextId++;
- pending[id] = { resolve, reject };
- worker?.postMessage({ id, code, input });
- }),
- );
-
- return { ensureReady, run, destroy: () => teardown() };
-};
-
const setResult = (
input: string,
output: string | null,
@@ -277,7 +187,8 @@ assemblyWasm.run = async (input?: string) => {
// Park the runner on the persisted namespace so a live reload reuses the warm
// worker instead of loading the runtimes again.
- const runner = (assemblyWasm.runner = assemblyWasm.runner || createRunner());
+ const runner = (assemblyWasm.runner =
+ assemblyWasm.runner || createWorkerRunner({ getWorkerSrc, label: 'Assembly' }));
try {
await ensureLoaded(runner);
diff --git a/src/livecodes/languages/clang-wasm/lang-clang-wasm-script.ts b/src/livecodes/languages/clang-wasm/lang-clang-wasm-script.ts
index 4b751753a9..6d53ab349b 100644
--- a/src/livecodes/languages/clang-wasm/lang-clang-wasm-script.ts
+++ b/src/livecodes/languages/clang-wasm/lang-clang-wasm-script.ts
@@ -1,6 +1,7 @@
/* eslint-disable no-console */
-import { createWorkerFromContent, getErrorMessage } from '../../utils/utils';
+import { getErrorMessage } from '../../utils/utils';
import { clangWasmBaseUrl } from '../../vendors';
+import { createWorkerRunner, type Runner } from '../worker-runner';
// One runner serves all four Clang languages. The language is read from the script tags the
// compiler injected into the page, so only the script type differs between them.
@@ -35,12 +36,6 @@ interface ClangWasmSettings {
args?: string[];
}
-interface WorkerRunResult {
- output: string;
- errors: string[];
- exitCode: number | null;
-}
-
interface RunResult {
input: string;
output: string | null;
@@ -48,11 +43,6 @@ interface RunResult {
exitCode: number | null;
}
-interface Runner {
- ensureReady: () => Promise;
- run: (code: string, input: string, options?: ClangWasmSettings) => Promise;
-}
-
interface ClangWasmApi {
ready: boolean;
input: string;
@@ -107,84 +97,6 @@ getCompiler().then(
);
`;
-interface Pending {
- resolve: (result: WorkerRunResult) => void;
- reject: (error: Error) => void;
-}
-
-const createRunner = (language: LanguageId): Runner => {
- let worker: Worker | null = null;
- let ready: Promise | null = null;
- let settleReady: ((error?: Error) => void) | null = null;
- let pending: Record = {};
- let nextId = 1;
-
- const failAll = (error: Error) => {
- for (const id of Object.keys(pending)) {
- pending[Number(id)].reject(error);
- }
- pending = {};
- };
-
- const teardown = (error: Error) => {
- worker?.terminate();
- worker = null;
- ready = null;
- settleReady?.(error);
- settleReady = null;
- failAll(error);
- };
-
- const onMessage = (event: MessageEvent) => {
- const message = event.data ?? {};
- if (message.type === 'ready') {
- settleReady?.();
- settleReady = null;
- return;
- }
- if (message.type === 'error') {
- // The runtime failed to load (network, or the browser is unsupported).
- teardown(new Error(message.message));
- return;
- }
- const request = pending[message.id];
- if (!request) return;
- delete pending[message.id];
- if (message.error != null) {
- request.reject(new Error(message.error));
- } else {
- request.resolve(message.result);
- }
- };
-
- const spawn = () => {
- ready = new Promise((resolve, reject) => {
- settleReady = (error?: Error) => (error ? reject(error) : resolve());
- });
- worker = createWorkerFromContent(getWorkerSrc(language));
- worker.onmessage = onMessage;
- worker.onerror = (event) => teardown(new Error(`The Clang worker crashed: ${event.message}`));
- };
-
- /** Spawn the worker if needed and resolve once the compiler has loaded. */
- const ensureReady = async () => {
- if (!ready) spawn();
- await ready;
- };
-
- const run = (code: string, input: string, options?: ClangWasmSettings) =>
- ensureReady().then(
- () =>
- new Promise((resolve, reject) => {
- const id = nextId++;
- pending[id] = { resolve, reject };
- worker?.postMessage({ id, code, input, options });
- }),
- );
-
- return { ensureReady, run };
-};
-
const getLanguage = (): LanguageId | null => {
for (const scriptType of SCRIPT_TYPES) {
if (document.querySelector(`script[type="${scriptType}"]`)) {
@@ -282,7 +194,8 @@ clangWasm.run = async (input?: string) => {
if (!code.trim()) return setResult(stdin, null, null, null);
const runner = (clangWasm.runners[language] =
- clangWasm.runners[language] || createRunner(language));
+ clangWasm.runners[language] ||
+ createWorkerRunner({ getWorkerSrc: () => getWorkerSrc(language), label: 'Clang' }));
try {
await ensureLoaded(runner);
diff --git a/src/livecodes/languages/cobol-wasm/__tests__/lang-cobol-wasm.spec.ts b/src/livecodes/languages/cobol-wasm/__tests__/lang-cobol-wasm.spec.ts
new file mode 100644
index 0000000000..8a3a719f6a
--- /dev/null
+++ b/src/livecodes/languages/cobol-wasm/__tests__/lang-cobol-wasm.spec.ts
@@ -0,0 +1,30 @@
+import { cobolWasm } from '../lang-cobol-wasm';
+
+describe('COBOL (Wasm) language spec', () => {
+ it('is registered as cobol-wasm, with the wasm compiler script', () => {
+ expect(cobolWasm.name).toBe('cobol-wasm');
+ expect(cobolWasm.title).toBe('COBOL (Wasm)');
+ expect(cobolWasm.compiler).toMatchObject({
+ scriptType: 'text/cobol-wasm',
+ compiledCodeLanguage: 'cobol',
+ liveReload: true,
+ });
+ });
+
+ it('accepts the common COBOL extensions', () => {
+ expect(cobolWasm.extensions).toEqual(
+ expect.arrayContaining(['cobol', 'cob', 'cbl', 'cpy', 'gnucobol']),
+ );
+ });
+
+ it('warns that the first run is a large download', () => {
+ // The GnuCOBOL + Clang toolchain is ~25 MB; the app shows a loading indicator for it.
+ expect(cobolWasm.largeDownload).toBe(true);
+ });
+
+ it('uses the COBOL editors', () => {
+ expect(cobolWasm.editor).toBe('script');
+ expect(cobolWasm.editorSupport?.monaco?.language).toBe('cobol');
+ expect(cobolWasm.editorSupport?.codejar?.language).toBe('cobol');
+ });
+});
diff --git a/src/livecodes/languages/cobol-wasm/index.ts b/src/livecodes/languages/cobol-wasm/index.ts
new file mode 100644
index 0000000000..10601c357d
--- /dev/null
+++ b/src/livecodes/languages/cobol-wasm/index.ts
@@ -0,0 +1 @@
+export * from './lang-cobol-wasm';
diff --git a/src/livecodes/languages/cobol-wasm/lang-cobol-wasm-script.ts b/src/livecodes/languages/cobol-wasm/lang-cobol-wasm-script.ts
new file mode 100644
index 0000000000..720c6d53e7
--- /dev/null
+++ b/src/livecodes/languages/cobol-wasm/lang-cobol-wasm-script.ts
@@ -0,0 +1,235 @@
+/* eslint-disable no-console */
+import { getErrorMessage } from '../../utils/utils';
+import { cobolWasmBaseUrl, cobolWasmClangBaseUrl } from '../../vendors';
+import { createWorkerRunner, type Runner } from '../worker-runner';
+
+// One runner for one language. GnuCOBOL is the real compiler (@live-codes/cobol-wasm), loaded from
+// its CDN build: the IIFE defines `self.cobolWasm`, which the worker reaches with importScripts.
+// It translates COBOL to C, compiles that with Clang and links libcob/GMP, then runs the resulting
+// WASI module in place, because a browser has no linker subprocess to hand a binary to.
+const SCRIPT_TYPE = 'text/cobol-wasm';
+
+/** Per-run options forwarded to `@live-codes/cobol-wasm`'s `run`, read from `config.customSettings`. */
+interface CobolWasmSettings {
+ sourceFormat?: 'free' | 'fixed';
+ compileArgs?: string[];
+ cCompileArgs?: string[];
+ args?: string[];
+ fileName?: string;
+}
+
+interface RunResult {
+ input: string;
+ output: string | null;
+ error: string | null;
+ exitCode: number | null;
+}
+
+interface CobolWasmApi {
+ ready: boolean;
+ failed: boolean;
+ input: string;
+ output: string | null;
+ error: string | null;
+ exitCode: number | null;
+ loaded: Promise;
+ init: Promise | null;
+ runner: Runner | null;
+ settings?: CobolWasmSettings;
+ run: (input?: string) => Promise;
+}
+
+declare const window: Window & {
+ livecodes: Record;
+};
+
+const getWorkerSrc = () => `
+importScripts(${JSON.stringify(cobolWasmBaseUrl + 'dist/cobol-wasm.global.js')});
+
+let compiler = null;
+
+const getCompiler = () => {
+ compiler =
+ compiler ||
+ self.cobolWasm.createCompiler({
+ baseUrl: ${JSON.stringify(cobolWasmBaseUrl + 'assets/')},
+ // The Clang half is pinned by the package, so it comes from that exact version's assets.
+ clangBaseUrl: ${JSON.stringify(cobolWasmClangBaseUrl)},
+ });
+ return compiler;
+};
+
+addEventListener('message', async (event) => {
+ const { id, code, input, options } = event.data;
+ try {
+ const result = await (await getCompiler()).run(code, input, options);
+ postMessage({
+ id,
+ result: {
+ output: result.output,
+ // The package reports the compiler's diagnostics here; empty when the program compiled.
+ errors: result.errors || [],
+ exitCode: result.exitCode,
+ },
+ });
+ } catch (error) {
+ postMessage({ id, error: String((error && error.message) || error) });
+ }
+});
+
+getCompiler().then(
+ () => postMessage({ type: 'ready' }),
+ (error) => postMessage({ type: 'error', message: String((error && error.message) || error) }),
+);
+`;
+
+// A single compile + run is normally quick; a long timeout guards against hangs (e.g. an infinite
+// loop in the user program) by killing and respawning the worker.
+const RUN_TIMEOUT_MS = 120000;
+
+/**
+ * Reads the program out of the result page.
+ *
+ * The result page writes the code inline as the `innerHTML` of a
+ * `` in a setting (e.g. a compile argument) from closing the tag.
+ const serialized = JSON.stringify(settings).replace(/ async (code) => code,
+ scripts: ({ baseUrl }) => [baseUrl + '{{hash:lang-cobol-wasm-script.js}}'],
+ inlineScript: ({ config }) => getSettingsScript(config),
+ scriptType: 'text/cobol-wasm',
+ compiledCodeLanguage: 'cobol',
+ liveReload: true,
+ },
+ extensions: ['cobol', 'cob', 'cbl', 'cpy', 'gnucobol', 'wasm.cobol'],
+ editor: 'script',
+ editorSupport: {
+ monaco: { languageSupport: monacoLanguagesBaseUrl + 'cobol.js', language: 'cobol' },
+ codemirror: {
+ languageSupport: async () =>
+ codemirrorLegacy((await import(codeMirrorBaseUrl + 'codemirror-lang-cobol.js')).cobol),
+ },
+ codejar: { language: 'cobol' },
+ },
+ largeDownload: true,
+};
diff --git a/src/livecodes/languages/fortran-wasm/lang-fortran-wasm-script.ts b/src/livecodes/languages/fortran-wasm/lang-fortran-wasm-script.ts
index 4b7f702c63..5ba0b8e61c 100644
--- a/src/livecodes/languages/fortran-wasm/lang-fortran-wasm-script.ts
+++ b/src/livecodes/languages/fortran-wasm/lang-fortran-wasm-script.ts
@@ -1,6 +1,7 @@
/* eslint-disable no-console */
-import { createWorkerFromContent, getErrorMessage } from '../../utils/utils';
+import { getErrorMessage } from '../../utils/utils';
import { fortranWasmBaseUrl } from '../../vendors';
+import { createWorkerRunner, type Runner } from '../worker-runner';
// One runner for one language. The compiler itself is @live-codes/lfortran-wasm, loaded from its
// CDN build: the IIFE defines `self.lfortranWasm`, which the worker reaches with importScripts.
@@ -8,12 +9,6 @@ import { fortranWasmBaseUrl } from '../../vendors';
// subprocess to hand a binary to.
const SCRIPT_TYPE = 'text/fortran-wasm';
-interface WorkerRunResult {
- output: string;
- errors: string[];
- exitCode: number | null;
-}
-
interface RunResult {
input: string;
output: string | null;
@@ -21,11 +16,6 @@ interface RunResult {
exitCode: number | null;
}
-interface Runner {
- ensureReady: () => Promise;
- run: (code: string, input: string) => Promise;
-}
-
interface FortranWasmApi {
ready: boolean;
input: string;
@@ -84,98 +74,6 @@ getCompiler().then(
// loop in the user program) by killing and respawning the worker.
const RUN_TIMEOUT_MS = 120000;
-interface Pending {
- resolve: (result: WorkerRunResult) => void;
- reject: (error: Error) => void;
- timer: ReturnType;
-}
-
-const createRunner = (): Runner => {
- let worker: Worker | null = null;
- let ready: Promise | null = null;
- let settleReady: ((error?: Error) => void) | null = null;
- let pending: Record = {};
- let nextId = 1;
-
- const failAll = (error: Error) => {
- for (const id of Object.keys(pending)) {
- const request = pending[Number(id)];
- clearTimeout(request.timer);
- request.reject(error);
- }
- pending = {};
- };
-
- const teardown = (error: Error) => {
- worker?.terminate();
- worker = null;
- ready = null;
- settleReady?.(error);
- settleReady = null;
- failAll(error);
- };
-
- const onMessage = (event: MessageEvent) => {
- const message = event.data ?? {};
- if (message.type === 'ready') {
- settleReady?.();
- settleReady = null;
- return;
- }
- if (message.type === 'error') {
- // The runtime failed to load (network, or the browser is unsupported).
- teardown(new Error(message.message));
- return;
- }
- const request = pending[message.id];
- if (!request) return;
- delete pending[message.id];
- clearTimeout(request.timer);
- if (message.error != null) {
- request.reject(new Error(message.error));
- } else {
- request.resolve(message.result);
- }
- };
-
- const spawn = () => {
- ready = new Promise((resolve, reject) => {
- settleReady = (error?: Error) => (error ? reject(error) : resolve());
- });
- worker = createWorkerFromContent(getWorkerSrc());
- worker.onmessage = onMessage;
- worker.onerror = (event) => teardown(new Error(`The Fortran worker crashed: ${event.message}`));
- };
-
- /** Spawn the worker if needed and resolve once the compiler has loaded. */
- const ensureReady = async () => {
- if (!ready) spawn();
- await ready;
- };
-
- const run = (code: string, input: string) =>
- ensureReady().then(
- () =>
- new Promise((resolve, reject) => {
- // `ensureReady` can resolve after the worker has been torn down (crash or timeout), so
- // the worker may be gone by the time the request is registered.
- if (!worker) {
- reject(new Error('The Fortran worker is not available'));
- return;
- }
- const id = nextId++;
- const timer = setTimeout(() => {
- // The worker hung — kill it and reject, so the next run respawns a fresh worker.
- teardown(new Error('The Fortran compiler timed out'));
- }, RUN_TIMEOUT_MS);
- pending[id] = { resolve, reject, timer };
- worker.postMessage({ id, code, input });
- }),
- );
-
- return { ensureReady, run };
-};
-
/**
* Reads the program out of the result page.
*
@@ -264,7 +162,9 @@ fortranWasm.run = async (input?: string) => {
return setResult(stdin, null, null, null);
}
- const runner = (fortranWasm.runner = fortranWasm.runner || createRunner());
+ const runner = (fortranWasm.runner =
+ fortranWasm.runner ||
+ createWorkerRunner({ getWorkerSrc, label: 'Fortran', timeoutMs: RUN_TIMEOUT_MS }));
try {
await ensureLoaded(runner);
diff --git a/src/livecodes/languages/languages.ts b/src/livecodes/languages/languages.ts
index 47e4e63a1e..b61e8f9365 100644
--- a/src/livecodes/languages/languages.ts
+++ b/src/livecodes/languages/languages.ts
@@ -14,6 +14,7 @@ import { cWasm, cppWasm, objcWasm, objcppWasm } from './clang-wasm';
import { clio } from './clio';
import { clojurescriptCherry } from './clojurescript-cherry';
import { clojurescriptSelfHosted } from './clojurescript-selfhosted';
+import { cobolWasm } from './cobol-wasm';
import { coffeescript } from './coffeescript';
import { commonlisp } from './commonlisp';
import { cpp } from './cpp';
@@ -171,6 +172,7 @@ export const languages: LanguageSpecs[] = [
objcWasm,
objcppWasm,
fortranWasm,
+ cobolWasm,
rustWasm,
swiftWasm,
zigWasm,
diff --git a/src/livecodes/languages/worker-runner.ts b/src/livecodes/languages/worker-runner.ts
new file mode 100644
index 0000000000..bf77e7557f
--- /dev/null
+++ b/src/livecodes/languages/worker-runner.ts
@@ -0,0 +1,130 @@
+import { createWorkerFromContent } from '../utils/utils';
+
+/** The result a language worker reports for a single compile + run. */
+export interface WorkerRunResult {
+ output: string;
+ errors: string[];
+ exitCode: number | null;
+}
+
+export interface Runner {
+ ensureReady: () => Promise;
+ run: (code: string, input: string, options?: unknown) => Promise;
+ destroy: () => void;
+}
+
+export interface WorkerRunnerOptions {
+ /**
+ * The classic worker that loads the runtime. It must post `{ type: 'ready' | 'error' }` when the
+ * runtime has loaded (or failed to), and a run result keyed by the request id otherwise.
+ */
+ getWorkerSrc: () => string;
+ /** Shown in crash, timeout and unavailability messages, e.g. `Fortran`. */
+ label: string;
+ /** Kill the worker when a single run does not settle within this many milliseconds. */
+ timeoutMs?: number;
+}
+
+interface Pending {
+ resolve: (result: TResult) => void;
+ reject: (error: Error) => void;
+ timer?: ReturnType;
+}
+
+/**
+ * A serialized worker runner shared by the WASM languages. It keeps one worker for the compiler's
+ * lifetime, tears it down on crashes/timeouts and respawns it on the next run.
+ */
+export const createWorkerRunner = ({
+ getWorkerSrc,
+ label,
+ timeoutMs,
+}: WorkerRunnerOptions): Runner => {
+ let worker: Worker | null = null;
+ let ready: Promise | null = null;
+ let settleReady: ((error?: Error) => void) | null = null;
+ let pending: Record> = {};
+ let nextId = 1;
+
+ const failAll = (error: Error) => {
+ for (const id of Object.keys(pending)) {
+ const request = pending[Number(id)];
+ if (request.timer) clearTimeout(request.timer);
+ request.reject(error);
+ }
+ pending = {};
+ };
+
+ const teardown = (error?: Error) => {
+ worker?.terminate();
+ worker = null;
+ ready = null;
+ settleReady?.(error);
+ settleReady = null;
+ if (error) failAll(error);
+ };
+
+ const onMessage = (event: MessageEvent) => {
+ const message = event.data ?? {};
+ if (message.type === 'ready') {
+ settleReady?.();
+ settleReady = null;
+ return;
+ }
+ if (message.type === 'error') {
+ // The runtime failed to load (network, or the browser is unsupported).
+ teardown(new Error(message.message));
+ return;
+ }
+ const request = pending[message.id];
+ if (!request) return;
+ delete pending[message.id];
+ if (request.timer) clearTimeout(request.timer);
+ if (message.error != null) {
+ request.reject(new Error(message.error));
+ } else {
+ request.resolve(message.result);
+ }
+ };
+
+ const spawn = () => {
+ ready = new Promise((resolve, reject) => {
+ settleReady = (error?: Error) => (error ? reject(error) : resolve());
+ });
+ worker = createWorkerFromContent(getWorkerSrc());
+ worker.onmessage = onMessage;
+ worker.onerror = (event) =>
+ teardown(new Error(`The ${label} worker crashed: ${event.message}`));
+ };
+
+ /** Spawn the worker if needed and resolve once the runtime has loaded. */
+ const ensureReady = async () => {
+ if (!ready) spawn();
+ await ready;
+ };
+
+ const run = (code: string, input: string, options?: unknown) =>
+ ensureReady().then(
+ () =>
+ new Promise((resolve, reject) => {
+ // `ensureReady` can resolve after the worker has been torn down (crash or timeout), so
+ // the worker may be gone by the time the request is registered.
+ if (!worker) {
+ reject(new Error(`The ${label} worker is not available`));
+ return;
+ }
+ const id = nextId++;
+ const request: Pending = { resolve, reject };
+ if (timeoutMs != null) {
+ request.timer = setTimeout(() => {
+ // The worker hung, so kill it and reject; the next run respawns a fresh worker.
+ teardown(new Error(`The ${label} compiler timed out`));
+ }, timeoutMs);
+ }
+ pending[id] = request;
+ worker.postMessage({ id, code, input, options });
+ }),
+ );
+
+ return { ensureReady, run, destroy: () => teardown() };
+};
diff --git a/src/livecodes/models.ts b/src/livecodes/models.ts
index 53bee5aee2..cdfe37a9bc 100644
--- a/src/livecodes/models.ts
+++ b/src/livecodes/models.ts
@@ -202,6 +202,7 @@ export interface Compiler {
| 'text/objc-wasm'
| 'text/objcpp-wasm'
| 'text/fortran-wasm'
+ | 'text/cobol-wasm'
| 'text/rust-wasm'
| 'text/zig-wasm'
| 'text/java'
diff --git a/src/livecodes/templates/starter/cobol-wasm-starter.ts b/src/livecodes/templates/starter/cobol-wasm-starter.ts
new file mode 100644
index 0000000000..bf511a1c6f
--- /dev/null
+++ b/src/livecodes/templates/starter/cobol-wasm-starter.ts
@@ -0,0 +1,102 @@
+import type { Template } from '../../models';
+
+/**
+ * The COBOL starter, matching the other Wasm starters: the markup drives the program through the
+ * `livecodes.cobol` API. The program's first line names the language — which is what the heading
+ * shows — and the second is a counter the button increments by re-running with new input.
+ */
+export const cobolWasmStarter: Template = {
+ name: 'cobol-wasm',
+ title: window.deps.translateString('templates.starter.cobol-wasm', 'COBOL Starter'),
+ thumbnail: 'assets/templates/cobol.svg',
+ activeEditor: 'script',
+ markup: {
+ language: 'html',
+ content: `
+
+
Hello, World!
+

+
You clicked 0 times.
+
+
+
+
+`.trimStart(),
+ },
+ style: {
+ language: 'css',
+ content: `
+.container,
+.container button {
+ text-align: center;
+ font: 1em sans-serif;
+}
+.logo {
+ width: 150px;
+}
+`.trimStart(),
+ },
+ script: {
+ language: 'cobol',
+ content: `
+IDENTIFICATION DIVISION.
+PROGRAM-ID. COUNTER.
+DATA DIVISION.
+WORKING-STORAGE SECTION.
+01 WS-COUNT PIC S9(3).
+01 WS-OUT PIC ZZZ9.
+PROCEDURE DIVISION.
+ DISPLAY "COBOL"
+ ACCEPT WS-COUNT
+ ADD 1 TO WS-COUNT
+ MOVE WS-COUNT TO WS-OUT
+ DISPLAY FUNCTION TRIM(WS-OUT)
+ STOP RUN.
+`.trimStart(),
+ },
+};
diff --git a/src/livecodes/templates/starter/index.ts b/src/livecodes/templates/starter/index.ts
index 7b172772c7..6647ec7b83 100644
--- a/src/livecodes/templates/starter/index.ts
+++ b/src/livecodes/templates/starter/index.ts
@@ -15,6 +15,7 @@ import { cWasmStarter, cppWasmStarter, objcWasmStarter } from './clang-wasm-star
import { clioStarter } from './clio-starter';
import { clojurescriptStarter } from './clojurescript-cherry-starter';
import { cljsSelfHostedStarter } from './clojurescript-selfhosted-starter';
+import { cobolWasmStarter } from './cobol-wasm-starter';
import { coffeescriptStarter } from './coffeescript-starter';
import { commonlispStarter } from './commonlisp-starter';
import { cppStarter } from './cpp-starter';
@@ -138,6 +139,7 @@ export const starterTemplates = [
cWasmStarter,
cppWasmStarter,
objcWasmStarter,
+ cobolWasmStarter,
fortranWasmStarter,
rustWasmStarter,
swiftWasmStarter,
diff --git a/src/livecodes/vendors.ts b/src/livecodes/vendors.ts
index 8fd81b246f..44fc5d65c5 100644
--- a/src/livecodes/vendors.ts
+++ b/src/livecodes/vendors.ts
@@ -102,6 +102,12 @@ export const cm6ThemeSolarizedDarkUrl = /* @__PURE__ */ getUrl(
'cm6-theme-solarized-dark@0.2.0/dist/index.js',
);
+export const cobolWasmBaseUrl = /* @__PURE__ */ getUrl('@live-codes/cobol-wasm@0.1.0/');
+
+// `@live-codes/cobol-wasm` pins this exact `@live-codes/clang-wasm` version for the Clang half of its
+// toolchain, and the runtime re-derives those assets' digests, so the two must stay in step.
+export const cobolWasmClangBaseUrl = /* @__PURE__ */ getUrl('@live-codes/clang-wasm@0.3.0/assets/');
+
export const codeiumProviderUrl = /* @__PURE__ */ getUrl(
'@live-codes/monaco-codeium-provider@0.2.2/dist/index.js',
);
diff --git a/src/sdk/models.ts b/src/sdk/models.ts
index b746207a07..2ade86ec3c 100644
--- a/src/sdk/models.ts
+++ b/src/sdk/models.ts
@@ -175,6 +175,13 @@ export type Language =
| 'wasm.c'
| 'clang.c'
| 'clang-c'
+ | 'cobol'
+ | 'cob'
+ | 'cbl'
+ | 'cpy'
+ | 'gnucobol'
+ | 'cobol-wasm'
+ | 'wasm.cobol'
| 'fortran'
| 'f90'
| 'f95'
@@ -484,6 +491,7 @@ export type TemplateName =
| 'cpp-wasm'
| 'objc-wasm'
| 'fortran-wasm'
+ | 'cobol-wasm'
| 'java'
| 'csharp-wasm'
| 'blazor-wasm'
diff --git a/storybook/_stories/EmbedOptions/template.ts b/storybook/_stories/EmbedOptions/template.ts
index d9ff83d65c..081df37858 100644
--- a/storybook/_stories/EmbedOptions/template.ts
+++ b/storybook/_stories/EmbedOptions/template.ts
@@ -51,6 +51,8 @@ const storyDef: StoryDef = {
CWasm: { props: { template: 'c-wasm' } },
CppWasm: { props: { template: 'cpp-wasm' } },
ObjcWasm: { props: { template: 'objc-wasm' } },
+ CobolWasm: { props: { template: 'cobol-wasm' }, storyName: 'COBOL (Wasm)' },
+ FortranWasm: { props: { template: 'fortran-wasm' }, storyName: 'Fortran (Wasm)' },
RustWasm: { props: { template: 'rust-wasm' } },
SwiftWasm: { props: { template: 'swift-wasm' } },
ZigWasm: { props: { template: 'zig-wasm' } },
diff --git a/typos.toml b/typos.toml
index 755cdc31ca..0144127c80 100644
--- a/typos.toml
+++ b/typos.toml
@@ -27,6 +27,7 @@ arange = "arange"
touchs = "touchs"
decid = "decid"
Wirth = "Wirth"
+cpy = "cpy"
[type.svg]
# Skip check contents for svg files
diff --git a/vendor-licenses.md b/vendor-licenses.md
index 1df1547e4a..f46ea0731e 100644
--- a/vendor-licenses.md
+++ b/vendor-licenses.md
@@ -344,6 +344,10 @@ wabt.js: [Apache-2.0 license](https://github.com/AssemblyScript/wabt.js/blob/182
wacl: [BSD 3-Clause License](https://github.com/ecky-l/wacl/blob/9daacabb0102a9986f33263261350edfeebdd83b/LICENSE)
+@live-codes/cobol-wasm: [MIT License](https://github.com/live-codes/browser-cobol/blob/main/LICENSE) (the [@live-codes/cobol-wasm](https://www.npmjs.com/package/@live-codes/cobol-wasm) package's own code is MIT, but it ships GnuCOBOL in its assets and so declares `(MIT AND GPL-3.0-or-later)`. Neither GnuCOBOL nor Clang is bundled by LiveCodes; both are loaded at run time)
+
+GnuCOBOL (Wasm): [GPL-3.0-or-later License](https://github.com/OCamlPro/gnucobol/blob/master/COPYING) (the COBOL compiler, shipped in `@live-codes/cobol-wasm`'s assets and loaded at run time by LiveCodes. Its `libcob` runtime is [LGPL-3.0-or-later](https://github.com/OCamlPro/gnucobol/blob/master/COPYING.LESSER), as is the GMP library it links)
+
@live-codes/lfortran-wasm: [MIT License](https://github.com/live-codes/browser-fortran/blob/main/LICENSE)
LFortran (Wasm): [BSD 3-Clause License](https://github.com/lfortran/lfortran/blob/main/LICENSE)