@manuscripts/body-editor 2.7.34 → 2.7.35

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.
@@ -52,12 +52,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
53
  exports.openEmbedDialog = exports.NoPreviewMessageWithLink = exports.InsertEmbedDialog = void 0;
54
54
  const style_guide_1 = require("@manuscripts/style-guide");
55
- const lodash_1 = require("lodash");
56
55
  const react_1 = __importStar(require("react"));
57
56
  const styled_components_1 = __importDefault(require("styled-components"));
58
57
  const commands_1 = require("../../commands");
59
58
  const oembed_1 = require("../../lib/oembed");
60
59
  const url_1 = require("../../lib/url");
60
+ const use_do_with_debounce_1 = require("../../lib/use-do-with-debounce");
61
61
  const editor_props_1 = require("../../plugins/editor-props");
62
62
  const ReactSubView_1 = __importDefault(require("../../views/ReactSubView"));
63
63
  const LinkForm_1 = require("../views/LinkForm");
@@ -82,39 +82,32 @@ const PreviewContainer = styled_components_1.default.div `
82
82
  border-radius: ${(props) => props.theme.grid.radius.small};
83
83
  padding: 6px ${(props) => props.theme.grid.unit * 4}px;
84
84
  `;
85
- const InsertEmbedDialog = ({ state, dispatch, operation, pos, }) => {
85
+ const InsertEmbedDialog = ({ state, dispatch, pos, }) => {
86
86
  var _a;
87
- const nodeAttr = pos ? (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs : undefined;
87
+ const attrs = pos ? (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs : undefined;
88
88
  const [isOpen, setOpen] = (0, react_1.useState)(true);
89
- const [url, setUrl] = (0, react_1.useState)((nodeAttr === null || nodeAttr === void 0 ? void 0 : nodeAttr.href) || undefined);
90
- const [oembedHTML, setOEmbedHTML] = (0, react_1.useState)(undefined);
91
- const action = () => {
92
- var _a;
93
- if (operation === 'Insert') {
89
+ const [url, setUrl] = (0, react_1.useState)(attrs === null || attrs === void 0 ? void 0 : attrs.href);
90
+ const [oembedHTML, setOEmbedHTML] = (0, react_1.useState)();
91
+ const debounce = (0, use_do_with_debounce_1.useDoWithDebounce)();
92
+ const handleSave = () => {
93
+ if (!pos) {
94
94
  (0, commands_1.insertEmbed)(state, dispatch, { href: url });
95
95
  }
96
96
  else {
97
- dispatch &&
98
- pos &&
99
- dispatch(state.tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs), { href: url })));
97
+ const tr = state.tr.setNodeAttribute(pos, 'href', url);
98
+ dispatch(tr);
100
99
  }
101
100
  setOpen(false);
102
101
  };
103
102
  (0, react_1.useEffect)(() => {
104
- url && updateEmbedHTML(url);
105
- }, [pos]);
106
- const debouncedUrlChange = (0, lodash_1.debounce)((e) => __awaiter(void 0, void 0, void 0, function* () {
107
- const url = e.target.value.trim();
108
- yield updateEmbedHTML(url);
109
- setUrl(url);
110
- }), 500);
111
- const updateEmbedHTML = (url) => __awaiter(void 0, void 0, void 0, function* () {
112
- const oEmbedUrl = yield (0, oembed_1.getOEmbedUrl)(url, 368, 217);
113
- const oembedJSON = oEmbedUrl && (yield (0, oembed_1.getOEmbedHTML)(oEmbedUrl, url));
114
- setOEmbedHTML(oembedJSON);
115
- });
103
+ debounce(() => __awaiter(void 0, void 0, void 0, function* () {
104
+ const html = yield (0, oembed_1.getOEmbedHTML)(url, 368, 217);
105
+ setOEmbedHTML(html);
106
+ }));
107
+ }, [url]);
108
+ const operation = pos ? 'Update' : 'Insert';
116
109
  return (react_1.default.createElement(style_guide_1.StyledModal, { isOpen: isOpen, onRequestClose: () => setOpen(false) },
117
- react_1.default.createElement(DialogContainer, null,
110
+ react_1.default.createElement(DialogContainer, { "data-cy": "media-editor" },
118
111
  react_1.default.createElement(HeaderContainer, null,
119
112
  operation,
120
113
  " external media"),
@@ -123,13 +116,13 @@ const InsertEmbedDialog = ({ state, dispatch, operation, pos, }) => {
123
116
  react_1.default.createElement(LinkForm_1.FieldHeading, null,
124
117
  react_1.default.createElement(Label, { htmlFor: 'embed-link' }, "Media link"),
125
118
  url && (0, url_1.allowedHref)(url) && (react_1.default.createElement(LinkForm_1.Open, { id: 'media-link', href: url, target: '_blank', rel: 'noopener' }))),
126
- react_1.default.createElement(style_guide_1.TextArea, { id: 'embed-link', rows: 2, cols: 2, defaultValue: url, autoFocus: true, required: true, placeholder: 'https://youtube.com/...', onChange: debouncedUrlChange })),
119
+ react_1.default.createElement(style_guide_1.TextArea, { id: 'embed-link', rows: 2, cols: 2, defaultValue: url, autoFocus: true, required: true, placeholder: 'https://youtube.com/...', onChange: (e) => setUrl(e.target.value.trim()) })),
127
120
  url && (0, url_1.allowedHref)(url) && (react_1.default.createElement(Container, null,
128
121
  react_1.default.createElement(Label, null, "Preview"),
129
122
  (oembedHTML && (react_1.default.createElement(PreviewContainer, { dangerouslySetInnerHTML: { __html: oembedHTML } }))) || react_1.default.createElement(NoPreviewMessage, null)))),
130
123
  react_1.default.createElement(style_guide_1.ButtonGroup, null,
131
124
  react_1.default.createElement(style_guide_1.SecondaryButton, { onClick: () => setOpen(false) }, "Cancel"),
132
- react_1.default.createElement(style_guide_1.PrimaryButton, { onClick: action, disabled: !(url && (0, url_1.allowedHref)(url)) }, operation)))));
125
+ react_1.default.createElement(style_guide_1.PrimaryButton, { onClick: handleSave, disabled: !(url && (0, url_1.allowedHref)(url)) }, operation)))));
133
126
  };
