Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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-119-blue)](https://livecodes.io/docs/languages/)
[![LiveCodes: languages](https://img.shields.io/badge/languages-121-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)
Expand Down
115 changes: 115 additions & 0 deletions docs/docs/languages/dart.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Dart

[Dart](https://dart.dev/) is a client-optimized, statically typed programming language developed by Google, with a focus on building fast apps on any platform.

Dart in LiveCodes is compiled to JavaScript in the browser, with no server. It uses the Dart team's own client-side toolchain — DDC, the analyzer and a subset of `pub`, the same one that powers [DartPad](https://dartpad.dev/) — packaged as [`@live-codes/dart-wasm`](https://www.npmjs.com/package/@live-codes/dart-wasm).

:::info

For Flutter support in LiveCodes, see [Flutter](./flutter.mdx).

:::

## Usage

Demo:

import LiveCodes from '../../src/components/LiveCodes.tsx';

export const dartConfig = {
activeEditor: 'script',
script: {
language: 'dart',
content: `void main() {\n print('Hello, World!');\n}`,
},
mode: 'simple',
editor: 'auto',
tools: {
status: 'full',
active: 'console',
},
};

<LiveCodes config={dartConfig}></LiveCodes>

The compiled JavaScript runs in the context of the [result page](../features/result.mdx), so a Dart program has the page, its DOM and the markup and styles from the other editors.

### Accessing the DOM

`dart:js_interop` ships with the SDK, so the program can reach the page directly — no packages and no network needed:

```ts
import 'dart:js_interop';

@JS('document')
external Document get document;

extension type Document(JSObject _) implements JSObject {
external Element? querySelector(String selectors);
}

extension type Element(JSObject _) implements JSObject {
external set textContent(String value);
}

void main() {
document.querySelector('#name')?.textContent = 'Dart';
}
```

What the program prints goes to the console.

Templates, collections and pattern matching behave as expected:

```ts
void main() {
final fibonacci = <int>[0, 1];
while (fibonacci.length < 10) {
fibonacci.add(fibonacci[fibonacci.length - 1] + fibonacci[fibonacci.length - 2]);
}
print('Fibonacci: $fibonacci');

final squares = {for (var i = 1; i <= 5; i++) i: i * i};
for (final entry in squares.entries) {
print('${entry.key}² = ${entry.value}');
}
}
```

## Language Info

### Name

`dart`

### Aliases / Extensions

`dartlang`, `dart`

### Editor

`script`

## Compiler

The Dart team's client-side toolchain: DDC (the Dart development compiler), using the [`dartpad`](https://pub.dev/packages/dartpad) package.

### Version

DartPad SDK 0.0.9

## Code Formatting

Dart's official formatter (the [`dart_style`](https://pub.dev/packages/dart_style) package behind `dart format`).

## Starter Template

https://livecodes.io/?template=dart

## Links

- [Dart official website](https://dart.dev/)
- [Dart documentation](https://dart.dev/guides)
- [DartPad](https://dartpad.dev/)
- [@live-codes/dart-wasm](https://www.npmjs.com/package/@live-codes/dart-wasm)
- [Flutter](./flutter.mdx) in LiveCodes
111 changes: 111 additions & 0 deletions docs/docs/languages/flutter.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Flutter

[Flutter](https://flutter.dev/) is Google's open-source framework for building natively compiled, multi-platform applications from a single codebase.

Flutter in LiveCodes is compiled in the browser, with no server, using the same client-side toolchain as [Dart](./dart.mdx) — packaged as [`@live-codes/dart-wasm`](https://www.npmjs.com/package/@live-codes/dart-wasm). The compiled app then boots the Flutter engine in the result page.

:::info

For Dart language support in LiveCodes, see [Dart](./dart.mdx).

:::

## Usage

Demo:

import LiveCodes from '../../src/components/LiveCodes.tsx';

export const flutterConfig = {
activeEditor: 'script',
script: {
language: 'flutter',
content: `import 'package:flutter/material.dart';\n\nvoid main() {\n runApp(\n const Center(\n child: Text('Hello, World!', textDirection: TextDirection.ltr),\n ),\n );\n}`,
},
mode: 'simple',
editor: 'auto',
};

<LiveCodes config={flutterConfig}></LiveCodes>

The app renders in the context of the [result page](../features/result.mdx), so it fills the result pane and responds to user interaction, just like any other Flutter web app.

A stateful counter is the usual way to see a rebuild:

```ts
import 'package:flutter/material.dart';

void main() {
runApp(const CounterApp());
}

class CounterApp extends StatefulWidget {
const CounterApp({super.key});

@override
State<CounterApp> createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
int _count = 0;

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('$_count', style: const TextStyle(fontSize: 56)),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => setState(() => _count++),
child: const Text('Increment'),
),
],
),
),
),
);
}
}
```

## Language Info

### Name

`flutter`

### Extensions

`flutter`

### Editor

`script`

## Compiler

The Dart team's client-side toolchain (DDC), using the [`dartpad`](https://pub.dev/packages/dartpad) package and the [CanvasKit](https://pub.dev/packages/canvas_kit) renderer.

### Version

DartPad SDK 0.0.9

## Code Formatting

Dart's official formatter (the [`dart_style`](https://pub.dev/packages/dart_style) package behind `dart format`).

## Starter Template

https://livecodes.io/?template=flutter

## Links

- [Flutter official website](https://flutter.dev/)
- [Flutter documentation](https://docs.flutter.dev/)
- [Introduction to widgets](https://docs.flutter.dev/ui)
- [@live-codes/dart-wasm](https://www.npmjs.com/package/@live-codes/dart-wasm)
- [Dart](./dart.mdx) in LiveCodes
2 changes: 2 additions & 0 deletions docs/src/components/LanguageSliders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export default function Sliders() {
{ name: 'cobol-wasm', title: 'COBOL (Wasm)' },
{ name: 'fortran', title: 'Fortran' },
{ name: 'd-wasm', title: 'D (Wasm)' },
{ name: 'dart', title: 'Dart' },
{ name: 'flutter', title: 'Flutter' },
{ name: 'v-wasm', title: 'V (Wasm)' },
{ name: 'rust-wasm', title: 'Rust (Wasm)' },
{ name: 'swift-wasm', title: 'Swift (Wasm)' },
Expand Down
2 changes: 2 additions & 0 deletions docs/src/components/TemplateList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ const templates = [
{ name: 'minizinc', title: 'MiniZinc Starter', thumbnail: 'minizinc.png' },
{ name: 'blockly', title: 'Blockly Starter', thumbnail: 'blockly.svg' },
{ name: 'diagrams', title: 'Diagrams Starter', thumbnail: 'diagrams.svg' },
{ name: 'dart', title: 'Dart Starter', thumbnail: 'dart.svg' },
{ name: 'flutter', title: 'Flutter Starter', thumbnail: 'flutter.svg' },
];

export default function TemplateList() {
Expand Down
54 changes: 54 additions & 0 deletions e2e/specs/starter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1837,4 +1837,58 @@
const counterText = await getResult().innerText('text=You clicked');
expect(counterText).toBe('You clicked 3 times.');
});

test('Dart Starter', async ({ page, getTestUrl }) => {
// the Dart toolchain (DDC, the analyzer and a subset of pub) 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=Dart Starter');

await waitForEditorFocus(app);
await waitForResultUpdate();

// the button stays disabled until the compiled program has run and wired it up
await expect(getResult().locator('#counter-button')).toBeEnabled({ 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('h1')).toHaveText('Hello, Dart!');
await expect(getResult().locator('text=You clicked')).toHaveText('You clicked 3 times.');
});

test('Flutter Starter', async ({ page, getTestUrl }) => {

Check failure on line 1867 in e2e/specs/starter.spec.ts

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Add at least one assertion to this test case.

See more on https://sonarcloud.io/project/issues?id=live-codes_livecodes&issues=AaEb5COvUnE48ujNDX3R&open=AaEb5COvUnE48ujNDX3R&pullRequest=1063
// the Flutter toolchain and the engine are downloaded on the first run
test.slow();

await page.goto(getTestUrl());

const { app, waitForResultUpdate } = await getLoadedApp(page);

await app.click('[aria-label="Project"]');
await app.click('text=New');
await app.click('text=Flutter Starter');

await waitForEditorFocus(app);
await waitForResultUpdate();

// the app renders to a canvas, so the engine booting is asserted through the line its main()
// prints
await app.click('#tools-pane-titles > .console');
await app.waitForFunction(
() =>
[...document.querySelectorAll('#console-container .luna-console-log-item')].some((item) =>
item.textContent?.includes('Hello from Flutter!'),
),
undefined,
{ timeout: 280_000 },
);
});
});
4 changes: 3 additions & 1 deletion functions/vendors/templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,7 @@ export const starterTemplates = {
"prolog": "Prolog Starter",
"minizinc": "MiniZinc Starter",
"blockly": "Blockly Starter",
"diagrams": "Diagrams Starter"
"diagrams": "Diagrams Starter",
"dart": "Dart Starter",
"flutter": "Flutter Starter"
}
3 changes: 3 additions & 0 deletions scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ const iifeBuild = () =>
'languages/fanak/lang-fanak-script.ts',
'languages/vb-wasm/lang-vb-wasm-script.ts',
'languages/zig-wasm/lang-zig-wasm-script.ts',
'languages/dart/lang-dart-compiler.ts',
'languages/dart/lang-dart-script.ts',
'languages/flutter/lang-flutter-script.ts',
'languages/dot/lang-dot-compiler.ts',
'languages/ejs/lang-ejs-compiler.ts',
'languages/elm/lang-elm-compiler.ts',
Expand Down
4 changes: 3 additions & 1 deletion server/php/inc/starter-templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,7 @@
"prolog": "Prolog Starter",
"minizinc": "MiniZinc Starter",
"blockly": "Blockly Starter",
"diagrams": "Diagrams Starter"
"diagrams": "Diagrams Starter",
"dart": "Dart Starter",
"flutter": "Flutter Starter"
}
2 changes: 2 additions & 0 deletions src/livecodes/UI/command-menu-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ export const getCommandMenuActions = ({
'minizinc',
'blockly',
'diagrams',
'dart',
'flutter',
).map((template) => ({
id: 'Starter template: ' + template,
title: window.deps.translateString('commandMenu.template', 'Template') + ': ' + template,
Expand Down
22 changes: 22 additions & 0 deletions src/livecodes/assets/templates/dart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading