markupeditor 0.9.9 → 0.9.10

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.
@@ -138,7 +138,7 @@
138
138
  "type": {
139
139
  "text": "object"
140
140
  },
141
- "default": "{ activeConfig, activeView, addButton, addCol, addDiv, addHeader, addRow, borderTable, 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, }",
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, }",
142
142
  "description": "The object whose methods comprise the MarkupEditor API."
143
143
  }
144
144
  ],
@@ -722,6 +722,11 @@
722
722
  }
723
723
  ]
724
724
  },
725
+ {
726
+ "kind": "function",
727
+ "name": "callbackSelectImage",
728
+ "description": "Callback to signal that the user wants to select an image from a file.\n\nThe messageHandler will need to do something like bring up a file picker\nand in turn execute insertImage."
729
+ },
725
730
  {
726
731
  "kind": "function",
727
732
  "name": "searchedCallback",
@@ -1505,6 +1510,14 @@
1505
1510
  "module": "src/markup.js"
1506
1511
  }
1507
1512
  },
1513
+ {
1514
+ "kind": "js",
1515
+ "name": "callbackSelectImage",
1516
+ "declaration": {
1517
+ "name": "callbackSelectImage",
1518
+ "module": "src/markup.js"
1519
+ }
1520
+ },
1508
1521
  {
1509
1522
  "kind": "js",
1510
1523
  "name": "searchedCallback",
@@ -2379,18 +2392,7 @@
2379
2392
  {
2380
2393
  "kind": "method",
2381
2394
  "name": "selectImage",
2382
- "parameters": [
2383
- {
2384
- "name": "state"
2385
- },
2386
- {
2387
- "name": "dispatch"
2388
- },
2389
- {
2390
- "name": "view"
2391
- }
2392
- ],
2393
- "description": "Tell the delegate to select an image to insert, because we don't know how to do that"
2395
+ "description": "Call back to the messageHandler after closing the dialog. The message handler should \nlet the delegate deal with bringing up a file picker of some kind."
2394
2396
  },
2395
2397
  {
2396
2398
  "kind": "method",
@@ -16150,6 +16150,121 @@ A command function that redoes the last undone change, if any.
16150
16150
  */
16151
16151
  const redo$1 = buildCommand(true, true);
16152
16152
 
16153
+ /**
16154
+ *
16155
+ * @param {EditorView} view
16156
+ * @param {string} text Text to be translated
16157
+ * @returns {string} The translated text if the view supports it
16158
+ */
16159
+ function translate(view, text) {
16160
+ return view._props.translate ? view._props.translate(text) : text;
16161
+ }
16162
+ /**
16163
+ * Add or remove a class from the element.
16164
+ *
16165
+ * Apparently a workaround for classList.toggle being broken in IE11
16166
+ *
16167
+ * @param {HTMLElement} dom
16168
+ * @param {string} cls The class name to add or remove
16169
+ * @param {boolean} on True to add the class name to the `classList`
16170
+ */
16171
+ function setClass(dom, cls, on) {
16172
+ if (on)
16173
+ dom.classList.add(cls);
16174
+ else
16175
+ dom.classList.remove(cls);
16176
+ }
16177
+
16178
+ /**
16179
+ * DOMAccess provides access to the MarkupToolbar and other well-known elements.
16180
+ */
16181
+ class DOMAccess {
16182
+
16183
+ constructor(prefix) {
16184
+ this.prefix = prefix ?? 'Markup';
16185
+ }
16186
+
16187
+ setPrefix(prefix) {
16188
+ this.prefix = prefix;
16189
+ }
16190
+
16191
+ /**
16192
+ * Return the toolbar div in `view`
16193
+ * @param {EditorView} view
16194
+ * @returns {HTMLDivElement} The toolbar div in the view
16195
+ */
16196
+ getToolbar(view) {
16197
+ return view.dom.getRootNode().getElementById(this.prefix + "-toolbar")
16198
+ }
16199
+
16200
+ getSearchItem(view) {
16201
+ return view.dom.getRootNode().getElementById(this.prefix + '-searchitem')
16202
+ }
16203
+
16204
+ getSearchbar(view) {
16205
+ return view.dom.getRootNode().getElementById(this.prefix + "-searchbar")
16206
+ }
16207
+
16208
+ getToolbarMore(view) {
16209
+ return view.dom.getRootNode().getElementById(this.prefix + "-toolbar-more")
16210
+ }
16211
+
16212
+ getWrapper(view) {
16213
+ return this.getToolbar(view)?.parentElement
16214
+ }
16215
+
16216
+ /** Adding promptShowing class on wrapper lets us suppress scroll while the prompt is showing */
16217
+ addPromptShowing(view) {
16218
+ setClass(getWrapper(view), promptShowing(), true);
16219
+ }
16220
+
16221
+ /** Removing promptShowing class on wrapper lets wrapper scroll again */
16222
+ removePromptShowing(view) {
16223
+ setClass(getWrapper(view), promptShowing(), false);
16224
+ }
16225
+
16226
+ promptShowing() {
16227
+ return this.prefix + "-prompt-showing"
16228
+ }
16229
+
16230
+ searchInput() {
16231
+ return this.prefix + "-searchinput"
16232
+ }
16233
+
16234
+ searchbarShowing() {
16235
+ return this.prefix + "-searchbar-showing"
16236
+ }
16237
+
16238
+ searchbarHidden() {
16239
+ return this.prefix + "-searchbar-hidden"
16240
+ }
16241
+
16242
+ isSearchFocused(view) {
16243
+ return view?.dom.getRootNode().getElementById(this.searchInput())?.matches(':focus') ?? false
16244
+ }
16245
+
16246
+ isPromptShowing(view) {
16247
+ return (view) ? this.getWrapper(view)?.classList.contains(this.promptShowing()) ?? false : false
16248
+ }
16249
+
16250
+ }
16251
+
16252
+ const _domAccess = new DOMAccess();
16253
+ const prefix = _domAccess.prefix;
16254
+ const setPrefix = _domAccess.setPrefix.bind(_domAccess);
16255
+ const getToolbar = _domAccess.getToolbar.bind(_domAccess);
16256
+ _domAccess.getSearchItem.bind(_domAccess);
16257
+ const getSearchbar = _domAccess.getSearchbar.bind(_domAccess);
16258
+ const getToolbarMore = _domAccess.getToolbarMore.bind(_domAccess);
16259
+ const getWrapper = _domAccess.getWrapper.bind(_domAccess);
16260
+ const addPromptShowing = _domAccess.addPromptShowing.bind(_domAccess);
16261
+ const removePromptShowing = _domAccess.removePromptShowing.bind(_domAccess);
16262
+ const promptShowing = _domAccess.promptShowing.bind(_domAccess);
16263
+ const searchbarShowing = _domAccess.searchbarShowing.bind(_domAccess);
16264
+ const searchbarHidden = _domAccess.searchbarHidden.bind(_domAccess);
16265
+ const isSearchFocused = _domAccess.isSearchFocused.bind(_domAccess);
16266
+ const isPromptShowing = _domAccess.isPromptShowing.bind(_domAccess);
16267
+
16153
16268
  /**
16154
16269
  * Define various arrays of tags used to represent MarkupEditor-specific concepts.
16155
16270
  *
@@ -17868,9 +17983,12 @@ function _getSelectionState() {
17868
17983
  // absolutely reflects the selection state at the time of the call regardless
17869
17984
  // of whether it is editable or not.
17870
17985
  const contentEditable = _getContentEditable();
17986
+ const view = activeView();
17871
17987
  state['divid'] = contentEditable.id; // Will be 'editor' or a div ID
17872
- state['valid'] = contentEditable.editable; // Valid means the selection is in something editable
17873
- if (!contentEditable.editable) return state; // No need to do more with state if it's not editable
17988
+ // Valid means the selection is in something editable and
17989
+ // neither search is focused nor is a prompt showing
17990
+ state['valid'] = contentEditable.editable && !(isSearchFocused(view) || isPromptShowing(view));
17991
+ if (!state['valid']) return state; // No need to do more with state if it's not editable
17874
17992
 
17875
17993
  // Selected text
17876
17994
  state['selection'] = _getSelectionText();
@@ -18198,6 +18316,17 @@ function _getIndented(state) {
18198
18316
  function callbackInput(element) {
18199
18317
  _callback('input' + (selectedID() ?? ''), element);
18200
18318
  }
18319
+ /**
18320
+ * Callback to signal that the user wants to select an image from a file.
18321
+ *
18322
+ * The messageHandler will need to do something like bring up a file picker
18323
+ * and in turn execute insertImage.
18324
+ */
18325
+ function callbackSelectImage() {
18326
+ let messageDict = { 'messageType' : 'selectImage' };
18327
+ _callback(JSON.stringify(messageDict));
18328
+ }
18329
+
18201
18330
  /**
18202
18331
  * Callback to signal that user-provided CSS and/or script files have
18203
18332
  * been loaded.
@@ -20806,107 +20935,6 @@ function add(elt, child) {
20806
20935
  }
20807
20936
  }
20808
20937
 
20809
- /**
20810
- *
20811
- * @param {EditorView} view
20812
- * @param {string} text Text to be translated
20813
- * @returns {string} The translated text if the view supports it
20814
- */
20815
- function translate(view, text) {
20816
- return view._props.translate ? view._props.translate(text) : text;
20817
- }
20818
- /**
20819
- * Add or remove a class from the element.
20820
- *
20821
- * Apparently a workaround for classList.toggle being broken in IE11
20822
- *
20823
- * @param {HTMLElement} dom
20824
- * @param {string} cls The class name to add or remove
20825
- * @param {boolean} on True to add the class name to the `classList`
20826
- */
20827
- function setClass(dom, cls, on) {
20828
- if (on)
20829
- dom.classList.add(cls);
20830
- else
20831
- dom.classList.remove(cls);
20832
- }
20833
-
20834
- /**
20835
- * DOMAccess provides access to the MarkupToolbar and other well-known elements.
20836
- */
20837
- class DOMAccess {
20838
-
20839
- constructor(prefix) {
20840
- this.prefix = prefix ?? 'Markup';
20841
- }
20842
-
20843
- setPrefix(prefix) {
20844
- this.prefix = prefix;
20845
- }
20846
-
20847
- /**
20848
- * Return the toolbar div in `view`
20849
- * @param {EditorView} view
20850
- * @returns {HTMLDivElement} The toolbar div in the view
20851
- */
20852
- getToolbar(view) {
20853
- return view.dom.getRootNode().getElementById(this.prefix + "-toolbar");
20854
- }
20855
-
20856
- getSearchItem(view) {
20857
- return view.dom.getRootNode().getElementById(this.prefix + '-searchitem')
20858
- }
20859
-
20860
- getSearchbar(view) {
20861
- return view.dom.getRootNode().getElementById(this.prefix + "-searchbar");
20862
- }
20863
-
20864
- getToolbarMore(view) {
20865
- return view.dom.getRootNode().getElementById(this.prefix + "-toolbar-more")
20866
- }
20867
-
20868
- getWrapper(view) {
20869
- return this.getToolbar(view).parentElement;
20870
- }
20871
-
20872
- /** Adding promptShowing class on wrapper lets us suppress scroll while the prompt is showing */
20873
- addPromptShowing(view) {
20874
- setClass(getWrapper(view), promptShowing(), true);
20875
- }
20876
-
20877
- /** Removing promptShowing class on wrapper lets wrapper scroll again */
20878
- removePromptShowing(view) {
20879
- setClass(getWrapper(view), promptShowing(), false);
20880
- }
20881
-
20882
- promptShowing() {
20883
- return this.prefix + "-prompt-showing"
20884
- }
20885
-
20886
- searchbarShowing() {
20887
- return this.prefix + "-searchbar-showing"
20888
- }
20889
-
20890
- searchbarHidden() {
20891
- return this.prefix + "-searchbar-hidden"
20892
- }
20893
-
20894
- }
20895
-
20896
- const _domAccess = new DOMAccess();
20897
- const prefix = _domAccess.prefix;
20898
- const setPrefix = _domAccess.setPrefix.bind(_domAccess);
20899
- const getToolbar = _domAccess.getToolbar.bind(_domAccess);
20900
- _domAccess.getSearchItem.bind(_domAccess);
20901
- const getSearchbar = _domAccess.getSearchbar.bind(_domAccess);
20902
- const getToolbarMore = _domAccess.getToolbarMore.bind(_domAccess);
20903
- const getWrapper = _domAccess.getWrapper.bind(_domAccess);
20904
- const addPromptShowing = _domAccess.addPromptShowing.bind(_domAccess);
20905
- const removePromptShowing = _domAccess.removePromptShowing.bind(_domAccess);
20906
- const promptShowing = _domAccess.promptShowing.bind(_domAccess);
20907
- const searchbarShowing = _domAccess.searchbarShowing.bind(_domAccess);
20908
- const searchbarHidden = _domAccess.searchbarHidden.bind(_domAccess);
20909
-
20910
20938
  function getIcon(root, icon) {
20911
20939
  let doc = (root.nodeType == 9 ? root : root.ownerDocument) || document;
20912
20940
  let node = doc.createElement("span");
@@ -21283,8 +21311,9 @@ class DialogItem {
21283
21311
  * @param {EditorView} view
21284
21312
  */
21285
21313
  openDialog(state, dispatch, view) {
21286
- setActiveView(view);
21314
+ setActiveView(view);
21287
21315
  this.createDialog(view);
21316
+ selectionChanged(); // Since it's pseudo modal, we can do it once
21288
21317
  this.dialog.show();
21289
21318
  }
21290
21319
 
@@ -21371,6 +21400,7 @@ class DialogItem {
21371
21400
  */
21372
21401
  closeDialog() {
21373
21402
  removePromptShowing(activeView());
21403
+ selectionChanged(); // Since it's pseudo modal, we can do it once
21374
21404
  this.toolbarOverlay?.parentElement?.removeChild(this.toolbarOverlay);
21375
21405
  this.overlay?.parentElement?.removeChild(this.overlay);
21376
21406
  this.selectionDiv?.parentElement?.removeChild(this.selectionDiv);
@@ -21866,10 +21896,10 @@ class ImageItem extends DialogItem {
21866
21896
  this.dialog.appendChild(buttonsDiv);
21867
21897
 
21868
21898
  // When local images are allowed, we insert a "Select..." button that will bring up a
21869
- // file chooser. However, the MarkupEditor can't do that itself, so it invokes the
21870
- // delegate's `markupSelectImage` method if it exists. Thus, when `selectImage` is
21871
- // true in BehaviorConfig, that method should exist. It should bring up a file chooser
21872
- // and then invoke `MU.insertImage`.
21899
+ // file chooser. However, the MarkupEditor can't do that itself, so it calls back to
21900
+ // the messageHandler, which in turn should invoke the delegate's `markupSelectImage`
21901
+ // method if it exists. Thus, when `selectImage` is true in BehaviorConfig, that method
21902
+ // should exist. It should bring up a file chooser and then invoke `MU.insertImage`.
21873
21903
  if (this.config.behavior.selectImage) {
21874
21904
  this.preview = null;
21875
21905
  let selectItem = cmdItem(this.selectImage.bind(this), {
@@ -21967,10 +21997,13 @@ class ImageItem extends DialogItem {
21967
21997
  return this.altArea.value
21968
21998
  }
21969
21999
 
21970
- /** Tell the delegate to select an image to insert, because we don't know how to do that */
21971
- selectImage(state, dispatch, view) {
22000
+ /**
22001
+ * Call back to the messageHandler after closing the dialog. The message handler should
22002
+ * let the delegate deal with bringing up a file picker of some kind.
22003
+ */
22004
+ selectImage() {
21972
22005
  this.closeDialog();
21973
- if (this.config.delegate?.markupSelectImage) this.config.delegate?.markupSelectImage(state, dispatch, view);
22006
+ callbackSelectImage();
21974
22007
  }
21975
22008
 
21976
22009
  /**
@@ -22206,7 +22239,8 @@ class SearchItem {
22206
22239
  showSearchbar(state, dispatch, view) {
22207
22240
  let toolbar = getToolbar(view);
22208
22241
  if (!toolbar) return;
22209
- let input = crelt('input', { type: 'search', placeholder: 'Search document...' });
22242
+ let inputId = prefix + "-searchinput";
22243
+ let input = crelt('input', { id: inputId, type: 'search', placeholder: 'Search document...' });
22210
22244
  input.addEventListener('keydown', e => { // Use keydown because 'input' isn't triggered for Enter
22211
22245
  if (e.key === 'Enter') {
22212
22246
  let direction = (e.shiftKey) ? 'backward' : 'forward';
@@ -22224,6 +22258,12 @@ class SearchItem {
22224
22258
  this.text = e.target.value;
22225
22259
  this.stopSearching(false); // Stop searching but leave focus in the input field
22226
22260
  });
22261
+ input.addEventListener('focus', () => {
22262
+ selectionChanged();
22263
+ });
22264
+ input.addEventListener('blur', () => {
22265
+ selectionChanged();
22266
+ });
22227
22267
  let idClass = prefix + "-searchbar";
22228
22268
  let searchbar = crelt("div", { class: idClass, id: idClass }, input);
22229
22269
  this.addSearchButtons(view, searchbar);
@@ -24340,6 +24380,9 @@ class MessageHandler {
24340
24380
  case 'copyImage':
24341
24381
  console.log('fix copyImage ' + messageData.src);
24342
24382
  return
24383
+ case 'selectImage':
24384
+ delegate?.markupSelectImage && delegate?.markupSelectImage();
24385
+ return
24343
24386
  case 'addedImage': {
24344
24387
  if (!delegate?.markupImageAdded) return;
24345
24388
  let divId = messageData.divId;
@@ -24794,6 +24837,7 @@ const MU = {
24794
24837
  addHeader,
24795
24838
  addRow,
24796
24839
  borderTable,
24840
+ callbackSelectImage,
24797
24841
  cancelSearch,
24798
24842
  canUndo,
24799
24843
  canRedo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markupeditor",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "A web component and API for WYSIWYG HTML editing.",
5
5
  "keywords": [
6
6
  "wysiwyg",