134
127
  exports.InsertEmbedDialog = InsertEmbedDialog;
135
128
  const Wrapper = styled_components_1.default.div `
@@ -154,7 +147,7 @@ const NoPreviewMessageWithLink = ({ href, }) => (react_1.default.createElement(N
154
147
  ' ',
155
148
  "to see the source media")));
156
149
  exports.NoPreviewMessageWithLink = NoPreviewMessageWithLink;
157
- const openEmbedDialog = (view, operation = 'Insert', pos) => {
150
+ const openEmbedDialog = (view, pos) => {
158
151
  if (!view) {
159
152
  return;
160
153
  }
@@ -162,7 +155,6 @@ const openEmbedDialog = (view, operation = 'Insert', pos) => {
162
155
  const dialog = (0, ReactSubView_1.default)((0, editor_props_1.getEditorProps)(state), exports.InsertEmbedDialog, {
163
156
  state,
164
157
  dispatch,
165
- operation,
166
158
  pos,
167
159
  }, state.doc, () => 0, view);
168
160
  document.body.appendChild(dialog);
@@ -69,25 +69,25 @@ const globToRegex = (glob) => {
69
69
  .replace(/\*/g, '.*');
70
70
  return new RegExp(`^${regex}$`);
71
71
  };
72
- const getOEmbedHTML = (oembedUrl, sourceLink) => __awaiter(void 0, void 0, void 0, function* () {
72
+ const getOEmbedHTML = (url, width, height) => __awaiter(void 0, void 0, void 0, function* () {
73
73
  try {
74
+ const oembedUrl = yield (0, exports.getOEmbedUrl)(url, width, height);
75
+ if (!oembedUrl) {
76
+ return;
77
+ }
74
78
  const response = yield fetch(oembedUrl);
75
79
  if (response.status === 200) {
76
- const oembed = yield response.json();
77
- return oembed.html || renderAlternativeHTML(oembed, sourceLink);
78
- }
79
- else {
80
- return undefined;
80
+ const json = yield response.json();
81
+ return json.html || renderAlternativeHTML(json);
81
82
  }
82
83
  }
83
84
  catch (e) {
84
- return undefined;
85
+ return;
85
86
  }
86
87
  });
87
88
  exports.getOEmbedHTML = getOEmbedHTML;
88
- const renderAlternativeHTML = (oembed, sourceLink) => {
89
+ const renderAlternativeHTML = (oembed) => {
89
90
  if (oembed.type === 'photo') {
90
91
  return `<img src="${oembed.url}">`;
91
92
  }
92
- return `<a href="${sourceLink}" target="_blank">${oembed.title || 'Media link'}</a>`;
93
93
  };
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MATHJAX_VERSION = exports.VERSION = void 0;
4
- exports.VERSION = '2.7.34';
4
+ exports.VERSION = '2.7.35';
5
5
  exports.MATHJAX_VERSION = '3.2.2';
@@ -44,7 +44,6 @@ class EmbedMediaView extends block_view_1.default {
44
44
  this.createElement = () => {
45
45
  this.container = document.createElement('div');
46
46
  this.container.classList.add('block');
47
- this.container.setAttribute('id', this.node.attrs.id);
48
47
  this.dom.appendChild(this.container);
49
48
  this.contentDOM = document.createElement('div');
50
49
  this.container.appendChild(this.contentDOM);
@@ -69,7 +68,7 @@ class EmbedMediaView extends block_view_1.default {
69
68
  },
70
69
  {
71
70
  label: 'Edit',
72
- action: () => (0, InsertEmbedDialog_1.openEmbedDialog)(this.view, 'Update', this.getPos()),
71
+ action: () => (0, InsertEmbedDialog_1.openEmbedDialog)(this.view, this.getPos()),
73
72
  icon: 'Edit',
74
73
  },
75
74
  ],
@@ -101,15 +100,13 @@ class EmbedMediaView extends block_view_1.default {
101
100
  else {
102
101
  this.container.prepend(preview);
103
102
  }
104
- const oEmbedUrl = yield (0, oembed_1.getOEmbedUrl)(this.href, 643, 363);
105
- if (oEmbedUrl) {
106
- const oembedHTML = yield (0, oembed_1.getOEmbedHTML)(oEmbedUrl, this.href);
107
- if (oembedHTML) {
108
- preview.innerHTML = oembedHTML;
109
- return;
110
- }
103
+ const html = yield (0, oembed_1.getOEmbedHTML)(this.href, 643, 363);
104
+ if (html) {
105
+ preview.innerHTML = html;
106
+ }
107
+ else {
108
+ this.showUnavailableMessage(preview);
111
109
  }
112
- this.showUnavailableMessage(preview);
113
110
  });
114
111
  }
115
112
  showUnavailableMessage(preview) {
@@ -23,12 +23,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
23
23
  });
24
24
  };
25
25
  import { ButtonGroup, DialogModalBody, MessageContainer, PrimaryBoldHeading, PrimaryButton, PrimarySmallText, SecondaryButton, StyledModal, TextArea, } from '@manuscripts/style-guide';
26
- import { debounce } from 'lodash';
27
26
  import React, { useEffect, useState } from 'react';
28
27
  import styled from 'styled-components';
29
28
  import { insertEmbed } from '../../commands';
30
- import { getOEmbedHTML, getOEmbedUrl } from '../../lib/oembed';
29
+ import { getOEmbedHTML } from '../../lib/oembed';
31
30
  import { allowedHref } from '../../lib/url';
31
+ import { useDoWithDebounce } from '../../lib/use-do-with-debounce';
32
32
  import { getEditorProps } from '../../plugins/editor-props';
33
33
  import ReactSubView from '../../views/ReactSubView';
34
34
  import { FieldHeading, Open } from '../views/LinkForm';
@@ -53,39 +53,32 @@ const PreviewContainer = styled.div `
53
53
  border-radius: ${(props) => props.theme.grid.radius.small};
