@gravity-ui/markdown-editor 13.12.1 → 13.14.0

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.
@@ -45,6 +45,11 @@ export interface Editor extends Receiver<EventMap>, CommonEditor {
45
45
  }): void;
46
46
  }
47
47
  declare type SetEditorModeOptions = Pick<ChangeEditorModeOptions, 'emit'>;
48
+ declare type ChangeEditorModeOptions = {
49
+ mode: EditorMode;
50
+ reason: 'error-boundary' | 'settings' | 'manually';
51
+ emit?: boolean;
52
+ };
48
53
  export declare type MarkupConfig = {
49
54
  /** Additional extensions for codemirror instance. */
50
55
  extensions?: CreateCodemirrorParams['extensions'];
@@ -59,6 +64,10 @@ export declare type MarkupConfig = {
59
64
  */
60
65
  languageData?: YfmLangOptions['languageData'];
61
66
  };
67
+ export declare type EscapeConfig = {
68
+ commonEscape?: RegExp;
69
+ startOfLineEscape?: RegExp;
70
+ };
62
71
  export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'linkify' | 'linkifyTlds' | 'extensions'> & {
63
72
  initialMarkup?: MarkupString;
64
73
  /** @default 'wysiwyg' */
@@ -82,11 +91,13 @@ export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'li
82
91
  * You can use it to pre-process the value from the markup editor before it gets into the wysiwyg editor.
83
92
  */
84
93
  prepareRawMarkup?: (value: MarkupString) => MarkupString;
94
+ experimental_beforeEditorModeChange?: (options: Pick<ChangeEditorModeOptions, 'mode' | 'reason'>) => boolean | undefined;
85
95
  splitMode?: SplitMode;
86
96
  renderPreview?: RenderPreview;
87
97
  preset: EditorPreset;
88
98
  /** @deprecated Put extra extensions via MarkdownEditorMarkupConfig */
89
99
  extraMarkupExtensions?: CodemirrorExtension[];
90
100
  markupConfig?: MarkupConfig;
101
+ escapeConfig?: EscapeConfig;
91
102
  };
92
103
  export {};
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
2
+ var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_escapeConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup, _EditorImpl_beforeEditorModeChange;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.EditorImpl = void 0;
5
5
  const tslib_1 = require("tslib");
@@ -25,6 +25,7 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
25
25
  _EditorImpl_wysiwygEditor.set(this, void 0);
26
26
  _EditorImpl_markupEditor.set(this, void 0);
27
27
  _EditorImpl_markupConfig.set(this, void 0);
28
+ _EditorImpl_escapeConfig.set(this, void 0);
28
29
  _EditorImpl_preset.set(this, void 0);
29
30
  _EditorImpl_allowHTML.set(this, void 0);
30
31
  _EditorImpl_linkify.set(this, void 0);
@@ -34,6 +35,7 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
34
35
  _EditorImpl_fileUploadHandler.set(this, void 0);
35
36
  _EditorImpl_needToSetDimensionsForUploadedImages.set(this, void 0);
36
37
  _EditorImpl_prepareRawMarkup.set(this, void 0);
38
+ _EditorImpl_beforeEditorModeChange.set(this, void 0);
37
39
  this.getValue = () => this.currentEditor.getValue();
38
40
  tslib_1.__classPrivateFieldSet(this, _EditorImpl_editorMode, (_a = opts.initialEditorMode) !== null && _a !== void 0 ? _a : 'wysiwyg', "f");
39
41
  tslib_1.__classPrivateFieldSet(this, _EditorImpl_toolbarVisible, Boolean(opts.initialToolbarVisible), "f");
@@ -52,6 +54,8 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
52
54
  tslib_1.__classPrivateFieldSet(this, _EditorImpl_fileUploadHandler, opts.fileUploadHandler, "f");
53
55
  tslib_1.__classPrivateFieldSet(this, _EditorImpl_needToSetDimensionsForUploadedImages, Boolean(opts.needToSetDimensionsForUploadedImages), "f");
54
56
  tslib_1.__classPrivateFieldSet(this, _EditorImpl_prepareRawMarkup, opts.prepareRawMarkup, "f");
57
+ tslib_1.__classPrivateFieldSet(this, _EditorImpl_escapeConfig, opts.escapeConfig, "f");
58
+ tslib_1.__classPrivateFieldSet(this, _EditorImpl_beforeEditorModeChange, opts.experimental_beforeEditorModeChange, "f");
55
59
  }
56
60
  get _wysiwygView() {
57
61
  var _a;
@@ -137,6 +141,7 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
137
141
  allowHTML: tslib_1.__classPrivateFieldGet(this, _EditorImpl_allowHTML, "f"),
138
142
  linkify: tslib_1.__classPrivateFieldGet(this, _EditorImpl_linkify, "f"),
139
143
  linkifyTlds: tslib_1.__classPrivateFieldGet(this, _EditorImpl_linkifyTlds, "f"),
144
+ escapeConfig: tslib_1.__classPrivateFieldGet(this, _EditorImpl_escapeConfig, "f"),
140
145
  onChange: () => this.emit('rerender-toolbar', null),
141
146
  onDocChange: () => this.emit('change', null),
142
147
  }), "f");
@@ -199,9 +204,13 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
199
204
  this.changeEditorMode({ mode, reason: 'manually', emit: opts === null || opts === void 0 ? void 0 : opts.emit });
200
205
  }
