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
63 changes: 33 additions & 30 deletions .github/workflows/runtime.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,35 @@ on:
branches:
- main
tags:
- '*'
- "*"
pull_request:

jobs:
Test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dart-lang/setup-dart@v1

- name: Install Globe Runtime
run: |
sudo apt-get update && sudo apt-get install -y jq curl
mkdir -p ~/.globe/runtime && cd ~/.globe/runtime
curl -s https://api.github.com/repos/invertase/globe_runtime/releases/latest \
| jq -r '.assets[] | select(.name == "libglobe_runtime-x86_64-unknown-linux-gnu.so") | .browser_download_url' \
| xargs curl -L -OJ

- name: Run Dart Tests
working-directory: packages/globe_runtime
run: dart test --reporter expanded --concurrency=1

Build:
needs: Test
name: Build - ${{ matrix.platform.os-name }}
strategy:
matrix:
platform:
- os-name: MacOS-x86_64
runs-on: macOS-latest
runs-on: macos-15-intel
target: x86_64-apple-darwin

- os-name: MacOS-aarch64
runs-on: macOS-latest
runs-on: macos-15
target: aarch64-apple-darwin

- os-name: Linux-x86_64
runs-on: ubuntu-22.04
target: x86_64-unknown-linux-gnu

- os-name: Linux-aarch64
runs-on: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
target: aarch64-unknown-linux-gnu

- os-name: Windows-x86_64
runs-on: windows-latest
runs-on: windows-2025
target: x86_64-pc-windows-msvc

runs-on: ${{ matrix.platform.runs-on }}
steps:
- name: Checkout
Expand Down Expand Up @@ -99,13 +80,37 @@ jobs:
mv "$ARTIFACT_FILE" "$NEW_NAME"

echo "artifact_path=$NEW_NAME" >> $GITHUB_ENV

- name: Upload built library as artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.artifact_path }}
path: ${{ env.artifact_path }}

Test:
needs: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Download Linux x86_64 artifact
uses: actions/download-artifact@v4
with:
name: libglobe_runtime-x86_64-unknown-linux-gnu.so
path: ./artifacts

- name: Add library path to environment
run: |
LIB_PATH="${GITHUB_WORKSPACE}/artifacts/libglobe_runtime-x86_64-unknown-linux-gnu.so"
echo "GLOBE_RUNTIME_LIB_PATH=${LIB_PATH}" >> $GITHUB_ENV
echo "Library path set to: ${LIB_PATH}"
ls -la "${LIB_PATH}"

- uses: dart-lang/setup-dart@v1
- name: Run Dart Tests
working-directory: packages/globe_runtime
run: dart test --reporter expanded --concurrency=1

Release:
name: Publish Release
if: github.ref_type == 'tag'
Expand All @@ -125,5 +130,3 @@ jobs:
uses: softprops/action-gh-release@v2
with:
files: dist/**/*


1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ javascript
node_modules
.dart_tool
.idea
dist

**/pubspec_overrides.yaml
*.iml
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ node-resolve = "2.2.0"
[build-dependencies]
bindgen = "0.71.1"
cc = "1.0"


[dependencies.libffi-sys]
version = "2.3.0"
features = ["system"]
9 changes: 4 additions & 5 deletions examples/basic_example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,10 @@ packages:
globe_runtime:
dependency: "direct main"
description:
name: globe_runtime
sha256: c538800ceabfacc1e7ab51d733cb58a5f269649cbc5c022f78531d64867fef40
url: "https://pub.dev"
source: hosted
version: "1.0.7"
path: "../../packages/globe_runtime"
relative: true
source: path
version: "1.0.8"
http:
dependency: transitive
description:
Expand Down
105 changes: 105 additions & 0 deletions examples/mjml/bin/main.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import 'dart:io';
import 'package:mjml_bridge/mjml_bridge.dart';

