diff --git a/README.md b/README.md
index ad23bf4e4e..14fea73e0c 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/ocaml-js.mdx b/docs/docs/languages/ocaml-js.mdx
new file mode 100644
index 0000000000..2e4c118f37
--- /dev/null
+++ b/docs/docs/languages/ocaml-js.mdx
@@ -0,0 +1,93 @@
+# OCaml (JS)
+
+[OCaml](https://ocaml.org/) is an industrial-strength programming language supporting functional, imperative and object-oriented styles.
+
+LiveCodes runs the OCaml compiler itself, built with [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml), so compilation happens in the browser and nothing is sent to a server. The compiler emits a JavaScript program, which the result page then runs.
+
+:::info Note
+
+LiveCodes also has an `ocaml` language, which runs the [ReScript](https://rescript-lang.org/) compiler. It is deprecated in favour of this one. Read documentation [here](./ocaml.mdx).
+
+:::
+
+## Demo
+
+import LiveCodes from '../../src/components/LiveCodes.tsx';
+
+export const params = {
+ 'ocaml-js': 'let () =\n print_endline "Hello, World!"\n',
+ console: 'full',
+};
+
+
+
+## Usage
+
+LiveCodes runs OCaml in the browser, including the standard library.
+
+Because the compiled program *is* JavaScript by the time it runs, it can interact with the page. JavaScript interoperability and DOM access come from [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml)'s `Js` and `Dom_html` with `open Js_of_ocaml` (see the [example below](#example-usage)).
+
+## Modules and Libraries
+
+The standard library is always available. Beyond it, these are linked on demand — the archive is fetched the first time a program names one of its modules, so a program that uses none of them downloads none of them.
+
+- **js_of_ocaml** — `Js`, `Dom_html`, and the rest of the browser APIs
+- **Str**, **Unix**, **Graphics** — from the OCaml distribution
+- **Lwt**, **js_of_ocaml-lwt** — promises and concurrency
+- **Re** — regular expressions
+- **jsonm**, **xmlm**, **uutf** — JSON, XML and Unicode text
+- **fmt**, **logs** — formatting and logging
+- **base64** — base64 encoding
+- **Zarith** — `Z` and `Q`, arbitrary-precision integers and rationals
+
+Everything here runs in the browser, so a library has to be pure OCaml, or have a JavaScript replacement for its C stubs — Zarith's are provided by `zarith_stubs_js`. Anything needing real threads, processes or a filesystem will not work, whatever is linked.
+
+This is the set built with the compiler. Other opam packages are not available.
+
+## Language Info
+
+### Name
+
+`ocaml-js`
+
+### Extensions
+
+`js.ocaml`, `js.ml`
+
+### Editor
+
+`script`
+
+## Compiler
+
+The OCaml compiler — the same `compiler-libs` frontend that compiles ordinary OCaml — compiled to JavaScript with [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml). It is published as [@live-codes/ocaml](https://www.npmjs.com/package/@live-codes/ocaml).
+
+### Version
+
+`@live-codes/ocaml`: v0.2.0
+
+## Code Formatting
+
+Not supported.
+
+## Limitations
+
+There is no ppx support, since a ppx would have to run at compile time and compilation happens at run time here. So `##`, `##.` and `[%js]` are not available; use `Js.Unsafe` and the rest of the bindings instead.
+
+## Example Usage
+
+This example counts button clicks in the DOM, using `Dom_html`:
+
+
+
+## Starter Template
+
+https://livecodes.io/?template=ocaml-js
+
+## Links
+
+- [OCaml website](https://ocaml.org/)
+- [OCaml documentation](https://ocaml.org/docs/)
+- [@live-codes/ocaml on npm](https://www.npmjs.com/package/@live-codes/ocaml)
+- [js_of_ocaml](https://github.com/ocsigen/js_of_ocaml)
+- [OCaml with the ReScript compiler](./ocaml.mdx) in LiveCodes
diff --git a/docs/docs/languages/ocaml.mdx b/docs/docs/languages/ocaml.mdx
index fe5b1d5b0f..5b9b2c2e12 100644
--- a/docs/docs/languages/ocaml.mdx
+++ b/docs/docs/languages/ocaml.mdx
@@ -4,6 +4,14 @@
LiveCodes compiles OCaml code to JavaScript using the [ReScript compiler](https://rescript-lang.org/). OCaml in LiveCodes supports JSX via a ReasonReact-compatible syntax.
+:::info Deprecation Note
+
+This language is deprecated in favour of [OCaml (JS)](./ocaml-js.mdx).
+
+To continue using this language use the language name `rescript-ocaml`.
+
+:::
+
## Usage
### Demo
@@ -66,6 +74,10 @@ OCaml React does not support React 19. Use an import map (in [custom settings](.
`ocaml`
+### Aliases
+
+`rescript-ocaml`
+
### Extensions
`.ml`, `.mli`
diff --git a/docs/src/components/LanguageSliders.tsx b/docs/src/components/LanguageSliders.tsx
index f9d6ce81aa..9c886360a0 100644
--- a/docs/src/components/LanguageSliders.tsx
+++ b/docs/src/components/LanguageSliders.tsx
@@ -77,6 +77,7 @@ export default function Sliders() {
{ name: 'elm', title: 'Elm' },
{ name: 'rescript', title: 'ReScript' },
{ name: 'reason', title: 'Reason' },
+ { name: 'ocaml-js', title: 'OCaml (JS)' },
{ name: 'ocaml', title: 'OCaml' },
{ name: 'nim', title: 'Nim' },
{ name: 'nim-wasm', title: 'Nim (Wasm)' },
diff --git a/docs/src/components/TemplateList.tsx b/docs/src/components/TemplateList.tsx
index 4ae8323165..434be56784 100644
--- a/docs/src/components/TemplateList.tsx
+++ b/docs/src/components/TemplateList.tsx
@@ -37,6 +37,7 @@ const templates = [
{ name: 'rescript', title: 'ReScript Starter', thumbnail: 'rescript.png' },
{ name: 'reason', title: 'Reason Starter', thumbnail: 'reason.svg' },
{ name: 'ocaml', title: 'Ocaml Starter', thumbnail: 'ocaml.svg' },
+ { name: 'ocaml-js', title: 'OCaml (JS) Starter', thumbnail: 'ocaml.svg' },
{ name: 'nim', title: 'Nim Starter', thumbnail: 'nim.svg' },
{ name: 'nim-wasm', title: 'Nim (Wasm) Starter', thumbnail: 'nim.svg' },
{ name: 'janet-wasm', title: 'Janet (Wasm) Starter', thumbnail: 'janet.png' },
diff --git a/e2e/specs/compilers.spec.ts b/e2e/specs/compilers.spec.ts
index d94f4cf736..4a106409e3 100644
--- a/e2e/specs/compilers.spec.ts
+++ b/e2e/specs/compilers.spec.ts
@@ -1494,6 +1494,30 @@ export class App {
};`);
});
+ test('OCaml (JS)', async ({ page, getTestUrl }) => {
+ await page.goto(getTestUrl());
+
+ const { app, getResult, waitForResultUpdate } = await getLoadedApp(page);
+
+ await app.click(':nth-match([title="Change Language"], 3)');
+ await (await app.$('[data-lang="ocaml-js"]'))?.click();
+ await waitForEditorFocus(app);
+ await page.keyboard.insertText(
+ [
+ 'let () =',
+ ' let squares = List.init 5 (fun i -> i * i) in',
+ ' Printf.printf "sum=%d\\n" (List.fold_left (+) 0 squares)',
+ ].join('\n'),
+ );
+
+ await waitForResultUpdate();
+ const resultText = await getResult().innerHTML('body > script');
+
+ // The real OCaml compiler, compiled to JavaScript, emitted a bundle the page runs.
+ expect(resultText).toContain('// Generated by js_of_ocaml');
+ expect(resultText).toContain('sum=');
+ });
+
test('LiveScript', async ({ page, getTestUrl, editor }) => {
test.skip(editor === 'codejar', 'please fix');
diff --git a/functions/vendors/templates.js b/functions/vendors/templates.js
index a9b989323d..523a9ba4c0 100644
--- a/functions/vendors/templates.js
+++ b/functions/vendors/templates.js
@@ -37,6 +37,7 @@ export const starterTemplates = {
"rescript": "ReScript Starter",
"reason": "Reason Starter",
"ocaml": "Ocaml Starter",
+ "ocaml-js": "OCaml (JS) Starter",
"nim": "Nim Starter",
"nim-wasm": "Nim (Wasm) Starter",
"crystal-wasm": "Crystal Starter",
diff --git a/scripts/build.js b/scripts/build.js
index 9436141539..5399a744b0 100644
--- a/scripts/build.js
+++ b/scripts/build.js
@@ -203,6 +203,7 @@ const esmBuild = () =>
'languages/postgresql/lang-postgresql-compiler-esm.ts',
'languages/duckdb/lang-duckdb-compiler-esm.ts',
'languages/r/lang-r-script-esm.ts',
+ 'languages/ocaml-js/lang-ocaml-js-compiler-esm.ts',
'languages/rescript/lang-rescript-compiler-esm.ts',
'i18n/i18n.ts',
]
diff --git a/server/php/inc/starter-templates.json b/server/php/inc/starter-templates.json
index 6c14769131..af0fff7c46 100644
--- a/server/php/inc/starter-templates.json
+++ b/server/php/inc/starter-templates.json
@@ -37,6 +37,7 @@
"rescript": "ReScript Starter",
"reason": "Reason Starter",
"ocaml": "Ocaml Starter",
+ "ocaml-js": "OCaml (JS) Starter",
"nim": "Nim Starter",
"nim-wasm": "Nim (Wasm) Starter",
"crystal-wasm": "Crystal Starter",
diff --git a/src/livecodes/UI/command-menu-actions.ts b/src/livecodes/UI/command-menu-actions.ts
index 45689e5e35..64d9c15564 100644
--- a/src/livecodes/UI/command-menu-actions.ts
+++ b/src/livecodes/UI/command-menu-actions.ts
@@ -293,6 +293,7 @@ export const getCommandMenuActions = ({
'rescript',
'reason',
'ocaml',
+ 'ocaml-js',
'nim',
'nim-wasm',
'janet-wasm',
diff --git a/src/livecodes/assets/templates/ocaml.svg b/src/livecodes/assets/templates/ocaml.svg
index 7df1be4624..675eb33351 100644
--- a/src/livecodes/assets/templates/ocaml.svg
+++ b/src/livecodes/assets/templates/ocaml.svg
@@ -1 +1,116 @@
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/livecodes/compiler/compile.page.ts b/src/livecodes/compiler/compile.page.ts
index 85d1792872..8fbd92515b 100644
--- a/src/livecodes/compiler/compile.page.ts
+++ b/src/livecodes/compiler/compile.page.ts
@@ -1,6 +1,7 @@
import { runOutsideWorker as diagrams } from '../languages/diagrams';
import { runOutsideWorker as duckdb } from '../languages/duckdb';
import { runOutsideWorker as mdx } from '../languages/mdx';
+import { runOutsideWorker as ocamlJs } from '../languages/ocaml-js';
import { runOutsideWorker as postgresql } from '../languages/postgresql';
import { runOutsideWorker as rescript } from '../languages/rescript';
@@ -8,6 +9,7 @@ import { runOutsideWorker as rescript } from '../languages/rescript';
rescript,
reason: rescript,
ocaml: rescript,
+ 'ocaml-js': ocamlJs,
mdx,
diagrams,
postgresql,
diff --git a/src/livecodes/html/language-info.html b/src/livecodes/html/language-info.html
index f3ace733f1..09f7d7a694 100644
--- a/src/livecodes/html/language-info.html
+++ b/src/livecodes/html/language-info.html
@@ -1834,6 +1834,33 @@
Objective-C++ (Wasm)
+
+ OCaml (JS)
+
+ OCaml is an industrial-strength programming language supporting functional, imperative and
+ object-oriented styles.
+
+
+ The OCaml compiler runs in the browser and compiles to JavaScript. Nothing is sent to a server.
+
+
+
+
OCaml
diff --git a/src/livecodes/i18n/locales/ar/language-info.lokalise.json b/src/livecodes/i18n/locales/ar/language-info.lokalise.json
index 66999f5637..54be4eed48 100644
--- a/src/livecodes/i18n/locales/ar/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ar/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml هي لغة برمجة صناعية تدعم الأنماط الوظيفية والإجرائية والكائنية."
+ },
+ "ocamlJs.desc2": {
+ "translation": "يعمل مُترجم OCaml في المتصفح ويُترجم إلى JavaScript. لا يُرسَل أي شيء إلى خادم."
+ },
+ "ocamlJs.link": {
+ "translation": "
موقع OCaml وثائق OCaml تعلم X في Y دقائق، حيث X=OCaml تحميل القالب الأولي "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal يعمل في المتصفح باستخدام pas2js (من فريق Free Pascal) ومُجمَّع إلى WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/ar/language-info.ts b/src/livecodes/i18n/locales/ar/language-info.ts
index ba790a63dc..902b978a49 100644
--- a/src/livecodes/i18n/locales/ar/language-info.ts
+++ b/src/livecodes/i18n/locales/ar/language-info.ts
@@ -352,6 +352,12 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>موقع OCaml2>1> <3> <4>وثائق OCaml4> 3> <5> <6>موقع ReScript6> 5> <7> <8>تعلم X في Y دقائق، حيث X=OCaml8> 7> <9> <10>تحميل القالب الأولي10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1: 'OCaml هي لغة برمجة صناعية تدعم الأنماط الوظيفية والإجرائية والكائنية.',
+ desc2: 'يعمل مُترجم OCaml في المتصفح ويُترجم إلى JavaScript. لا يُرسَل أي شيء إلى خادم.',
+ link: '<1><2>موقع OCaml2>1> <3> <4>وثائق OCaml4> 3> <5> <6>تعلم X في Y دقائق، حيث X=OCaml6> 5> <7> <8>تحميل القالب الأولي8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal يعمل في المتصفح باستخدام pas2js (من فريق Free Pascal) ومُجمَّع إلى WebAssembly.',
link: '<1> <2>الموقع الرسمي لـ Free Pascal2> 1> <3> <4>وثائق pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>وثائق LiveCodes8> 7> <9> <10>تحميل القالب الأولي10> 9>',
diff --git a/src/livecodes/i18n/locales/ar/translation.lokalise.json b/src/livecodes/i18n/locales/ar/translation.lokalise.json
index 9c6151e3c1..bce1615867 100644
--- a/src/livecodes/i18n/locales/ar/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ar/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "قالب Ocaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "قالب OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "قالب Pascal"
},
diff --git a/src/livecodes/i18n/locales/ar/translation.ts b/src/livecodes/i18n/locales/ar/translation.ts
index 310eaed198..b69c1e35e5 100644
--- a/src/livecodes/i18n/locales/ar/translation.ts
+++ b/src/livecodes/i18n/locales/ar/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'قالب Nim (Wasm)',
'objc-wasm': 'قالب Objective-C (Wasm)',
ocaml: 'قالب Ocaml',
+ 'ocaml-js': 'قالب OCaml (JS)',
pascal: 'قالب Pascal',
perl: 'قالب Perl',
phaser: 'قالب Phaser',
diff --git a/src/livecodes/i18n/locales/bn/language-info.lokalise.json b/src/livecodes/i18n/locales/bn/language-info.lokalise.json
index 1d41fda745..d2992dd1b4 100644
--- a/src/livecodes/i18n/locales/bn/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/bn/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml একটি শিল্প-মানের প্রোগ্রামিং ভাষা যা ফাংশনাল, ইম্পেরেটিভ এবং অবজেক্ট-ওরিয়েন্টেড স্টাইল সমর্থন করে।"
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml কম্পাইলার ব্রাউজারে চলে এবং JavaScript-এ কম্পাইল করে। কোনো সার্ভারে কিছু পাঠানো হয় না।"
+ },
+ "ocamlJs.link": {
+ "translation": "
OCaml ওয়েবসাইট OCaml ডকুমেন্টেশন Y মিনিটে X শিখুন, যেখানে X=OCaml স্টার্টার টেমপ্লেট লোড করুন "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Free Pascal দলের pas2js ব্যবহার করে ব্রাউজারে Pascal চলছে, যা WebAssembly-তে কম্পাইল করা।"
},
diff --git a/src/livecodes/i18n/locales/bn/language-info.ts b/src/livecodes/i18n/locales/bn/language-info.ts
index 5584ffced1..c286897d47 100644
--- a/src/livecodes/i18n/locales/bn/language-info.ts
+++ b/src/livecodes/i18n/locales/bn/language-info.ts
@@ -354,6 +354,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml ওয়েবসাইট2>1> <3> <4>OCaml ডকুমেন্টেশন4> 3> <5> <6>ReScript ওয়েবসাইট6> 5> <7> <8>Y মিনিটে X শিখুন, যেখানে X=OCaml8> 7> <9> <10>স্টার্টার টেমপ্লেট লোড করুন10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml একটি শিল্প-মানের প্রোগ্রামিং ভাষা যা ফাংশনাল, ইম্পেরেটিভ এবং অবজেক্ট-ওরিয়েন্টেড স্টাইল সমর্থন করে।',
+ desc2:
+ 'OCaml কম্পাইলার ব্রাউজারে চলে এবং JavaScript-এ কম্পাইল করে। কোনো সার্ভারে কিছু পাঠানো হয় না।',
+ link: '<1><2>OCaml ওয়েবসাইট2>1> <3> <4>OCaml ডকুমেন্টেশন4> 3> <5> <6>Y মিনিটে X শিখুন, যেখানে X=OCaml6> 5> <7> <8>স্টার্টার টেমপ্লেট লোড করুন8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Free Pascal দলের pas2js ব্যবহার করে ব্রাউজারে Pascal চলছে, যা WebAssembly-তে কম্পাইল করা।',
link: '<1> <2>Free Pascal অফিসিয়াল ওয়েবসাইট2> 1> <3> <4>pas2js ডকুমেন্টেশন4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes ডকুমেন্টেশন8> 7> <9> <10>স্টার্টার টেমপ্লেট লোড করুন10> 9>',
diff --git a/src/livecodes/i18n/locales/bn/translation.lokalise.json b/src/livecodes/i18n/locales/bn/translation.lokalise.json
index 0eb6f4228f..35cb6a6598 100644
--- a/src/livecodes/i18n/locales/bn/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/bn/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Ocaml স্টার্টার"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS) স্টার্টার"
+ },
"templates.starter.pascal": {
"translation": "Pascal স্টার্টার"
},
diff --git a/src/livecodes/i18n/locales/bn/translation.ts b/src/livecodes/i18n/locales/bn/translation.ts
index 12d0ac84aa..261aff8d1f 100644
--- a/src/livecodes/i18n/locales/bn/translation.ts
+++ b/src/livecodes/i18n/locales/bn/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm) স্টার্টার',
'objc-wasm': 'Objective-C (Wasm) স্টার্টার',
ocaml: 'Ocaml স্টার্টার',
+ 'ocaml-js': 'OCaml (JS) স্টার্টার',
pascal: 'Pascal স্টার্টার',
perl: 'Perl স্টার্টার',
phaser: 'Phaser স্টার্টার',
diff --git a/src/livecodes/i18n/locales/de/language-info.lokalise.json b/src/livecodes/i18n/locales/de/language-info.lokalise.json
index b2f38934bd..07ea64207b 100644
--- a/src/livecodes/i18n/locales/de/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/de/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml ist eine industrietaugliche Programmiersprache, die funktionale, imperative und objektorientierte Stile unterstützt."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Der OCaml-Compiler läuft im Browser und kompiliert zu JavaScript. Es wird nichts an einen Server gesendet."
+ },
+ "ocamlJs.link": {
+ "translation": "
OCaml Website OCaml Dokumentation Lerne X in Y Minuten, wobei X=OCaml Starter-Vorlage laden "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal läuft im Browser mit pas2js (vom Free Pascal-Team) und wird zu WebAssembly kompiliert."
},
diff --git a/src/livecodes/i18n/locales/de/language-info.ts b/src/livecodes/i18n/locales/de/language-info.ts
index 2fd50e8499..4eadb5a4f1 100644
--- a/src/livecodes/i18n/locales/de/language-info.ts
+++ b/src/livecodes/i18n/locales/de/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml Website2>1> <3> <4>OCaml Dokumentation4> 3> <5> <6>ReScript Website6> 5> <7> <8>Lerne X in Y Minuten, wobei X=OCaml8> 7> <9> <10>Starter-Vorlage laden10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml ist eine industrietaugliche Programmiersprache, die funktionale, imperative und objektorientierte Stile unterstützt.',
+ desc2:
+ 'Der OCaml-Compiler läuft im Browser und kompiliert zu JavaScript. Es wird nichts an einen Server gesendet.',
+ link: '<1><2>OCaml Website2>1> <3> <4>OCaml Dokumentation4> 3> <5> <6>Lerne X in Y Minuten, wobei X=OCaml6> 5> <7> <8>Starter-Vorlage laden8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal läuft im Browser mit pas2js (vom Free Pascal-Team) und wird zu WebAssembly kompiliert.',
link: '<1> <2>Offizielle Free Pascal-Website2> 1> <3> <4>pas2js-Dokumentation4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes-Dokumentationen8> 7> <9> <10>Starter-Vorlage laden10> 9>',
diff --git a/src/livecodes/i18n/locales/de/translation.lokalise.json b/src/livecodes/i18n/locales/de/translation.lokalise.json
index ff2f1db7e4..275aad54b4 100644
--- a/src/livecodes/i18n/locales/de/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/de/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "OCaml-Starter"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS)-Starter"
+ },
"templates.starter.pascal": {
"translation": "Pascal-Starter"
},
diff --git a/src/livecodes/i18n/locales/de/translation.ts b/src/livecodes/i18n/locales/de/translation.ts
index 06096e119e..a53e893385 100644
--- a/src/livecodes/i18n/locales/de/translation.ts
+++ b/src/livecodes/i18n/locales/de/translation.ts
@@ -1039,6 +1039,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm)-Starter',
'objc-wasm': 'Objective-C (Wasm)-Starter',
ocaml: 'OCaml-Starter',
+ 'ocaml-js': 'OCaml (JS)-Starter',
pascal: 'Pascal-Starter',
perl: 'Perl-Starter',
phaser: 'Phaser-Starter',
diff --git a/src/livecodes/i18n/locales/en/language-info.lokalise.json b/src/livecodes/i18n/locales/en/language-info.lokalise.json
index bc97a3e294..9bdead6b5b 100644
--- a/src/livecodes/i18n/locales/en/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/en/language-info.lokalise.json
@@ -848,6 +848,22 @@
"notes": "",
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "notes": "",
+ "translation": "OCaml is an industrial-strength programming language supporting functional, imperative and object-oriented styles."
+ },
+ "ocamlJs.desc2": {
+ "notes": "",
+ "translation": "The OCaml compiler runs in the browser and compiles to JavaScript. Nothing is sent to a server."
+ },
+ "ocamlJs.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": "OCaml website OCaml documentation Learn X in Y minutes, where X=OCaml Load starter template "
+ },
+ "ocamlJs.name": {
+ "notes": "",
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"notes": "",
"translation": "Pascal running in the browser using pas2js (by the Free Pascal team) compiled to WebAssembly."
diff --git a/src/livecodes/i18n/locales/en/language-info.ts b/src/livecodes/i18n/locales/en/language-info.ts
index 00c565f32e..fb94cc5632 100644
--- a/src/livecodes/i18n/locales/en/language-info.ts
+++ b/src/livecodes/i18n/locales/en/language-info.ts
@@ -367,6 +367,14 @@ const languageInfo = {
link: '<1><2>OCaml website2>1> <3> <4>OCaml documentation4> 3> <5> <6>ReScript website6> 5> <7> <8>Learn X in Y minutes, where X=OCaml8> 7> <9> <10>Load starter template10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml is an industrial-strength programming language supporting functional, imperative and object-oriented styles.',
+ desc2:
+ 'The OCaml compiler runs in the browser and compiles to JavaScript. Nothing is sent to a server.',
+ link: '<1><2>OCaml website2>1> <3> <4>OCaml documentation4> 3> <5> <6>Learn X in Y minutes, where X=OCaml6> 5> <7> <8>Load starter template8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal running in the browser using pas2js (by the Free Pascal team) compiled to WebAssembly.',
link: '<1> <2>Free Pascal website2> 1> <3> <4>pas2js documentation4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes Documentation8> 7> <9> <10>Load starter template10> 9>',
diff --git a/src/livecodes/i18n/locales/en/translation.lokalise.json b/src/livecodes/i18n/locales/en/translation.lokalise.json
index 0b576592fc..96ea439984 100644
--- a/src/livecodes/i18n/locales/en/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/en/translation.lokalise.json
@@ -2796,6 +2796,10 @@
"notes": "",
"translation": "Ocaml Starter"
},
+ "templates.starter.ocaml-js": {
+ "notes": "",
+ "translation": "OCaml (JS) Starter"
+ },
"templates.starter.pascal": {
"notes": "",
"translation": "Pascal Starter"
diff --git a/src/livecodes/i18n/locales/en/translation.ts b/src/livecodes/i18n/locales/en/translation.ts
index d5d471fa69..e3940de1b2 100644
--- a/src/livecodes/i18n/locales/en/translation.ts
+++ b/src/livecodes/i18n/locales/en/translation.ts
@@ -1045,6 +1045,7 @@ const translation = {
'nim-wasm': 'Nim (Wasm) Starter',
'objc-wasm': 'Objective-C (Wasm) Starter',
ocaml: 'Ocaml Starter',
+ 'ocaml-js': 'OCaml (JS) Starter',
pascal: 'Pascal Starter',
perl: 'Perl Starter',
phaser: 'Phaser Starter',
diff --git a/src/livecodes/i18n/locales/es/language-info.lokalise.json b/src/livecodes/i18n/locales/es/language-info.lokalise.json
index 3e8ab5a1f2..519fbe2dfc 100644
--- a/src/livecodes/i18n/locales/es/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/es/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml es un lenguaje de programación de calidad industrial que admite estilos funcionales, imperativos y orientados a objetos."
+ },
+ "ocamlJs.desc2": {
+ "translation": "El compilador de OCaml se ejecuta en el navegador y compila a JavaScript. No se envía nada a un servidor."
+ },
+ "ocamlJs.link": {
+ "translation": "Sitio web de OCaml Documentación de OCaml Aprende X en Y minutos, donde X=OCaml Cargar plantilla inicial "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal ejecutándose en el navegador usando pas2js (por el equipo de Free Pascal), compilado a WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/es/language-info.ts b/src/livecodes/i18n/locales/es/language-info.ts
index 0d08961637..0deceb75ac 100644
--- a/src/livecodes/i18n/locales/es/language-info.ts
+++ b/src/livecodes/i18n/locales/es/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Sitio web de OCaml2>1> <3> <4>Documentación de OCaml4> 3> <5> <6>Sitio web de ReScript6> 5> <7> <8>Aprende X en Y minutos, donde X=OCaml8> 7> <9> <10>Cargar plantilla inicial10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml es un lenguaje de programación de calidad industrial que admite estilos funcionales, imperativos y orientados a objetos.',
+ desc2:
+ 'El compilador de OCaml se ejecuta en el navegador y compila a JavaScript. No se envía nada a un servidor.',
+ link: '<1><2>Sitio web de OCaml2>1> <3> <4>Documentación de OCaml4> 3> <5> <6>Aprende X en Y minutos, donde X=OCaml6> 5> <7> <8>Cargar plantilla inicial8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal ejecutándose en el navegador usando pas2js (por el equipo de Free Pascal), compilado a WebAssembly.',
link: '<1> <2>Sitio web oficial de Free Pascal2> 1> <3> <4>Documentación de pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Documentación de LiveCodes8> 7> <9> <10>Cargar plantilla inicial10> 9>',
diff --git a/src/livecodes/i18n/locales/es/translation.lokalise.json b/src/livecodes/i18n/locales/es/translation.lokalise.json
index f891de46a9..d283f38192 100644
--- a/src/livecodes/i18n/locales/es/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/es/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Inicio Ocaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Inicio OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Inicio Pascal"
},
diff --git a/src/livecodes/i18n/locales/es/translation.ts b/src/livecodes/i18n/locales/es/translation.ts
index 5d28d699e6..c5f3a96fdb 100644
--- a/src/livecodes/i18n/locales/es/translation.ts
+++ b/src/livecodes/i18n/locales/es/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Inicio Nim (Wasm)',
'objc-wasm': 'Inicio Objective-C (Wasm)',
ocaml: 'Inicio Ocaml',
+ 'ocaml-js': 'Inicio OCaml (JS)',
pascal: 'Inicio Pascal',
perl: 'Inicio Perl',
phaser: 'Inicio Phaser',
diff --git a/src/livecodes/i18n/locales/fa/language-info.lokalise.json b/src/livecodes/i18n/locales/fa/language-info.lokalise.json
index 2f8987b4fa..b38d70c44a 100644
--- a/src/livecodes/i18n/locales/fa/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/fa/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml یک زبان برنامهنویسی با قدرت صنعتی است که از سبکهای تابعی، دستوری و شیگرا پشتیبانی میکند."
+ },
+ "ocamlJs.desc2": {
+ "translation": "کامپایلر OCaml در مرورگر اجرا میشود و به JavaScript کامپایل میکند. هیچ چیزی به سرور فرستاده نمیشود."
+ },
+ "ocamlJs.link": {
+ "translation": "وبسایت OCaml مستندات OCaml یادگیری X در Y دقیقه، جایی که X=OCaml بارگذاری قالب شروع کننده "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal با استفاده از pas2js (توسط تیم Free Pascal) در مرورگر اجرا میشود و به WebAssembly کامپایل شده است."
},
diff --git a/src/livecodes/i18n/locales/fa/language-info.ts b/src/livecodes/i18n/locales/fa/language-info.ts
index 89b0a7e546..fd34c35141 100644
--- a/src/livecodes/i18n/locales/fa/language-info.ts
+++ b/src/livecodes/i18n/locales/fa/language-info.ts
@@ -355,6 +355,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>وبسایت OCaml2>1> <3> <4>مستندات OCaml4> 3> <5> <6>وبسایت ReScript6> 5> <7> <8>یادگیری X در Y دقیقه، جایی که X=OCaml8> 7> <9> <10>بارگذاری قالب شروع کننده10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml یک زبان برنامهنویسی با قدرت صنعتی است که از سبکهای تابعی، دستوری و شیگرا پشتیبانی میکند.',
+ desc2:
+ 'کامپایلر OCaml در مرورگر اجرا میشود و به JavaScript کامپایل میکند. هیچ چیزی به سرور فرستاده نمیشود.',
+ link: '<1><2>وبسایت OCaml2>1> <3> <4>مستندات OCaml4> 3> <5> <6>یادگیری X در Y دقیقه، جایی که X=OCaml6> 5> <7> <8>بارگذاری قالب شروع کننده8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal با استفاده از pas2js (توسط تیم Free Pascal) در مرورگر اجرا میشود و به WebAssembly کامپایل شده است.',
link: '<1> <2>وبسایت رسمی Free Pascal2> 1> <3> <4>مستندات pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>مستندات LiveCodes8> 7> <9> <10>بارگذاری قالب شروع کننده10> 9>',
diff --git a/src/livecodes/i18n/locales/fa/translation.lokalise.json b/src/livecodes/i18n/locales/fa/translation.lokalise.json
index d428fe0928..35d3b127f8 100644
--- a/src/livecodes/i18n/locales/fa/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/fa/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "شروع کننده Ocaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "شروع کننده OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "شروع کننده Pascal"
},
diff --git a/src/livecodes/i18n/locales/fa/translation.ts b/src/livecodes/i18n/locales/fa/translation.ts
index 1d2f6d1d67..51b6c0b6fa 100644
--- a/src/livecodes/i18n/locales/fa/translation.ts
+++ b/src/livecodes/i18n/locales/fa/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'شروع کننده Nim (Wasm)',
'objc-wasm': 'شروع کننده Objective-C (Wasm)',
ocaml: 'شروع کننده Ocaml',
+ 'ocaml-js': 'شروع کننده OCaml (JS)',
pascal: 'شروع کننده Pascal',
perl: 'شروع کننده Perl',
phaser: 'شروع کننده Phaser',
diff --git a/src/livecodes/i18n/locales/fr/language-info.lokalise.json b/src/livecodes/i18n/locales/fr/language-info.lokalise.json
index 8aa0cbdde7..8e19867a15 100644
--- a/src/livecodes/i18n/locales/fr/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/fr/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml est un langage de programmation de qualité industrielle supportant les styles fonctionnel, impératif et orienté objet."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Le compilateur OCaml s'exécute dans le navigateur et compile en JavaScript. Rien n'est envoyé à un serveur."
+ },
+ "ocamlJs.link": {
+ "translation": "Site web OCaml Documentation OCaml Apprenez X en Y minutes, où X=OCaml Charger le modèle de démarrage "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal s'exécutant dans le navigateur en utilisant pas2js (par l'équipe Free Pascal), compilé en WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/fr/language-info.ts b/src/livecodes/i18n/locales/fr/language-info.ts
index 9947601f43..305e414031 100644
--- a/src/livecodes/i18n/locales/fr/language-info.ts
+++ b/src/livecodes/i18n/locales/fr/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Site web OCaml2>1> <3> <4>Documentation OCaml4> 3> <5> <6>Site web ReScript6> 5> <7> <8>Apprenez X en Y minutes, où X=OCaml8> 7> <9> <10>Charger le modèle de démarrage10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml est un langage de programmation de qualité industrielle supportant les styles fonctionnel, impératif et orienté objet.',
+ desc2:
+ "Le compilateur OCaml s'exécute dans le navigateur et compile en JavaScript. Rien n'est envoyé à un serveur.",
+ link: '<1><2>Site web OCaml2>1> <3> <4>Documentation OCaml4> 3> <5> <6>Apprenez X en Y minutes, où X=OCaml6> 5> <7> <8>Charger le modèle de démarrage8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: "Pascal s'exécutant dans le navigateur en utilisant pas2js (par l'équipe Free Pascal), compilé en WebAssembly.",
link: '<1> <2>Site officiel de Free Pascal2> 1> <3> <4>Documentation pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Documentations LiveCodes8> 7> <9> <10>Charger le modèle de démarrage10> 9>',
diff --git a/src/livecodes/i18n/locales/fr/translation.lokalise.json b/src/livecodes/i18n/locales/fr/translation.lokalise.json
index 7a5274215b..8d389cfed0 100644
--- a/src/livecodes/i18n/locales/fr/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/fr/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Démarrage OCaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Démarrage OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Démarrage Pascal"
},
diff --git a/src/livecodes/i18n/locales/fr/translation.ts b/src/livecodes/i18n/locales/fr/translation.ts
index abf00fb010..5dd8217e05 100644
--- a/src/livecodes/i18n/locales/fr/translation.ts
+++ b/src/livecodes/i18n/locales/fr/translation.ts
@@ -1039,6 +1039,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Démarrage Nim (Wasm)',
'objc-wasm': 'Démarrage Objective-C (Wasm)',
ocaml: 'Démarrage OCaml',
+ 'ocaml-js': 'Démarrage OCaml (JS)',
pascal: 'Démarrage Pascal',
perl: 'Démarrage Perl',
phaser: 'Démarrage Phaser',
diff --git a/src/livecodes/i18n/locales/hi/language-info.lokalise.json b/src/livecodes/i18n/locales/hi/language-info.lokalise.json
index 02bb9b3cf1..659b0f0871 100644
--- a/src/livecodes/i18n/locales/hi/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/hi/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml एक औद्योगिक-स्तरीय प्रोग्रामिंग भाषा है जो कार्यात्मक, आदेशात्मक और ऑब्जेक्ट-उन्मुख शैलियों का समर्थन करती है।"
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml कंपाइलर ब्राउज़र में चलता है और JavaScript में कंपाइल करता है। किसी सर्वर पर कुछ नहीं भेजा जाता है।"
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml वेबसाइट OCaml दस्तावेज़ीकरण X को Y मिनटों में सीखें, जहां X=OCaml स्टार्टर टेम्पलेट लोड करें "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Free Pascal टीम द्वारा pas2js का उपयोग करके ब्राउज़र में चलने वाला Pascal, जो WebAssembly में संकलित है।"
},
diff --git a/src/livecodes/i18n/locales/hi/language-info.ts b/src/livecodes/i18n/locales/hi/language-info.ts
index da1df6a9d4..b86018be36 100644
--- a/src/livecodes/i18n/locales/hi/language-info.ts
+++ b/src/livecodes/i18n/locales/hi/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml वेबसाइट2>1> <3> <4>OCaml दस्तावेज़ीकरण4> 3> <5> <6>ReScript वेबसाइट6> 5> <7> <8>X को Y मिनटों में सीखें, जहां X=OCaml8> 7> <9> <10>स्टार्टर टेम्पलेट लोड करें10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml एक औद्योगिक-स्तरीय प्रोग्रामिंग भाषा है जो कार्यात्मक, आदेशात्मक और ऑब्जेक्ट-उन्मुख शैलियों का समर्थन करती है।',
+ desc2:
+ 'OCaml कंपाइलर ब्राउज़र में चलता है और JavaScript में कंपाइल करता है। किसी सर्वर पर कुछ नहीं भेजा जाता है।',
+ link: '<1><2>OCaml वेबसाइट2>1> <3> <4>OCaml दस्तावेज़ीकरण4> 3> <5> <6>X को Y मिनटों में सीखें, जहां X=OCaml6> 5> <7> <8>स्टार्टर टेम्पलेट लोड करें8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Free Pascal टीम द्वारा pas2js का उपयोग करके ब्राउज़र में चलने वाला Pascal, जो WebAssembly में संकलित है।',
link: '<1> <2>Free Pascal आधिकारिक वेबसाइट2> 1> <3> <4>pas2js दस्तावेज़ीकरण4> 3> <5> <6>pas2js wiki6> 5> <7> <8>लाइवकोड्स (LiveCodes) दस्तावेज़8> 7> <9> <10>स्टार्टर टेम्पलेट लोड करें10> 9>',
diff --git a/src/livecodes/i18n/locales/hi/translation.lokalise.json b/src/livecodes/i18n/locales/hi/translation.lokalise.json
index 4586943c8d..8f97d032be 100644
--- a/src/livecodes/i18n/locales/hi/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/hi/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "OCaml स्टार्टर"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS) स्टार्टर"
+ },
"templates.starter.pascal": {
"translation": "Pascal स्टार्टर"
},
diff --git a/src/livecodes/i18n/locales/hi/translation.ts b/src/livecodes/i18n/locales/hi/translation.ts
index bedcf6fe12..9c4acc8b72 100644
--- a/src/livecodes/i18n/locales/hi/translation.ts
+++ b/src/livecodes/i18n/locales/hi/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm) स्टार्टर',
'objc-wasm': 'Objective-C (Wasm) स्टार्टर',
ocaml: 'OCaml स्टार्टर',
+ 'ocaml-js': 'OCaml (JS) स्टार्टर',
pascal: 'Pascal स्टार्टर',
perl: 'Perl स्टार्टर',
phaser: 'Phaser स्टार्टर',
diff --git a/src/livecodes/i18n/locales/hu/language-info.lokalise.json b/src/livecodes/i18n/locales/hu/language-info.lokalise.json
index d98cd14b15..eb61d66ee4 100644
--- a/src/livecodes/i18n/locales/hu/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/hu/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "Az OCaml egy ipari szintű programozási nyelv, amely támogatja a funkcionális, imperatív és objektumorientált stílusokat."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Az OCaml-fordító a böngészőben fut és JavaScript-re fordít. Semmit sem küld szerverre."
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml weboldal OCaml dokumentáció Tanulj X-et Y perc alatt, ahol X=OCaml Kezdő sablon betöltése "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "A Pascal a pas2js (a Free Pascal csapatától) segítségével fut a böngészőben, WebAssembly-re fordítva."
},
diff --git a/src/livecodes/i18n/locales/hu/language-info.ts b/src/livecodes/i18n/locales/hu/language-info.ts
index d0050b1970..bb4cedb9a9 100644
--- a/src/livecodes/i18n/locales/hu/language-info.ts
+++ b/src/livecodes/i18n/locales/hu/language-info.ts
@@ -356,6 +356,13 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml weboldal2>1> <3> <4>OCaml dokumentáció4> 3> <5> <6>ReScript weboldal6> 5> <7> <8>Tanulj X-et Y perc alatt, ahol X=OCaml8> 7> <9> <10>Kezdő sablon betöltése10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'Az OCaml egy ipari szintű programozási nyelv, amely támogatja a funkcionális, imperatív és objektumorientált stílusokat.',
+ desc2: 'Az OCaml-fordító a böngészőben fut és JavaScript-re fordít. Semmit sem küld szerverre.',
+ link: '<1><2>OCaml weboldal2>1> <3> <4>OCaml dokumentáció4> 3> <5> <6>Tanulj X-et Y perc alatt, ahol X=OCaml6> 5> <7> <8>Kezdő sablon betöltése8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'A Pascal a pas2js (a Free Pascal csapatától) segítségével fut a böngészőben, WebAssembly-re fordítva.',
link: '<1> <2>Free Pascal hivatalos weboldal2> 1> <3> <4>pas2js dokumentáció4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes dokumentációk8> 7> <9> <10>Kezdő sablon betöltése10> 9>',
diff --git a/src/livecodes/i18n/locales/hu/translation.lokalise.json b/src/livecodes/i18n/locales/hu/translation.lokalise.json
index bfa3a76193..5635b2b280 100644
--- a/src/livecodes/i18n/locales/hu/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/hu/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "OCaml kezdő"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS) kezdő"
+ },
"templates.starter.pascal": {
"translation": "Pascal kezdő"
},
diff --git a/src/livecodes/i18n/locales/hu/translation.ts b/src/livecodes/i18n/locales/hu/translation.ts
index f6620bc854..3a0efce1a6 100644
--- a/src/livecodes/i18n/locales/hu/translation.ts
+++ b/src/livecodes/i18n/locales/hu/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm) kezdő',
'objc-wasm': 'Objective-C (Wasm) kezdő',
ocaml: 'OCaml kezdő',
+ 'ocaml-js': 'OCaml (JS) kezdő',
pascal: 'Pascal kezdő',
perl: 'Perl kezdő',
phaser: 'Phaser kezdő',
diff --git a/src/livecodes/i18n/locales/id/language-info.lokalise.json b/src/livecodes/i18n/locales/id/language-info.lokalise.json
index 93dc5a4fe9..6b2534e828 100644
--- a/src/livecodes/i18n/locales/id/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/id/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml adalah bahasa pemrograman tingkat industri yang mendukung gaya fungsional, imperatif, dan berorientasi objek."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Kompiler OCaml berjalan di browser dan mengompilasi ke JavaScript. Tidak ada yang dikirim ke server."
+ },
+ "ocamlJs.link": {
+ "translation": "Situs web OCaml Dokumentasi OCaml Pelajari X dalam Y menit, dengan X=OCaml Muat template pemula "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal berjalan di browser menggunakan pas2js (oleh tim Free Pascal), dikompilasi ke WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/id/language-info.ts b/src/livecodes/i18n/locales/id/language-info.ts
index 6fa26feef7..d5501b3d8a 100644
--- a/src/livecodes/i18n/locales/id/language-info.ts
+++ b/src/livecodes/i18n/locales/id/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Situs web OCaml2>1> <3> <4>Dokumentasi OCaml4> 3> <5> <6>Situs web ReScript6> 5> <7> <8>Pelajari X dalam Y menit, dengan X=OCaml8> 7> <9> <10>Muat template pemula10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml adalah bahasa pemrograman tingkat industri yang mendukung gaya fungsional, imperatif, dan berorientasi objek.',
+ desc2:
+ 'Kompiler OCaml berjalan di browser dan mengompilasi ke JavaScript. Tidak ada yang dikirim ke server.',
+ link: '<1><2>Situs web OCaml2>1> <3> <4>Dokumentasi OCaml4> 3> <5> <6>Pelajari X dalam Y menit, dengan X=OCaml6> 5> <7> <8>Muat template pemula8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal berjalan di browser menggunakan pas2js (oleh tim Free Pascal), dikompilasi ke WebAssembly.',
link: '<1> <2>Situs web resmi Free Pascal2> 1> <3> <4>Dokumentasi pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Dokumentasi LiveCodes8> 7> <9> <10>Muat template pemula10> 9>',
diff --git a/src/livecodes/i18n/locales/id/translation.lokalise.json b/src/livecodes/i18n/locales/id/translation.lokalise.json
index 8692aa62d4..8bd8ef1060 100644
--- a/src/livecodes/i18n/locales/id/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/id/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Pemula Ocaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Pemula OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Pemula Pascal"
},
diff --git a/src/livecodes/i18n/locales/id/translation.ts b/src/livecodes/i18n/locales/id/translation.ts
index c025ca477b..ceca4fe3e9 100644
--- a/src/livecodes/i18n/locales/id/translation.ts
+++ b/src/livecodes/i18n/locales/id/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Pemula Nim (Wasm)',
'objc-wasm': 'Pemula Objective-C (Wasm)',
ocaml: 'Pemula Ocaml',
+ 'ocaml-js': 'Pemula OCaml (JS)',
pascal: 'Pemula Pascal',
perl: 'Pemula Perl',
phaser: 'Pemula Phaser',
diff --git a/src/livecodes/i18n/locales/it/language-info.lokalise.json b/src/livecodes/i18n/locales/it/language-info.lokalise.json
index 666bd9b59f..2fabcfaf9a 100644
--- a/src/livecodes/i18n/locales/it/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/it/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml è un linguaggio di programmazione di livello industriale che supporta stili funzionali, imperativi e orientati agli oggetti."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Il compilatore OCaml viene eseguito nel browser e compila in JavaScript. Niente viene inviato a un server."
+ },
+ "ocamlJs.link": {
+ "translation": "Sito web di OCaml Documentazione di OCaml Impara X in Y minuti, dove X=OCaml Carica modello di partenza "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal in esecuzione nel browser utilizzando pas2js (del team Free Pascal), compilato in WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/it/language-info.ts b/src/livecodes/i18n/locales/it/language-info.ts
index 2ff5f7546a..b451da494b 100644
--- a/src/livecodes/i18n/locales/it/language-info.ts
+++ b/src/livecodes/i18n/locales/it/language-info.ts
@@ -355,6 +355,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Sito web di OCaml2>1> <3> <4>Documentazione di OCaml4> 3> <5> <6>Sito web di ReScript6> 5> <7> <8>Impara X in Y minuti, dove X=OCaml8> 7> <9> <10>Carica modello di partenza10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml è un linguaggio di programmazione di livello industriale che supporta stili funzionali, imperativi e orientati agli oggetti.',
+ desc2:
+ 'Il compilatore OCaml viene eseguito nel browser e compila in JavaScript. Niente viene inviato a un server.',
+ link: '<1><2>Sito web di OCaml2>1> <3> <4>Documentazione di OCaml4> 3> <5> <6>Impara X in Y minuti, dove X=OCaml6> 5> <7> <8>Carica modello di partenza8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal in esecuzione nel browser utilizzando pas2js (del team Free Pascal), compilato in WebAssembly.',
link: '<1> <2>Sito ufficiale di Free Pascal2> 1> <3> <4>Documentazione di pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Documentazione LiveCodes8> 7> <9> <10>Carica modello di partenza10> 9>',
diff --git a/src/livecodes/i18n/locales/it/translation.lokalise.json b/src/livecodes/i18n/locales/it/translation.lokalise.json
index b0fb46284a..a63c0094ba 100644
--- a/src/livecodes/i18n/locales/it/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/it/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Starter OCaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Starter OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Starter Pascal"
},
diff --git a/src/livecodes/i18n/locales/it/translation.ts b/src/livecodes/i18n/locales/it/translation.ts
index f58d0479ce..cd499d5189 100644
--- a/src/livecodes/i18n/locales/it/translation.ts
+++ b/src/livecodes/i18n/locales/it/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Starter Nim (Wasm)',
'objc-wasm': 'Starter Objective-C (Wasm)',
ocaml: 'Starter OCaml',
+ 'ocaml-js': 'Starter OCaml (JS)',
pascal: 'Starter Pascal',
perl: 'Starter Perl',
phaser: 'Starter Phaser',
diff --git a/src/livecodes/i18n/locales/ja/language-info.lokalise.json b/src/livecodes/i18n/locales/ja/language-info.lokalise.json
index f53213bab5..1290fff804 100644
--- a/src/livecodes/i18n/locales/ja/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ja/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml は、関数型、命令型、オブジェクト指向スタイルをサポートする産業用プログラミング言語です。"
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml コンパイラはブラウザ内で実行され、JavaScript にコンパイルされます。サーバーには何も送信されません。"
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml ウェブサイト OCaml ドキュメント X分でYを学ぶ、X=OCaml スターターテンプレートを読み込む "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "pas2js(Free Pascal チームによる)を使用してブラウザで動作する Pascal。WebAssembly にコンパイルされます。"
},
diff --git a/src/livecodes/i18n/locales/ja/language-info.ts b/src/livecodes/i18n/locales/ja/language-info.ts
index 7adf4071ee..d7162414a3 100644
--- a/src/livecodes/i18n/locales/ja/language-info.ts
+++ b/src/livecodes/i18n/locales/ja/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml ウェブサイト2>1> <3> <4>OCaml ドキュメント4> 3> <5> <6>ReScript ウェブサイト6> 5> <7> <8>X分でYを学ぶ、X=OCaml8> 7> <9> <10>スターターテンプレートを読み込む10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml は、関数型、命令型、オブジェクト指向スタイルをサポートする産業用プログラミング言語です。',
+ desc2:
+ 'OCaml コンパイラはブラウザ内で実行され、JavaScript にコンパイルされます。サーバーには何も送信されません。',
+ link: '<1><2>OCaml ウェブサイト2>1> <3> <4>OCaml ドキュメント4> 3> <5> <6>X分でYを学ぶ、X=OCaml6> 5> <7> <8>スターターテンプレートを読み込む8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'pas2js(Free Pascal チームによる)を使用してブラウザで動作する Pascal。WebAssembly にコンパイルされます。',
link: '<1> <2>Free Pascal 公式ウェブサイト2> 1> <3> <4>pas2js ドキュメント4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes ドキュメント8> 7> <9> <10>スターターテンプレートを読み込む10> 9>',
diff --git a/src/livecodes/i18n/locales/ja/translation.lokalise.json b/src/livecodes/i18n/locales/ja/translation.lokalise.json
index 1f5141fe25..02cab7c9df 100644
--- a/src/livecodes/i18n/locales/ja/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ja/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "OCamlスターター"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml(JS)スターター"
+ },
"templates.starter.pascal": {
"translation": "Pascalスターター"
},
diff --git a/src/livecodes/i18n/locales/ja/translation.ts b/src/livecodes/i18n/locales/ja/translation.ts
index 494d0b5174..54c2e43544 100644
--- a/src/livecodes/i18n/locales/ja/translation.ts
+++ b/src/livecodes/i18n/locales/ja/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim(Wasm)スターター',
'objc-wasm': 'Objective-C(Wasm)スターター',
ocaml: 'OCamlスターター',
+ 'ocaml-js': 'OCaml(JS)スターター',
pascal: 'Pascalスターター',
perl: 'Perlスターター',
phaser: 'Phaserスターター',
diff --git a/src/livecodes/i18n/locales/nl/language-info.lokalise.json b/src/livecodes/i18n/locales/nl/language-info.lokalise.json
index 9e791e5f3e..23635c8f14 100644
--- a/src/livecodes/i18n/locales/nl/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/nl/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml is een industriële programmeertaal die functionele, imperatieve en objectgeoriënteerde stijlen ondersteunt."
+ },
+ "ocamlJs.desc2": {
+ "translation": "De OCaml-compiler draait in de browser en compileert naar JavaScript. Er wordt niets naar een server verzonden."
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml website OCaml documentatie Leer X in Y minuten, waarbij X=OCaml Startsjabloon laden "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal draaiend in de browser met pas2js (van het Free Pascal-team), gecompileerd naar WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/nl/language-info.ts b/src/livecodes/i18n/locales/nl/language-info.ts
index fe5a3b303f..07f21b04f4 100644
--- a/src/livecodes/i18n/locales/nl/language-info.ts
+++ b/src/livecodes/i18n/locales/nl/language-info.ts
@@ -355,6 +355,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml website2>1> <3> <4>OCaml documentatie4> 3> <5> <6>ReScript website6> 5> <7> <8>Leer X in Y minuten, waarbij X=OCaml8> 7> <9> <10>Startsjabloon laden10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml is een industriële programmeertaal die functionele, imperatieve en objectgeoriënteerde stijlen ondersteunt.',
+ desc2:
+ 'De OCaml-compiler draait in de browser en compileert naar JavaScript. Er wordt niets naar een server verzonden.',
+ link: '<1><2>OCaml website2>1> <3> <4>OCaml documentatie4> 3> <5> <6>Leer X in Y minuten, waarbij X=OCaml6> 5> <7> <8>Startsjabloon laden8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal draaiend in de browser met pas2js (van het Free Pascal-team), gecompileerd naar WebAssembly.',
link: '<1> <2>Free Pascal officiële website2> 1> <3> <4>pas2js-documentatie4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes-documentatie8> 7> <9> <10>Startsjabloon laden10> 9>',
diff --git a/src/livecodes/i18n/locales/nl/translation.lokalise.json b/src/livecodes/i18n/locales/nl/translation.lokalise.json
index 6e1729fe00..0bb23e27cd 100644
--- a/src/livecodes/i18n/locales/nl/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/nl/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Ocaml-starter"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS)-starter"
+ },
"templates.starter.pascal": {
"translation": "Pascal-starter"
},
diff --git a/src/livecodes/i18n/locales/nl/translation.ts b/src/livecodes/i18n/locales/nl/translation.ts
index fce2ffb52a..d802e88094 100644
--- a/src/livecodes/i18n/locales/nl/translation.ts
+++ b/src/livecodes/i18n/locales/nl/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm)-starter',
'objc-wasm': 'Objective-C (Wasm)-starter',
ocaml: 'Ocaml-starter',
+ 'ocaml-js': 'OCaml (JS)-starter',
pascal: 'Pascal-starter',
perl: 'Perl-starter',
phaser: 'Phaser-starter',
diff --git a/src/livecodes/i18n/locales/pt/language-info.lokalise.json b/src/livecodes/i18n/locales/pt/language-info.lokalise.json
index 18a2fea497..229555b5c8 100644
--- a/src/livecodes/i18n/locales/pt/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/pt/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml é uma linguagem de programação de nível industrial que suporta estilos funcionais, imperativos e orientados a objetos."
+ },
+ "ocamlJs.desc2": {
+ "translation": "O compilador OCaml é executado no navegador e compila para JavaScript. Nada é enviado a um servidor."
+ },
+ "ocamlJs.link": {
+ "translation": "Site do OCaml Documentação do OCaml Aprenda X em Y minutos, onde X=OCaml Carregar modelo inicial "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal rodando no navegador usando pas2js (pela equipe do Free Pascal), compilado para WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/pt/language-info.ts b/src/livecodes/i18n/locales/pt/language-info.ts
index dc7df1f9b9..88c90bdd67 100644
--- a/src/livecodes/i18n/locales/pt/language-info.ts
+++ b/src/livecodes/i18n/locales/pt/language-info.ts
@@ -355,6 +355,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Site do OCaml2>1> <3> <4>Documentação do OCaml4> 3> <5> <6>Site do ReScript6> 5> <7> <8>Aprenda X em Y minutos, onde X=OCaml8> 7> <9> <10>Carregar modelo inicial10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml é uma linguagem de programação de nível industrial que suporta estilos funcionais, imperativos e orientados a objetos.',
+ desc2:
+ 'O compilador OCaml é executado no navegador e compila para JavaScript. Nada é enviado a um servidor.',
+ link: '<1><2>Site do OCaml2>1> <3> <4>Documentação do OCaml4> 3> <5> <6>Aprenda X em Y minutos, onde X=OCaml6> 5> <7> <8>Carregar modelo inicial8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal rodando no navegador usando pas2js (pela equipe do Free Pascal), compilado para WebAssembly.',
link: '<1> <2>Site oficial do Free Pascal2> 1> <3> <4>Documentação do pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Documentação do LiveCodes8> 7> <9> <10>Carregar modelo inicial10> 9>',
diff --git a/src/livecodes/i18n/locales/pt/translation.lokalise.json b/src/livecodes/i18n/locales/pt/translation.lokalise.json
index 3ec5ee1dda..2a4a6f1bd8 100644
--- a/src/livecodes/i18n/locales/pt/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/pt/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Iniciante OCaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Iniciante OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Iniciante Pascal"
},
diff --git a/src/livecodes/i18n/locales/pt/translation.ts b/src/livecodes/i18n/locales/pt/translation.ts
index 6fbed58c5f..66bff1e295 100644
--- a/src/livecodes/i18n/locales/pt/translation.ts
+++ b/src/livecodes/i18n/locales/pt/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Iniciante Nim (Wasm)',
'objc-wasm': 'Iniciante Objective-C (Wasm)',
ocaml: 'Iniciante OCaml',
+ 'ocaml-js': 'Iniciante OCaml (JS)',
pascal: 'Iniciante Pascal',
perl: 'Iniciante Perl',
phaser: 'Iniciante Phaser',
diff --git a/src/livecodes/i18n/locales/ru/language-info.lokalise.json b/src/livecodes/i18n/locales/ru/language-info.lokalise.json
index a37d96b9ed..b4125d6bee 100644
--- a/src/livecodes/i18n/locales/ru/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ru/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml - это язык программирования промышленного уровня, поддерживающий функциональный, императивный и объектно-ориентированный стили."
+ },
+ "ocamlJs.desc2": {
+ "translation": "Компилятор OCaml работает в браузере и компилирует в JavaScript. Ничего не отправляется на сервер."
+ },
+ "ocamlJs.link": {
+ "translation": "Сайт OCaml Документация OCaml Изучите X за Y минут, где X=OCaml Загрузить стартовый шаблон "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal, работающий в браузере с использованием pas2js (от команды Free Pascal), скомпилирован в WebAssembly."
},
diff --git a/src/livecodes/i18n/locales/ru/language-info.ts b/src/livecodes/i18n/locales/ru/language-info.ts
index 0ae66ae67a..d22bc60a2d 100644
--- a/src/livecodes/i18n/locales/ru/language-info.ts
+++ b/src/livecodes/i18n/locales/ru/language-info.ts
@@ -357,6 +357,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>Сайт OCaml2>1> <3> <4>Документация OCaml4> 3> <5> <6>Сайт ReScript6> 5> <7> <8>Изучите X за Y минут, где X=OCaml8> 7> <9> <10>Загрузить стартовый шаблон10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml - это язык программирования промышленного уровня, поддерживающий функциональный, императивный и объектно-ориентированный стили.',
+ desc2:
+ 'Компилятор OCaml работает в браузере и компилирует в JavaScript. Ничего не отправляется на сервер.',
+ link: '<1><2>Сайт OCaml2>1> <3> <4>Документация OCaml4> 3> <5> <6>Изучите X за Y минут, где X=OCaml6> 5> <7> <8>Загрузить стартовый шаблон8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Pascal, работающий в браузере с использованием pas2js (от команды Free Pascal), скомпилирован в WebAssembly.',
link: '<1> <2>Официальный сайт Free Pascal2> 1> <3> <4>Документация pas2js4> 3> <5> <6>pas2js wiki6> 5> <7> <8>Документация LiveCodes8> 7> <9> <10>Загрузить стартовый шаблон10> 9>',
diff --git a/src/livecodes/i18n/locales/ru/translation.lokalise.json b/src/livecodes/i18n/locales/ru/translation.lokalise.json
index 698a451697..33358355ec 100644
--- a/src/livecodes/i18n/locales/ru/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ru/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Стартер OCaml"
},
+ "templates.starter.ocaml-js": {
+ "translation": "Стартер OCaml (JS)"
+ },
"templates.starter.pascal": {
"translation": "Стартер Pascal"
},
diff --git a/src/livecodes/i18n/locales/ru/translation.ts b/src/livecodes/i18n/locales/ru/translation.ts
index 12b2c9d264..b85d575c47 100644
--- a/src/livecodes/i18n/locales/ru/translation.ts
+++ b/src/livecodes/i18n/locales/ru/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Стартер Nim (Wasm)',
'objc-wasm': 'Стартер Objective-C (Wasm)',
ocaml: 'Стартер OCaml',
+ 'ocaml-js': 'Стартер OCaml (JS)',
pascal: 'Стартер Pascal',
perl: 'Стартер Perl',
phaser: 'Стартер Phaser',
diff --git a/src/livecodes/i18n/locales/tr/language-info.lokalise.json b/src/livecodes/i18n/locales/tr/language-info.lokalise.json
index 12a018af49..a5f57575df 100644
--- a/src/livecodes/i18n/locales/tr/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/tr/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml, fonksiyonel, zorunlu ve nesne yönelimli stilleri destekleyen endüstriyel güçte bir programlama dilidir."
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml derleyicisi tarayıcıda çalışır ve JavaScript'e derler. Sunucuya hiçbir şey gönderilmez."
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml web sitesi OCaml dokümantasyonu Y Dakikada X Öğrenin, X=OCaml Başlangıç şablonunu yükle "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Pascal, Free Pascal ekibi tarafından pas2js kullanılarak tarayıcıda çalışır ve WebAssembly'ye derlenir."
},
diff --git a/src/livecodes/i18n/locales/tr/language-info.ts b/src/livecodes/i18n/locales/tr/language-info.ts
index c9919b01ee..732cb48712 100644
--- a/src/livecodes/i18n/locales/tr/language-info.ts
+++ b/src/livecodes/i18n/locales/tr/language-info.ts
@@ -356,6 +356,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml web sitesi2>1> <3> <4>OCaml dokümantasyonu4> 3> <5> <6>ReScript web sitesi6> 5> <7> <8>Y Dakikada X Öğrenin, X=OCaml8> 7> <9> <10>Başlangıç şablonunu yükle10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1:
+ 'OCaml, fonksiyonel, zorunlu ve nesne yönelimli stilleri destekleyen endüstriyel güçte bir programlama dilidir.',
+ desc2:
+ "OCaml derleyicisi tarayıcıda çalışır ve JavaScript'e derler. Sunucuya hiçbir şey gönderilmez.",
+ link: '<1><2>OCaml web sitesi2>1> <3> <4>OCaml dokümantasyonu4> 3> <5> <6>Y Dakikada X Öğrenin, X=OCaml6> 5> <7> <8>Başlangıç şablonunu yükle8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: "Pascal, Free Pascal ekibi tarafından pas2js kullanılarak tarayıcıda çalışır ve WebAssembly'ye derlenir.",
link: '<1> <2>Free Pascal resmi web sitesi2> 1> <3> <4>pas2js dokümantasyonu4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes Belgeleri8> 7> <9> <10>Başlangıç şablonunu yükle10> 9>',
diff --git a/src/livecodes/i18n/locales/tr/translation.lokalise.json b/src/livecodes/i18n/locales/tr/translation.lokalise.json
index 21f71ca22e..f4661766e2 100644
--- a/src/livecodes/i18n/locales/tr/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/tr/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Ocaml Başlangıç"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS) Başlangıç"
+ },
"templates.starter.pascal": {
"translation": "Pascal Başlangıç"
},
diff --git a/src/livecodes/i18n/locales/tr/translation.ts b/src/livecodes/i18n/locales/tr/translation.ts
index 40cbbb8a62..c33e0c0cd3 100644
--- a/src/livecodes/i18n/locales/tr/translation.ts
+++ b/src/livecodes/i18n/locales/tr/translation.ts
@@ -1038,6 +1038,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (Wasm) Başlangıç',
'objc-wasm': 'Objective-C (Wasm) Başlangıç',
ocaml: 'Ocaml Başlangıç',
+ 'ocaml-js': 'OCaml (JS) Başlangıç',
pascal: 'Pascal Başlangıç',
perl: 'Perl Başlangıç',
phaser: 'Phaser 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 3b41cfa401..11cee31c51 100644
--- a/src/livecodes/i18n/locales/ur/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/ur/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "او کیمل"
},
+ "ocamlJs.desc1": {
+ "translation": "او کیمل ایک صنعتی طاقت کی پروگرامنگ زبان ہے جو فنکشنل، امپیریٹیو اور آبجیکٹ اورینٹڈ طرزوں کی معاونت کرتی ہے۔"
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml کمپائلر براؤزر میں چلتا ہے اور JavaScript میں کمپائل کرتا ہے۔ سرور پر کچھ نہیں بھیجا جاتا۔"
+ },
+ "ocamlJs.link": {
+ "translation": "او کیمل ویب سائٹ او کیمل دستاویزات X کو Y منٹ میں سیکھیں، جہاں X=او کیمل ابتدائی سانچہ لوڈ کریں "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "Free Pascal ٹیم کے pas2js کا استعمال کرتے ہوئے براؤزر میں چلنے والا Pascal، جو WebAssembly میں مرتب کیا گیا ہے۔"
},
diff --git a/src/livecodes/i18n/locales/ur/language-info.ts b/src/livecodes/i18n/locales/ur/language-info.ts
index 65134f09f6..8ecd10f1f3 100644
--- a/src/livecodes/i18n/locales/ur/language-info.ts
+++ b/src/livecodes/i18n/locales/ur/language-info.ts
@@ -357,6 +357,14 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>او کیمل ویب سائٹ2>1> <3> <4>او کیمل دستاویزات4> 3> <5> <6>ری اسکرپٹ ویب سائٹ6> 5> <7> <8>X کو Y منٹ میں سیکھیں، جہاں X=او کیمل8> 7> <9> <10>ابتدائی سانچہ لوڈ کریں10> 9>',
name: 'او کیمل',
},
+ ocamlJs: {
+ desc1:
+ 'او کیمل ایک صنعتی طاقت کی پروگرامنگ زبان ہے جو فنکشنل، امپیریٹیو اور آبجیکٹ اورینٹڈ طرزوں کی معاونت کرتی ہے۔',
+ desc2:
+ 'OCaml کمپائلر براؤزر میں چلتا ہے اور JavaScript میں کمپائل کرتا ہے۔ سرور پر کچھ نہیں بھیجا جاتا۔',
+ link: '<1><2>او کیمل ویب سائٹ2>1> <3> <4>او کیمل دستاویزات4> 3> <5> <6>X کو Y منٹ میں سیکھیں، جہاں X=او کیمل6> 5> <7> <8>ابتدائی سانچہ لوڈ کریں8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: 'Free Pascal ٹیم کے pas2js کا استعمال کرتے ہوئے براؤزر میں چلنے والا Pascal، جو WebAssembly میں مرتب کیا گیا ہے۔',
link: '<1> <2>Free Pascal کی سرکاری ویب سائٹ2> 1> <3> <4>pas2js دستاویزات4> 3> <5> <6>pas2js wiki6> 5> <7> <8>لائیو کوڈز دستاویزات8> 7> <9> <10>ابتدائی سانچہ لوڈ کریں10> 9>',
diff --git a/src/livecodes/i18n/locales/ur/translation.lokalise.json b/src/livecodes/i18n/locales/ur/translation.lokalise.json
index 00ba8dd0c1..4d466e54af 100644
--- a/src/livecodes/i18n/locales/ur/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/ur/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "اوکامل شروعاتی"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml (JS) شروعاتی"
+ },
"templates.starter.pascal": {
"translation": "پاسکل شروعاتی"
},
diff --git a/src/livecodes/i18n/locales/ur/translation.ts b/src/livecodes/i18n/locales/ur/translation.ts
index 5e27137393..88479ceb56 100644
--- a/src/livecodes/i18n/locales/ur/translation.ts
+++ b/src/livecodes/i18n/locales/ur/translation.ts
@@ -1037,6 +1037,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim (واسم) شروعاتی',
'objc-wasm': 'Objective-C (واسم) شروعاتی',
ocaml: 'اوکامل شروعاتی',
+ 'ocaml-js': 'OCaml (JS) شروعاتی',
pascal: 'پاسکل شروعاتی',
perl: 'پرل شروعاتی',
phaser: 'فیزر شروعاتی',
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 5abff12b47..d42dabcb53 100644
--- a/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json
+++ b/src/livecodes/i18n/locales/zh-CN/language-info.lokalise.json
@@ -636,6 +636,18 @@
"ocaml.name": {
"translation": "OCaml"
},
+ "ocamlJs.desc1": {
+ "translation": "OCaml 是一种工业级编程语言,支持函数式、命令式和面向对象编程范式。"
+ },
+ "ocamlJs.desc2": {
+ "translation": "OCaml 编译器在浏览器中运行并编译为 JavaScript。不会向服务器发送任何内容。"
+ },
+ "ocamlJs.link": {
+ "translation": "OCaml 官方网站 OCaml 文档 在 Y 分钟内学习 X,其中 X=OCaml 加载启动模板 "
+ },
+ "ocamlJs.name": {
+ "translation": "OCaml (JS)"
+ },
"pascal.desc": {
"translation": "使用 Free Pascal 团队的 pas2js 在浏览器中运行的 Pascal,并编译为 WebAssembly。"
},
diff --git a/src/livecodes/i18n/locales/zh-CN/language-info.ts b/src/livecodes/i18n/locales/zh-CN/language-info.ts
index 286e371b41..ef14343087 100644
--- a/src/livecodes/i18n/locales/zh-CN/language-info.ts
+++ b/src/livecodes/i18n/locales/zh-CN/language-info.ts
@@ -350,6 +350,12 @@ const languageInfo: I18nLangInfoTranslation = {
link: '<1><2>OCaml 官方网站2>1> <3> <4>OCaml 文档4> 3> <5> <6>ReScript 网站6> 5> <7> <8>在 Y 分钟内学习 X,其中 X=OCaml8> 7> <9> <10>加载启动模板10> 9>',
name: 'OCaml',
},
+ ocamlJs: {
+ desc1: 'OCaml 是一种工业级编程语言,支持函数式、命令式和面向对象编程范式。',
+ desc2: 'OCaml 编译器在浏览器中运行并编译为 JavaScript。不会向服务器发送任何内容。',
+ link: '<1><2>OCaml 官方网站2>1> <3> <4>OCaml 文档4> 3> <5> <6>在 Y 分钟内学习 X,其中 X=OCaml6> 5> <7> <8>加载启动模板8> 7>',
+ name: 'OCaml (JS)',
+ },
pascal: {
desc: '使用 Free Pascal 团队的 pas2js 在浏览器中运行的 Pascal,并编译为 WebAssembly。',
link: '<1> <2>Free Pascal 官网2> 1> <3> <4>pas2js 文档4> 3> <5> <6>pas2js wiki6> 5> <7> <8>LiveCodes 文档8> 7> <9> <10>加载启动模板10> 9>',
diff --git a/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json b/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
index a60b50a2f4..ed3cdfc3a6 100644
--- a/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
+++ b/src/livecodes/i18n/locales/zh-CN/translation.lokalise.json
@@ -2097,6 +2097,9 @@
"templates.starter.ocaml": {
"translation": "Ocaml 启动模板"
},
+ "templates.starter.ocaml-js": {
+ "translation": "OCaml(JS)启动模板"
+ },
"templates.starter.pascal": {
"translation": "Pascal 启动模板"
},
diff --git a/src/livecodes/i18n/locales/zh-CN/translation.ts b/src/livecodes/i18n/locales/zh-CN/translation.ts
index 11c63750d6..6566987f14 100644
--- a/src/livecodes/i18n/locales/zh-CN/translation.ts
+++ b/src/livecodes/i18n/locales/zh-CN/translation.ts
@@ -1035,6 +1035,7 @@ const translation: I18nTranslation = {
'nim-wasm': 'Nim(WASM)启动模板',
'objc-wasm': 'Objective-C(WASM)启动模板',
ocaml: 'Ocaml 启动模板',
+ 'ocaml-js': 'OCaml(JS)启动模板',
pascal: 'Pascal 启动模板',
perl: 'Perl 启动模板',
phaser: 'Phaser 启动模板',
diff --git a/src/livecodes/languages/languages.ts b/src/livecodes/languages/languages.ts
index 5f13c0f553..72b5ac0b3e 100644
--- a/src/livecodes/languages/languages.ts
+++ b/src/livecodes/languages/languages.ts
@@ -65,6 +65,7 @@ import { mustache } from './mustache';
import { nim, nimWasm } from './nim';
import { nunjucks } from './nunjucks';
import { ocaml } from './ocaml';
+import { ocamlJs } from './ocaml-js';
import { pascal } from './pascal';
import { perl } from './perl';
import { php } from './php';
@@ -165,6 +166,7 @@ export const languages: LanguageSpecs[] = [
rescript,
reason,
ocaml,
+ ocamlJs,
nim,
nimWasm,
crystalWasm,
diff --git a/src/livecodes/languages/ocaml-js/index.ts b/src/livecodes/languages/ocaml-js/index.ts
new file mode 100644
index 0000000000..a771523b52
--- /dev/null
+++ b/src/livecodes/languages/ocaml-js/index.ts
@@ -0,0 +1 @@
+export * from './lang-ocaml-js';
diff --git a/src/livecodes/languages/ocaml-js/lang-ocaml-js-compiler-esm.ts b/src/livecodes/languages/ocaml-js/lang-ocaml-js-compiler-esm.ts
new file mode 100644
index 0000000000..13454087b5
--- /dev/null
+++ b/src/livecodes/languages/ocaml-js/lang-ocaml-js-compiler-esm.ts
@@ -0,0 +1,53 @@
+// The OCaml compiler is a package of its own (@live-codes/ocaml), loaded from the
+// CDN. It runs in the page rather than in the compile worker because it creates its
+// own workers, one per compiler program per compile, and because it is an ES module
+// where the compile worker is a classic one.
+import type { CompilerFunction } from '../../models';
+import { getErrorMessage } from '../../utils';
+import { ocamlJsBaseUrl } from '../../vendors';
+
+const ocamlJsCompilerUrl = ocamlJsBaseUrl + 'src/compiler/index.js';
+const ocamlJsAssetsBaseUrl = ocamlJsBaseUrl + 'assets/compiler/';
+
+interface OcamlCompiler {
+ compile: (code: string) => Promise<{ js: string | null; diagnostics: string[]; error?: string }>;
+}
+
+// One instance, reused: it holds no per-program state, and loading it means fetching
+// and parsing two compilers.
+let loading: Promise | undefined;
+
+const getCompiler = (): Promise => {
+ if (!loading) {
+ loading = import(ocamlJsCompilerUrl).then(({ createCompiler }) =>
+ createCompiler({ baseUrl: ocamlJsAssetsBaseUrl }),
+ );
+ // do not keep a failed boot (e.g. a transient network error)
+ loading.catch(() => {
+ loading = undefined;
+ });
+ }
+ return loading;
+};
+
+export const ocamlCompiler: CompilerFunction = async (code: string) => {
+ if (!code.trim()) return '';
+
+ // Loading the compiler can reject (e.g. a transient CDN error), and `compile` can
+ // reject when the compiler worker itself fails, as opposed to the program not
+ // compiling. Surface both as compilation errors instead of letting the rejection
+ // leave the compile request pending.
+ try {
+ const compiler = await getCompiler();
+ const { js, diagnostics, error } = await compiler.compile(code);
+
+ // `error` is the toolchain failing, as opposed to the program not compiling;
+ // `diagnostics` carries the compiler's own messages, errors and warnings alike.
+ if (!js) {
+ return { code: '', info: { errors: error ? [...diagnostics, error] : diagnostics } };
+ }
+ return { code: js, info: {} };
+ } catch (err) {
+ return { code: '', info: { errors: [getErrorMessage(err)] } };
+ }
+};
diff --git a/src/livecodes/languages/ocaml-js/lang-ocaml-js.ts b/src/livecodes/languages/ocaml-js/lang-ocaml-js.ts
new file mode 100644
index 0000000000..3bca72d939
--- /dev/null
+++ b/src/livecodes/languages/ocaml-js/lang-ocaml-js.ts
@@ -0,0 +1,29 @@
+import { codemirrorLegacy } from '../../editor/codemirror/utils';
+import type { CompilerFunction, LanguageSpecs } from '../../models';
+import { codeMirrorBaseUrl, monacoLanguagesBaseUrl } from '../../vendors';
+
+export const runOutsideWorker: CompilerFunction = async (code: string, { baseUrl, language }) => {
+ const { ocamlCompiler } = await import(baseUrl + '{{hash:lang-ocaml-js-compiler-esm.js}}');
+ return ocamlCompiler(code, { baseUrl, language });
+};
+
+export const ocamlJs: LanguageSpecs = {
+ name: 'ocaml-js',
+ title: 'OCaml (JS)',
+ longTitle: 'OCaml (compiled to JavaScript)',
+ compiler: {
+ factory: () => async (code) => code,
+ runOutsideWorker,
+ },
+ extensions: ['ocaml-js', 'js.ocaml', 'js.ml'],
+ editor: 'script',
+ editorSupport: {
+ monaco: { languageSupport: monacoLanguagesBaseUrl + 'ocaml.js', language: 'ocaml' },
+ codemirror: {
+ languageSupport: async () =>
+ codemirrorLegacy((await import(codeMirrorBaseUrl + 'codemirror-lang-mllike.js')).oCaml),
+ },
+ codejar: { language: 'ocaml' },
+ },
+ largeDownload: true,
+};
diff --git a/src/livecodes/languages/ocaml/lang-ocaml.ts b/src/livecodes/languages/ocaml/lang-ocaml.ts
index e99087f5cc..6d9673ba97 100644
--- a/src/livecodes/languages/ocaml/lang-ocaml.ts
+++ b/src/livecodes/languages/ocaml/lang-ocaml.ts
@@ -1,12 +1,16 @@
import { codemirrorLegacy } from '../../editor/codemirror/utils';
-import type { LanguageSpecs } from '../../models';
+import type { Language, LanguageSpecs } from '../../models';
import { codeMirrorBaseUrl } from '../../vendors';
export const ocaml: LanguageSpecs = {
name: 'ocaml',
title: 'OCaml',
compiler: 'rescript',
- extensions: ['ml', 'mli'],
+ // This entry runs the ReScript compiler, not OCaml. `ocaml-js` is the real one;
+ // until the swap, `ocaml` still resolves here, with a warning.
+ deprecation: (lang: Language) =>
+ ['ocaml', 'ml', 'mli'].includes(lang) ? { old: 'rescript-ocaml', new: 'ocaml-js' } : undefined,
+ extensions: ['ml', 'mli', 'rescript-ocaml'],
editor: 'script',
editorSupport: {
monaco: { language: 'csharp' },
diff --git a/src/livecodes/templates/starter/index.ts b/src/livecodes/templates/starter/index.ts
index 18a2a1e3b9..4fc6bd22a0 100644
--- a/src/livecodes/templates/starter/index.ts
+++ b/src/livecodes/templates/starter/index.ts
@@ -58,6 +58,7 @@ import { mdxStarter } from './mdx-starter';
import { minizincStarter } from './minizinc-starter';
import { nimStarter } from './nim-starter';
import { nimWasmStarter } from './nim-wasm-starter';
+import { ocamlJsStarter } from './ocaml-js-starter';
import { ocamlStarter } from './ocaml-starter';
import { pascalStarter } from './pascal-starter';
import { perlStarter } from './perl-starter';
@@ -135,6 +136,7 @@ export const starterTemplates = [
rescriptStarter,
reasonStarter,
ocamlStarter,
+ ocamlJsStarter,
nimStarter,
nimWasmStarter,
crystalWasmStarter,
diff --git a/src/livecodes/templates/starter/ocaml-js-starter.ts b/src/livecodes/templates/starter/ocaml-js-starter.ts
new file mode 100644
index 0000000000..7c1b20af18
--- /dev/null
+++ b/src/livecodes/templates/starter/ocaml-js-starter.ts
@@ -0,0 +1,61 @@
+import type { Template } from '../../models';
+
+export const ocamlJsStarter: Template = {
+ name: 'ocaml-js',
+ title: window.deps.translateString('templates.starter.ocaml-js', 'OCaml (JS) Starter'),
+ thumbnail: 'assets/templates/ocaml.svg',
+ activeEditor: 'script',
+ markup: {
+ language: 'html',
+ content: `
+
+
Hello, World !
+
+
You clicked 0 times.
+
Click me
+
+`.trimStart(),
+ },
+ style: {
+ language: 'css',
+ content: `
+.container,
+.container button {
+ text-align: center;
+ font: 1em sans-serif;
+}
+.logo {
+ width: 150px;
+}
+`.trimStart(),
+ },
+ script: {
+ language: 'ocaml-js',
+ content: `
+open Js_of_ocaml
+
+let () =
+ let select id =
+ Js.Unsafe.meth_call Dom_html.document "querySelector"
+ [| Js.Unsafe.inject (Js.string ("#" ^ id)) |]
+ in
+ let title = select "title" in
+ let counter = select "counter" in
+ let button = select "counter-button" in
+
+ Js.Unsafe.set title "innerText" (Js.string "OCaml");
+ let count = ref 0 in
+
+ ignore
+ (Js.Unsafe.meth_call button "addEventListener"
+ [|
+ Js.Unsafe.inject (Js.string "click");
+ Js.Unsafe.inject
+ (Js.wrap_callback (fun _ ->
+ incr count;
+ Js.Unsafe.set counter "innerText"
+ (Js.string (string_of_int !count))));
+ |])
+`.trimStart(),
+ },
+};
diff --git a/src/livecodes/utils/utils.ts b/src/livecodes/utils/utils.ts
index 11c3a5ac20..e95cfc688f 100644
--- a/src/livecodes/utils/utils.ts
+++ b/src/livecodes/utils/utils.ts
@@ -738,9 +738,15 @@ export const onLoad = /* @__PURE__ */ (fn: (...args: any[]) => any) => {
export const getDocsUrl = () => {
const docsBaseUrl = predefinedValues.DOCS_BASE_URL || 'docs/';
- const docsUrl = docsBaseUrl.startsWith('http')
- ? docsBaseUrl
- : new URL(docsBaseUrl, location.href).href;
+ let docsUrl = docsBaseUrl;
+ if (!docsBaseUrl.startsWith('http')) {
+ try {
+ docsUrl = new URL(docsBaseUrl, location.href).href;
+ } catch {
+ // `location.href` is not always usable as a base, e.g. in a worker loaded from
+ // a data:/blob: URL. Fall back to the configured (relative) value.
+ }
+ }
return docsUrl.endsWith('/') ? docsUrl : `${docsUrl}/`;
};
diff --git a/src/livecodes/vendors.ts b/src/livecodes/vendors.ts
index 5c60c99741..2aa4ae9235 100644
--- a/src/livecodes/vendors.ts
+++ b/src/livecodes/vendors.ts
@@ -477,6 +477,8 @@ export const reasonReactUrl = /* @__PURE__ */ getUrl(
export const reasonStdLibBaseUrl = /* @__PURE__ */ getUrl('@rescript/std@9.1.3/lib/es6/');
+export const ocamlJsBaseUrl = /* @__PURE__ */ getUrl('@live-codes/ocaml@0.2.0/');
+
export const rescriptCdnBaseUrl = /* @__PURE__ */ getUrl('https://cdn.rescript-lang.org/v11.1.2/');
export const rescriptStdLibBaseUrl = /* @__PURE__ */ getUrl('@rescript/std@11.1.2/lib/es6/');
diff --git a/src/sdk/models.ts b/src/sdk/models.ts
index 956ec547e4..9b29b0bdac 100644
--- a/src/sdk/models.ts
+++ b/src/sdk/models.ts
@@ -316,6 +316,10 @@ export type Language =
| 'ocaml'
| 'ml'
| 'mli'
+ | 'ocaml-js'
+ | 'js.ocaml'
+ | 'js.ml'
+ | 'rescript-ocaml'
| 'cr'
| 'crystal'
| 'crystal-wasm'
@@ -506,6 +510,7 @@ export type TemplateName =
| 'rescript'
| 'reason'
| 'ocaml'
+ | 'ocaml-js'
| 'nim'
| 'nim-wasm'
| 'janet-wasm'
diff --git a/storybook/_stories/EmbedOptions/template.ts b/storybook/_stories/EmbedOptions/template.ts
index b2408f34eb..12d299bfca 100644
--- a/storybook/_stories/EmbedOptions/template.ts
+++ b/storybook/_stories/EmbedOptions/template.ts
@@ -39,6 +39,7 @@ const storyDef: StoryDef = {
ReScript: { props: { template: 'rescript' }, storyName: 'ReScript' },
Reason: { props: { template: 'reason' } },
Ocaml: { props: { template: 'ocaml' } },
+ OcamlJs: { props: { template: 'ocaml-js' } },
Nim: { props: { template: 'nim' } },
NimWasm: { props: { template: 'nim-wasm' } },
JanetWasm: { props: { template: 'janet-wasm' } },
diff --git a/vendor-licenses.md b/vendor-licenses.md
index 2c581b3e45..a7841eded0 100644
--- a/vendor-licenses.md
+++ b/vendor-licenses.md
@@ -268,6 +268,8 @@ quill-html-edit-button: [MIT License](https://github.com/benwinding/quill-html-e
require.js: [MIT License](https://github.com/marella/require.js/blob/e88122fb11fdd10fb649dd8999723d34074ed647/LICENSE)
+@live-codes/ocaml: [LGPL-2.1-or-later with OCaml linking exception](https://github.com/live-codes/browser-ocaml/blob/main/packages/ocaml/LICENSE)
+
ReScript: [License](https://github.com/rescript-lang/rescript-compiler/blob/d93260cb2d4be63e387959e69f3204af85e5b1b3/LICENSE)
ReScript/React: [MIT License](https://github.com/rescript-lang/rescript-react/blob/c3017ec4bbce5847c3b2da8d2d536450a3e2fd6d/LICENSE)