201
206
  changeEditorMode(_a) {
207
+ var _b;
202
208
  var { emit = true } = _a, opts = tslib_1.__rest(_a, ["emit"]);
203
209
  if (tslib_1.__classPrivateFieldGet(this, _EditorImpl_editorMode, "f") === opts.mode)
204
210
  return;
211
+ if (((_b = tslib_1.__classPrivateFieldGet(this, _EditorImpl_beforeEditorModeChange, "f")) === null || _b === void 0 ? void 0 : _b.call(this, { mode: opts.mode, reason: opts.reason })) === false) {
212
+ return;
213
+ }
205
214
  this.currentMode = opts.mode;
206
215
  this.emit('rerender', null);
207
216
  if (emit) {
@@ -276,9 +285,9 @@ class EditorImpl extends event_emitter_1.SafeEventEmitter {
276
285
  }
277
286
  shouldReplaceMarkupEditorValue(markupValue, wysiwygValue) {
278
287
  var _a;
279
- const serializedEditorMarkup = (_a = tslib_1.__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f")) === null || _a === void 0 ? void 0 : _a.serializer.serialize(tslib_1.__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f").parser.parse(markupValue));
288
+ const serializedEditorMarkup = (_a = tslib_1.__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f")) === null || _a === void 0 ? void 0 : _a.serializer.serialize(tslib_1.__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f").parser.parse(markupValue), tslib_1.__classPrivateFieldGet(this, _EditorImpl_escapeConfig, "f"));
280
289
  return (serializedEditorMarkup === null || serializedEditorMarkup === void 0 ? void 0 : serializedEditorMarkup.trim()) !== wysiwygValue.trim();
281
290
  }
282
291
  }
283
292
  exports.EditorImpl = EditorImpl;
284
- _EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap();
293
+ _EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_escapeConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap(), _EditorImpl_beforeEditorModeChange = new WeakMap();
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
2
  import { ClassNameProps } from '../../classname';
3
3
  import type { EditorMode, SplitMode } from '../Editor';
4
- export declare type EditorSettingsProps = SettingsContentProps & {
4
+ export declare type EditorSettingsProps = Omit<SettingsContentProps, 'onClose'> & {
5
5
  renderPreviewButton?: boolean;
6
6
  };
7
7
  export declare const EditorSettings: React.NamedExoticComponent<EditorSettingsProps>;
8
8
  declare type SettingsContentProps = ClassNameProps & {
9
9
  mode: EditorMode;
10
+ onClose: () => void;
10
11
  onModeChange: (mode: EditorMode) => void;
11
12
  onShowPreviewChange: (showPreview: boolean) => void;
12
13
  showPreview: boolean;
@@ -32,14 +32,20 @@ exports.EditorSettings = react_1.default.memo(function EditorSettings(props) {
32
32
  react_1.default.createElement(uikit_1.Button, { size: "m", view: "flat", ref: chevronRef, pin: "round-round", onClick: togglePopup, className: bSettings('dropdown-button') },
33
33
  react_1.default.createElement(uikit_1.Icon, { data: icons_1.Gear })),
34
34
  react_1.default.createElement(uikit_1.Popup, { open: popupShown, anchorRef: chevronRef, placement: placement, onClose: hidePopup },
35
- react_1.default.createElement(SettingsContent, Object.assign({}, props, { className: bSettings('content') })))));
35
+ react_1.default.createElement(SettingsContent, Object.assign({}, props, { onClose: hidePopup, className: bSettings('content') })))));
36
36
  });
37
37
  const mdHelpPlacement = ['bottom', 'bottom-end', 'right-start', 'right', 'left'];