const mjmlSource = r'''
<mjml>
<mj-body background-color="#F4F4F4">
<mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="0px" padding-top="30px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-logo.png" target="_blank" width="214px"></mj-image>
<mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="15px" padding-top="0px" padding="10px 25px">
<p style="text-align: center; margin: 10px 0;color:#151e23;font-size:14px;font-family:Georgia,Helvetica,Arial,sans-serif">Product | Concept | Contact</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section background-repeat="repeat" padding-bottom="0px" padding-top="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding-bottom="0px" padding-left="0px" padding-right="0px" padding-top="0px" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-hero.jpg" target="_blank" width="600px"></mj-image>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" background-size="auto" padding-bottom="0px" padding-top="30px" padding="20px 0" text-align="center">
<mj-column>
<mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="30px" line-height="22px" padding-bottom="10px" padding-top="10px" padding="10px 25px">
<p style="line-height: 30px; margin: 10px 0; text-align: center; color:#151e23; font-size:30p; font-family:Georgia,Helvetica,Arial,sans-serif">- Our Holiday Recipes -</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding-bottom="20px" padding-left="30px" padding-right="30px" padding-top="0px" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-product-1.jpg" target="_blank" width="1200px"></mj-image>
</mj-column>
<mj-column>
<mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="0px" padding-left="40px" padding-right="40px" padding-top="0px" padding="10px 25px">
<p style="margin: 10px 0; color:#151e23; font-size:16px; font-family:Georgia,Helvetica,Arial,sans-serif"><b>Cake Title</b></p>
<p style="line-height: 16px; margin: 10px 0;font-size:14px; color:#151e23; font-family:Georgia,Helvetica,Arial,sans-serif; color:#354552">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
<p style="line-height: 16px; margin: 10px 0; color:#354552; font-size:14px; font-family:Georgia,Helvetica,Arial,sans-serif"><u>Choose me</u> &gt;</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" direction="rtl" padding-bottom="0px" padding-top="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding-bottom="20px" padding-left="30px" padding-right="30px" padding-top="20px" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-product-2.jpg" target="_blank" width="1200px"></mj-image>
</mj-column>
<mj-column>
<mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="0px" padding-left="40px" padding-right="40px" padding-top="0px" padding="10px 25px">
<p style="margin: 10px 0; color:#151e23; font-size:16px; font-family:Georgia,Helvetica,Arial,sans-serif"><b>Cake Title</b></p>
<p style="line-height: 16px; margin: 10px 0;font-size:14px; color:#151e23; font-family:Georgia,Helvetica,Arial,sans-serif; color:#354552">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
<p style="line-height: 16px; margin: 10px 0; color:#354552; font-size:14px; font-family:Georgia,Helvetica,Arial,sans-serif"><u>Choose me</u> &gt;</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="0px" padding-top="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding-bottom="20px" padding-left="30px" padding-right="30px" padding-top="20px" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-product-3.jpg" target="_blank" width="1200px"></mj-image>
</mj-column>
<mj-column>
<mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="0px" padding-left="40px" padding-right="40px" padding-top="0px" padding="10px 25px">
<p style="margin: 10px 0; color:#151e23; font-size:16px; font-family:Georgia,Helvetica,Arial,sans-serif"><b>Cake Title</b></p>
<p style="line-height: 16px; margin: 10px 0;font-size:14px; color:#151e23; font-family:Georgia,Helvetica,Arial,sans-serif; color:#354552">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.</p>
<p style="line-height: 16px; margin: 10px 0; color:#354552; font-size:14px; font-family:Georgia,Helvetica,Arial,sans-serif"><u>Choose me</u> &gt;</p>
</mj-text>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" padding-top="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-button align="center" background-color="#354552" border-radius="3px" color="#ffffff" font-family="Georgia, Helvetica, Arial, sans-serif" font-size="14px" font-weight="normal" inner-padding="10px 25px" padding="10px 25px" text-decoration="none" text-transform="none" vertical-align="middle">Discover all desserts</mj-button>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" padding-bottom="0px" padding-top="0px" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding-bottom="0px" padding-left="0px" padding-right="0px" padding-top="0px" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-footer.jpg" target="_blank" width="600px"></mj-image>
</mj-column>
</mj-section>
<mj-section background-color="#ffffff" background-repeat="repeat" padding="20px 0" text-align="center">
<mj-column>
<mj-image align="center" padding="10px 25px" src="https://static.mailjet.com/mjml-website/templates/christmas-logo.png" target="_blank" width="202px"></mj-image>
<mj-social align="center">
<mj-social-element name="facebook"></mj-social-element>
<mj-social-element name="pinterest"></mj-social-element>
<mj-social-element name="instagram"></mj-social-element>
</mj-social>
</mj-column>
</mj-section>
</mj-body>
</mjml>
''';

void main() async {
final result = await mjmlSource.render();

final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);
server.listen((request) {
request.response.headers.contentType = ContentType.html;
request.response
..write(result.html)
..close();
});

if (Platform.isWindows) {
await Process.run('cmd', ['/c', 'start', 'http://localhost:8080']);
} else if (Platform.isMacOS) {
await Process.run('open', ['http://localhost:8080']);
} else if (Platform.isLinux) {
await Process.run('xdg-open', ['http://localhost:8080']);
}
}
69 changes: 69 additions & 0 deletions examples/mjml/lib/mjml_bridge.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import 'dart:async';

import 'package:globe_runtime/globe_runtime.dart';
import 'package:mjml_bridge/mjml_bridge_source.dart';

const _module = InlinedModule(name: 'mjml_bridge', sourceCode: packageSource);

extension MjMlExtension on String {
Future<MJMLResult> render({MJMLOptions? options}) async {
final completer = Completer<MJMLResult>();

await _module.register();

_module.callFunction(
'render',
args: [
this.toFFIType,
(options?.toJson() ?? {}).toFFIType,
],
onData: (data) {
if (data.hasError()) {
completer.completeError(data.error);
} else {
final json = data.data.unpack();
completer.complete(MJMLResult.fromJson(json));
}
return true;
},
);
return completer.future;
}
}

class MJMLOptions {
final bool? keepComments;
final bool? socialIconPath;
final String? fonts;
final String? validationLevel;

const MJMLOptions({
this.keepComments,
this.socialIconPath,
this.fonts,
this.validationLevel,
});

Map<String, dynamic> toJson() {
return {
if (keepComments != null) 'keepComments': keepComments,
if (socialIconPath != null) 'socialIconPath': socialIconPath,
if (fonts != null) 'fonts': fonts,
if (validationLevel != null) 'validationLevel': validationLevel,
};
}
}

class MJMLResult {
final String html;
final List<dynamic> errors;

const MJMLResult({required this.html, required this.errors});

factory MJMLResult.fromJson(Map<dynamic, dynamic> json) {
return MJMLResult(
html: json['html'] ?? '',
errors: json['errors'] ?? [],
);
}
}
13 changes: 13 additions & 0 deletions examples/mjml/lib/mjml_bridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import mjml2html from "mjml-browser";

function render(_: any, mjml: string, options: any, callbackId: number) {
const result = mjml2html(mjml, options);
const encoded = JsonPayload.encode(result);
Dart.send_value(callbackId, encoded);
}

export default {
functions: {
render,
},
};
Loading