markupeditor 0.9.20 → 0.9.22

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.
@@ -79,7 +79,7 @@
79
79
  "append": null
80
80
  },
81
81
  "appearance": {
82
- "accentColor": { "light": "blue", "dark": "lightblue" },
82
+ "accentColor": { "light": "AccentColor", "dark": "AccentColor" },
83
83
  "toolbarBg": { "light": "rgba(250, 249, 246, 0.95)", "dark": "rgba(40, 40, 43, 0.9)" },
84
84
  "buttonBg": { "light": "white", "dark": "black" },
85
85
  "borderColor": { "light": "lightgray", "dark": "gray" },
@@ -7,99 +7,48 @@
7
7
  "path": "src/main.js",
8
8
  "declarations": [
9
9
  {
10
- "kind": "class",
11
- "description": "A web component and API for WYSIWYG HTML editing. The element is available as `<markup-editor>`. The API is available using the element property `MU`.",
12
- "name": "MarkupEditorElement",
13
- "members": [
14
- {
15
- "kind": "field",
16
- "name": "editorContainer"
17
- }
18
- ],
19
- "attributes": [
20
- {
21
- "type": {
22
- "text": "string"
23
- },
24
- "description": "HTML that should be displayed when the editor is empty.",
25
- "name": "placeholder"
26
- },
27
- {
28
- "type": {
29
- "text": "string"
30
- },
31
- "description": "An HTML file whose contents should be loaded for the initial contents of the editor. If you also supply HTML within the <markup-editor> itself (e.g., <markup-editor><p>Hello, world</p></markupeditor>), the content of filename will take precedence.",
32
- "name": "filename"
33
- },
34
- {
35
- "type": {
36
- "text": "string"
37
- },
38
- "description": "The relative path for image src attributes in the editor. By default, if `filename` is specified with a path, `base` will be set to the directory containing the file. For example, if filename is “demo/guide/guide.html”, `base` will be set to “demo/guide/” so that an image with `src=“myImage.png”` will load. If you want this image to load from the “resources” directory below \"demo/guide\", then set base to “demo/guide/resources/” (with a trailing slash).",
39
- "name": "base"
40
- },
41
- {
42
- "type": {
43
- "text": "string"
44
- },
45
- "description": "A JavaScript file that should be loaded as a script within the <markup-editor> element. The script can reference the global MU for access to MarkupEditor functionality. For example, the script could contain code to create and register a MarkupDelegate to receive callbacks during editing, or define a custom ToolbarConfiguration.",
46
- "name": "userscript"
47
- },
48
- {
49
- "type": {
50
- "text": "string"
51
- },
52
- "description": "A CSS file that should be linked within the <markup-editor> element to supplement the MarkupEditor base styling.",
53
- "name": "userstyle"
54
- },
55
- {
56
- "type": {
57
- "text": "string"
58
- },
59
- "description": "The name of a MarkupDelegate that has been registered. See the documentation on MarkupDelegates for details on implementation, usage, and registration.",
60
- "name": "delegate"
61
- },
62
- {
63
- "type": {
64
- "text": "string"
65
- },
66
- "description": "The name of a MessageHandler that has been registered. See the documemtation on MessageHandler for details.",
67
- "name": "handler"
68
- },
69
- {
70
- "type": {
71
- "text": "string"
72
- },
73
- "description": "The name of a ToolbarConfig that has been registered. See the documentation on ToolbarConfig for details of customizing the toolbar configuration and registering configs.",
74
- "name": "toolbar"
75
- },
10
+ "kind": "function",
11
+ "name": "loadPlugins",
12
+ "parameters": [
76
13
  {
14
+ "name": "pluginPaths",
15
+ "description": "Resolved paths to plugin modules.",
77
16
  "type": {
78
- "text": "string"
79
- },
80
- "description": "The name of a KeymapConfig that has been registered. See the documentation on KeymapConfig for details of customizing the keymap configuration and registering configs.",
81
- "name": "keymap"
17
+ "text": "string[]"
18
+ }
82
19
  },
83
20
  {
21
+ "name": "delegate",
22
+ "description": "A MarkupDelegate instance (may be null/undefined).",
84
23
  "type": {
85
- "text": "string"
86
- },
87
- "description": "The name of a BehaviorConfig that has been registered. See the documentation on BehaviorConfig for details of customizing the behavior configuration and registering configs.",
88
- "name": "behavior"
24
+ "text": "object|null"
25
+ }
89
26
  },
90
27
  {
28
+ "name": "importFn",
29
+ "default": "(path) => import(path)",
30
+ "description": "Optional import function; defaults to the native dynamic\n import. Provided for testing.",
31
+ "optional": true,
91
32
  "type": {
92
- "text": "string"
93
- },
94
- "description": "The name of a toolbar that has been registered, whose `menuItems` will be placed before the MarkupToolbar. See the documentation on Extending the Toolbar for details.",
95
- "name": "prepend:"
96
- },
33
+ "text": "function"
34
+ }
35
+ }
36
+ ],
37
+ "description": "Load plugins from an array of paths and notify the delegate on completion.\n\nEach plugin module is imported individually. A per-plugin import failure is caught\nand logged; it does not abort the remaining loads or prevent `markupPluginsDidLoad`\nfrom firing. When all imports have settled, `markupPluginsDidLoad` is called on the\ndelegate (if it defines that method) with an array of manifests for the plugins that\nregistered successfully. The function is a no-op (no delegate call) when `pluginPaths`\nis empty.",
38
+ "return": {
39
+ "type": {
40
+ "text": "Promise<void>"
41
+ }
42
+ }
43
+ },
44
+ {
45
+ "kind": "class",
46
+ "description": "",
47
+ "name": "MarkupEditorElement",
48
+ "members": [
97
49
  {
98
- "type": {
99
- "text": "string"
100
- },
101
- "description": "The name of a toolbar that has been registered, whose `menuItems` will be placed after the MarkupToolbar. See the documentation on Extending the Toolbar for details.",
102
- "name": "append"
50
+ "kind": "field",
51
+ "name": "editorContainer"
103
52
  }
104
53
  ],
105
54
  "superclass": {
@@ -118,6 +67,14 @@
118
67
  "module": "src/main.js"
119
68
  }
120
69
  },