38
- const SettingsContent = function SettingsContent({ mode, onModeChange, toolbarVisibility, onToolbarVisibilityChange, onSplitModeChange, splitMode = false, splitModeEnabled, className, showPreview, }) {
38
+ const SettingsContent = function SettingsContent({ mode, onClose, onModeChange, toolbarVisibility, onToolbarVisibilityChange, onSplitModeChange, splitMode = false, splitModeEnabled, className, showPreview, }) {
39
39
  return (react_1.default.createElement("div", { className: bContent(null, [className]) },
40
40
  react_1.default.createElement(uikit_1.Menu, { size: "l", className: bContent('mode') },
41
- react_1.default.createElement(uikit_1.Menu.Item, { active: mode === 'wysiwyg', onClick: () => onModeChange('wysiwyg'), icon: react_1.default.createElement(uikit_1.Icon, { data: WysiwygMode_1.default }) }, (0, bundle_1.i18n)('settings_wysiwyg')),
42
- react_1.default.createElement(uikit_1.Menu.Item, { active: mode === 'markup', onClick: () => onModeChange('markup'), icon: react_1.default.createElement(uikit_1.Icon, { data: icons_1.LogoMarkdown }) },
41
+ react_1.default.createElement(uikit_1.Menu.Item, { active: mode === 'wysiwyg', onClick: () => {
42
+ onModeChange('wysiwyg');
43
+ onClose();
44
+ }, icon: react_1.default.createElement(uikit_1.Icon, { data: WysiwygMode_1.default }) }, (0, bundle_1.i18n)('settings_wysiwyg')),
45
+ react_1.default.createElement(uikit_1.Menu.Item, { active: mode === 'markup', onClick: () => {
46
+ onModeChange('markup');
47
+ onClose();
48
+ }, icon: react_1.default.createElement(uikit_1.Icon, { data: icons_1.LogoMarkdown }) },
43
49
  (0, bundle_1.i18n)('settings_markup'),
44
50
  react_1.default.createElement(components_1.HelpPopover, { content: react_1.default.createElement("div", { onClick: (e) => {
45
51
  // stop clicks propagation
@@ -5,6 +5,10 @@ import type { Extension } from './types/extension';
5
5
  import type { Parser } from './types/parser';
6
6
  import type { Serializer } from './types/serializer';
7
7
  declare type OnChange = (editor: WysiwygEditor) => void;
8
+ declare type EscapeConfig = {
9
+ commonEscape?: RegExp;
10
+ startOfLineEscape?: RegExp;
11
+ };
8
12
  export declare type WysiwygEditorOptions = {
9
13
  domElem?: Element;
10
14
  /** markdown markup */
@@ -15,6 +19,7 @@ export declare type WysiwygEditorOptions = {
15
19
  allowHTML?: boolean;
16
20
  linkify?: boolean;
17
21
  linkifyTlds?: string | string[];
22
+ escapeConfig?: EscapeConfig;
18
23
  /** Call on any state change (move cursor, change selection, etc...) */
19
24
  onChange?: OnChange;
20
25
  /** Call only if document change */
@@ -26,7 +31,7 @@ export declare class WysiwygEditor implements CommonEditor, ActionStorage {
26
31
  get serializer(): Serializer;
27
32
  get parser(): Parser;
28
33
  get actions(): WysiwygEditor.Actions;
29
- constructor({ domElem, initialContent, extensions, allowHTML, mdPreset, linkify, linkifyTlds, onChange, onDocChange, }: WysiwygEditorOptions);
34
+ constructor({ domElem, initialContent, extensions, allowHTML, mdPreset, linkify, linkifyTlds, escapeConfig, onChange, onDocChange, }: WysiwygEditorOptions);
30
35
  action<T extends keyof WysiwygEditor.Actions>(actionName: T): WysiwygEditor.Actions[T];
31
36
  focus(): void;
32
37
  hasFocus(): boolean;
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var _WysiwygEditor_view, _WysiwygEditor_serializer, _WysiwygEditor_parser, _WysiwygEditor_actions, _WysiwygEditor_contentHandler;
2
+ var _WysiwygEditor_view, _WysiwygEditor_serializer, _WysiwygEditor_parser, _WysiwygEditor_actions, _WysiwygEditor_contentHandler, _WysiwygEditor_escapeConfig;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.WysiwygEditor = void 0;
5
5
  const tslib_1 = require("tslib");
@@ -10,12 +10,13 @@ const ExtensionsManager_1 = require("./ExtensionsManager");
10
10
  const actions_1 = require("./utils/actions");
11
11
  const metrics_1 = require("./utils/metrics");
12
12
  class WysiwygEditor {
13
- constructor({ domElem, initialContent = '', extensions = () => { }, allowHTML, mdPreset, linkify, linkifyTlds, onChange, onDocChange, }) {
13
+ constructor({ domElem, initialContent = '', extensions = () => { }, allowHTML, mdPreset, linkify, linkifyTlds, escapeConfig, onChange, onDocChange, }) {
14
14
  _WysiwygEditor_view.set(this, void 0);
15
15
  _WysiwygEditor_serializer.set(this, void 0);
16
16
  _WysiwygEditor_parser.set(this, void 0);
17
17
  _WysiwygEditor_actions.set(this, void 0);
18
18
  _WysiwygEditor_contentHandler.set(this, void 0);
19
+ _WysiwygEditor_escapeConfig.set(this, void 0);
19
20
  const { schema, markupParser: parser, serializer, nodeViews, markViews, plugins, rawActions, actions, } = ExtensionsManager_1.ExtensionsManager.process(extensions, {
20
21
  // "breaks" option only affects the renderer, but not the parser
21
22
  mdOpts: { html: allowHTML, linkify, breaks: true, preset: mdPreset },
@@ -47,6 +48,7 @@ class WysiwygEditor {
47
48
  tslib_1.__classPrivateFieldSet(this, _WysiwygEditor_serializer, serializer, "f");
48
49
  tslib_1.__classPrivateFieldSet(this, _WysiwygEditor_parser, parser, "f");
49
50
  tslib_1.__classPrivateFieldSet(this, _WysiwygEditor_contentHandler, new ContentHandler_1.WysiwygContentHandler(tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_view, "f"), parser), "f");
51
+ tslib_1.__classPrivateFieldSet(this, _WysiwygEditor_escapeConfig, escapeConfig, "f");
50
52
  }
51
53
  get dom() {
52
54
  return tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_view, "f").dom;
@@ -74,7 +76,7 @@ class WysiwygEditor {
74
76
  return tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_view, "f").hasFocus();
75
77
  }
76
78
  getValue() {
77
- return tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_serializer, "f").serialize(tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_view, "f").state.doc);
79
+ return tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_serializer, "f").serialize(tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_view, "f").state.doc, tslib_1.__classPrivateFieldGet(this, _WysiwygEditor_escapeConfig, "f"));
78
80
  }
79
81
  isEmpty() {
80
82
  var _a;
@@ -113,4 +115,4 @@ class WysiwygEditor {
113
115
  }
114
116
  }
115
117
  exports.WysiwygEditor = WysiwygEditor;
116
- _WysiwygEditor_view = new WeakMap(), _WysiwygEditor_serializer = new WeakMap(), _WysiwygEditor_parser = new WeakMap(), _WysiwygEditor_actions = new WeakMap(), _WysiwygEditor_contentHandler = new WeakMap();
118
+ _WysiwygEditor_view = new WeakMap(), _WysiwygEditor_serializer = new WeakMap(), _WysiwygEditor_parser = new WeakMap(), _WysiwygEditor_actions = new WeakMap(), _WysiwygEditor_contentHandler = new WeakMap(), _WysiwygEditor_escapeConfig = new WeakMap();
@@ -308,10 +308,12 @@ class MarkdownSerializerState {
308
308
  // content. If `startOfLine` is true, also escape characters that
309
309
  // have special meaning only at the start of the line.
310
310
  esc(str, startOfLine) {
311
- // TODO: add a setting which characters need to be escaped
312
- str = str.replace(/[`\^+*\\\|~\[\]\{\}<>\$]/g, '\\$&');
311
+ var _a, _b;
312
+ const escRegexp = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.commonEscape) || /[`\^+*\\\|~\[\]\{\}<>\$]/g;
313
+ const startOfLineEscRegexp = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.startOfLineEscape) || /^[:#\-*+>]/;
314
+ str = str.replace(escRegexp, '\\$&');
313
315
  if (startOfLine)
314
- str = str.replace(/^[:#\-*+>]/, '\\$&').replace(/^(\s*\d+)\./, '$1\\.');
316
+ str = str.replace(startOfLineEscRegexp, '\\$&').replace(/^(\s*\d+)\./, '$1\\.');
315
317
  return str;
316
318
  }
317
319
  escWhitespace(str) {
@@ -138,7 +138,8 @@ const CodeEditMode = ({ initialText, onSave, onCancel }) => {
138
138
  react_1.default.createElement(uikit_1.Button, { onClick: () => onSave(text), view: 'action' },
139
139
  react_1.default.createElement("span", { className: (0, exports.cnHelper)({ 'prosemirror-stop-event': true }) }, (0, common_1.i18n)('save'))))))));
140
140
  };
141
- const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useConfig, sanitize, styles, baseTarget = '_' } }) => {
141
+ const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useConfig, sanitize, styles, baseTarget = '_parent', head: headContent = '' }, }) => {
142
+ var _a;
142
143
  const [editing, setEditing, unsetEditing, toggleEditing] = (0, hooks_1.useBooleanState)(Boolean(node.attrs[const_1.YfmHtmlBlockConsts.NodeAttrs.newCreated]));
143
144
  const config = useConfig === null || useConfig === void 0 ? void 0 : useConfig();
144
145
  const [menuOpen, , , toggleMenuOpen] = (0, hooks_1.useBooleanState)(false);
@@ -152,17 +153,20 @@ const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useConfig,
152
153
  unsetEditing();
153
154
  } }));
154
155
  }
155
- let dirtyHtml = `<base target="${baseTarget}">` + node.attrs[const_1.YfmHtmlBlockConsts.NodeAttrs.srcdoc];
156
+ let additional = baseTarget ? `<base target="${baseTarget}">` : '';
156
157
  if (styles) {
157
158
  const stylesContent = typeof styles === 'string'
158
159
  ? `<link rel="stylesheet" href="${styles}" />`
159
160
  : `<style>${(0, html_extension_1.getStyles)(styles)}</style>`;
160
- dirtyHtml = stylesContent + dirtyHtml;
161
+ additional += stylesContent;
161
162
  }
162
- const html = sanitize ? sanitize(dirtyHtml) : dirtyHtml;
163
+ const head = `<head>${headContent || additional}</head>`;
164
+ const body = `<body>${(_a = node.attrs[const_1.YfmHtmlBlockConsts.NodeAttrs.srcdoc]) !== null && _a !== void 0 ? _a : ''}</body>`;
165
+ const html = `<!DOCTYPE html><html>${head}${body}</html>`;
166
+ const resultHtml = sanitize ? sanitize(html) : html;
163
167
  return (react_1.default.createElement("div", { className: b(), onDoubleClick: setEditing },
164
168
  react_1.default.createElement(uikit_1.Label, { className: b('label'), icon: react_1.default.createElement(uikit_1.Icon, { size: 16, data: icons_1.Eye }) }, (0, common_1.i18n)('preview')),
165
- react_1.default.createElement(YfmHtmlBlockPreview, { html: html, "on\u0421lick": handleClick, config: config }),
169
+ react_1.default.createElement(YfmHtmlBlockPreview, { html: resultHtml, "on\u0421lick": handleClick, config: config }),
166
170
  react_1.default.createElement("div", { className: b('menu') },
167
171
  react_1.default.createElement(uikit_1.Button, { onClick: toggleMenuOpen, ref: buttonRef, size: 's', className: (0, exports.cnHelper)({ 'prosemirror-stop-event': true }) },
168
172
  react_1.default.createElement(uikit_1.Icon, { data: icons_1.Ellipsis, className: (0, exports.cnHelper)({ 'prosemirror-stop-event': true }) })),
@@ -7,6 +7,7 @@ export declare type YfmHtmlBlockOptions = {
7
7
  sanitize?: (dirtyHtml: string) => string;
8
8
  styles?: string | StylesObject;
9
9
  baseTarget?: BaseTarget;
10
+ head?: string;
10
11
  };
11
12
  export declare const YfmHtmlBlock: ExtensionAuto<YfmHtmlBlockOptions>;
12
13
  declare global {
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
4
  /** During build process, the current version will be injected here */
5
- exports.VERSION = typeof '13.12.1' !== 'undefined' ? '13.12.1' : 'unknown';
5
+ exports.VERSION = typeof '13.14.0' !== 'undefined' ? '13.14.0' : 'unknown';
@@ -45,6 +45,11 @@ export interface Editor extends Receiver<EventMap>, CommonEditor {
45
45
  }): void;
46
46
  }
47
47
  declare type SetEditorModeOptions = Pick<ChangeEditorModeOptions, 'emit'>;
48
+ declare type ChangeEditorModeOptions = {
49
+ mode: EditorMode;
50
+ reason: 'error-boundary' | 'settings' | 'manually';
51
+ emit?: boolean;
52
+ };
48
53
  export declare type MarkupConfig = {
49
54
  /** Additional extensions for codemirror instance. */
50
55
  extensions?: CreateCodemirrorParams['extensions'];
@@ -59,6 +64,10 @@ export declare type MarkupConfig = {
59
64
  */
60
65
  languageData?: YfmLangOptions['languageData'];
61
66
  };
67
+ export declare type EscapeConfig = {
68
+ commonEscape?: RegExp;
69
+ startOfLineEscape?: RegExp;
70
+ };
62
71
  export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'linkify' | 'linkifyTlds' | 'extensions'> & {
63
72
  initialMarkup?: MarkupString;
64
73
  /** @default 'wysiwyg' */
@@ -82,11 +91,13 @@ export declare type EditorOptions = Pick<WysiwygEditorOptions, 'allowHTML' | 'li
82
91
  * You can use it to pre-process the value from the markup editor before it gets into the wysiwyg editor.
83
92
  */
84
93
  prepareRawMarkup?: (value: MarkupString) => MarkupString;
94
+ experimental_beforeEditorModeChange?: (options: Pick<ChangeEditorModeOptions, 'mode' | 'reason'>) => boolean | undefined;
85
95
  splitMode?: SplitMode;
86
96
  renderPreview?: RenderPreview;
87
97
  preset: EditorPreset;
88
98
  /** @deprecated Put extra extensions via MarkdownEditorMarkupConfig */
89
99
  extraMarkupExtensions?: CodemirrorExtension[];
90
100
  markupConfig?: MarkupConfig;
101
+ escapeConfig?: EscapeConfig;
91
102
  };
92
103
  export {};
@@ -1,4 +1,4 @@
1
- var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup;
1
+ var _EditorImpl_markup, _EditorImpl_editorMode, _EditorImpl_toolbarVisible, _EditorImpl_splitModeEnabled, _EditorImpl_splitMode, _EditorImpl_renderPreview, _EditorImpl_wysiwygEditor, _EditorImpl_markupEditor, _EditorImpl_markupConfig, _EditorImpl_escapeConfig, _EditorImpl_preset, _EditorImpl_allowHTML, _EditorImpl_linkify, _EditorImpl_linkifyTlds, _EditorImpl_extensions, _EditorImpl_renderStorage, _EditorImpl_fileUploadHandler, _EditorImpl_needToSetDimensionsForUploadedImages, _EditorImpl_prepareRawMarkup, _EditorImpl_beforeEditorModeChange;
2
2
  import { __classPrivateFieldGet, __classPrivateFieldSet, __rest } from "tslib";
3
3
  import { TextSelection } from 'prosemirror-state';
4
4
  import { WysiwygEditor } from '../core';
@@ -22,6 +22,7 @@ export class EditorImpl extends SafeEventEmitter {
22
22
  _EditorImpl_wysiwygEditor.set(this, void 0);
23
23
  _EditorImpl_markupEditor.set(this, void 0);
24
24
  _EditorImpl_markupConfig.set(this, void 0);
25
+ _EditorImpl_escapeConfig.set(this, void 0);
25
26
  _EditorImpl_preset.set(this, void 0);
26
27
  _EditorImpl_allowHTML.set(this, void 0);
27
28
  _EditorImpl_linkify.set(this, void 0);
@@ -31,6 +32,7 @@ export class EditorImpl extends SafeEventEmitter {
31
32
  _EditorImpl_fileUploadHandler.set(this, void 0);
32
33
  _EditorImpl_needToSetDimensionsForUploadedImages.set(this, void 0);
33
34
  _EditorImpl_prepareRawMarkup.set(this, void 0);
35
+ _EditorImpl_beforeEditorModeChange.set(this, void 0);
34
36
  this.getValue = () => this.currentEditor.getValue();
35
37
  __classPrivateFieldSet(this, _EditorImpl_editorMode, (_a = opts.initialEditorMode) !== null && _a !== void 0 ? _a : 'wysiwyg', "f");
36
38
  __classPrivateFieldSet(this, _EditorImpl_toolbarVisible, Boolean(opts.initialToolbarVisible), "f");
@@ -49,6 +51,8 @@ export class EditorImpl extends SafeEventEmitter {
49
51
  __classPrivateFieldSet(this, _EditorImpl_fileUploadHandler, opts.fileUploadHandler, "f");
50
52
  __classPrivateFieldSet(this, _EditorImpl_needToSetDimensionsForUploadedImages, Boolean(opts.needToSetDimensionsForUploadedImages), "f");
51
53
  __classPrivateFieldSet(this, _EditorImpl_prepareRawMarkup, opts.prepareRawMarkup, "f");
54
+ __classPrivateFieldSet(this, _EditorImpl_escapeConfig, opts.escapeConfig, "f");
55
+ __classPrivateFieldSet(this, _EditorImpl_beforeEditorModeChange, opts.experimental_beforeEditorModeChange, "f");
52
56
  }
53
57
  get _wysiwygView() {
54
58
  var _a;
@@ -134,6 +138,7 @@ export class EditorImpl extends SafeEventEmitter {
134
138
  allowHTML: __classPrivateFieldGet(this, _EditorImpl_allowHTML, "f"),
135
139
  linkify: __classPrivateFieldGet(this, _EditorImpl_linkify, "f"),
136
140
  linkifyTlds: __classPrivateFieldGet(this, _EditorImpl_linkifyTlds, "f"),
141
+ escapeConfig: __classPrivateFieldGet(this, _EditorImpl_escapeConfig, "f"),
137
142
  onChange: () => this.emit('rerender-toolbar', null),
138
143
  onDocChange: () => this.emit('change', null),
139
144
  }), "f");
@@ -196,9 +201,13 @@ export class EditorImpl extends SafeEventEmitter {
196
201
  this.changeEditorMode({ mode, reason: 'manually', emit: opts === null || opts === void 0 ? void 0 : opts.emit });
197
202
  }
198
203
  changeEditorMode(_a) {
204
+ var _b;
199
205
  var { emit = true } = _a, opts = __rest(_a, ["emit"]);
200
206
  if (__classPrivateFieldGet(this, _EditorImpl_editorMode, "f") === opts.mode)
201
207
  return;
208
+ if (((_b = __classPrivateFieldGet(this, _EditorImpl_beforeEditorModeChange, "f")) === null || _b === void 0 ? void 0 : _b.call(this, { mode: opts.mode, reason: opts.reason })) === false) {
209
+ return;
210
+ }
202
211
  this.currentMode = opts.mode;
203
212
  this.emit('rerender', null);
204
213
  if (emit) {
@@ -273,8 +282,8 @@ export class EditorImpl extends SafeEventEmitter {
273
282
  }
274
283
  shouldReplaceMarkupEditorValue(markupValue, wysiwygValue) {
275
284
  var _a;
276
- const serializedEditorMarkup = (_a = __classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f")) === null || _a === void 0 ? void 0 : _a.serializer.serialize(__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f").parser.parse(markupValue));
285
+ const serializedEditorMarkup = (_a = __classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f")) === null || _a === void 0 ? void 0 : _a.serializer.serialize(__classPrivateFieldGet(this, _EditorImpl_wysiwygEditor, "f").parser.parse(markupValue), __classPrivateFieldGet(this, _EditorImpl_escapeConfig, "f"));
277
286
  return (serializedEditorMarkup === null || serializedEditorMarkup === void 0 ? void 0 : serializedEditorMarkup.trim()) !== wysiwygValue.trim();
278
287
  }
279
288
  }
280
- _EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap();
289
+ _EditorImpl_markup = new WeakMap(), _EditorImpl_editorMode = new WeakMap(), _EditorImpl_toolbarVisible = new WeakMap(), _EditorImpl_splitModeEnabled = new WeakMap(), _EditorImpl_splitMode = new WeakMap(), _EditorImpl_renderPreview = new WeakMap(), _EditorImpl_wysiwygEditor = new WeakMap(), _EditorImpl_markupEditor = new WeakMap(), _EditorImpl_markupConfig = new WeakMap(), _EditorImpl_escapeConfig = new WeakMap(), _EditorImpl_preset = new WeakMap(), _EditorImpl_allowHTML = new WeakMap(), _EditorImpl_linkify = new WeakMap(), _EditorImpl_linkifyTlds = new WeakMap(), _EditorImpl_extensions = new WeakMap(), _EditorImpl_renderStorage = new WeakMap(), _EditorImpl_fileUploadHandler = new WeakMap(), _EditorImpl_needToSetDimensionsForUploadedImages = new WeakMap(), _EditorImpl_prepareRawMarkup = new WeakMap(), _EditorImpl_beforeEditorModeChange = new WeakMap();
@@ -2,12 +2,13 @@ import React from 'react';
2
2
  import { ClassNameProps } from '../../classname';
3
3
  import type { EditorMode, SplitMode } from '../Editor';
4
4
  import './index.css';
5
- export declare type EditorSettingsProps = SettingsContentProps & {
5
+ export declare type EditorSettingsProps = Omit<SettingsContentProps, 'onClose'> & {
6
6
  renderPreviewButton?: boolean;
7
7
  };
8
8
  export declare const EditorSettings: React.NamedExoticComponent<EditorSettingsProps>;
9
9
  declare type SettingsContentProps = ClassNameProps & {
10
10
  mode: EditorMode;
11
+ onClose: () => void;
11
12
  onModeChange: (mode: EditorMode) => void;
12
13
  onShowPreviewChange: (showPreview: boolean) => void;
13
14
  showPreview: boolean;
@@ -29,14 +29,20 @@ export const EditorSettings = React.memo(function EditorSettings(props) {
29
29
  React.createElement(Button, { size: "m", view: "flat", ref: chevronRef, pin: "round-round", onClick: togglePopup, className: bSettings('dropdown-button') },
30
30
  React.createElement(Icon, { data: Gear })),
31
31
  React.createElement(Popup, { open: popupShown, anchorRef: chevronRef, placement: placement, onClose: hidePopup },
32
- React.createElement(SettingsContent, Object.assign({}, props, { className: bSettings('content') })))));
32
+ React.createElement(SettingsContent, Object.assign({}, props, { onClose: hidePopup, className: bSettings('content') })))));
33
33
  });
34
34
  const mdHelpPlacement = ['bottom', 'bottom-end', 'right-start', 'right', 'left'];
35
- const SettingsContent = function SettingsContent({ mode, onModeChange, toolbarVisibility, onToolbarVisibilityChange, onSplitModeChange, splitMode = false, splitModeEnabled, className, showPreview, }) {
35
+ const SettingsContent = function SettingsContent({ mode, onClose, onModeChange, toolbarVisibility, onToolbarVisibilityChange, onSplitModeChange, splitMode = false, splitModeEnabled, className, showPreview, }) {
36
36
  return (React.createElement("div", { className: bContent(null, [className]) },
37
37
  React.createElement(Menu, { size: "l", className: bContent('mode') },
38
- React.createElement(Menu.Item, { active: mode === 'wysiwyg', onClick: () => onModeChange('wysiwyg'), icon: React.createElement(Icon, { data: WysiwygModeIcon }) }, i18n('settings_wysiwyg')),
39
- React.createElement(Menu.Item, { active: mode === 'markup', onClick: () => onModeChange('markup'), icon: React.createElement(Icon, { data: LogoMarkdown }) },
38
+ React.createElement(Menu.Item, { active: mode === 'wysiwyg', onClick: () => {
39
+ onModeChange('wysiwyg');
40
+ onClose();
41
+ }, icon: React.createElement(Icon, { data: WysiwygModeIcon }) }, i18n('settings_wysiwyg')),
42
+ React.createElement(Menu.Item, { active: mode === 'markup', onClick: () => {
43
+ onModeChange('markup');
44
+ onClose();
45
+ }, icon: React.createElement(Icon, { data: LogoMarkdown }) },
40
46
  i18n('settings_markup'),
41
47
  React.createElement(HelpPopover, { content: React.createElement("div", { onClick: (e) => {
42
48
  // stop clicks propagation
@@ -5,6 +5,10 @@ import type { Extension } from './types/extension';
5
5
  import type { Parser } from './types/parser';
6
6
  import type { Serializer } from './types/serializer';
7
7
  declare type OnChange = (editor: WysiwygEditor) => void;
8
+ declare type EscapeConfig = {
9
+ commonEscape?: RegExp;
10
+ startOfLineEscape?: RegExp;
11
+ };
8
12
  export declare type WysiwygEditorOptions = {
9
13
  domElem?: Element;
10
14
  /** markdown markup */
@@ -15,6 +19,7 @@ export declare type WysiwygEditorOptions = {
15
19
  allowHTML?: boolean;
16
20
  linkify?: boolean;
17
21
  linkifyTlds?: string | string[];
22
+ escapeConfig?: EscapeConfig;
18
23
  /** Call on any state change (move cursor, change selection, etc...) */
19
24
  onChange?: OnChange;
20
25
  /** Call only if document change */
@@ -26,7 +31,7 @@ export declare class WysiwygEditor implements CommonEditor, ActionStorage {
26
31
  get serializer(): Serializer;
27
32
  get parser(): Parser;
28
33
  get actions(): WysiwygEditor.Actions;
29
- constructor({ domElem, initialContent, extensions, allowHTML, mdPreset, linkify, linkifyTlds, onChange, onDocChange, }: WysiwygEditorOptions);
34
+ constructor({ domElem, initialContent, extensions, allowHTML, mdPreset, linkify, linkifyTlds, escapeConfig, onChange, onDocChange, }: WysiwygEditorOptions);
30
35
  action<T extends keyof WysiwygEditor.Actions>(actionName: T): WysiwygEditor.Actions[T];
31
36
  focus(): void;
32
37
  hasFocus(): boolean;
@@ -1,4 +1,4 @@
1
- var _WysiwygEditor_view, _WysiwygEditor_serializer, _WysiwygEditor_parser, _WysiwygEditor_actions, _WysiwygEditor_contentHandler;
1
+ var _WysiwygEditor_view, _WysiwygEditor_serializer, _WysiwygEditor_parser, _WysiwygEditor_actions, _WysiwygEditor_contentHandler, _WysiwygEditor_escapeConfig;
2
2
  import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
3
  import { EditorState } from 'prosemirror-state';
4
4
  import { EditorView } from 'prosemirror-view';
@@ -7,12 +7,13 @@ import { ExtensionsManager } from './ExtensionsManager';
7
7
  import { bindActions } from './utils/actions';
8
8
  import { logTransactionMetrics } from './utils/metrics';
9
9
  export class WysiwygEditor {
10
- constructor({ domElem, initialContent = '', extensions = () => { }, allowHTML, mdPreset, linkify, linkifyTlds, onChange, onDocChange, }) {
10
+ constructor({ domElem, initialContent = '', extensions = () => { }, allowHTML, mdPreset, linkify, linkifyTlds, escapeConfig, onChange, onDocChange, }) {
11
11
  _WysiwygEditor_view.set(this, void 0);
12
12
  _WysiwygEditor_serializer.set(this, void 0);
13
13
  _WysiwygEditor_parser.set(this, void 0);
14
14
  _WysiwygEditor_actions.set(this, void 0);
15
15
  _WysiwygEditor_contentHandler.set(this, void 0);
16
+ _WysiwygEditor_escapeConfig.set(this, void 0);
16
17
  const { schema, markupParser: parser, serializer, nodeViews, markViews, plugins, rawActions, actions, } = ExtensionsManager.process(extensions, {
17
18
  // "breaks" option only affects the renderer, but not the parser
18
19
  mdOpts: { html: allowHTML, linkify, breaks: true, preset: mdPreset },
@@ -44,6 +45,7 @@ export class WysiwygEditor {
44
45
  __classPrivateFieldSet(this, _WysiwygEditor_serializer, serializer, "f");
45
46
  __classPrivateFieldSet(this, _WysiwygEditor_parser, parser, "f");
46
47
  __classPrivateFieldSet(this, _WysiwygEditor_contentHandler, new WysiwygContentHandler(__classPrivateFieldGet(this, _WysiwygEditor_view, "f"), parser), "f");
48
+ __classPrivateFieldSet(this, _WysiwygEditor_escapeConfig, escapeConfig, "f");
47
49
  }
48
50
  get dom() {
49
51
  return __classPrivateFieldGet(this, _WysiwygEditor_view, "f").dom;
@@ -71,7 +73,7 @@ export class WysiwygEditor {
71
73
  return __classPrivateFieldGet(this, _WysiwygEditor_view, "f").hasFocus();
72
74
  }
73
75
  getValue() {
74
- return __classPrivateFieldGet(this, _WysiwygEditor_serializer, "f").serialize(__classPrivateFieldGet(this, _WysiwygEditor_view, "f").state.doc);
76
+ return __classPrivateFieldGet(this, _WysiwygEditor_serializer, "f").serialize(__classPrivateFieldGet(this, _WysiwygEditor_view, "f").state.doc, __classPrivateFieldGet(this, _WysiwygEditor_escapeConfig, "f"));
75
77
  }
76
78
  isEmpty() {
77
79
  var _a;
@@ -109,4 +111,4 @@ export class WysiwygEditor {
109
111
  }
110
112
  }
111
113
  }
112
- _WysiwygEditor_view = new WeakMap(), _WysiwygEditor_serializer = new WeakMap(), _WysiwygEditor_parser = new WeakMap(), _WysiwygEditor_actions = new WeakMap(), _WysiwygEditor_contentHandler = new WeakMap();
114
+ _WysiwygEditor_view = new WeakMap(), _WysiwygEditor_serializer = new WeakMap(), _WysiwygEditor_parser = new WeakMap(), _WysiwygEditor_actions = new WeakMap(), _WysiwygEditor_contentHandler = new WeakMap(), _WysiwygEditor_escapeConfig = new WeakMap();
@@ -304,10 +304,12 @@ export class MarkdownSerializerState {
304
304
  // content. If `startOfLine` is true, also escape characters that
305
305
  // have special meaning only at the start of the line.
306
306
  esc(str, startOfLine) {
307
- // TODO: add a setting which characters need to be escaped
308
- str = str.replace(/[`\^+*\\\|~\[\]\{\}<>\$]/g, '\\$&');
307
+ var _a, _b;
308
+ const escRegexp = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.commonEscape) || /[`\^+*\\\|~\[\]\{\}<>\$]/g;
309
+ const startOfLineEscRegexp = ((_b = this.options) === null || _b === void 0 ? void 0 : _b.startOfLineEscape) || /^[:#\-*+>]/;
310
+ str = str.replace(escRegexp, '\\$&');
309
311
  if (startOfLine)
310
- str = str.replace(/^[:#\-*+>]/, '\\$&').replace(/^(\s*\d+)\./, '$1\\.');
312
+ str = str.replace(startOfLineEscRegexp, '\\$&').replace(/^(\s*\d+)\./, '$1\\.');
311
313
  return str;
312
314
  }
313
315
  escWhitespace(str) {
@@ -134,7 +134,8 @@ const CodeEditMode = ({ initialText, onSave, onCancel }) => {
134
134
  React.createElement(Button, { onClick: () => onSave(text), view: 'action' },
135
135
  React.createElement("span", { className: cnHelper({ 'prosemirror-stop-event': true }) }, i18n('save'))))))));
136
136
  };
137
- export const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useConfig, sanitize, styles, baseTarget = '_' } }) => {
137
+ export const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useConfig, sanitize, styles, baseTarget = '_parent', head: headContent = '' }, }) => {
138
+ var _a;
138
139
  const [editing, setEditing, unsetEditing, toggleEditing] = useBooleanState(Boolean(node.attrs[YfmHtmlBlockConsts.NodeAttrs.newCreated]));
139
140
  const config = useConfig === null || useConfig === void 0 ? void 0 : useConfig();
140
141
  const [menuOpen, , , toggleMenuOpen] = useBooleanState(false);
@@ -148,17 +149,20 @@ export const YfmHtmlBlockView = ({ onChange, node, getPos, view, options: { useC
148
149
  unsetEditing();
149
150
  } }));
150
151
  }
151
- let dirtyHtml = `<base target="${baseTarget}">` + node.attrs[YfmHtmlBlockConsts.NodeAttrs.srcdoc];
152
+ let additional = baseTarget ? `<base target="${baseTarget}">` : '';
152
153
  if (styles) {
153
154
  const stylesContent = typeof styles === 'string'
154
155
  ? `<link rel="stylesheet" href="${styles}" />`
155
156
  : `<style>${getStyles(styles)}</style>`;
156
- dirtyHtml = stylesContent + dirtyHtml;
157
+ additional += stylesContent;
157
158
  }
158
- const html = sanitize ? sanitize(dirtyHtml) : dirtyHtml;
159
+ const head = `<head>${headContent || additional}</head>`;
160
+ const body = `<body>${(_a = node.attrs[YfmHtmlBlockConsts.NodeAttrs.srcdoc]) !== null && _a !== void 0 ? _a : ''}</body>`;
161
+ const html = `<!DOCTYPE html><html>${head}${body}</html>`;
162
+ const resultHtml = sanitize ? sanitize(html) : html;
159
163
  return (React.createElement("div", { className: b(), onDoubleClick: setEditing },
160
164
  React.createElement(Label, { className: b('label'), icon: React.createElement(Icon, { size: 16, data: Eye }) }, i18n('preview')),
161
- React.createElement(YfmHtmlBlockPreview, { html: html, "on\u0421lick": handleClick, config: config }),
165
+ React.createElement(YfmHtmlBlockPreview, { html: resultHtml, "on\u0421lick": handleClick, config: config }),
162
166
  React.createElement("div", { className: b('menu') },
163
167
  React.createElement(Button, { onClick: toggleMenuOpen, ref: buttonRef, size: 's', className: cnHelper({ 'prosemirror-stop-event': true }) },
164
168
  React.createElement(Icon, { data: DotsIcon, className: cnHelper({ 'prosemirror-stop-event': true }) })),
@@ -7,6 +7,7 @@ export declare type YfmHtmlBlockOptions = {
7
7
  sanitize?: (dirtyHtml: string) => string;
8
8
  styles?: string | StylesObject;
9
9
  baseTarget?: BaseTarget;
10
+ head?: string;
10
11
  };
11
12
  export declare const YfmHtmlBlock: ExtensionAuto<YfmHtmlBlockOptions>;
12
13
  declare global {
@@ -1,2 +1,2 @@
1
1
  /** During build process, the current version will be injected here */
2
- export const VERSION = typeof '13.12.1' !== 'undefined' ? '13.12.1' : 'unknown';
2
+ export const VERSION = typeof '13.14.0' !== 'undefined' ? '13.14.0' : 'unknown';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/markdown-editor",
3
- "version": "13.12.1",
3
+ "version": "13.14.0",
4
4
  "description": "Markdown wysiwyg and markup editor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -200,7 +200,7 @@
200
200
  },
201
201
  "devDependencies": {
202
202
  "@diplodoc/folding-headings-extension": "0.1.0",
203
- "@diplodoc/html-extension": "1.3.3",
203
+ "@diplodoc/html-extension": "1.5.0",
204
204
  "@diplodoc/latex-extension": "1.0.3",
205
205
  "@diplodoc/mermaid-extension": "1.2.1",
206
206
  "@diplodoc/transform": "4.22.0",