54
54
  padding: 6px ${(props) => props.theme.grid.unit * 4}px;
55
55
  `;
56
- export const InsertEmbedDialog = ({ state, dispatch, operation, pos, }) => {
56
+ export const InsertEmbedDialog = ({ state, dispatch, pos, }) => {
57
57
  var _a;
58
- const nodeAttr = pos ? (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs : undefined;
58
+ const attrs = pos ? (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs : undefined;
59
59
  const [isOpen, setOpen] = useState(true);
60
- const [url, setUrl] = useState((nodeAttr === null || nodeAttr === void 0 ? void 0 : nodeAttr.href) || undefined);
61
- const [oembedHTML, setOEmbedHTML] = useState(undefined);
62
- const action = () => {
63
- var _a;
64
- if (operation === 'Insert') {
60
+ const [url, setUrl] = useState(attrs === null || attrs === void 0 ? void 0 : attrs.href);
61
+ const [oembedHTML, setOEmbedHTML] = useState();
62
+ const debounce = useDoWithDebounce();
63
+ const handleSave = () => {
64
+ if (!pos) {
65
65
  insertEmbed(state, dispatch, { href: url });
66
66
  }
67
67
  else {
68
- dispatch &&
69
- pos &&
70
- dispatch(state.tr.setNodeMarkup(pos, undefined, Object.assign(Object.assign({}, (_a = state.doc.nodeAt(pos)) === null || _a === void 0 ? void 0 : _a.attrs), { href: url })));
68
+ const tr = state.tr.setNodeAttribute(pos, 'href', url);
69
+ dispatch(tr);
71
70
  }
72
71
  setOpen(false);
73
72
  };
74
73
  useEffect(() => {
75
- url && updateEmbedHTML(url);
76
- }, [pos]);
77
- const debouncedUrlChange = debounce((e) => __awaiter(void 0, void 0, void 0, function* () {
78
- const url = e.target.value.trim();
79
- yield updateEmbedHTML(url);
80
- setUrl(url);
81
- }), 500);
82
- const updateEmbedHTML = (url) => __awaiter(void 0, void 0, void 0, function* () {
83
- const oEmbedUrl = yield getOEmbedUrl(url, 368, 217);
84
- const oembedJSON = oEmbedUrl && (yield getOEmbedHTML(oEmbedUrl, url));
85
- setOEmbedHTML(oembedJSON);
86
- });
74
+ debounce(() => __awaiter(void 0, void 0, void 0, function* () {
75
+ const html = yield getOEmbedHTML(url, 368, 217);
76
+ setOEmbedHTML(html);
77
+ }));
78
+ }, [url]);
79
+ const operation = pos ? 'Update' : 'Insert';
87
80
  return (React.createElement(StyledModal, { isOpen: isOpen, onRequestClose: () => setOpen(false) },
88
- React.createElement(DialogContainer, null,
81
+ React.createElement(DialogContainer, { "data-cy": "media-editor" },
89
82
  React.createElement(HeaderContainer, null,
90
83
  operation,
91
84
  " external media"),
@@ -94,13 +87,13 @@ export const InsertEmbedDialog = ({ state, dispatch, operation, pos, }) => {
94
87
  React.createElement(FieldHeading, null,
95
88
  React.createElement(Label, { htmlFor: 'embed-link' }, "Media link"),
96
89
  url && allowedHref(url) && (React.createElement(Open, { id: 'media-link', href: url, target: '_blank', rel: 'noopener' }))),
97
- React.createElement(TextArea, { id: 'embed-link', rows: 2, cols: 2, defaultValue: url, autoFocus: true, required: true, placeholder: 'https://youtube.com/...', onChange: debouncedUrlChange })),
90
+ React.createElement(TextArea, { id: 'embed-link', rows: 2, cols: 2, defaultValue: url, autoFocus: true, required: true, placeholder: 'https://youtube.com/...', onChange: (e) => setUrl(e.target.value.trim()) })),
98
91
  url && allowedHref(url) && (React.createElement(Container, null,
99
92
  React.createElement(Label, null, "Preview"),
100
93
  (oembedHTML && (React.createElement(PreviewContainer, { dangerouslySetInnerHTML: { __html: oembedHTML } }))) || React.createElement(NoPreviewMessage, null)))),
101
94
  React.createElement(ButtonGroup, null,
102
95
  React.createElement(SecondaryButton, { onClick: () => setOpen(false) }, "Cancel"),
103
- React.createElement(PrimaryButton, { onClick: action, disabled: !(url && allowedHref(url)) }, operation)))));
96
+ React.createElement(PrimaryButton, { onClick: handleSave, disabled: !(url && allowedHref(url)) }, operation)))));
104
97
  };
105
98
  const Wrapper = styled.div `
