Skip to content

Commit c240d40

Browse files
authored
Merge pull request #1375 from thewtex/dist-esm
docs(typescript): esm example
2 parents db86168 + d006969 commit c240d40

13 files changed

Lines changed: 531 additions & 115 deletions

File tree

.github/workflows/playwright.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Playwright Tests
2+
on:
3+
push:
4+
branches: [ main ]
5+
pull_request:
6+
branches: [ main ]
7+
jobs:
8+
test:
9+
defaults:
10+
run:
11+
working-directory: ./examples/esm
12+
timeout-minutes: 60
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: actions/setup-node@v4
17+
with:
18+
node-version: lts/*
19+
- name: Install dependencies
20+
run: npm install
21+
- name: Install Playwright Browsers
22+
run: npx playwright install --with-deps
23+
- name: Run Playwright tests
24+
run: npm run test
25+
- uses: actions/upload-artifact@v4
26+
if: ${{ !cancelled() }}
27+
with:
28+
name: playwright-report
29+
path: playwright-report/
30+
retention-days: 30

docs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ ITK-Wasm
1313
[![itkwasm version](https://badge.fury.io/py/itkwasm.svg)](https://pypi.org/project/itkwasm/)
1414

1515
[![DOI](https://zenodo.org/badge/45812381.svg)](https://zenodo.org/badge/latestdoi/45812381)
16+
[![Give it a star!](https://img.shields.io/github/stars/InsightSoftwareConsortium/ITK-Wasm?style=social)](https://github.com/InsightSoftwareConsortium/ITK-Wasm)
1617

1718
![License](https://img.shields.io/github/license/InsightSoftwareConsortium/ITK-Wasm) ![GitHub commit activity](https://img.shields.io/github/commit-activity/y/InsightSoftwareConsortium/ITK-Wasm)
1819
</div>
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Distribution
22

3-
This sections walks through examples on how to distribution applications for deployment that depend on itk-wasm packages.
3+
This section provides examples of how to distribute applications
4+
for deployment that rely on [ITK-Wasm packages](../../introduction/packages.md).
45

56
```{toctree}
67
:maxdepth: 1
@@ -10,4 +11,4 @@ umd.md
1011
vite.md
1112
webpack.md
1213
node.md
13-
```
14+
```

examples/esm/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
# Playwright
3+
node_modules/
4+
/test-results/
5+
/playwright-report/
6+
/blob-report/
7+
/playwright/.cache/

examples/esm/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
ITK-Wasm ESM Example
2+
====================
3+
4+
This example demonstrates how to use the
5+
[ITK-Wasm](https://wasm.itk.org/) ESM module from
6+
a an HTML script tag for access to the image and mesh IO module that are
7+
distributed on the [jsDelivr](https://www.jsdelivr.com/) [content delivery
8+
network](https://en.wikipedia.org/wiki/Content_delivery_network).
9+
10+
More information can be found in the [example
11+
documentation](https://docs.itk.org/projects/wasm/en/latest/typescript/distribution/esm.html).
12+
13+
## Run Locally
14+
15+
```
16+
npm install
17+
npm run start
18+
```
19+
20+
And visit [http://localhost:8080/](http://localhost:8080/).
21+
22+
## Development
23+
24+
```
25+
npm install
26+
npm test
27+
```

examples/esm/dist/index.html

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>ITK-Wasm ESM Example</title>
5+
<meta charset="UTF-8" />
6+
<link rel="stylesheet" href="styles.css">
7+
</head>
8+
9+
<body>
10+
<!-- Selector -->
11+
<div>
12+
<label>Select image:</label>
13+
<input name="input-file" type="file">
14+
</div>
15+
16+
<!-- Image visualization -->
17+
<div id="viewer">
18+
<canvas height="600"></canvas>
19+
</div>
20+
21+
<!-- Image information -->
22+
<textarea readonly name="image-information">Image information...</textarea>
23+
24+
<!-- Javascript -->
25+
<script type="module">
26+
// Example ITK-Wasm package, @itk-wasm/image-io
27+
import { readImage } from "https://cdn.jsdelivr.net/npm/@itk-wasm/image-io@1.6.0/dist/bundle/index-worker-embedded.min.js";
28+
29+
// Visualization
30+
import { Niivue, MULTIPLANAR_TYPE } from "https://cdn.jsdelivr.net/npm/@niivue/niivue@0.56.0/dist/index.js";
31+
// Convert ITK-Wasm Image to Niivue Image
32+
import { iwi2niiCore } from "https://cdn.jsdelivr.net/npm/@niivue/cbor-loader@1.2.1/+esm";
33+
34+
async function processImage(event) {
35+
const outputTextArea = document.querySelector("textarea");
36+
outputTextArea.textContent = "Loading...";
37+
38+
const dataTransfer = event.dataTransfer;
39+
const files = event.target.files || dataTransfer.files;
40+
41+
const { image } = await readImage(files[0]);
42+
43+
function replacer(key, value) {
44+
if (!!value && value.byteLength !== undefined) {
45+
return String(value.slice(0, 6)) + "...";
46+
}
47+
return value;
48+
}
49+
outputTextArea.textContent = JSON.stringify(image, replacer, 4);
50+
51+
const canvas = document.querySelector('#viewer > canvas');
52+
const nv = new Niivue({ multiplanarLayout: MULTIPLANAR_TYPE.GRID });
53+
await nv.attachToCanvas(canvas);
54+
const niiImage = iwi2niiCore(image);
55+
await nv.loadVolumes([{ url: niiImage, name: 'image.nii' }])
56+
}
57+
58+
const imageInput = document.querySelector("input[name='input-file']");
59+
imageInput.addEventListener("change", processImage);
60+
</script>
61+
62+
</body>
63+
</html>
64+

examples/esm/dist/styles.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
html, body {
2+
height: 90%;
3+
}
4+
5+
textarea {
6+
resize: none;
7+
overflow-y: scroll;
8+
box-sizing: border-box;
9+
width: 600px;
10+
height: 400px;
11+
}

examples/esm/package.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "itk-wasm-esm-example",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "This example demonstrates how to use an ITK-Wasm package ESM module from an HTML script tag.",
6+
"scripts": {
7+
"start": "http-server -c-1 ./dist/",
8+
"test:browser": "npx playwright test",
9+
"test:browser:ui": "npx playwright test --ui",
10+
"test:browser:debug": "npx playwright test --debug",
11+
"test:browser:report": "npx playwright show-report",
12+
"test:debug": "start-server-and-test start http://localhost:8080 test:browser:debug",
13+
"test:ui": "start-server-and-test start http://localhost:8080 test:browser:ui",
14+
"test": "start-server-and-test start http://localhost:8080 test:browser"
15+
},
16+
"repository": {
17+
"type": "git",
18+
"url": "https://github.com/InsightSoftwareConsortium/ITK-Wasm.git"
19+
},
20+
"keywords": [
21+
"itk",
22+
"esm"
23+
],
24+
"author": "Matt McCormick <matt@fideus.io>",
25+
"license": "Apache-2.0",
26+
"bugs": {
27+
"url": "https://github.com/InsightSoftwareConsortium/ITK-Wasm/issues"
28+
},
29+
"homepage": "https://github.com/InsightSoftwareConsortium/ITK-Wasm#readme",
30+
"devDependencies": {
31+
"@playwright/test": "^1.52.0",
32+
"@types/node": "^22.13.13",
33+
"http-server": "^14.1.1",
34+
"start-server-and-test": "^2.0.11"
35+
}
36+
}

examples/esm/playwright.config.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// @ts-check
2+
import { defineConfig, devices } from '@playwright/test';
3+
4+
/**
5+
* Read environment variables from file.
6+
* https://github.com/motdotla/dotenv
7+
*/
8+
// import dotenv from 'dotenv';
9+
// import path from 'path';
10+
// dotenv.config({ path: path.resolve(__dirname, '.env') });
11+
12+
/**
13+
* @see https://playwright.dev/docs/test-configuration
14+
*/
15+
export default defineConfig({
16+
testDir: './tests',
17+
/* Run tests in files in parallel */
18+
fullyParallel: true,
19+
/* Fail the build on CI if you accidentally left test.only in the source code. */
20+
forbidOnly: !!process.env.CI,
21+
/* Retry on CI only */
22+
retries: process.env.CI ? 2 : 0,
23+
/* Opt out of parallel tests on CI. */
24+
workers: process.env.CI ? 1 : undefined,
25+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
26+
reporter: 'html',
27+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
28+
use: {
29+
/* Base URL to use in actions like `await page.goto('/')`. */
30+
// baseURL: 'http://127.0.0.1:3000',
31+
32+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
33+
trace: 'on-first-retry',
34+
},
35+
36+
/* Configure projects for major browsers */
37+
projects: [
38+
{
39+
name: 'chromium',
40+
use: { ...devices['Desktop Chrome'] },
41+
},
42+
43+
{
44+
name: 'firefox',
45+
use: { ...devices['Desktop Firefox'] },
46+
},
47+
48+
{
49+
name: 'webkit',
50+
use: { ...devices['Desktop Safari'] },
51+
},
52+
53+
/* Test against mobile viewports. */
54+
// {
55+
// name: 'Mobile Chrome',
56+
// use: { ...devices['Pixel 5'] },
57+
// },
58+
// {
59+
// name: 'Mobile Safari',
60+
// use: { ...devices['iPhone 12'] },
61+
// },
62+
63+
/* Test against branded browsers. */
64+
// {
65+
// name: 'Microsoft Edge',
66+
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
67+
// },
68+
// {
69+
// name: 'Google Chrome',
70+
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
71+
// },
72+
],
73+
74+
/* Run your local dev server before starting the tests */
75+
// webServer: {
76+
// command: 'npm run start',
77+
// url: 'http://127.0.0.1:3000',
78+
// reuseExistingServer: !process.env.CI,
79+
// },
80+
});
81+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// @ts-check
2+
import { test, expect } from "@playwright/test";
3+
4+
test("loads an image", async ({ page }) => {
5+
await page.goto("http://localhost:8080/");
6+
7+
await expect(page).toHaveTitle(/ITK-Wasm ESM/);
8+
9+
const fileInput = page.locator("input[type='file']");
10+
await fileInput.setInputFiles("tests/tooth.nrrd");
11+
12+
const textarea = page.locator("textarea");
13+
await expect(textarea).toHaveText(/imageType/);
14+
});

0 commit comments

Comments
 (0)