diff --git a/.agents/skills/livecodes/language-support/references/languages.md b/.agents/skills/livecodes/language-support/references/languages.md index ef36376c5f..ff62a7f14e 100644 --- a/.agents/skills/livecodes/language-support/references/languages.md +++ b/.agents/skills/livecodes/language-support/references/languages.md @@ -131,6 +131,7 @@ Enabled via `processors` config: | ClojureScript | `clojurescript`, `clojure`, `cljs`, `clj` | Clojure | | Perl | `perl`, `pl`, `pm` | Perl runtime | | Gleam | `gleam` | Gleam language | +| Elm | `elm` | Elm compiler (WASM) | | Haskell | `haskell`, `hs`, `lhs` | MicroHs (not GHC) | | Haskell (Wasm) | `haskell-wasm`, `hs-wasm`, `wasm.hs`, `hswasm` | GHC WASM | | Tcl | `tcl` | Tcl interpreter | diff --git a/README.md b/README.md index a6e50f0563..714347b920 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A [feature-rich](https://livecodes.io/docs/features/), open-source, **client-sid [![LiveCodes: npm version](https://img.shields.io/npm/v/livecodes)](https://www.npmjs.com/package/livecodes) [![LiveCodes: npm downloads](https://img.shields.io/npm/dm/livecodes)](https://www.npmjs.com/package/livecodes) [![LiveCodes: jsdelivr downloads](https://data.jsdelivr.com/v1/package/npm/livecodes/badge?style=rounded)](https://www.jsdelivr.com/package/npm/livecodes) -[![LiveCodes: languages](https://img.shields.io/badge/languages-104-blue)](https://livecodes.io/docs/languages/) +[![LiveCodes: languages](https://img.shields.io/badge/languages-105-blue)](https://livecodes.io/docs/languages/) [![LiveCodes: docs](https://img.shields.io/badge/Documentation-575757?logo=gitbook&logoColor=white)](https://livecodes.io/docs/) [![LiveCodes: llms.txt](https://img.shields.io/badge/llms.txt-575757?logo=googledocs&logoColor=white)](https://livecodes.io/docs/llms.txt) [![LiveCodes: llms-full.txt](https://img.shields.io/badge/llms--full.txt-575757?logo=googledocs&logoColor=white)](https://livecodes.io/docs/llms-full.txt) diff --git a/docs/docs/languages/elm.mdx b/docs/docs/languages/elm.mdx new file mode 100644 index 0000000000..eff7a25111 --- /dev/null +++ b/docs/docs/languages/elm.mdx @@ -0,0 +1,108 @@ +# Elm + +[Elm](https://elm-lang.org/) is a delightful language for reliable web applications. +It is a purely functional language that compiles to JavaScript. + +LiveCodes compiles Elm in the browser using +[@live-codes/elm-wasm](https://www.npmjs.com/package/@live-codes/elm-wasm), +a WebAssembly build of the Elm compiler. + +## Basic Demo + +import LiveCodes from '../../src/components/LiveCodes.tsx'; + +export const config = { + activeEditor: 'script', + script: { + language: 'elm', + content: `module Main exposing (main)\n +import Browser +import Html exposing (Html, button, div, h1, text) +import Html.Events exposing (onClick)\n\n +type alias Model = + Int\n\n +type Msg + = Increment\n\n +update : Msg -> Model -> Model +update msg model = + case msg of + Increment -> + model + 1\n\n +view : Model -> Html Msg +view model = + div [] + [ h1 [] [ text ("You clicked " ++ String.fromInt model ++ " times.") ] + , button [ onClick Increment ] [ text "Click me" ] + ]\n\n +main : Program () Model Msg +main = + Browser.sandbox { init = 0, update = update, view = view } +`, + }, + mode: 'simple', + editor: 'auto', +}; + + + +See below for more examples. + +## Usage + +Write Elm code in the script editor. The module must expose `main` (e.g. +`module Main exposing (main)`), as required by the Elm compiler. + +The code is compiled to JavaScript, then the compiled program is initialized in the result page +by a `Elm..init({ node })` call into a `div` appended to the page body. +If you wish to use a specific DOM element use `"livecodes-app"` as the element `id`. +This works for the common program types (`Browser.sandbox`, `Browser.element`, `Browser.document` and `Browser.application`). + +Imports of modules from Elm packages are detected automatically. Packages the compiler ships with +(a set of `elm/*` packages, provided as precompiled artifacts) are enabled without downloading +anything; any other package is downloaded from jsDelivr and installed into the compiler's virtual +file system. + +The generated JavaScript can be inspected in the **Compiled code** tool pane. + +## Language Info + +### Name + +`elm` + +### Aliases / Extensions + +`elm` + +### Editor + +`script` + +## Compiler + +[@live-codes/elm-wasm](https://www.npmjs.com/package/@live-codes/elm-wasm), a WebAssembly build +of the [Elm compiler](https://github.com/elm/compiler). + +### Version + +Elm 0.19.1 (`@live-codes/elm-wasm` 0.2.1) + +## Code Formatting + +Not supported. + +## Limitations + +- The first run downloads the compiler (~10.6 MB `ulm.wasm`) in addition to the Elm package + data. +- Elm source is compiled as a single module. Other modules are provided by installed packages, + which are resolved at compile time (jsDelivr by default). + +## Starter Template + +https://livecodes.io/?template=elm + +## Links + +- [Elm](https://elm-lang.org/) +- [Elm guide](https://guide.elm-lang.org/) diff --git a/docs/src/components/LanguageSliders.tsx b/docs/src/components/LanguageSliders.tsx index e4c56c7a2b..e90d8b6d5d 100644 --- a/docs/src/components/LanguageSliders.tsx +++ b/docs/src/components/LanguageSliders.tsx @@ -74,6 +74,7 @@ export default function Sliders() { { name: 'civet', title: 'Civet' }, { name: 'clio', title: 'Clio' }, { name: 'imba', title: 'Imba' }, + { name: 'elm', title: 'Elm' }, { name: 'rescript', title: 'ReScript' }, { name: 'reason', title: 'Reason' }, { name: 'ocaml', title: 'OCaml' }, diff --git a/docs/src/components/TemplateList.tsx b/docs/src/components/TemplateList.tsx index 5ac3e7211b..ce33bf68f5 100644 --- a/docs/src/components/TemplateList.tsx +++ b/docs/src/components/TemplateList.tsx @@ -33,6 +33,7 @@ const templates = [ { name: 'civet', title: 'Civet Starter', thumbnail: 'civet.png' }, { name: 'clio', title: 'Clio Starter', thumbnail: 'clio.png' }, { name: 'imba', title: 'Imba Starter', thumbnail: 'imba.svg' }, + { name: 'elm', title: 'Elm Starter', thumbnail: 'elm.svg' }, { name: 'rescript', title: 'ReScript Starter', thumbnail: 'rescript.png' }, { name: 'reason', title: 'Reason Starter', thumbnail: 'reason.svg' }, { name: 'ocaml', title: 'Ocaml Starter', thumbnail: 'ocaml.svg' }, diff --git a/e2e/specs/starter.spec.ts b/e2e/specs/starter.spec.ts index 2e29c6120a..60701f091f 100644 --- a/e2e/specs/starter.spec.ts +++ b/e2e/specs/starter.spec.ts @@ -295,6 +295,31 @@ test.describe('Starter Templates from UI', () => { await expect(getResult().locator('text=You clicked')).toHaveText('You clicked 3 times.'); }); + test('elm Starter', async ({ page, getTestUrl }) => { + // the Elm compiler (ulm.wasm, ~10.6 MB) is downloaded on the first run + test.slow(); + + await page.goto(getTestUrl()); + + const { app, getResult, waitForResultUpdate } = await getLoadedApp(page); + + await app.click('[aria-label="Project"]'); + await app.click('text=New'); + await app.click('text=Elm Starter'); + + await waitForEditorFocus(app); + await waitForResultUpdate(); + + // nothing is rendered until the compiler is downloaded and the code has run + await expect(getResult().locator('h1')).toHaveText('Hello, Elm!', { timeout: 280_000 }); + + await getResult().click('text=Click me'); + await getResult().click('text=Click me'); + await getResult().click('text=Click me'); + + await expect(getResult().locator('text=You clicked')).toHaveText('You clicked 3 times.'); + }); + test('d3 Starter', async ({ page, getTestUrl, editor }) => { test.slow(); diff --git a/functions/vendors/templates.js b/functions/vendors/templates.js index f42650170b..4777e147c6 100644 --- a/functions/vendors/templates.js +++ b/functions/vendors/templates.js @@ -33,6 +33,7 @@ export const starterTemplates = { "civet": "Civet Starter", "clio": "Clio Starter", "imba": "Imba Starter", + "elm": "Elm Starter", "rescript": "ReScript Starter", "reason": "Reason Starter", "ocaml": "Ocaml Starter", diff --git a/scripts/build.js b/scripts/build.js index 3ff359933f..e04b579e42 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -233,6 +233,7 @@ const iifeBuild = () => 'languages/zig-wasm/lang-zig-wasm-script.ts', 'languages/dot/lang-dot-compiler.ts', 'languages/ejs/lang-ejs-compiler.ts', + 'languages/elm/lang-elm-compiler.ts', 'languages/eta/lang-eta-compiler.ts', 'languages/fsharp/lang-fsharp-compiler.ts', 'languages/fsharp-wasm/lang-fsharp-wasm-script.ts', diff --git a/scripts/generate-stories.mts b/scripts/generate-stories.mts index bb06a84b26..70292b949b 100644 --- a/scripts/generate-stories.mts +++ b/scripts/generate-stories.mts @@ -11,7 +11,10 @@ const frameworks = ['preact', 'react', 'solid', 'svelte', 'vue', 'web-components const solidSDK = fs.readFileSync(path.join('src', 'sdk', 'solid.ts'), 'utf8'); const patchedSolidSDK = '/* eslint-disable */\n' + - solidSDK.replaceAll('./index', 'livecodes').replaceAll('./models', 'livecodes'); + solidSDK + .replaceAll('./index', 'livecodes') + .replaceAll('./models', 'livecodes') + .replace('// eslint-disable-next-line import/order', ''); fs.writeFileSync(path.join(basePath, 'solid', 'src', 'solid.ts'), patchedSolidSDK, 'utf8'); const readDefs = async (dir: string) => { diff --git a/server/php/inc/starter-templates.json b/server/php/inc/starter-templates.json index 38d33774d5..57432caea5 100644 --- a/server/php/inc/starter-templates.json +++ b/server/php/inc/starter-templates.json @@ -33,6 +33,7 @@ "civet": "Civet Starter", "clio": "Clio Starter", "imba": "Imba Starter", + "elm": "Elm Starter", "rescript": "ReScript Starter", "reason": "Reason Starter", "ocaml": "Ocaml Starter", diff --git a/src/livecodes/UI/command-menu-actions.ts b/src/livecodes/UI/command-menu-actions.ts index 0a8005e9a6..a1d62a039e 100644 --- a/src/livecodes/UI/command-menu-actions.ts +++ b/src/livecodes/UI/command-menu-actions.ts @@ -289,6 +289,7 @@ export const getCommandMenuActions = ({ 'civet', 'clio', 'imba', + 'elm', 'rescript', 'reason', 'ocaml', diff --git a/src/livecodes/assets/templates/elm.svg b/src/livecodes/assets/templates/elm.svg new file mode 100644 index 0000000000..0463fba8a4 --- /dev/null +++ b/src/livecodes/assets/templates/elm.svg @@ -0,0 +1 @@ + diff --git a/src/livecodes/html/language-info.html b/src/livecodes/html/language-info.html index 735e7e7e81..fba2ccd5ff 100644 --- a/src/livecodes/html/language-info.html +++ b/src/livecodes/html/language-info.html @@ -464,6 +464,26 @@

EJS

+
+

Elm

+
+ Elm is compiled to JavaScript in the browser by a WebAssembly build of the Elm compiler. +
+ +

Eta

diff --git a/src/livecodes/i18n/locales/en/language-info.lokalise.json b/src/livecodes/i18n/locales/en/language-info.lokalise.json index d5dc3b9561..7e520df184 100644 --- a/src/livecodes/i18n/locales/en/language-info.lokalise.json +++ b/src/livecodes/i18n/locales/en/language-info.lokalise.json @@ -228,6 +228,18 @@ "notes": "", "translation": "EJS" }, + "elm.desc": { + "notes": "", + "translation": "Elm is compiled to JavaScript in the browser by a WebAssembly build of the Elm compiler." + }, + "elm.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": "Elm official website Elm guide LiveCodes Documentation Load starter template " + }, + "elm.name": { + "notes": "", + "translation": "Elm" + }, "eta.desc": { "notes": "", "translation": "Embedded JS template engine for Node, Deno, and the browser. Lightweight, fast, and pluggable. Written in TypeScript." diff --git a/src/livecodes/i18n/locales/en/language-info.ts b/src/livecodes/i18n/locales/en/language-info.ts index bd1c1f5bd5..3e347c3958 100644 --- a/src/livecodes/i18n/locales/en/language-info.ts +++ b/src/livecodes/i18n/locales/en/language-info.ts @@ -105,6 +105,11 @@ const languageInfo = { link: '<1><2>Official website <3> <4>LiveCodes Documentations ', name: 'EJS', }, + elm: { + desc: 'Elm is compiled to JavaScript in the browser by a WebAssembly build of the Elm compiler.', + link: '<1><2>Elm official website <3><4>Elm guide <5> <6>LiveCodes Documentation <7> <8>Load starter template ', + name: 'Elm', + }, eta: { desc: 'Embedded JS template engine for Node, Deno, and the browser. Lightweight, fast, and pluggable. Written in TypeScript.', link: '<1><2>Official website <3> <4>Documentation <5> <6>LiveCodes Documentations ', diff --git a/src/livecodes/i18n/locales/en/translation.lokalise.json b/src/livecodes/i18n/locales/en/translation.lokalise.json index 85fa70786b..96b07a3de6 100644 --- a/src/livecodes/i18n/locales/en/translation.lokalise.json +++ b/src/livecodes/i18n/locales/en/translation.lokalise.json @@ -2616,6 +2616,10 @@ "notes": "", "translation": "Diagrams Starter" }, + "templates.starter.elm": { + "notes": "", + "translation": "Elm Starter" + }, "templates.starter.fennel": { "notes": "", "translation": "Fennel Starter" diff --git a/src/livecodes/i18n/locales/en/translation.ts b/src/livecodes/i18n/locales/en/translation.ts index 74d078ece0..f4156980e9 100644 --- a/src/livecodes/i18n/locales/en/translation.ts +++ b/src/livecodes/i18n/locales/en/translation.ts @@ -1000,6 +1000,7 @@ const translation = { d3: 'D3 Starter', daisyui: 'daisyUI Starter', diagrams: 'Diagrams Starter', + elm: 'Elm Starter', fennel: 'Fennel Starter', fsharp: 'F# Starter', 'fsharp-wasm': 'F# (Wasm) Starter', diff --git a/src/livecodes/languages/elm/index.ts b/src/livecodes/languages/elm/index.ts new file mode 100644 index 0000000000..c72456c3c6 --- /dev/null +++ b/src/livecodes/languages/elm/index.ts @@ -0,0 +1 @@ +export * from './lang-elm'; diff --git a/src/livecodes/languages/elm/lang-elm-compiler.ts b/src/livecodes/languages/elm/lang-elm-compiler.ts new file mode 100644 index 0000000000..b9897c1fd6 --- /dev/null +++ b/src/livecodes/languages/elm/lang-elm-compiler.ts @@ -0,0 +1,65 @@ +import type { CompilerFunction } from '../../models'; +import { elmWasmBaseUrl } from '../../vendors'; + +interface ElmCompiler { + compile: (source: string) => Promise<{ js: string; name: string }>; +} + +declare const self: { + importScripts: (...args: string[]) => void; + ElmWasm: { + createCompiler: (options: { baseUrl: string }) => Promise; + /** renders the structured Elm problems as readable text */ + formatError: (error: unknown) => string; + }; + createElmCompiler: () => CompilerFunction; +}; + +/** + * Runs the compiled Elm program in the result page. + * Elm's output is a classic script that defines the global `Elm`, so the program is + * initialized here (instead of by the user's code) into a node appended to the page. + */ +const getMountCode = (name: string) => ` +;(function () { + const node = + document.querySelector('#livecodes-app') || + document.body.appendChild(document.createElement('div')); + try { + Elm[${JSON.stringify(name)}].init({ node }); + } catch (err) { + console.error('Failed to initialize Elm:', err); + } +})(); +`; + +self.createElmCompiler = (): CompilerFunction => { + let compiler: Promise | undefined; + + const getCompiler = () => { + if (!compiler) { + compiler = (async () => { + self.importScripts(elmWasmBaseUrl + 'index.umd.js'); + return self.ElmWasm.createCompiler({ baseUrl: elmWasmBaseUrl }); + })(); + // do not keep a failed boot (e.g. a transient network error) + compiler.catch(() => { + compiler = undefined; + }); + } + return compiler; + }; + + // the compiler (a ~10 MB WASM module plus the Elm package data) is loaded once and kept warm + getCompiler().catch(() => undefined); + + return async (code) => { + if (!code.trim()) return ''; + try { + const { js, name } = await (await getCompiler()).compile(code); + return `${js.trimEnd()}\n${getMountCode(name)}`; + } catch (err) { + throw new Error(self.ElmWasm.formatError(err)); + } + }; +}; diff --git a/src/livecodes/languages/elm/lang-elm.ts b/src/livecodes/languages/elm/lang-elm.ts new file mode 100644 index 0000000000..9f44e0016a --- /dev/null +++ b/src/livecodes/languages/elm/lang-elm.ts @@ -0,0 +1,24 @@ +import { codemirrorLegacy } from '../../editor/codemirror/utils'; +import type { LanguageSpecs } from '../../models'; +import { codeMirrorBaseUrl, monacoLanguagesBaseUrl } from '../../vendors'; + +export const elm: LanguageSpecs = { + name: 'elm', + title: 'Elm', + compiler: { + factory: (_config, baseUrl) => { + (self as any).importScripts(baseUrl + '{{hash:lang-elm-compiler.js}}'); + return (self as any).createElmCompiler(); + }, + }, + extensions: ['elm'], + editor: 'script', + editorSupport: { + monaco: { languageSupport: monacoLanguagesBaseUrl + 'elm.js' }, + codemirror: { + languageSupport: async () => + codemirrorLegacy((await import(codeMirrorBaseUrl + 'codemirror-lang-elm.js')).elm), + }, + }, + largeDownload: true, +}; diff --git a/src/livecodes/languages/languages.ts b/src/livecodes/languages/languages.ts index f87667b480..6fdc306b85 100644 --- a/src/livecodes/languages/languages.ts +++ b/src/livecodes/languages/languages.ts @@ -18,6 +18,7 @@ import { css } from './css'; import { diagrams } from './diagrams'; import { dot } from './dot'; import { ejs } from './ejs'; +import { elm } from './elm'; import { eta } from './eta'; import { fennel } from './fennel'; import { flow } from './flow'; @@ -142,6 +143,7 @@ export const languages: LanguageSpecs[] = [ civet, clio, imba, + elm, rescript, reason, ocaml, diff --git a/src/livecodes/templates/starter/elm-starter.ts b/src/livecodes/templates/starter/elm-starter.ts new file mode 100644 index 0000000000..d24c469a34 --- /dev/null +++ b/src/livecodes/templates/starter/elm-starter.ts @@ -0,0 +1,75 @@ +import type { Template } from '../../models'; + +export const elmStarter: Template = { + name: 'elm', + title: window.deps.translateString('templates.starter.elm', 'Elm Starter'), + thumbnail: 'assets/templates/elm.svg', + activeEditor: 'script', + markup: { + language: 'html', + content: '', + }, + style: { + language: 'css', + content: ` +.container, +.container button { + text-align: center; + font: 1em sans-serif; +} +.logo { + width: 100px; +} +`.trimStart(), + }, + script: { + language: 'elm', + content: ` +module Main exposing (main) + +import Browser +import Html exposing (Html, button, div, h1, img, p, span, text) +import Html.Attributes exposing (alt, class, id, src) +import Html.Events exposing (onClick) + + +type alias Model = + Int + + +type Msg + = Increment + + +update : Msg -> Model -> Model +update msg model = + case msg of + Increment -> + model + 1 + + +view : Model -> Html Msg +view model = + div [ class "container" ] + [ h1 [] + [ text "Hello, " + , span [ id "name" ] [ text "Elm" ] + , text "!" + ] + , img [ class "logo", alt "logo", src "{{ __livecodes_baseUrl__ }}assets/templates/elm.svg" ] [] + , p [] + [ text "You clicked " + , span [ id "counter" ] [ text (String.fromInt model) ] + , text " times." + ] + , button [ id "counter-button", onClick Increment ] + [ text "Click me" ] + ] + + +main : Program () Model Msg +main = + Browser.sandbox { init = 0, update = update, view = view } +`.trimStart(), + }, +}; diff --git a/src/livecodes/templates/starter/index.ts b/src/livecodes/templates/starter/index.ts index 4f806cc056..73a63e716d 100644 --- a/src/livecodes/templates/starter/index.ts +++ b/src/livecodes/templates/starter/index.ts @@ -18,6 +18,7 @@ import { csharpWasmStarter } from './csharp-wasm-starter'; import { d3Starter } from './d3-starter'; import { daisyuiStarter } from './daisyui-starter'; import { diagramsStarter } from './diagrams-starter'; +import { elmStarter } from './elm-starter'; import { fennelStarter } from './fennel-starter'; import { fsharpStarter } from './fsharp-starter'; import { fsharpWasmStarter } from './fsharp-wasm-starter'; @@ -111,6 +112,7 @@ export const starterTemplates = [ civetStarter, clioStarter, imbaStarter, + elmStarter, rescriptStarter, reasonStarter, ocamlStarter, diff --git a/src/livecodes/vendors.ts b/src/livecodes/vendors.ts index 6ddc4a68d9..a565d2d713 100644 --- a/src/livecodes/vendors.ts +++ b/src/livecodes/vendors.ts @@ -134,6 +134,8 @@ export const ejsUrl = /* @__PURE__ */ getUrl('ejs@4.0.1/ejs.js'); export const elkjsBaseUrl = /* @__PURE__ */ getUrl('elkjs@0.8.2/lib/'); +export const elmWasmBaseUrl = /* @__PURE__ */ getUrl('@live-codes/elm-wasm@0.2.1/dist/'); + export const emmetMonacoUrl = /* @__PURE__ */ getUrl('emmet-monaco-es@5.5.0/dist/emmet-monaco.js'); export const esModuleShimsPath = 'es-module-shims@1.10.0/dist/es-module-shims.js'; @@ -334,7 +336,7 @@ export const monacoBaseUrl = /* @__PURE__ */ getUrl('@live-codes/monaco-editor@0 export const monacoEmacsUrl = /* @__PURE__ */ getUrl('monaco-emacs@0.3.0/dist/monaco-emacs.js'); export const monacoLanguagesBaseUrl = /* @__PURE__ */ getUrl( - '@live-codes/monaco-languages@0.3.2/dist/', + '@live-codes/monaco-languages@0.3.4/dist/', ); export const monacoThemesBaseUrl = /* @__PURE__ */ getUrl('monaco-themes@0.4.4/themes/'); diff --git a/src/sdk/models.ts b/src/sdk/models.ts index 079506f515..528762d247 100644 --- a/src/sdk/models.ts +++ b/src/sdk/models.ts @@ -128,6 +128,7 @@ export type Language = | 'civet' | 'clio' | 'imba' + | 'elm' | 'assemblyscript' | 'as' | 'python' @@ -433,6 +434,7 @@ export type TemplateName = | 'commonlisp' | 'clojurescript' | 'gleam' + | 'elm' | 'tcl' | 'markdown' | 'assemblyscript' diff --git a/storybook/_stories/EmbedOptions/template.ts b/storybook/_stories/EmbedOptions/template.ts index 8cb755bbd8..28b968c83f 100644 --- a/storybook/_stories/EmbedOptions/template.ts +++ b/storybook/_stories/EmbedOptions/template.ts @@ -35,6 +35,7 @@ const storyDef: StoryDef = { Civet: { props: { template: 'civet' } }, Clio: { props: { template: 'clio' } }, Imba: { props: { template: 'imba' } }, + Elm: { props: { template: 'elm' } }, ReScript: { props: { template: 'rescript' }, storyName: 'ReScript' }, Reason: { props: { template: 'reason' } }, Ocaml: { props: { template: 'ocaml' } }, diff --git a/storybook/preact/stories/EmbedOptions/template.stories.ts b/storybook/preact/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/preact/stories/EmbedOptions/template.stories.ts +++ b/storybook/preact/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/storybook/react/stories/EmbedOptions/template.stories.ts b/storybook/react/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/react/stories/EmbedOptions/template.stories.ts +++ b/storybook/react/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/storybook/solid/src/solid.ts b/storybook/solid/src/solid.ts index b196750b3e..8319c10a3e 100644 --- a/storybook/solid/src/solid.ts +++ b/storybook/solid/src/solid.ts @@ -8,10 +8,9 @@ */ import { createComponent } from '@live-codes/solid-sdk'; -import type { Component, JSX } from 'solid-js'; -import { createPlayground } from 'livecodes'; - import type { EmbedOptions, Playground } from 'livecodes'; +import { createPlayground } from 'livecodes'; +import type { Component, JSX } from 'solid-js'; export type { Code, Config, EmbedOptions, Language, Playground } from 'livecodes'; /** diff --git a/storybook/solid/stories/EmbedOptions/template.stories.ts b/storybook/solid/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/solid/stories/EmbedOptions/template.stories.ts +++ b/storybook/solid/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/storybook/svelte/stories/EmbedOptions/template.stories.ts b/storybook/svelte/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/svelte/stories/EmbedOptions/template.stories.ts +++ b/storybook/svelte/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/storybook/vue/stories/EmbedOptions/template.stories.ts b/storybook/vue/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/vue/stories/EmbedOptions/template.stories.ts +++ b/storybook/vue/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/storybook/web-components/stories/EmbedOptions/template.stories.ts b/storybook/web-components/stories/EmbedOptions/template.stories.ts index 59039bec2c..a5206392b6 100644 --- a/storybook/web-components/stories/EmbedOptions/template.stories.ts +++ b/storybook/web-components/stories/EmbedOptions/template.stories.ts @@ -74,6 +74,7 @@ export const Scheme = livecodesStory({ template: 'scheme' }); export const CommonLisp = livecodesStory({ template: 'commonlisp' }); export const ClojureScript = livecodesStory({ template: 'clojurescript' }); ClojureScript.storyName = 'ClojureScript'; +export const Elm = livecodesStory({ template: 'elm' }); export const Perl = livecodesStory({ template: 'perl' }); export const Lua = livecodesStory({ template: 'lua' }); export const LuaWasm = livecodesStory({ template: 'lua-wasm' }); diff --git a/vendor-licenses.md b/vendor-licenses.md index 1cd543c5b5..3ff02207b3 100644 --- a/vendor-licenses.md +++ b/vendor-licenses.md @@ -74,6 +74,8 @@ EJS: [Apache License 2.0](https://github.com/mde/ejs/blob/f47d7aedd51a983e4f7304 elkjs-svg: [MIT License](https://github.com/EmilStenstrom/elkjs-svg/blob/4a8709b2407d23218904f523552c565a37764e40/LICENSE) +Elm: [BSD-3-Clause License](https://github.com/elm/compiler/blob/1bd5b36915a38335195ca7792fe3995f53d84d5e/LICENSE) + emmet-monaco-es: [MIT License](https://github.com/troy351/emmet-monaco-es/blob/b578210738fb591c65fb34530d28c0d0341fbb7d/LICENSE) ES Module Shims: [MIT License](https://github.com/guybedford/es-module-shims/blob/986733009f4c9374decd4c0348740134ff499157/LICENSE)