70
+ {
71
+ "kind": "js",
72
+ "name": "loadPlugins",
73
+ "declaration": {
74
+ "name": "loadPlugins",
75
+ "module": "src/main.js"
76
+ }
77
+ },
121
78
  {
122
79
  "kind": "custom-element-definition",
123
80
  "name": "markup-editor",
@@ -132,13 +89,27 @@
132
89
  "kind": "javascript-module",
133
90
  "path": "src/markupeditor.js",
134
91
  "declarations": [
92
+ {
93
+ "kind": "function",
94
+ "name": "setToolbarVisible",
95
+ "parameters": [
96
+ {
97
+ "name": "visible",
98
+ "description": "True if the toolbar should be visible, else false.",
99
+ "type": {
100
+ "text": "boolean"
101
+ }
102
+ }
103
+ ],
104
+ "description": "Set the visibility of the toolbarView using the display property."
105
+ },
135
106
  {
136
107
  "kind": "variable",
137
108
  "name": "MU",
138
109
  "type": {
139
110
  "text": "object"
140
111
  },
141
- "default": "{ activeConfig, activeView, addButton, addCol, addDiv, addHeader, addRow, borderTable, callbackSelectImage, cancelSearch, canUndo, canRedo, consoleLog, cutImage, deactivateSearch, deleteLink, deleteTableArea, doRedo, doUndo, emptyDocument, focus, focusOn, focused, getDataImages, getHTML, getHeight, getImageAttributes, getLinkAttributes, getSelectionState, getTestHTML, indent, insertImage, insertLink, insertTable, loadUserFiles, modifyImage, openImageDialog, openLinkDialog, outdent, padBottom, pasteHTML, pasteText, removeAllDivs, removeButton, removeDiv, resetSelection, savedDataImage, searchFor, setActiveView, setHTML, setStyle, setTestHTML, setTopLevelAttributes, testBlockquoteEnter, testExtractContents, testListEnter, testPasteHTMLPreprocessing, testPasteTextPreprocessing, toggleBold, toggleCode, toggleItalic, toggleListItem, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline, // Helpers to create custom toolbar items MenuItem, Dropdown, DropdownSubmenu, cmdItem, renderGrouped, renderDropdownItems, toggleSearch, // Config access ToolbarConfig, KeymapConfig, BehaviorConfig, // Registry access registerAugmentation, registerConfig, registerDelegate, registerMessageHandler, }",
112
+ "default": "{ activeConfig, activeView, addButton, addCol, addDiv, addHeader, addRow, borderTable, callbackSelectImage, cancelSearch, canUndo, canRedo, consoleLog, cutImage, deactivateSearch, deleteLink, deleteTableArea, doRedo, doUndo, emptyDocument, focus, focusOn, focused, getDataImages, getLocalImages, getHTML, getHeight, getImageAttributes, getLinkAttributes, getSelectionState, getTestHTML, indent, insertImage, insertLink, insertTable, insertHRule, loadUserFiles, modifyImage, openImageDialog, openLinkDialog, outdent, padBottom, pasteCode, pasteHTML, pasteText, removeAllDivs, removeButton, removeDiv, resetSelection, savedDataImage, searchFor, setActiveView, setHTML, setStyle, setTestHTML, setToolbarVisible, setTopLevelAttributes, testBlockquoteEnter, testExtractContents, testListEnter, testPasteHTMLPreprocessing, testPasteTextPreprocessing, toggleBold, toggleCode, toggleItalic, toggleListItem, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline, // Helpers to create custom toolbar items MenuItem, Dropdown, DropdownSubmenu, cmdItem, renderGrouped, renderDropdownItems, toggleSearch, // Config access ToolbarConfig, KeymapConfig, BehaviorConfig, // Registry access registerAugmentation, registerConfig, registerDelegate, registerMessageHandler, registerPlugin, getPluginManifest, invokePlugin, }",
142
113
  "description": "The object whose methods comprise the MarkupEditor API."
143
114
  }
144
115
  ],
@@ -276,12 +247,26 @@
276
247
  "name": "event",
277
248
  "description": "A mocked ClipboardEvent for testing",
278
249
  "type": {
279
- "text": "ClipboardEvent | bull"
250
+ "text": "ClipboardEvent | null"
280
251
  }
281
252
  }
282
253
  ],
283
254
  "description": "Paste html at the selection, replacing the selection as-needed."
284
255
  },
256
+ {
257
+ "kind": "function",
258
+ "name": "pasteCode",
259
+ "parameters": [
260
+ {
261
+ "name": "text",
262
+ "description": "The text to be pasted in a preformatted code block",
263
+ "type": {
264
+ "text": "string"
265
+ }
266
+ }
267
+ ],
268
+ "description": "Paste the `text` into a code block. Caller determines whether to use this method\nbased on the selection state."
269
+ },
285
270
  {
286
271
  "kind": "function",
287
272
  "name": "pasteText",
@@ -297,7 +282,7 @@
297
282
  "name": "event",
298
283
  "description": "A mocked ClipboardEvent for testing",
299
284
  "type": {
300
- "text": "ClipboardEvent | bull"
285
+ "text": "ClipboardEvent | null"
301
286
  }
302
287
  }
303
288
  ],
@@ -328,6 +313,16 @@
328
313
  }
329
314
  }
330
315
  },
316
+ {
317
+ "kind": "function",
318
+ "name": "getLocalImages",
319
+ "description": "Return an array of `src` attributes for images that contain relative references, empty if there are none.",
320
+ "return": {
321
+ "type": {
322
+ "text": "Array<string>"
323
+ }
324
+ }
325
+ },
331
326
  {
332
327
  "kind": "function",
333
328
  "name": "savedDataImage",
@@ -919,6 +914,15 @@
919
914
  }
920
915
  ]
921
916
  },
917
+ {
918
+ "kind": "function",
919
+ "name": "insertHRule",
920
+ "description": "Insert the horizontal rule at the selection."
921
+ },
922
+ {
923
+ "kind": "function",
924
+ "name": "insertHRuleCommand"
925
+ },
922
926
  {
923
927
  "kind": "function",
924
928
  "name": "insertImage",
@@ -1131,6 +1135,15 @@
1131
1135
  ],
1132
1136
  "description": "Set the class of the table to style it using CSS.\nThe default draws a border around everything."
1133
1137
  },
1138
+ {
1139
+ "kind": "function",
1140
+ "name": "isHRuleSelected",
1141
+ "parameters": [
1142
+ {
1143
+ "name": "state"
1144
+ }
1145
+ ]
1146
+ },
1134
1147
  {
1135
1148
  "kind": "function",
1136
1149
  "name": "isTableSelected",
@@ -1222,6 +1235,14 @@
1222
1235
  "module": "src/markup.js"
1223
1236
  }
1224
1237
  },
1238
+ {
1239
+ "kind": "js",
1240
+ "name": "pasteCode",
1241
+ "declaration": {
1242
+ "name": "pasteCode",
1243
+ "module": "src/markup.js"
1244
+ }
1245
+ },
1225
1246
  {
1226
1247
  "kind": "js",
1227
1248
  "name": "pasteText",
@@ -1254,6 +1275,14 @@
1254
1275
  "module": "src/markup.js"
1255
1276
  }
1256
1277
  },
1278
+ {
1279
+ "kind": "js",
1280
+ "name": "getLocalImages",
1281
+ "declaration": {
1282
+ "name": "getLocalImages",
1283
+ "module": "src/markup.js"
1284
+ }
1285
+ },
1257
1286
  {
1258
1287
  "kind": "js",
1259
1288
  "name": "savedDataImage",
@@ -1686,6 +1715,22 @@
1686
1715
  "module": "src/markup.js"
1687
1716
  }
1688
1717
  },
1718
+ {
1719
+ "kind": "js",
1720
+ "name": "insertHRule",
1721
+ "declaration": {
1722
+ "name": "insertHRule",
1723
+ "module": "src/markup.js"
1724
+ }
1725
+ },
1726
+ {
1727
+ "kind": "js",
1728
+ "name": "insertHRuleCommand",
1729
+ "declaration": {
1730
+ "name": "insertHRuleCommand",
1731
+ "module": "src/markup.js"
1732
+ }
1733
+ },
1689
1734
  {
1690
1735
  "kind": "js",
1691
1736
  "name": "insertImage",
@@ -1814,6 +1859,14 @@
1814
1859
  "module": "src/markup.js"
1815
1860
  }
1816
1861
  },
1862
+ {
1863
+ "kind": "js",
1864
+ "name": "isHRuleSelected",
1865
+ "declaration": {
1866
+ "name": "isHRuleSelected",
1867
+ "module": "src/markup.js"
1868
+ }
1869
+ },
1817
1870
  {
1818
1871
  "kind": "js",
1819
1872
  "name": "isTableSelected",
@@ -2939,6 +2992,10 @@
2939
2992
  "kind": "field",
2940
2993
  "name": "icons"
2941
2994
  },
2995
+ {
2996
+ "kind": "field",
2997
+ "name": "help"
2998
+ },
2942
2999
  {
2943
3000
  "kind": "field",
2944
3001
  "name": "command"
@@ -3399,6 +3456,9 @@
3399
3456
  "parameters": [
3400
3457
  {
3401
3458
  "name": "content"
3459
+ },
3460
+ {
3461
+ "name": "visible"
3402
3462
  }
3403
3463
  ]
3404
3464
  }
