Skip to content

Commit 09c2d17

Browse files
authored
Mount a directory from the browser (#1482)
## Motivation for the change, related issues We would like to enable developers to mount local directories into their Playground-based projects by prompting users to select a directory. After the directory is selected the folder can be mounted into Playground and used by it. For example, this could be used to load local plugins and themes into Playground. ## Implementation details This PR adds a window message listener that takes the provided directory handle and mounts it to the mountpoint. ```javascript window.showDirectoryPicker().then(function (directoryHandle) { window.parent.postMessage({ type: 'mount-directory-handle', directoryHandle, mountpoint: '/wordpress/wp-content/uploads/markdown/', }); }); ``` ## Testing Instructions (or ideally a Blueprint) - Add this code after line 280 in `packages/playground/remote/src/lib/worker-thread.ts` ``` primaryPhp.writeFile( '/wordpress/mount.php', `<!DOCTYPE html> <html> <head> <title>Directory picker</title> </head> <body> <button id="pick">Pick directory</button> <script> document.getElementById('pick').addEventListener('click', function() { if (!('showDirectoryPicker' in window)) { alert('Your browser does not support the Directory Picker API'); return; } window.showDirectoryPicker().then(function(directoryHandle) { window.parent.postMessage( { type: 'mount-directory-handle', directoryHandle, mountpoint: '/wordpress/wp-content/uploads/markdown/', } ); }); }); </script> </body> </html>` ); ``` - open this blueprint http://localhost:5400/website-server/?url=/mount.php - Click the button and select a local folder that contains an HTML file - Change the URL in the Playground header to `/wp-content/uploads/markdown/YOUR-HTML-FILE.html` - Confirm that your file was loaded
1 parent ef8830a commit 09c2d17

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Mount data
2+
3+
## Mount a directory from the browser
4+
5+
You can mount a directory from the browser to Playground using the `window.showDirectoryPicker` API. Check the [Browser compatibility](https://developer.mozilla.org/en-US/docs/Web/API/Window/showDirectoryPicker#browser_compatibility) before using this API.
6+
7+
```javascript
8+
window.showDirectoryPicker().then(function (directoryHandle) {
9+
window.parent.postMessage({
10+
type: 'mount-directory-handle',
11+
directoryHandle,
12+
mountpoint: '/wordpress/wp-content/uploads/markdown/',
13+
});
14+
});
15+
```

packages/playground/remote/src/lib/boot-playground-remote.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
exposeAPI,
1010
consumeAPI,
1111
setupPostMessageRelay,
12-
SyncProgressCallback
12+
SyncProgressCallback,
1313
} from '@php-wasm/web';
1414

1515
import type { PlaygroundWorkerEndpoint } from './worker-thread';
@@ -221,6 +221,7 @@ export async function bootPlaygroundRemote() {
221221
wpFrame,
222222
getOrigin((await playground.absoluteUrl)!)
223223
);
224+
setupMountListener(playground);
224225
if (withNetworking) {
225226
await setupFetchNetworkTransport(workerApi);
226227
}
@@ -242,6 +243,27 @@ function getOrigin(url: string) {
242243
return new URL(url, 'https://example.com').origin;
243244
}
244245

246+
function setupMountListener(playground: WebClientMixin) {
247+
window.addEventListener('message', async (event) => {
248+
if (typeof event.data !== 'object') {
249+
return;
250+
}
251+
if (event.data.type !== 'mount-directory-handle') {
252+
return;
253+
}
254+
if (typeof event.data.directoryHandle !== 'object') {
255+
return;
256+
}
257+
if (!event.data.mountpoint) {
258+
return;
259+
}
260+
await playground.bindOpfs({
261+
opfs: event.data.directoryHandle,
262+
mountpoint: event.data.mountpoint,
263+
});
264+
});
265+
}
266+
245267
function parseVersion<T>(value: string | undefined | null, latest: T) {
246268
if (!value || value === 'latest') {
247269
return latest as string;

0 commit comments

Comments
 (0)