106
99
  display: flex;
@@ -123,7 +116,7 @@ export const NoPreviewMessageWithLink = ({ href, }) => (React.createElement(NoPr
123
116
  React.createElement("a", { href: href, target: '_blank', rel: "noreferrer" }, "Click here"),
124
117
  ' ',
125
118
  "to see the source media")));
126
- export const openEmbedDialog = (view, operation = 'Insert', pos) => {
119
+ export const openEmbedDialog = (view, pos) => {
127
120
  if (!view) {
128
121
  return;
129
122
  }
@@ -131,7 +124,6 @@ export const openEmbedDialog = (view, operation = 'Insert', pos) => {
131
124
  const dialog = ReactSubView(getEditorProps(state), InsertEmbedDialog, {
132
125
  state,
133
126
  dispatch,
134
- operation,
135
127
  pos,
136
128
  }, state.doc, () => 0, view);
137
129
  document.body.appendChild(dialog);
@@ -62,24 +62,24 @@ const globToRegex = (glob) => {
62
62
  .replace(/\*/g, '.*');
63
63
  return new RegExp(`^${regex}$`);
64
64
  };
65
- export const getOEmbedHTML = (oembedUrl, sourceLink) => __awaiter(void 0, void 0, void 0, function* () {
65
+ export const getOEmbedHTML = (url, width, height) => __awaiter(void 0, void 0, void 0, function* () {
66
66
  try {
67
+ const oembedUrl = yield getOEmbedUrl(url, width, height);
68
+ if (!oembedUrl) {
69
+ return;
70
+ }
67
71
  const response = yield fetch(oembedUrl);
68
72
  if (response.status === 200) {
69
- const oembed = yield response.json();
70
- return oembed.html || renderAlternativeHTML(oembed, sourceLink);
71
- }
72
- else {
73
- return undefined;
73
+ const json = yield response.json();
74
+ return json.html || renderAlternativeHTML(json);
74
75
  }
75
76
  }
76
77
  catch (e) {
77
- return undefined;
78
+ return;
78
79
  }
79
80
  });
80
- const renderAlternativeHTML = (oembed, sourceLink) => {
81
+ const renderAlternativeHTML = (oembed) => {
81
82
  if (oembed.type === 'photo') {
82
83
  return `<img src="${oembed.url}">`;
83
84
  }
84
- return `<a href="${sourceLink}" target="_blank">${oembed.title || 'Media link'}</a>`;
85
85
  };
@@ -1,2 +1,2 @@
1
- export const VERSION = '2.7.34';
1
+ export const VERSION = '2.7.35';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -26,7 +26,7 @@ import { ContextMenu } from '@manuscripts/style-guide';
26
26
  import { addNodeComment } from '../commands';
27
27
  import { NoPreviewMessageWithLink, openEmbedDialog, } from '../components/toolbar/InsertEmbedDialog';
28
28
  import { openDeleteEmbedDialog } from '../components/views/DeleteEmbedDialog';
29
- import { getOEmbedHTML, getOEmbedUrl } from '../lib/oembed';
29
+ import { getOEmbedHTML } from '../lib/oembed';
30
30
  import BlockView from './block_view';
31
31
  import { createNodeView } from './creators';
32
32
  import ReactSubView from './ReactSubView';
@@ -38,7 +38,6 @@ export class EmbedMediaView extends BlockView {
38
38
  this.createElement = () => {
39
39
  this.container = document.createElement('div');
40
40
  this.container.classList.add('block');
41
- this.container.setAttribute('id', this.node.attrs.id);
42
41
  this.dom.appendChild(this.container);
43
42
  this.contentDOM = document.createElement('div');
44
43
  this.container.appendChild(this.contentDOM);
@@ -63,7 +62,7 @@ export class EmbedMediaView extends BlockView {
63
62
  },
64
63
  {
65
64
  label: 'Edit',
66
- action: () => openEmbedDialog(this.view, 'Update', this.getPos()),
65
+ action: () => openEmbedDialog(this.view, this.getPos()),
67
66
  icon: 'Edit',
68
67
  },
69
68
  ],
@@ -95,15 +94,13 @@ export class EmbedMediaView extends BlockView {
95
94
  else {
96
95
  this.container.prepend(preview);
97
96
  }
98
- const oEmbedUrl = yield getOEmbedUrl(this.href, 643, 363);
99
- if (oEmbedUrl) {
100
- const oembedHTML = yield getOEmbedHTML(oEmbedUrl, this.href);
101
- if (oembedHTML) {
102
- preview.innerHTML = oembedHTML;
103
- return;
104
- }
97
+ const html = yield getOEmbedHTML(this.href, 643, 363);
98
+ if (html) {
99
+ preview.innerHTML = html;
100
+ }
101
+ else {
102
+ this.showUnavailableMessage(preview);
105
103
  }
106
- this.showUnavailableMessage(preview);
107
104
  });
108
105
  }
109
106
  showUnavailableMessage(preview) {
@@ -19,12 +19,11 @@ import React from 'react';
19
19
  import { Dispatch } from '../../commands';
20
20
  export type InsertEmbedDialogProps = {
21
21
  state: ManuscriptEditorState;
22
- dispatch?: Dispatch;
23
- operation: 'Insert' | 'Update';
22
+ dispatch: Dispatch;
24
23
  pos?: number;
25
24
  };
26
25
  export declare const InsertEmbedDialog: React.FC<InsertEmbedDialogProps>;
27
26
  export declare const NoPreviewMessageWithLink: React.FC<{
28
27
  href: string;
29
28
  }>;
30
- export declare const openEmbedDialog: (view?: EditorView, operation?: string, pos?: number) => void;
29
+ export declare const openEmbedDialog: (view?: EditorView, pos?: number) => void;
@@ -5,4 +5,4 @@ export type ProviderJson = {
5
5
  title?: string;
6
6
  };
7
7
  export declare const getOEmbedUrl: (url: string, width: number, height: number) => Promise<string | undefined>;
8
- export declare const getOEmbedHTML: (oembedUrl: string, sourceLink: string) => Promise<any>;
8
+ export declare const getOEmbedHTML: (url: string, width: number, height: number) => Promise<any>;
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "2.7.34";
1
+ export declare const VERSION = "2.7.35";
2
2
  export declare const MATHJAX_VERSION = "3.2.2";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "2.7.34",
4
+ "version": "2.7.35",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",