@metapages/metapage 1.8.35 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +461 -52
  2. package/package.json +4 -2
  3. package/src/declarations.d.ts +4 -1
  4. package/src/metapage/Metapage.ts +1 -1
  5. package/src/metapage/conversions-metaframe.ts +32 -3
  6. package/src/metapage/v2/metaframe.ts +29 -2
  7. package/dist/index.d.ts +0 -20
  8. package/dist/index.d.ts.map +0 -1
  9. package/dist/index.js +0 -3705
  10. package/dist/index.js.map +0 -1
  11. package/dist/metapage/Constants.d.ts +0 -6
  12. package/dist/metapage/Constants.d.ts.map +0 -1
  13. package/dist/metapage/Metaframe.d.ts +0 -79
  14. package/dist/metapage/Metaframe.d.ts.map +0 -1
  15. package/dist/metapage/Metapage.d.ts +0 -105
  16. package/dist/metapage/Metapage.d.ts.map +0 -1
  17. package/dist/metapage/MetapageIFrameRpcClient.d.ts +0 -64
  18. package/dist/metapage/MetapageIFrameRpcClient.d.ts.map +0 -1
  19. package/dist/metapage/MetapageTools.d.ts +0 -21
  20. package/dist/metapage/MetapageTools.d.ts.map +0 -1
  21. package/dist/metapage/Shared.d.ts +0 -16
  22. package/dist/metapage/Shared.d.ts.map +0 -1
  23. package/dist/metapage/conversions-metaframe.d.ts +0 -14
  24. package/dist/metapage/conversions-metaframe.d.ts.map +0 -1
  25. package/dist/metapage/conversions-metapage.d.ts +0 -9
  26. package/dist/metapage/conversions-metapage.d.ts.map +0 -1
  27. package/dist/metapage/core.d.ts +0 -7
  28. package/dist/metapage/core.d.ts.map +0 -1
  29. package/dist/metapage/data.d.ts +0 -25
  30. package/dist/metapage/data.d.ts.map +0 -1
  31. package/dist/metapage/errors/MissingMetaframeJson.d.ts +0 -10
  32. package/dist/metapage/errors/MissingMetaframeJson.d.ts.map +0 -1
  33. package/dist/metapage/errors/RootMetapageError.d.ts +0 -10
  34. package/dist/metapage/errors/RootMetapageError.d.ts.map +0 -1
  35. package/dist/metapage/events.d.ts +0 -24
  36. package/dist/metapage/events.d.ts.map +0 -1
  37. package/dist/metapage/jsonrpc.d.ts +0 -35
  38. package/dist/metapage/jsonrpc.d.ts.map +0 -1
  39. package/dist/metapage/jsonrpc2.d.ts +0 -35
  40. package/dist/metapage/jsonrpc2.d.ts.map +0 -1
  41. package/dist/metapage/metapageRenderer.d.ts +0 -42
  42. package/dist/metapage/metapageRenderer.d.ts.map +0 -1
  43. package/dist/metapage/metapageRendererExample.d.ts +0 -13
  44. package/dist/metapage/metapageRendererExample.d.ts.map +0 -1
  45. package/dist/metapage/util.d.ts +0 -8
  46. package/dist/metapage/util.d.ts.map +0 -1
  47. package/dist/metapage/v0_1_0/all.d.ts +0 -110
  48. package/dist/metapage/v0_1_0/all.d.ts.map +0 -1
  49. package/dist/metapage/v0_2/all.d.ts +0 -68
  50. package/dist/metapage/v0_2/all.d.ts.map +0 -1
  51. package/dist/metapage/v0_3/JsonRpcMethods.d.ts +0 -42
  52. package/dist/metapage/v0_3/JsonRpcMethods.d.ts.map +0 -1
  53. package/dist/metapage/v0_3/all.d.ts +0 -11
  54. package/dist/metapage/v0_3/all.d.ts.map +0 -1
  55. package/dist/metapage/v0_4/index.d.ts +0 -3
  56. package/dist/metapage/v0_4/index.d.ts.map +0 -1
  57. package/dist/metapage/v0_4/metaframe.d.ts +0 -136
  58. package/dist/metapage/v0_4/metaframe.d.ts.map +0 -1
  59. package/dist/metapage/v0_4/metapage.d.ts +0 -34
  60. package/dist/metapage/v0_4/metapage.d.ts.map +0 -1
  61. package/dist/metapage/v1/index.d.ts +0 -3
  62. package/dist/metapage/v1/index.d.ts.map +0 -1
  63. package/dist/metapage/v1/metaframe.d.ts +0 -59
  64. package/dist/metapage/v1/metaframe.d.ts.map +0 -1
  65. package/dist/metapage/v1/metapage.d.ts +0 -26
  66. package/dist/metapage/v1/metapage.d.ts.map +0 -1
  67. package/dist/metapage/v2/index.d.ts +0 -3
  68. package/dist/metapage/v2/index.d.ts.map +0 -1
  69. package/dist/metapage/v2/metaframe.d.ts +0 -25
  70. package/dist/metapage/v2/metaframe.d.ts.map +0 -1
  71. package/dist/metapage/v2/metapage.d.ts +0 -22
  72. package/dist/metapage/v2/metapage.d.ts.map +0 -1
  73. package/dist/metapage/versions.d.ts +0 -7
  74. package/dist/metapage/versions.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,38 +1,208 @@