@@ -3467,7 +3527,7 @@
3467
3527
  "declarations": [
3468
3528
  {
3469
3529
  "kind": "class",
3470
- "description": "ToolbarConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the configuration of the MarkupEditor toolbar. The class makes it convenient \nto write and use the utility methods, but an instance of ToolbarConfig itself is not meaningful.\n\n`ToolbarConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new ToolbarConfig by name using the `toolbar` attribute of the `<markup-editor>` \nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own ToolbarConfig.\n\nTo customize the toolbar, for example, in a `userscript` named `mytoolbar.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet toolbarConfig = MU.ToolbarConfig.full(true); // Grab the full toolbar, including correction, as a baseline\ntoolbarConfig.insertBar.tableMenu = false; // Turn off table insert menu\nMU.registerConfig(toolbarConfig, \"MyToolbarConfig\") // Register the instance by name so we can reference it\n````\n\nThen, where you insert the `<markup-editor>` element, set the ToolbarConfig by name:\n\n```\n<markup-editor userscript=\"mytoolbar.js\" toolbar=\"MyToolbarConfig\">\n```\n \nTurn off entire toolbars and menus using the \"visibility\" settings. Turn off specific items\nwithin a toolbar or menu using the settings specific to that toolbar or menu. Customize \nleft-to-right ordering using the \"ordering\" settings. Specify icon SVG in the \"icon\" settings.\nUse \"augmentation\" to prepend and/or append a toolbar you define yourself.\n\nThe following properties are supported:\n\n```\n{\n \"visibility\": { // Control the visibility of toolbars, etc\n \"toolbar\": true, // Whether the toolbar is visible at all\n \"correctionBar\": true, // Whether the correction bar (undo/redo) is visible\n \"insertBar\": true, // Whether the insert bar (link, image, table) is visible\n \"styleMenu\": true, // Whether the style menu (p, h1-h6, code) is visible\n \"styleBar\": true, // Whether the style bar (bullet/numbered lists) is visible\n \"formatBar\": true, // Whether the format bar (b, i, u, etc) is visible\n \"search\": true, // Whether the search item (hide/show search bar) is visible\n },\n \"ordering\": { // Control the ordering of toolbars, etc, ascending left-to-right\n \"correctionBar\": 10, // Correction bar order if it is visible\n \"insertBar\": 20, // Insert bar (link, image, table) order if it is visible\n \"styleMenu\": 30, // Style menu (p, h1-h6, code) order if it is visible\n \"styleBar\": 40, // Style bar (bullet/numbered lists) order if it is visible\n \"formatBar\": 50, // Format bar (b, i, u, etc) order if it is visible\n \"search\": 60, // Search item (hide/show search bar) order if it is visible\n },\n \"insertBar\": {\n \"link\": true, // Whether the link menu item is visible\n \"image\": true, // Whether the image menu item is visible\n \"tableMenu\": true, // Whether the table menu is visible\n },\n \"formatBar\": {\n \"bold\": true, // Whether the bold menu item is visible\n \"italic\": true, // Whether the italic menu item is visible\n \"underline\": true, // Whether the underline menu item is visible\n \"code\": true, // Whether the code menu item is visible\n \"strikethrough\": true, // Whether the strikethrough menu item is visible\n \"subscript\": true, // Whether the subscript menu item is visible\n \"superscript\": true, // Whether the superscript menu item is visible\n },\n \"styleMenu\": {\n \"p\": \"Body\", // The label in the menu for \"P\" style\n \"h1\": \"H1\", // The label in the menu for \"H1\" style\n \"h2\": \"H2\", // The label in the menu for \"H2\" style\n \"h3\": \"H3\", // The label in the menu for \"H3\" style\n \"h4\": \"H4\", // The label in the menu for \"H4\" style\n \"h5\": \"H5\", // The label in the menu for \"H5\" style\n \"h6\": \"H6\", // The label in the menu for \"H6\" style\n \"pre\": \"Code\", // The label in the menu for \"PRE\" aka code_block style\n },\n \"styleBar\": {\n \"list\": true, // Whether bullet and numbered list items are visible\n \"dent\": true, // Whether indent and outdent items are visible\n },\n \"tableMenu\": {\n \"header\": true, // Whether the \"Header\" item is visible in the \"Table->Add\" menu\n \"border\": true, // Whether the \"Border\" item is visible in the \"Table\" menu\n },\n \"augmentation\": {\n \"prepend\": null, // Name of a registered array of cmdItems to prepend\n \"append\": null // Name of a registered array of cmdItems to append\n },\n \"icons\": { // Outlined 400 weight versions from https://fonts.google.com/icons\n // undo\n \"undo\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z\\\"/></svg>\",\n // redo\n \"redo\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z\\\"/></svg>\",\n // format_bold\n \"strong\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z\\\"/></svg>\",\n // format_italic\n \"em\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-200v-100h160l120-360H320v-100h400v100H580L460-300h140v100H200Z\\\"/></svg>\",\n // format_underlined\n \"u\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120v-80h560v80H200Zm280-160q-101 0-157-63t-56-167v-330h103v336q0 56 28 91t82 35q54 0 82-35t28-91v-336h103v330q0 104-56 167t-157 63Z\\\"/></svg>\",\n // strikethrough_s\n \"s\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M486-160q-76 0-135-45t-85-123l88-38q14 48 48.5 79t85.5 31q42 0 76-20t34-64q0-18-7-33t-19-27h112q5 14 7.5 28.5T694-340q0 86-61.5 133T486-160ZM80-480v-80h800v80H80Zm402-326q66 0 115.5 32.5T674-674l-88 39q-9-29-33.5-52T484-710q-41 0-68 18.5T386-640h-96q2-69 54.5-117.5T482-806Z\\\"/></svg>\",\n // data_object\n \"code\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M560-160v-80h120q17 0 28.5-11.5T720-280v-80q0-38 22-69t58-44v-14q-36-13-58-44t-22-69v-80q0-17-11.5-28.5T680-720H560v-80h120q50 0 85 35t35 85v80q0 17 11.5 28.5T840-560h40v160h-40q-17 0-28.5 11.5T800-360v80q0 50-35 85t-85 35H560Zm-280 0q-50 0-85-35t-35-85v-80q0-17-11.5-28.5T120-400H80v-160h40q17 0 28.5-11.5T160-600v-80q0-50 35-85t85-35h120v80H280q-17 0-28.5 11.5T240-680v80q0 38-22 69t-58 44v14q36 13 58 44t22 69v80q0 17 11.5 28.5T280-240h120v80H280Z\\\"/></svg>\",\n // subscript\n \"sub\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M760-160v-80q0-17 11.5-28.5T800-280h80v-40H760v-40h120q17 0 28.5 11.5T920-320v40q0 17-11.5 28.5T880-240h-80v40h120v40H760Zm-525-80 185-291-172-269h106l124 200h4l123-200h107L539-531l186 291H618L482-457h-4L342-240H235Z\\\"/></svg>\",\n // superscript\n \"sup\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M760-600v-80q0-17 11.5-28.5T800-720h80v-40H760v-40h120q17 0 28.5 11.5T920-760v40q0 17-11.5 28.5T880-680h-80v40h120v40H760ZM235-160l185-291-172-269h106l124 200h4l123-200h107L539-451l186 291H618L482-377h-4L342-160H235Z\\\"/></svg>\",\n // link\n \"link\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z\\\"/></svg>\",\n // image\n \"image\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z\\\"/></svg>\",\n // table\n \"table\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm240-240H200v160h240v-160Zm80 0v160h240v-160H520Zm-80-80v-160H200v160h240Zm80 0h240v-160H520v160ZM200-680h560v-80H200v80Z\\\"/></svg>\",\n // format_list_bulleted\n \"bulletList\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M360-200v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360ZM200-160q-33 0-56.5-23.5T120-240q0-33 23.5-56.5T200-320q33 0 56.5 23.5T280-240q0 33-23.5 56.5T200-160Zm0-240q-33 0-56.5-23.5T120-480q0-33 23.5-56.5T200-560q33 0 56.5 23.5T280-480q0 33-23.5 56.5T200-400Zm0-240q-33 0-56.5-23.5T120-720q0-33 23.5-56.5T200-800q33 0 56.5 23.5T280-720q0 33-23.5 56.5T200-640Z\\\"/></svg>\",\n // format_list_numbered\n \"orderedList\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-80v-60h100v-30h-60v-60h60v-30H120v-60h120q17 0 28.5 11.5T280-280v40q0 17-11.5 28.5T240-200q17 0 28.5 11.5T280-160v40q0 17-11.5 28.5T240-80H120Zm0-280v-110q0-17 11.5-28.5T160-510h60v-30H120v-60h120q17 0 28.5 11.5T280-560v70q0 17-11.5 28.5T240-450h-60v30h100v60H120Zm60-280v-180h-60v-60h120v240h-60Zm180 440v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360Z\\\"/></svg>\",\n // format_indent_increase\n \"blockquote\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm0 440v-320l160 160-160 160Z\\\"/></svg>\",\n // format_indent_decrease\n \"lift\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm160 440L120-480l160-160v320Z\\\"/></svg>\",\n // search\n \"search\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z\\\"/></svg>\",\n // chevron_forward\n \"searchForward\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z\\\"/></svg>\",\n // chevron_backward\n \"searchBackward\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z\\\"/></svg>\",\n // match_case\n \"matchCase\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"m131-252 165-440h79l165 440h-76l-39-112H247l-40 112h-76Zm139-176h131l-64-182h-4l-63 182Zm395 186q-51 0-81-27.5T554-342q0-44 34.5-72.5T677-443q23 0 45 4t38 11v-12q0-29-20.5-47T685-505q-23 0-42 9.5T610-468l-47-35q24-29 54.5-43t68.5-14q69 0 103 32.5t34 97.5v178h-63v-37h-4q-14 23-38 35t-53 12Zm12-54q35 0 59.5-24t24.5-56q-14-8-33.5-12.5T689-393q-32 0-50 14t-18 37q0 20 16 33t40 13Z\\\"/></svg>\",\n // format_paragraph\n \"paragraphStyle\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M360-160v-240q-83 0-141.5-58.5T160-600q0-83 58.5-141.5T360-800h360v80h-80v560h-80v-560H440v560h-80Z\\\"/></svg>\",\n // more_horiz\n \"more\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M240-400q-33 0-56.5-23.5T160-480q0-33 23.5-56.5T240-560q33 0 56.5 23.5T320-480q0 33-23.5 56.5T240-400Zm240 0q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm240 0q-33 0-56.5-23.5T640-480q0-33 23.5-56.5T720-560q33 0 56.5 23.5T800-480q0 33-23.5 56.5T720-400Z\\\"/></svg>\"\n }\n}\n```",
3530
+ "description": "ToolbarConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the configuration of the MarkupEditor toolbar. The class makes it convenient \nto write and use the utility methods, but an instance of ToolbarConfig itself is not meaningful.\n\n`ToolbarConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new ToolbarConfig by name using the `toolbar` attribute of the `<markup-editor>` \nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own ToolbarConfig.\n\nTo customize the toolbar, for example, in a `userscript` named `mytoolbar.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet toolbarConfig = MU.ToolbarConfig.full(true); // Grab the full toolbar, including correction, as a baseline\ntoolbarConfig.insertBar.tableMenu = false; // Turn off table insert menu\nMU.registerConfig(toolbarConfig, \"MyToolbarConfig\") // Register the instance by name so we can reference it\n````\n\nThen, where you insert the `<markup-editor>` element, set the ToolbarConfig by name:\n\n```\n<markup-editor userscript=\"mytoolbar.js\" toolbar=\"MyToolbarConfig\">\n```\n \nTurn off entire toolbars and menus using the \"visibility\" settings. Turn off specific items\nwithin a toolbar or menu using the settings specific to that toolbar or menu. Customize \nleft-to-right ordering using the \"ordering\" settings. Specify icon SVG in the \"icon\" settings.\nUse \"augmentation\" to prepend and/or append a toolbar you define yourself.\n\nThe following properties are supported:\n\n```\n{\n \"visibility\": { // Control the visibility of toolbars, etc\n \"toolbar\": true, // Whether the toolbar is visible at all\n \"correctionBar\": true, // Whether the correction bar (undo/redo) is visible\n \"insertBar\": true, // Whether the insert bar (link, image, table) is visible\n \"styleMenu\": true, // Whether the style menu (p, h1-h6, code) is visible\n \"styleBar\": true, // Whether the style bar (bullet/numbered lists) is visible\n \"formatBar\": true, // Whether the format bar (b, i, u, etc) is visible\n \"search\": true // Whether the search item (hide/show search bar) is visible\n },\n \"ordering\": { // Control the ordering of toolbars, etc, ascending left-to-right\n \"correctionBar\": 10, // Correction bar order if it is visible\n \"insertBar\": 20, // Insert bar (link, image, table) order if it is visible\n \"styleMenu\": 30, // Style menu (p, h1-h6, code) order if it is visible\n \"styleBar\": 40, // Style bar (bullet/numbered lists) order if it is visible\n \"formatBar\": 50, // Format bar (b, i, u, etc) order if it is visible\n \"search\": 60 // Search item (hide/show search bar) order if it is visible\n },\n \"menus\": {\n \"styleName\": true // Whether to show the style name or just use a paragraph symbol\n \"tableHeader\": true, // Whether the \"Header\" item is visible in the \"Table->Add\" menu\n \"tableBorder\": true // Whether the \"Border\" item is visible in the \"Table\" menu\n },\n \"insertBar\": {\n \"link\": true, // Whether the link menu item is visible\n \"image\": true, // Whether the image menu item is visible\n \"tableMenu\": true, // Whether the table menu is visible\n \"hRule\": true // Whether the horizontal rule menu item is visible\n },\n \"formatBar\": {\n \"bold\": true, // Whether the bold menu item is visible\n \"italic\": true, // Whether the italic menu item is visible\n \"underline\": true, // Whether the underline menu item is visible\n \"code\": true, // Whether the code menu item is visible\n \"strikethrough\": true, // Whether the strikethrough menu item is visible\n \"subscript\": true, // Whether the subscript menu item is visible\n \"superscript\": true // Whether the superscript menu item is visible\n },\n \"styleMenu\": {\n \"p\": \"Body\", // The label in the menu for \"P\" style\n \"h1\": \"H1\", // The label in the menu for \"H1\" style\n \"h2\": \"H2\", // The label in the menu for \"H2\" style\n \"h3\": \"H3\", // The label in the menu for \"H3\" style\n \"h4\": \"H4\", // The label in the menu for \"H4\" style\n \"h5\": \"H5\", // The label in the menu for \"H5\" style\n \"h6\": \"H6\", // The label in the menu for \"H6\" style\n \"pre\": \"Code\" // The label in the menu for \"PRE\" aka code_block style\n },\n \"styleBar\": {\n \"list\": true, // Whether bullet and numbered list items are visible\n \"dent\": true // Whether indent and outdent items are visible\n },\n \"augmentation\": {\n \"prepend\": null, // Name of a registered array of cmdItems to prepend\n \"append\": null // Name of a registered array of cmdItems to append\n },\n \"appearance\": { // Colors (light and dark mode) and sizes, vars in toolbar.css\n \"accentColor\": { \"light\": \"blue\", \"dark\": \"lightblue\" },\n \"toolbarBg\": { \"light\": \"rgba(250, 249, 246, 0.95)\", \"dark\": \"rgba(40, 40, 43, 0.9)\" },\n \"buttonBg\": { \"light\": \"white\", \"dark\": \"black\" },\n \"borderColor\": { \"light\": \"lightgray\", \"dark\": \"gray\" },\n \"hoverBg\": { \"light\": \"#f2f2f2\", \"dark\": \"rgb(80, 80, 80)\" },\n \"buttonSize\": \"28px\",\n \"buttonFontSize\": \"24px\"\n },\n \"icons\": { // Outlined 400 weight versions from https://fonts.google.com/icons\n // undo\n \"undo\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z\\\"/></svg>\",\n // redo\n \"redo\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z\\\"/></svg>\",\n // format_bold\n \"strong\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z\\\"/></svg>\",\n // format_italic\n \"em\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-200v-100h160l120-360H320v-100h400v100H580L460-300h140v100H200Z\\\"/></svg>\",\n // format_underlined\n \"u\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120v-80h560v80H200Zm280-160q-101 0-157-63t-56-167v-330h103v336q0 56 28 91t82 35q54 0 82-35t28-91v-336h103v330q0 104-56 167t-157 63Z\\\"/></svg>\",\n // strikethrough_s\n \"s\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M486-160q-76 0-135-45t-85-123l88-38q14 48 48.5 79t85.5 31q42 0 76-20t34-64q0-18-7-33t-19-27h112q5 14 7.5 28.5T694-340q0 86-61.5 133T486-160ZM80-480v-80h800v80H80Zm402-326q66 0 115.5 32.5T674-674l-88 39q-9-29-33.5-52T484-710q-41 0-68 18.5T386-640h-96q2-69 54.5-117.5T482-806Z\\\"/></svg>\",\n // data_object\n \"code\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M560-160v-80h120q17 0 28.5-11.5T720-280v-80q0-38 22-69t58-44v-14q-36-13-58-44t-22-69v-80q0-17-11.5-28.5T680-720H560v-80h120q50 0 85 35t35 85v80q0 17 11.5 28.5T840-560h40v160h-40q-17 0-28.5 11.5T800-360v80q0 50-35 85t-85 35H560Zm-280 0q-50 0-85-35t-35-85v-80q0-17-11.5-28.5T120-400H80v-160h40q17 0 28.5-11.5T160-600v-80q0-50 35-85t85-35h120v80H280q-17 0-28.5 11.5T240-680v80q0 38-22 69t-58 44v14q36 13 58 44t22 69v80q0 17 11.5 28.5T280-240h120v80H280Z\\\"/></svg>\",\n // subscript\n \"sub\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M760-160v-80q0-17 11.5-28.5T800-280h80v-40H760v-40h120q17 0 28.5 11.5T920-320v40q0 17-11.5 28.5T880-240h-80v40h120v40H760Zm-525-80 185-291-172-269h106l124 200h4l123-200h107L539-531l186 291H618L482-457h-4L342-240H235Z\\\"/></svg>\",\n // superscript\n \"sup\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M760-600v-80q0-17 11.5-28.5T800-720h80v-40H760v-40h120q17 0 28.5 11.5T920-760v40q0 17-11.5 28.5T880-680h-80v40h120v40H760ZM235-160l185-291-172-269h106l124 200h4l123-200h107L539-451l186 291H618L482-377h-4L342-160H235Z\\\"/></svg>\",\n // link\n \"link\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 0 24 24\\\" width=\\\"24px\\\"><path d=\\\"M0 0h24v24H0V0z\\\" fill=\\\"none\\\"/><path d=\\\"M17 7h-4v2h4c1.65 0 3 1.35 3 3s-1.35 3-3 3h-4v2h4c2.76 0 5-2.24 5-5s-2.24-5-5-5zm-6 8H7c-1.65 0-3-1.35-3-3s1.35-3 3-3h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-2zm-3-4h8v2H8z\\\"/></svg>\",\n // image\n \"image\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z\\\"/></svg>\",\n // table\n \"table\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm240-240H200v160h240v-160Zm80 0v160h240v-160H520Zm-80-80v-160H200v160h240Zm80 0h240v-160H520v160ZM200-680h560v-80H200v80Z\\\"/></svg>\",\n // format_list_bulleted\n \"bulletList\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M360-200v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360ZM200-160q-33 0-56.5-23.5T120-240q0-33 23.5-56.5T200-320q33 0 56.5 23.5T280-240q0 33-23.5 56.5T200-160Zm0-240q-33 0-56.5-23.5T120-480q0-33 23.5-56.5T200-560q33 0 56.5 23.5T280-480q0 33-23.5 56.5T200-400Zm0-240q-33 0-56.5-23.5T120-720q0-33 23.5-56.5T200-800q33 0 56.5 23.5T280-720q0 33-23.5 56.5T200-640Z\\\"/></svg>\",\n // format_list_numbered\n \"orderedList\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-80v-60h100v-30h-60v-60h60v-30H120v-60h120q17 0 28.5 11.5T280-280v40q0 17-11.5 28.5T240-200q17 0 28.5 11.5T280-160v40q0 17-11.5 28.5T240-80H120Zm0-280v-110q0-17 11.5-28.5T160-510h60v-30H120v-60h120q17 0 28.5 11.5T280-560v70q0 17-11.5 28.5T240-450h-60v30h100v60H120Zm60-280v-180h-60v-60h120v240h-60Zm180 440v-80h480v80H360Zm0-240v-80h480v80H360Zm0-240v-80h480v80H360Z\\\"/></svg>\",\n // format_indent_increase\n \"blockquote\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm0 440v-320l160 160-160 160Z\\\"/></svg>\",\n // format_indent_decrease\n \"lift\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"><path d=\\\"M120-120v-80h720v80H120Zm320-160v-80h400v80H440Zm0-160v-80h400v80H440Zm0-160v-80h400v80H440ZM120-760v-80h720v80H120Zm160 440L120-480l160-160v320Z\\\"/></svg>\",\n // search\n \"search\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M784-120 532-372q-30 24-69 38t-83 14q-109 0-184.5-75.5T120-580q0-109 75.5-184.5T380-840q109 0 184.5 75.5T640-580q0 44-14 83t-38 69l252 252-56 56ZM380-400q75 0 127.5-52.5T560-580q0-75-52.5-127.5T380-760q-75 0-127.5 52.5T200-580q0 75 52.5 127.5T380-400Z\\\"/></svg>\",\n // chevron_forward\n \"searchForward\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z\\\"/></svg>\",\n // chevron_backward\n \"searchBackward\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z\\\"/></svg>\",\n // match_case\n \"matchCase\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"m131-252 165-440h79l165 440h-76l-39-112H247l-40 112h-76Zm139-176h131l-64-182h-4l-63 182Zm395 186q-51 0-81-27.5T554-342q0-44 34.5-72.5T677-443q23 0 45 4t38 11v-12q0-29-20.5-47T685-505q-23 0-42 9.5T610-468l-47-35q24-29 54.5-43t68.5-14q69 0 103 32.5t34 97.5v178h-63v-37h-4q-14 23-38 35t-53 12Zm12-54q35 0 59.5-24t24.5-56q-14-8-33.5-12.5T689-393q-32 0-50 14t-18 37q0 20 16 33t40 13Z\\\"/></svg>\",\n // format_paragraph\n \"paragraphStyle\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M360-160v-240q-83 0-141.5-58.5T160-600q0-83 58.5-141.5T360-800h360v80h-80v560h-80v-560H440v560h-80Z\\\"/></svg>\",\n // more_horiz\n \"more\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\" fill=\\\"#1f1f1f\\\"><path d=\\\"M240-400q-33 0-56.5-23.5T160-480q0-33 23.5-56.5T240-560q33 0 56.5 23.5T320-480q0 33-23.5 56.5T240-400Zm240 0q-33 0-56.5-23.5T400-480q0-33 23.5-56.5T480-560q33 0 56.5 23.5T560-480q0 33-23.5 56.5T480-400Zm240 0q-33 0-56.5-23.5T640-480q0-33 23.5-56.5T720-560q33 0 56.5 23.5T800-480q0 33-23.5 56.5T720-400Z\\\"/></svg>\",\n // custom, since horizontal_rule was inadequate\n \"hRule\": \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" height=\\\"24px\\\" viewBox=\\\"0 -960 960 960\\\" width=\\\"24px\\\"> <path fill-rule=\\\"evenodd\\\" d=\\\"M160-80q-33 0-56.5-23.5T80-160v-640q0-33 23.5-56.5T160-880h640q33 0 56.5 23.5T880-800v640q0 33-23.5 56.5T800-80H160ZM160-800H800V-160H160Z\\\" fill=\\\"currentColor\\\"/> <path d=\\\"M240-340H720V-260H240Z\\\" fill=\\\"currentColor\\\"/> <path d=\\\"M340-600H620V-520H340ZM440-700H520V-420H440Z\\\" fill=\\\"currentColor\\\"/></svg>\"\n }\n}\n```",
3471
3531
  "name": "ToolbarConfig",
3472
3532
  "members": [
3473
3533
  {
@@ -3625,7 +3685,7 @@
3625
3685
  "declarations": [
3626
3686
  {
3627
3687
  "kind": "class",
3628
- "description": "KeymapConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the key mapping configuration of the MarkupEditor toolbar. The class makes it convenient \nto write and use the utility methods, but an instance of KeymapConfig itself is not meaningful.\n\n`KeymapConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new KeymapConfig by name using the `keymap` attribute of the `<markup-editor>` \nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own KeymapConfig.\n\nTo customize the key mapping, for example, in a `userscript` named `mykeymap.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet keymapConfig = MU.KeymapConfig.standard(); // Grab the standard keymap config as a baseline\nkeymapConfig.link = [\"Ctrl-L\", \"Ctrl-l\"]; // Use Control+L instead of Command+k\nMU.registerConfig(keymapConfig, \"MyKeymapConfig\") // Register the instance by name so we can reference it\n```\n\nThen, where you insert the `<markup-editor>` element, set the KeymapConfig by name:\n\n```\n<markup-editor userscript=\"mykeymap.js\" keymap=\"MyKeymapConfig\">\n```\n \nNote that the key mapping will exist and work regardless of whether you disable a toolbar \nor a specific item in a menu. For example, undo/redo by default map to Mod-z/Shift-Mod-z even \nthough the \"correctionBar\" is off by default in the MarkupEditor. You can remove a key mapping \nby setting its value to null or an empty string. \n\nThe following properties are supported:\n\n```\n{\n // Correction\n \"undo\": \"Mod-z\",\n \"redo\": \"Shift-Mod-z\",\n // Insert (no hotkeys for image or table)\n \"link\": [\"Mod-K\", \"Mod-k\"],\n // Stylemenu\n \"p\": \"Ctrl-Shift-0\",\n \"h1\": \"Ctrl-Shift-1\",\n \"h2\": \"Ctrl-Shift-2\",\n \"h3\": \"Ctrl-Shift-3\",\n \"h4\": \"Ctrl-Shift-4\",\n \"h5\": \"Ctrl-Shift-5\",\n \"h6\": \"Ctrl-Shift-6\",\n // Stylebar\n \"bullet\": [\"Ctrl-U\", \"Ctrl-u\"],\n \"number\": [\"Ctrl-O\", \"Ctrl-o\"],\n \"indent\": [\"Mod-]\", \"Ctrl-q\"],\n \"outdent\": [\"Mod-[\", \"Shift-Ctrl-q\"],\n // Format\n \"bold\": [\"Mod-B\", \"Mod-b\"],\n \"italic\": [\"Mod-I\", \"Mod-i\"],\n \"underline\": [\"Mod-U\", \"Mod-u\"],\n \"strikethrough\": [\"Ctrl-S\", \"Ctrl-s\"],\n \"code\": \"Mod-`\",\n \"subscript\": \"Ctrl-Mod--\",\n \"superscript\": \"Ctrl-Mod-+\",\n // Search\n \"search\": [\"Ctrl-F\", \"Ctrl-f\"],\n}\n```",
3688
+ "description": "KeymapConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the key mapping configuration of the MarkupEditor toolbar. The class makes it convenient \nto write and use the utility methods, but an instance of KeymapConfig itself is not meaningful.\n\n`KeymapConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new KeymapConfig by name using the `keymap` attribute of the `<markup-editor>` \nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own KeymapConfig.\n\nTo customize the key mapping, for example, in a `userscript` named `mykeymap.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet keymapConfig = MU.KeymapConfig.standard(); // Grab the standard keymap config as a baseline\nkeymapConfig.link = [\"Ctrl-L\", \"Ctrl-l\"]; // Use Control+L instead of Command+k\nMU.registerConfig(keymapConfig, \"MyKeymapConfig\") // Register the instance by name so we can reference it\n```\n\nThen, where you insert the `<markup-editor>` element, set the KeymapConfig by name:\n\n```\n<markup-editor userscript=\"mykeymap.js\" keymap=\"MyKeymapConfig\">\n```\n \nNote that the key mapping will exist and work regardless of whether you disable a toolbar \nor a specific item in a menu. For example, undo/redo by default map to Mod-z/Shift-Mod-z even \nthough the \"correctionBar\" is off by default in the MarkupEditor. You can remove a key mapping \nby setting its value to null or an empty string. \n\nThe following properties are supported:\n\n```\n{\n // Correction\n \"undo\": \"Mod-z\",\n \"redo\": \"Shift-Mod-z\",\n // Insert (no hotkeys for image or table)\n \"link\": \"Mod-k\",\n // Stylemenu\n \"p\": \"Ctrl-Shift-0\",\n \"h1\": \"Ctrl-Shift-1\",\n \"h2\": \"Ctrl-Shift-2\",\n \"h3\": \"Ctrl-Shift-3\",\n \"h4\": \"Ctrl-Shift-4\",\n \"h5\": \"Ctrl-Shift-5\",\n \"h6\": \"Ctrl-Shift-6\",\n // Stylebar\n \"bullet\": Ctrl-u\",\n \"number\": \"Ctrl-o\",\n \"indent\": [\"Mod-]\", \"Ctrl-q\"],\n \"outdent\": [\"Mod-[\", \"Shift-Ctrl-q\"],\n // Format\n \"bold\": \"Mod-b\",\n \"italic\": \"Mod-i\",\n \"underline\": \"Mod-u\",\n \"strikethrough\": \"Ctrl-s\",\n \"code\": \"Mod-`\",\n \"subscript\": \"Ctrl-Mod--\",\n \"superscript\": \"Ctrl-Mod-+\",\n // Search\n \"search\": \"Ctrl-f\"\n}\n```",
3629
3689
  "name": "KeymapConfig",
3630
3690
  "members": [
3631
3691
  {
@@ -3712,7 +3772,7 @@
3712
3772
  "declarations": [
3713
3773
  {
3714
3774
  "kind": "class",
3715
- "description": "BehaviorConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the behavior configuration of the MarkupEditor. The class makes it convenient \nto write and use the utility methods, but an instance of BehaviorConfig itself is not meaningful.\n\n`BehaviorConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new BehaviorConfig by name using the `behavior` attribute of the `<markup-editor> `\nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own BehaviorConfig.\n\nTo customize the behavior config, for example, in a `userscript` named `mybehavior.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet behaviorConfig = MU.BehaviorConfig.desktop() // Use the desktop config as a baseline\nMU.registerConfig(behaviorConfig, \"MyBehaviorConfig\") // Register the instance by name so we can reference it\n```\n\nThen, where you insert the `<markup-editor>` element, set the BehaviorConfig by name:\n\n```\n<markup-editor userscript=\"mybehavior.js\" behavior=\"MyBehaviorConfig\">\n```\n \nBehaviorConfig lets you control whether the editor takes focus immediately or not, and\nallows you to defer to the MarkupDelegate for insert options, so you can use your own \n(perhaps \"native\") dialogs for file selection, link insertion, and image insertion.\n\nThe following properties are supported:\n\n```\n{\n \"focusAfterLoad\": true, // Whether the editor should take focus after loading\n \"selectImage\": false, // Whether to show a \"Select...\" button in the Insert Image dialog\n \"insertLink\": false, // Whether to defer to the MarkupDelegate rather than use the default LinkDialog\n \"insertImage\": false, // Whether to defer to the MarkupDelagate rather than use the default ImageDialog\n \"showStyle\": true // Whether to show the selected style in a labeled drop-down rather than a (smaller) icon\n}\n```",
3775
+ "description": "BehaviorConfig contains static utility methods to obtain a JavaScript object with properties \nthat define the behavior configuration of the MarkupEditor. The class makes it convenient \nto write and use the utility methods, but an instance of BehaviorConfig itself is not meaningful.\n\n`BehaviorConfig.standard()` is the default for the MarkupEditor. It can be overridden by \npassing a new BehaviorConfig by name using the `behavior` attribute of the `<markup-editor> `\nelement. You can use the pre-defined static methods like `standard()` and customize what \nit returns, or you can use your own BehaviorConfig.\n\nTo customize the behavior config, for example, in a `userscript` named `mybehavior.js`:\n\n```\nimport {MU} from \"src/markup-editor.js\"\nlet behaviorConfig = MU.BehaviorConfig.desktop() // Use the desktop config as a baseline\nMU.registerConfig(behaviorConfig, \"MyBehaviorConfig\") // Register the instance by name so we can reference it\n```\n\nThen, where you insert the `<markup-editor>` element, set the BehaviorConfig by name:\n\n```\n<markup-editor userscript=\"mybehavior.js\" behavior=\"MyBehaviorConfig\">\n```\n \nBehaviorConfig lets you control whether the editor takes focus immediately or not, and\nallows you to defer to the MarkupDelegate for insert options, so you can use your own \n(perhaps \"native\") dialogs for file selection, link insertion, and image insertion.\n\nThe following properties are supported:\n\n```\n{\n \"focusAfterLoad\": true, // Whether the editor should take focus after loading\n \"selectImage\": false, // Whether to show a \"Select...\" button in the Insert Image dialog\n \"insertLink\": false, // Whether to defer to the MarkupDelegate rather than use the default LinkDialog\n \"insertImage\": false, // Whether to defer to the MarkupDelagate rather than use the default ImageDialog\n}\n```",
3716
3776
  "name": "BehaviorConfig",
3717
3777
  "members": [
3718
3778
  {
@@ -3975,6 +4035,26 @@
3975
4035
  {
3976
4036
  "kind": "variable",
3977
4037
  "name": "setSelectedID"
4038
+ },
4039
+ {
4040
+ "kind": "variable",
4041
+ "name": "registerPlugin"
4042
+ },
4043
+ {
4044
+ "kind": "variable",
4045
+ "name": "unregisterPlugin"
4046
+ },
4047
+ {
4048
+ "kind": "variable",
4049
+ "name": "getPlugin"
4050
+ },
4051
+ {
4052
+ "kind": "variable",
4053
+ "name": "getPluginManifest"
4054
+ },
4055
+ {
4056
+ "kind": "variable",
4057
+ "name": "invokePlugin"
3978
4058
  }
3979
4059
  ],
3980
4060
  "exports": [
@@ -4177,6 +4257,46 @@
4177
4257
  "name": "setSelectedID",
4178
4258
  "module": "src/registry.js"
4179
4259
  }
4260
+ },
4261
+ {
4262
+ "kind": "js",
4263
+ "name": "registerPlugin",
4264
+ "declaration": {
4265
+ "name": "registerPlugin",
4266
+ "module": "src/registry.js"
4267
+ }
4268
+ },
4269
+ {
4270
+ "kind": "js",
4271
+ "name": "unregisterPlugin",
4272
+ "declaration": {
4273
+ "name": "unregisterPlugin",
4274
+ "module": "src/registry.js"
4275
+ }
4276
+ },
4277
+ {
4278
+ "kind": "js",
4279
+ "name": "getPlugin",
4280
+ "declaration": {
4281
+ "name": "getPlugin",
4282
+ "module": "src/registry.js"
4283
+ }
4284
+ },
4285
+ {
4286
+ "kind": "js",
4287
+ "name": "getPluginManifest",
4288
+ "declaration": {
4289
+ "name": "getPluginManifest",
4290
+ "module": "src/registry.js"
4291
+ }
4292
+ },
4293
+ {
4294
+ "kind": "js",
4295
+ "name": "invokePlugin",
4296
+ "declaration": {
4297
+ "name": "invokePlugin",
4298
+ "module": "src/registry.js"
4299
+ }
4180
4300
  }
4181
4301
  ]
4182
4302
  }
@@ -22,6 +22,7 @@ class Registry {
22
22
  this._configs = new Map();
23
23
  this._augmentations = new Map();
24
24
  this._handlers = new Map();
25
+ this._plugins = new Map();
25
26
  this._activeMuId = null;
26
27
  }
27
28
 
@@ -227,6 +228,64 @@ class Registry {
227
228
  setSelectedID(string) {
228
229
  if (this.activeEditor()) this.activeEditor().selectedID = string;
229
230
  }
231
+
232
+ /**
233
+ * Add `plugin` to the registry, keyed by `name`.
234
+ *
235
+ * @param {object} plugin Plugin object with { name, extension, export, import }.
236
+ * @param {string} name The key used to retrieve and invoke the plugin.
237
+ */
238
+ registerPlugin(plugin, name) {
239
+ this._plugins.set(name ?? plugin.name, plugin);
240
+ }
241
+
242
+ /**
243
+ * Remove the plugin with `name` from the registry.
244
+ *
245
+ * @param {string} name The key used to identify the plugin.
246
+ */
247
+ unregisterPlugin(name) {
248
+ this._plugins.delete(name);
249
+ }
250
+
251
+ /**
252
+ * Return the plugin object with `name`, or undefined if not found.
253
+ *
254
+ * @param {string} name The key used to identify the plugin.
255
+ * @returns {object|undefined}
256
+ */
257
+ getPlugin(name) {
258
+ return this._plugins.get(name)
259
+ }
260
+
261
+ /**
262
+ * Return the public manifest for all registered plugins.
263
+ * Each entry contains only { id, name, extension } — function references are excluded.
264
+ *
265
+ * @returns {Array<{id: string, name: string, extension: string}>}
266
+ */
267
+ getPluginManifest() {
268
+ const manifest = [];
269
+ for (const plugin of this._plugins.values()) {
270
+ manifest.push({ name: plugin.name, extension: plugin.extension });
271
+ }
272
+ return manifest
273
+ }
274
+
275
+ /**
276
+ * Invoke `action` on the named plugin, passing `...args`.
277
+ * Returns null if the plugin is not found or does not define the action.
278
+ *
279
+ * @param {string} name The key used to identify the plugin.
280
+ * @param {string} action The action to invoke (e.g. 'export', 'import').
281
+ * @param {...*} args Arguments forwarded to the plugin action.
282
+ * @returns {*|null}
283
+ */
284
+ invokePlugin(name, action, ...args) {
285
+ const plugin = this._plugins.get(name);
286
+ if (!plugin || typeof plugin[action] !== 'function') return null
287
+ return plugin[action](...args)
288
+ }
230
289
  }
231
290
 
232
291
  /**
@@ -324,6 +383,11 @@ _registry.activeMessageHandler.bind(_registry);
324
383
  const activeSearcher = _registry.activeSearcher.bind(_registry);
325
384
  const selectedID = _registry.selectedID.bind(_registry);
326
385
  const setSelectedID = _registry.setSelectedID.bind(_registry);
386
+ const registerPlugin = _registry.registerPlugin.bind(_registry);
387
+ _registry.unregisterPlugin.bind(_registry);
388
+ _registry.getPlugin.bind(_registry);
389
+ const getPluginManifest = _registry.getPluginManifest.bind(_registry);
390
+ const invokePlugin = _registry.invokePlugin.bind(_registry);
327
391
 
328
392
  /**
329
393
  * MUError captures internal errors and makes it easy to communicate them externally.
@@ -19690,8 +19754,8 @@ var augmentation = {
19690
19754
  };
19691
19755
  var appearance = {
19692
19756
  accentColor: {
19693
- light: "blue",
19694
- dark: "lightblue"
19757
+ light: "AccentColor",
19758
+ dark: "AccentColor"
19695
19759
  },
19696
19760
  toolbarBg: {
19697
19761
  light: "rgba(250, 249, 246, 0.95)",
@@ -19840,14 +19904,14 @@ var toolbarConfig = {
19840
19904
  * "prepend": null, // Name of a registered array of cmdItems to prepend
19841
19905
  * "append": null // Name of a registered array of cmdItems to append
19842
19906
  * },
19843
- * "appearance": { // Colors (light and dark mode) and sizes, vars in toolbar.css
19844
- * "accentColor": { "light": "blue", "dark": "lightblue" },
19845
- * "toolbarBg": { "light": "rgba(250, 249, 246, 0.95)", "dark": "rgba(40, 40, 43, 0.9)" },
19846
- * "buttonBg": { "light": "white", "dark": "black" },
19847
- * "borderColor": { "light": "lightgray", "dark": "gray" },
19848
- * "hoverBg": { "light": "#f2f2f2", "dark": "rgb(80, 80, 80)" },
19849
- * "buttonSize": "28px",
19850
- * "buttonFontSize": "24px"
19907
+ * "appearance": { // AccentColor adapts to light and dark
19908
+ * "accentColor": { "light": "AccentColor", "dark": "AccentColor" }, // System accent color for button icons, infill, and borders
19909
+ * "toolbarBg": { "light": "rgba(250, 249, 246, 0.95)", "dark": "rgba(40, 40, 43, 0.9)" }, // Toolbar background
19910
+ * "buttonBg": { "light": "white", "dark": "black" }, // Button background
19911
+ * "borderColor": { "light": "lightgray", "dark": "gray" }, // Border at bottom of toolbar, around menus
19912
+ * "hoverBg": { "light": "#f2f2f2", "dark": "rgb(80, 80, 80)" }, // Highlight menu item on hover
19913
+ * "buttonSize": "28px", // Side length of rounded square buttons, height otherwise
19914
+ * "buttonFontSize": "24px" // Font size inside of buttons/menus
19851
19915
  * },
19852
19916
  * "icons": { // Outlined 400 weight versions from https://fonts.google.com/icons
19853
19917
  * // undo
@@ -25095,37 +25159,46 @@ const MU = {
25095
25159
  registerConfig,
25096
25160
  registerDelegate,
25097
25161
  registerMessageHandler,
25162
+ registerPlugin,
25163
+ getPluginManifest,
25164
+ invokePlugin,
25098
25165
  };
25099
25166
 
25100
25167
  /**
25101
- * A web component and API for WYSIWYG HTML editing. The element is available as `<markup-editor>`. The API is available using the element property `MU`.
25102
- *
25103
- * @element markup-editor
25104
- *
25105
- * @attr {string} placeholder - HTML that should be displayed when the editor is empty.
25106
- *
25107
- * @attr {string} filename - An HTML file whose contents should be loaded for the initial contents of the editor. If you also supply HTML within the <markup-editor> itself (e.g., <markup-editor><p>Hello, world</p></markupeditor>), the content of filename will take precedence.
25108
- *
25109
- * @attr {string} base - The relative path for image src attributes in the editor. By default, if `filename` is specified with a path, `base` will be set to the directory containing the file. For example, if filename is “demo/guide/guide.html”, `base` will be set to “demo/guide/” so that an image with `src=“myImage.png”` will load. If you want this image to load from the “resources” directory below "demo/guide", then set base to “demo/guide/resources/” (with a trailing slash).
25110
- *
25111
- * @attr {string} userscript - A JavaScript file that should be loaded as a script within the <markup-editor> element. The script can reference the global MU for access to MarkupEditor functionality. For example, the script could contain code to create and register a MarkupDelegate to receive callbacks during editing, or define a custom ToolbarConfiguration.
25112
- *
25113
- * @attr {string} userstyle - A CSS file that should be linked within the <markup-editor> element to supplement the MarkupEditor base styling.
25114
- *
25115
- * @attr {string} delegate - The name of a MarkupDelegate that has been registered. See the documentation on MarkupDelegates for details on implementation, usage, and registration.
25116
- *
25117
- * @attr {string} handler - The name of a MessageHandler that has been registered. See the documemtation on MessageHandler for details.
25118
- *
25119
- * @attr {string} toolbar - The name of a ToolbarConfig that has been registered. See the documentation on ToolbarConfig for details of customizing the toolbar configuration and registering configs.
25120
- *
25121
- * @attr {string} keymap - The name of a KeymapConfig that has been registered. See the documentation on KeymapConfig for details of customizing the keymap configuration and registering configs.
25122
- *
25123
- * @attr {string} behavior - The name of a BehaviorConfig that has been registered. See the documentation on BehaviorConfig for details of customizing the behavior configuration and registering configs.
25124
- *
25125
- * @attr {string} prepend: The name of a toolbar that has been registered, whose `menuItems` will be placed before the MarkupToolbar. See the documentation on Extending the Toolbar for details.
25126
- *
25127
- * @attr {string} append - The name of a toolbar that has been registered, whose `menuItems` will be placed after the MarkupToolbar. See the documentation on Extending the Toolbar for details.
25168
+ * Load plugins from an array of paths and notify the delegate on completion.
25169
+ *
25170
+ * Each plugin module is imported individually. A per-plugin import failure is caught
25171
+ * and logged; it does not abort the remaining loads or prevent `markupPluginsDidLoad`
25172
+ * from firing. When all imports have settled, `markupPluginsDidLoad` is called on the
25173
+ * delegate (if it defines that method) with an array of manifests for the plugins that
25174
+ * registered successfully. The function is a no-op (no delegate call) when `pluginPaths`
25175
+ * is empty.
25176
+ *
25177
+ * @param {string[]} pluginPaths Resolved paths to plugin modules.
25178
+ * @param {object|null} delegate A MarkupDelegate instance (may be null/undefined).
25179
+ * @param {function} [importFn] Optional import function; defaults to the native dynamic
25180
+ * import. Provided for testing.
25181
+ * @returns {Promise<void>}
25128
25182
  */
25183
+ async function loadPlugins(pluginPaths, delegate, importFn = (path) => import(path)) {
25184
+ if (!pluginPaths || pluginPaths.length === 0) return
25185
+ const before = new Set(MU.getPluginManifest().map(m => m.name));
25186
+ await Promise.all(
25187
+ pluginPaths.map(path =>
25188
+ importFn(path).catch(err => {
25189
+ console.error('Plugin load failed:', path, err);
25190
+ return null
25191
+ })
25192
+ )
25193
+ );
25194
+ const after = MU.getPluginManifest();
25195
+ const newManifests = after.filter(m => !before.has(m.name));
25196
+ delegate?.markupPluginsDidLoad && delegate.markupPluginsDidLoad(newManifests);
25197
+ }
25198
+
25199
+ // Expose loadPlugins on the MU namespace so it is accessible from tests and external callers.
25200
+ MU.loadPlugins = loadPlugins;
25201
+
25129
25202
  class MarkupEditorElement extends HTMLElement {
25130
25203
 
25131
25204
  /**
@@ -25172,8 +25245,20 @@ class MarkupEditorElement extends HTMLElement {
25172
25245
  // The first `muCallback` will be `loadedUserFiles`, which will
25173
25246
  // cause the editor instance to be created before posting the
25174
25247
  // message.
25175
- this.editorContainer.addEventListener('muCallback', (e) => {
25248
+ this.editorContainer.addEventListener('muCallback', async (e) => {
25176
25249
  if (!this.editor) this.createEditor();
25250
+ if (e.message === 'loadedUserFiles') {
25251
+ const pluginsAttr = this.getAttribute('plugins');
25252
+ const pluginPaths = pluginsAttr ? JSON.parse(pluginsAttr) : [];
25253
+ const delegate = this.editor.config?.delegate;
25254
+ await loadPlugins(pluginPaths, delegate);
25255
+ const manifests = MU.getPluginManifest();
25256
+ if (manifests.length > 0) {
25257
+ this.editor.messageHandler.postMessage(
25258
+ JSON.stringify({ messageType: 'markupPluginsDidLoad', plugins: manifests })
25259
+ );
25260
+ }
25261
+ }
25177
25262
  this.editor.messageHandler.postMessage(e.message);
25178
25263
  });
25179
25264
 
@@ -25344,4 +25429,4 @@ class MarkupEditorElement extends HTMLElement {
25344
25429
  // Let the browser know about the custom element
25345
25430
  customElements.define('markup-editor', MarkupEditorElement);
25346
25431
 
25347
- export { MU };
25432
+ export { MU, loadPlugins };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markupeditor",
3
- "version": "0.9.20",
3
+ "version": "0.9.22",
4
4
  "description": "A web component and API for WYSIWYG HTML editing.",
5
5
  "keywords": [
6
6
  "wysiwyg",