1
- # [Metapages](https://docs.metapage.io/docs)
1
+ # @metapages/metapage
2
2
 
3
- A _metapage_ is a set of connected iframes (_metaframes_).
3
+ > Build composable, interconnected web applications using iframes and data pipes
4
4
 
5
- - Examples: [https://metapage.io](https://metapage.io)
6
- - Documentation: [https://docs.metapage.io/docs](https://docs.metapage.io/docs)
7
- - Online tests and conversion tools: [https://module.metapage.io](https://module.metapage.io)
8
- - Example javascript component: [https://js.mtfm.io](https://js.mtfm.io)
5
+ [![npm version](https://badge.fury.io/js/%40metapages%2Fmetapage.svg)](https://www.npmjs.com/package/@metapages/metapage)
9
6
 
10
- Each component iframe runs the metapage module and establishes input/output pipes. Now you can create, edit, and embed whole complex applications directly in your own apps, or simply create using the [metapage editor]((https://metapage.io) and publish and share immediately.
7
+ **@metapages/metapage** is a JavaScript library that lets you create and embed interactive workflows in the browser by connecting independent iframe components together through input/output data pipes.
11
8
 
12
- ## Quickstart metapage
9
+ ## Quick Links
13
10
 
14
- Load and render a metapage definition
11
+ - 📚 [Full Documentation](https://docs.metapage.io/docs)
12
+ - 🎨 [Live Examples](https://metapage.io)
13
+ - 🛠️ [Interactive Tools](https://module.metapage.io)
14
+ - 💻 [Example Component](https://js.mtfm.io)
15
+
16
+ ## What is this?
17
+
18
+ A **metapage** is a web application made up of connected iframes called **metaframes**. Each metaframe can:
19
+
20
+ - Receive data from other metaframes (inputs)
21
+ - Send data to other metaframes (outputs)
22
+ - Run independently (JavaScript, Docker containers, markdown editors, or any web component)
23
+
24
+ Think of it like a visual programming environment where each component is a full web application that can communicate with others through simple JSON data pipes.
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @metapages/metapage
30
+ ```
31
+
32
+ Or use directly from CDN:
15
33
 
16
34
  ```javascript
17
- import { renderMetapage } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.15";
35
+ import {
36
+ renderMetapage,
37
+ Metapage,
38
+ Metaframe,
39
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
40
+ ```
41
+
42
+ ## Quick Start
43
+
44
+ ### Rendering a Metapage
18
45
 
19
- // download a metapage definition from metapage.io
20
- // or just use your own definition JSON
46
+ The simplest way to embed a workflow is using `renderMetapage`:
47
+
48
+ ```javascript
49
+ import { renderMetapage } from "@metapages/metapage";
50
+
51
+ // Fetch a metapage definition (or define your own JSON)
21
52
  const response = await fetch(
22
53
  "https://metapage.io/m/87ae11673508447e883b598bf7da9c5d/metapage.json",
23
54
  );
24
- const metapageDefinition = await response.json();
25
- await renderMetapage({
26
- definition: metapageDefinition,
27
- rootDiv: document.getElementById("metapage-container"),
55
+ const definition = await response.json();
56
+
57
+ // Render it
58
+ const { setInputs, dispose } = await renderMetapage({
59
+ definition,
60
+ rootDiv: document.getElementById("container"),
28
61
  });
29
62
  ```
30
63
 
31
- The rendered workflow:
64
+ The `renderMetapage` function the `react-grid-layout` layout in `metapage.json`:
65
+
66
+ ```json
67
+ {
68
+ "meta": {
69
+ "layouts": {
70
+ "react-grid-layout": {
71
+ ...
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ [Implentation in source code](https://github.com/metapages/metapage/blob/2ef8bd7bfb151ad1616da46aa9797bcf2b1c3d78/app/libs/src/metapage/metapageRenderer.ts#L204)
32
79
 
33
- ![Logo](https://unpkg.com/@metapages/metapage/assets/example-01.png)
80
+ ### Creating a Metaframe (Inside an iframe)
34
81
 
35
- ## Full example
82
+ If you're building a component to use in a metapage:
83
+
84
+ ```javascript
85
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
86
+
87
+ const metaframe = new Metaframe();
88
+
89
+ // Listen for input data from other metaframes
90
+ metaframe.onInput("data", (value) => {
91
+ console.log("Received:", value);
92
+ // Process the data and send output
93
+ metaframe.setOutput("result", value.toUpperCase());
94
+ });
95
+
96
+ // Or listen to all inputs at once
97
+ metaframe.onInputs((inputs) => {
98
+ console.log("All inputs:", inputs);
99
+ });
100
+ ```
101
+
102
+ ## Core Concepts
103
+
104
+ ### Metapage Definition
105
+
106
+ A metapage is defined using JSON that specifies which metaframes to load and how they connect:
107
+
108
+ ```javascript
109
+ {
110
+ "version": "2",
111
+ "metaframes": {
112
+ "input": {
113
+ "url": "https://editor.mtfm.io/#?hm=disabled"
114
+ },
115
+ "processor": {
116
+ "url": "https://js.mtfm.io/",
117
+ "inputs": [
118
+ {
119
+ "metaframe": "input",
120
+ "source": "text",
121
+ "target": "code"
122
+ }
123
+ ]
124
+ },
125
+ "output": {
126
+ "url": "https://markdown.mtfm.io/",
127
+ "inputs": [
128
+ {
129
+ "metaframe": "processor",
130
+ "source": "output"
131
+ }
132
+ ]
133
+ }
134
+ }
135
+ }
136
+ ```
137
+
138
+ This creates a pipeline: `input` → `processor` → `output`
139
+
140
+
141
+ ### Metaframe Definition
142
+
143
+ See [code](https://github.com/metapages/metapage/blob/73549f9f3e27da7a2aef5a935ec112c5bdb130db/app/libs/src/metapage/v2/metaframe.ts#L40)
144
+
145
+ This is provided either by:
146
+
147
+ - `https://<your metaframe>/metaframe.json`
148
+ - `https://<your metaframe>/#?definition=<json encoded hash param>`
149
+
150
+ The definition describes inputs, outputs, security, and the types of hash parameters (so AI tools can correctly modify)
151
+
152
+ ```typescript
153
+ export interface MetaframeDefinitionV2 {
154
+ version: VersionsMetaframe;
155
+ inputs?: {
156
+ [key: string]: MetaframePipeDefinition;
157
+ }; // <MetaframePipeId, MetaframePipeDefinition>
158
+ outputs?: {
159
+ [key: string]: MetaframePipeDefinition;
160
+ }; // <MetaframePipeId, MetaframePipeDefinition>
161
+ metadata: MetaframeMetadataV2;
162
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Feature_Policy/Using_Feature_Policy#the_iframe_allow_attribute
163
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy#directives
164
+ allow?: string;
165
+ // Set or override allowed features for the iframe
166
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox
167
+ sandbox?: string;
168
+ // Hash parameters configuration.
169
+ // Accepts both legacy array format (string[]) and new object format (HashParamsObject).
170
+ // When fetched via helper methods, array format is normalized to object format.
171
+ hashParams?: HashParamsRaw;
172
+ }
173
+ ```
174
+
175
+ ### Data Pipes
176
+
177
+ Pipes connect metaframe outputs to other metaframe inputs:
178
+
179
+ ```javascript
180
+ {
181
+ "metaframe": "sourceMetaframeId", // Where data comes from
182
+ "source": "outputPipeName", // Name of the output pipe
183
+ "target": "inputPipeName" // Name of the input pipe (optional, defaults to source)
184
+ }
185
+ ```
186
+
187
+ ### Working with Data
188
+
189
+ The library automatically handles serialization of complex data types:
190
+
191
+ ```javascript
192
+ // In a metaframe - these are automatically serialized when sent between iframes
193
+ metaframe.setOutput("file", new File([blob], "data.txt"));
194
+ metaframe.setOutput("binary", new Uint8Array([1, 2, 3]));
195
+ metaframe.setOutput("buffer", arrayBuffer);
196
+
197
+ // And automatically deserialized when received
198
+ metaframe.onInput("file", (file) => {
199
+ console.log(file instanceof File); // true
200
+ });
201
+ ```
202
+
203
+ ## Usage Examples
204
+
205
+ ### Full HTML Example
36
206
 
37
207
  ```html
38
208
  <!DOCTYPE html>
@@ -40,61 +210,300 @@ The rendered workflow:
40
210
  <head>
41
211
  <meta charset="utf-8" />
42
212
  <style>
43
- * {
44
- box-sizing: border-box;
213
+ body {
45
214
  margin: 0;
46
215
  padding: 0;
47
- }
48
-
49
- body {
50
216
  width: 100vw;
51
217
  height: 100vh;
52
218
  }
53
-
54
- iframe {
55
- overflow: hidden;
56
- border: 0;
57
- height: 100%;
219
+ #metapage-container {
58
220
  width: 100%;
221
+ height: 100%;
59
222
  }
60
223
  </style>
61
224
  </head>
62
-
63
225
  <body>
64
- <div style="width: 100%; height: 100%" id="metapage-container"></div>
226
+ <div id="metapage-container"></div>
65
227
 
66
228
  <script type="module">
67
- // the only function you need to import to render a metapage
68
- import { renderMetapage } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.15";
229
+ import { renderMetapage } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
69
230
 
70
- // download a metapage definition from metapage.io
71
- // or just use your own definition JSON
72
- const response = await fetch(
231
+ const definition = await fetch(
73
232
  "https://metapage.io/m/87ae11673508447e883b598bf7da9c5d/metapage.json",
74
- );
75
- const metapageDefinition = await response.json();
76
-
77
- // handle metapage outputs
78
- const onOutputs = (outputs) => {
79
- // do something with the outputs
80
- console.log("outputs", outputs);
81
- };
82
- // set input values with the provided setInputs function
83
- // dispose removes all event listeners and unloads the metapage
84
- const { setInputs, dispose } = await renderMetapage({
85
- definition: metapageDefinition,
86
- onOutputs,
233
+ ).then((r) => r.json());
234
+
235
+ const { setInputs, dispose, metapage } = await renderMetapage({
236
+ definition,
87
237
  rootDiv: document.getElementById("metapage-container"),
238
+ onOutputs: (outputs) => {
239
+ console.log("Metaframe outputs:", outputs);
240
+ },
88
241
  options: {
89
- hideBorder: true,
90
242
  hideFrameBorders: true,
91
243
  hideOptions: true,
92
- hideMetaframeLabels: true,
93
244
  },
94
245
  });
246
+
247
+ // Send inputs to metaframes
248
+ setInputs({
249
+ metaframeId: {
250
+ inputPipeName: "some value",
251
+ },
252
+ });
253
+
254
+ // Clean up when done
255
+ // dispose();
256
+ </script>
257
+ </body>
258
+ </html>
259
+ ```
260
+
261
+ ### Building a Metaframe Component
262
+
263
+ ```javascript
264
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
265
+
266
+ const metaframe = new Metaframe();
267
+
268
+ // Handle inputs
269
+ metaframe.onInputs((inputs) => {
270
+ const { data, config } = inputs;
271
+
272
+ // Process inputs
273
+ const result = processData(data, config);
274
+
275
+ // Send outputs
276
+ metaframe.setOutputs({
277
+ result: result,
278
+ timestamp: Date.now(),
279
+ });
280
+ });
281
+
282
+ // Individual input listener
283
+ metaframe.onInput("reset", () => {
284
+ metaframe.setOutputs({});
285
+ });
286
+
287
+ // Get a specific input value
288
+ const currentValue = metaframe.getInput("data");
289
+
290
+ // Get all inputs
291
+ const allInputs = metaframe.getInputs();
292
+
293
+ // Clean up
294
+ metaframe.dispose();
295
+ ```
296
+
297
+ ### Programmatic Metapage Control
298
+
299
+ ```javascript
300
+ import { Metapage } from "@metapages/metapage";
301
+
302
+ const metapage = new Metapage({
303
+ definition: {
304
+ version: "2",
305
+ metaframes: {
306
+ viewer: {
307
+ url: "https://markdown.mtfm.io/",
308
+ },
309
+ },
310
+ },
311
+ });
312
+
313
+ // Listen to metaframe outputs
314
+ metapage.on(Metapage.OUTPUTS, (outputs) => {
315
+ console.log("Outputs from all metaframes:", outputs);
316
+ });
317
+
318
+ // Set inputs to metaframes
319
+ await metapage.setInputs({
320
+ viewer: {
321
+ text: "# Hello World",
322
+ },
323
+ });
324
+
325
+ // Get current outputs
326
+ const outputs = metapage.getState().metaframes.outputs;
327
+
328
+ // Clean up
329
+ metapage.dispose();
330
+ ```
331
+
332
+ ## Advanced Features
333
+
334
+ ### Hash Parameters in Metaframes
335
+
336
+ Metaframes can read and write to their URL hash parameters:
337
+
338
+ ```javascript
339
+ import {
340
+ getHashParamValueJsonFromWindow,
341
+ setHashParamValueJsonInWindow,
342
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
343
+
344
+ // Read from URL hash
345
+ const config = getHashParamValueJsonFromWindow("config");
346
+
347
+ // Write to URL hash
348
+ setHashParamValueJsonInWindow("config", { theme: "dark" });
349
+ ```
350
+
351
+ ### Pattern Matching in Pipes
352
+
353
+ Use glob patterns to match multiple outputs:
354
+
355
+ ```javascript
356
+ {
357
+ "inputs": [
358
+ {
359
+ "metaframe": "source",
360
+ "source": "data/*", // Matches data/foo, data/bar, etc.
361
+ "target": "inputs/"
362
+ }
363
+ ]
364
+ }
365
+ ```
366
+
367
+ ### Binary Data Handling
368
+
369
+ ```javascript
370
+ // Send binary data
371
+ const imageData = await fetch("/image.png").then((r) => r.arrayBuffer());
372
+ metaframe.setOutput("image", imageData);
373
+
374
+ // Receive and use
375
+ metaframe.onInput("image", async (data) => {
376
+ const blob = new Blob([data]);
377
+ const url = URL.createObjectURL(blob);
378
+ document.getElementById("img").src = url;
379
+ });
380
+ ```
381
+
382
+ ## API Overview
383
+
384
+ ### renderMetapage(options)
385
+
386
+ Render a metapage into a DOM element.
387
+
388
+ **Parameters:**
389
+
390
+ - `definition`: Metapage definition object
391
+ - `rootDiv`: DOM element to render into
392
+ - `onOutputs`: Callback for metaframe outputs (optional)
393
+ - `options`: Rendering options (optional)
394
+ - `hideBorder`: Hide metapage border
395
+ - `hideFrameBorders`: Hide individual metaframe borders
396
+ - `hideOptions`: Hide options panel
397
+ - `hideMetaframeLabels`: Hide metaframe labels
398
+
399
+ **Returns:** `{ setInputs, setOutputs, dispose, metapage }`
400
+
401
+ ### Metapage Class
402
+
403
+ **Methods:**
404
+
405
+ - `setInputs(inputs)`: Set inputs for metaframes
406
+ - `getState()`: Get current state (inputs/outputs)
407
+ - `dispose()`: Clean up and remove all listeners
408
+ - `on(event, handler)`: Listen to events
409
+
410
+ **Events:**
411
+
412
+ - `Metapage.OUTPUTS`: When metaframe outputs change
413
+ - `Metapage.INPUTS`: When metapage inputs change
414
+ - `Metapage.DEFINITION`: When definition changes
415
+
416
+ ### Metaframe Class
417
+
418
+ **Methods:**
419
+
420
+ - `setOutput(name, value)`: Set a single output
421
+ - `setOutputs(outputs)`: Set multiple outputs
422
+ - `getInput(name)`: Get a single input value
423
+ - `getInputs()`: Get all input values
424
+ - `onInput(name, callback)`: Listen to specific input
425
+ - `onInputs(callback)`: Listen to all inputs
426
+ - `dispose()`: Clean up
427
+
428
+ **Properties:**
429
+
430
+ - `id`: Metaframe ID assigned by parent metapage
431
+ - `isInputOutputBlobSerialization`: Enable/disable automatic binary serialization
432
+
433
+ ## Creating Your Own Metaframes
434
+
435
+ Any web application can become a metaframe by:
436
+
437
+ 1. Loading the library
438
+ 2. Creating a `Metaframe` instance
439
+ 3. Listening for inputs
440
+ 4. Sending outputs
441
+
442
+ Example minimal metaframe:
443
+
444
+ ```html
445
+ <!DOCTYPE html>
446
+ <html>
447
+ <head>
448
+ <title>My Metaframe</title>
449
+ </head>
450
+ <body>
451
+ <script type="module">
452
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
453
+
454
+ const metaframe = new Metaframe();
455
+
456
+ metaframe.onInputs((inputs) => {
457
+ // Your logic here
458
+ metaframe.setOutput("result", "processed: " + JSON.stringify(inputs));
459
+ });
95
460
  </script>
96
461
  </body>
97
462
  </html>
98
463
  ```
99
464
 
100
- Online tests and conversion tools: [https://module.metapage.io](https://module.metapage.io)
465
+ ## TypeScript Support
466
+
467
+ Full TypeScript definitions are included:
468
+
469
+ ```typescript
470
+ import {
471
+ Metapage,
472
+ Metaframe,
473
+ MetapageDefinitionV2,
474
+ MetaframeInputMap,
475
+ MetapageInstanceInputs,
476
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
477
+
478
+ const definition: MetapageDefinitionV2 = {
479
+ version: "2",
480
+ metaframes: {
481
+ example: {
482
+ url: "https://example.com",
483
+ },
484
+ },
485
+ };
486
+
487
+ const metapage = new Metapage({ definition });
488
+ ```
489
+
490
+ ## Browser Support
491
+
492
+ - Chrome 78+
493
+ - Modern browsers with ES2020 support
494
+ - ES modules required
495
+
496
+ ## License
497
+
498
+ Apache-2.0
499
+
500
+ ## Contributing
501
+
502
+ Issues and pull requests welcome at [https://github.com/metapages/metapage](https://github.com/metapages/metapage)
503
+
504
+ ## More Resources
505
+
506
+ - [Documentation](https://docs.metapage.io)
507
+ - [Examples Gallery](https://metapage.io)
508
+ - [Create Metaframes](https://js.mtfm.io)
509
+ - [Community](https://github.com/metapages/metapage/discussions)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@metapages/metapage",
3
3
  "public": true,
4
- "version": "1.8.35",
4
+ "version": "1.9.1",
5
5
  "description": "Connect web pages together",
6
6
  "repository": "https://github.com/metapages/metapage",
7
7
  "homepage": "https://metapage.io/",
@@ -31,7 +31,7 @@
31
31
  "fetch-retry": "^6.0.0",
32
32
  "mutative": "^1.0.11",
33
33
  "object-hash": "^3.0.0",
34
- "picomatch-browser": "^2.2.6"
34
+ "picomatch": "^4.0.2"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@rollup/plugin-typescript": "^11.1.5",
@@ -39,6 +39,7 @@
39
39
  "@vitest/browser": "^3.2.4",
40
40
  "playwright": "^1.54.2",
41
41
  "rollup-plugin-typescript-paths": "^1.4.0",
42
+ "tslib": "^2.6.2",
42
43
  "typescript": "^5.3.3",
43
44
  "vite": "^4.4.11",
44
45
  "vitest": "^3.2.4"
@@ -52,6 +53,7 @@
52
53
  ],
53
54
  "author": "Dion Whitehead <dion@metapage.io>",
54
55
  "scripts": {
56
+ "build": "just build",
55
57
  "format": "npx prettier . --write",
56
58
  "test": "vitest run",
57
59
  "test-watch": "vitest",
@@ -1 +1,4 @@
1
- declare module "picomatch-browser";
1
+ declare module "picomatch/posix" {
2
+ import picomatch from "picomatch";
3
+ export = picomatch;
4
+ }
@@ -1,6 +1,6 @@
1
1
  import { ListenerFn } from "eventemitter3";
2
2
  import { create } from "mutative";
3
- import picomatch from "picomatch-browser";
3
+ import picomatch from "picomatch/posix";
4
4
 
5
5
  import { VERSION_METAPAGE } from "./Constants";
6
6
  import {
@@ -9,10 +9,34 @@ import {
9
9
  } from "./v0_4/index.js";
10
10
  import { MetaframeDefinitionV1 } from "./v1/index.js";
11
11
  import { MetaframeVersionCurrent, type VersionsMetaframe } from "./versions.js";
12
- import { MetaframeDefinitionV2 } from "./v2/metaframe.js";
12
+ import {
13
+ HashParamsObject,
14
+ HashParamsRaw,
15
+ MetaframeDefinitionV2,
16
+ } from "./v2/metaframe.js";
13
17
 
14
18
  const fetchRetry = fetchRetryWrapper(fetch);
15
19
 
20
+ /**
21
+ * Normalizes hashParams from legacy array format to object format.
22
+ * - Array format ["foo", "bar"] becomes { foo: {}, bar: {} }
23
+ * - Object format is passed through unchanged
24
+ * - undefined/null returns undefined
25
+ */
26
+ export const normalizeHashParams = (
27
+ hashParams: HashParamsRaw | undefined,
28
+ ): HashParamsObject | undefined => {
29
+ if (!hashParams) return undefined;
30
+ if (Array.isArray(hashParams)) {
31
+ const result: HashParamsObject = {};
32
+ for (const key of hashParams) {
33
+ result[key] = {};
34
+ }
35
+ return result;
36
+ }
37
+ return hashParams;
38
+ };
39
+
16
40
  type AnyMetaframeDefinition =
17
41
  | MetaframeDefinitionV03
18
42
  | MetaframeDefinitionV4
@@ -70,7 +94,7 @@ export const convertMetaframeDefinitionToVersion = async (
70
94
 
71
95
  export const convertMetaframeDefinitionToCurrentVersion = async (
72
96
  def: any | AnyMetaframeDefinition,
73
- ): Promise<MetaframeDefinitionV1> => {
97
+ ): Promise<MetaframeDefinitionV2> => {
74
98
  return convertMetaframeDefinitionToVersion(def, MetaframeVersionCurrent);
75
99
  };
76
100
 
@@ -213,7 +237,12 @@ export const convertMetaframeJsonToCurrentVersion = async (
213
237
  if (!m) {
214
238
  return;
215
239
  }
216
- return convertMetaframeDefinitionToCurrentVersion(m);
240
+ const converted = await convertMetaframeDefinitionToCurrentVersion(m);
241
+ // Normalize hashParams from array format to object format
242
+ if (converted?.hashParams) {
243
+ converted.hashParams = normalizeHashParams(converted.hashParams);
244
+ }
245
+ return converted;
217
246
  };
218
247
 
219
248
  const definition_v0_4_to_v0_3 = (def: MetaframeDefinitionV4) => {