@wordpress/format-library 5.32.0 → 5.32.1-next.ff1cebbba.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.
Files changed (132) hide show
  1. package/build/bold/index.js +69 -58
  2. package/build/bold/index.js.map +7 -1
  3. package/build/code/index.js +62 -54
  4. package/build/code/index.js.map +7 -1
  5. package/build/default-formats.js +52 -24
  6. package/build/default-formats.js.map +7 -1
  7. package/build/image/index.js +185 -153
  8. package/build/image/index.js.map +7 -1
  9. package/build/index.js +28 -18
  10. package/build/index.js.map +7 -1
  11. package/build/italic/index.js +69 -58
  12. package/build/italic/index.js.map +7 -1
  13. package/build/keyboard/index.js +47 -36
  14. package/build/keyboard/index.js.map +7 -1
  15. package/build/language/index.js +145 -113
  16. package/build/language/index.js.map +7 -1
  17. package/build/link/css-classes-setting.js +81 -0
  18. package/build/link/css-classes-setting.js.map +7 -0
  19. package/build/link/index.js +162 -167
  20. package/build/link/index.js.map +7 -1
  21. package/build/link/inline.js +186 -174
  22. package/build/link/inline.js.map +7 -1
  23. package/build/link/use-link-instance-key.js +25 -19
  24. package/build/link/use-link-instance-key.js.map +7 -1
  25. package/build/link/utils.js +66 -115
  26. package/build/link/utils.js.map +7 -1
  27. package/build/lock-unlock.js +31 -15
  28. package/build/lock-unlock.js.map +7 -1
  29. package/build/non-breaking-space/index.js +44 -28
  30. package/build/non-breaking-space/index.js.map +7 -1
  31. package/build/strikethrough/index.js +57 -42
  32. package/build/strikethrough/index.js.map +7 -1
  33. package/build/subscript/index.js +47 -36
  34. package/build/subscript/index.js.map +7 -1
  35. package/build/superscript/index.js +47 -36
  36. package/build/superscript/index.js.map +7 -1
  37. package/build/text-color/index.js +102 -70
  38. package/build/text-color/index.js.map +7 -1
  39. package/build/text-color/inline.js +118 -116
  40. package/build/text-color/inline.js.map +7 -1
  41. package/build/underline/index.js +62 -40
  42. package/build/underline/index.js.map +7 -1
  43. package/build/unknown/index.js +51 -37
  44. package/build/unknown/index.js.map +7 -1
  45. package/build-module/bold/index.js +52 -52
  46. package/build-module/bold/index.js.map +7 -1
  47. package/build-module/code/index.js +41 -46
  48. package/build-module/code/index.js.map +7 -1
  49. package/build-module/default-formats.js +34 -19
  50. package/build-module/default-formats.js.map +7 -1
  51. package/build-module/image/index.js +174 -144
  52. package/build-module/image/index.js.map +7 -1
  53. package/build-module/index.js +6 -14
  54. package/build-module/index.js.map +7 -1
  55. package/build-module/italic/index.js +52 -52
  56. package/build-module/italic/index.js.map +7 -1
  57. package/build-module/keyboard/index.js +25 -30
  58. package/build-module/keyboard/index.js.map +7 -1
  59. package/build-module/language/index.js +128 -105
  60. package/build-module/language/index.js.map +7 -1
  61. package/build-module/link/css-classes-setting.js +67 -0
  62. package/build-module/link/css-classes-setting.js.map +7 -0
  63. package/build-module/link/index.js +128 -146
  64. package/build-module/link/index.js.map +7 -1
  65. package/build-module/link/inline.js +158 -154
  66. package/build-module/link/inline.js.map +7 -1
  67. package/build-module/link/use-link-instance-key.js +7 -14
  68. package/build-module/link/use-link-instance-key.js.map +7 -1
  69. package/build-module/link/utils.js +46 -101
  70. package/build-module/link/utils.js.map +7 -1
  71. package/build-module/lock-unlock.js +8 -7
  72. package/build-module/lock-unlock.js.map +7 -1
  73. package/build-module/non-breaking-space/index.js +22 -22
  74. package/build-module/non-breaking-space/index.js.map +7 -1
  75. package/build-module/strikethrough/index.js +38 -36
  76. package/build-module/strikethrough/index.js.map +7 -1
  77. package/build-module/subscript/index.js +25 -30
  78. package/build-module/subscript/index.js.map +7 -1
  79. package/build-module/superscript/index.js +25 -30
  80. package/build-module/superscript/index.js.map +7 -1
  81. package/build-module/text-color/index.js +72 -61
  82. package/build-module/text-color/index.js.map +7 -1
  83. package/build-module/text-color/inline.js +107 -106
  84. package/build-module/text-color/inline.js.map +7 -1
  85. package/build-module/underline/index.js +43 -34
  86. package/build-module/underline/index.js.map +7 -1
  87. package/build-module/unknown/index.js +26 -28
  88. package/build-module/unknown/index.js.map +7 -1
  89. package/build-style/style-rtl.css +0 -194
  90. package/build-style/style.css +0 -194
  91. package/package.json +21 -15
  92. package/src/image/style.scss +3 -0
  93. package/src/link/css-classes-setting.js +89 -0
  94. package/src/link/index.js +1 -0
  95. package/src/link/inline.js +19 -0
  96. package/src/link/style.scss +3 -0
  97. package/src/link/test/css-classes-setting.js +144 -0
  98. package/src/link/utils.js +8 -0
  99. package/src/style.scss +4 -4
  100. package/src/text-color/style.scss +2 -0
  101. package/build/default-formats.native.js +0 -16
  102. package/build/default-formats.native.js.map +0 -1
  103. package/build/link/index.native.js +0 -174
  104. package/build/link/index.native.js.map +0 -1
  105. package/build/link/modal-screens/link-picker-screen.native.js +0 -67
  106. package/build/link/modal-screens/link-picker-screen.native.js.map +0 -1
  107. package/build/link/modal-screens/link-settings-screen.native.js +0 -226
  108. package/build/link/modal-screens/link-settings-screen.native.js.map +0 -1
  109. package/build/link/modal-screens/screens.native.js +0 -11
  110. package/build/link/modal-screens/screens.native.js.map +0 -1
  111. package/build/link/modal.native.js +0 -53
  112. package/build/link/modal.native.js.map +0 -1
  113. package/build/text-color/index.native.js +0 -134
  114. package/build/text-color/index.native.js.map +0 -1
  115. package/build/text-color/inline.native.js +0 -150
  116. package/build/text-color/inline.native.js.map +0 -1
  117. package/build-module/default-formats.native.js +0 -10
  118. package/build-module/default-formats.native.js.map +0 -1
  119. package/build-module/link/index.native.js +0 -166
  120. package/build-module/link/index.native.js.map +0 -1
  121. package/build-module/link/modal-screens/link-picker-screen.native.js +0 -59
  122. package/build-module/link/modal-screens/link-picker-screen.native.js.map +0 -1
  123. package/build-module/link/modal-screens/link-settings-screen.native.js +0 -218
  124. package/build-module/link/modal-screens/link-settings-screen.native.js.map +0 -1
  125. package/build-module/link/modal-screens/screens.native.js +0 -5
  126. package/build-module/link/modal-screens/screens.native.js.map +0 -1
  127. package/build-module/link/modal.native.js +0 -45
  128. package/build-module/link/modal.native.js.map +0 -1
  129. package/build-module/text-color/index.native.js +0 -126
  130. package/build-module/text-color/index.native.js.map +0 -1
  131. package/build-module/text-color/inline.native.js +0 -142
  132. package/build-module/text-color/inline.native.js.map +0 -1
@@ -1,35 +1,50 @@
1
- "use strict";
2
-
3
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
- Object.defineProperty(exports, "__esModule", {
5
- value: true
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name2 in all)
9
+ __defProp(target, name2, { get: all[name2], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var link_exports = {};
29
+ __export(link_exports, {
30
+ link: () => link
6
31
  });
7
- exports.link = void 0;
8
- var _i18n = require("@wordpress/i18n");
9
- var _element = require("@wordpress/element");
10
- var _richText = require("@wordpress/rich-text");
11
- var _url = require("@wordpress/url");
12
- var _blockEditor = require("@wordpress/block-editor");
13
- var _htmlEntities = require("@wordpress/html-entities");
14
- var _icons = require("@wordpress/icons");
15
- var _a11y = require("@wordpress/a11y");
16
- var _inline = _interopRequireDefault(require("./inline"));
17
- var _utils = require("./utils");
18
- var _lockUnlock = require("../lock-unlock");
19
- var _jsxRuntime = require("react/jsx-runtime");
20
- /**
21
- * WordPress dependencies
22
- */
23
-
24
- /**
25
- * Internal dependencies
26
- */
27
-
28
- const {
29
- essentialFormatKey
30
- } = (0, _lockUnlock.unlock)(_blockEditor.privateApis);
31
- const name = 'core/link';
32
- const title = (0, _i18n.__)('Link');
32
+ module.exports = __toCommonJS(link_exports);
33
+ var import_jsx_runtime = require("react/jsx-runtime");
34
+ var import_i18n = require("@wordpress/i18n");
35
+ var import_element = require("@wordpress/element");
36
+ var import_rich_text = require("@wordpress/rich-text");
37
+ var import_url = require("@wordpress/url");
38
+ var import_block_editor = require("@wordpress/block-editor");
39
+ var import_html_entities = require("@wordpress/html-entities");
40
+ var import_icons = require("@wordpress/icons");
41
+ var import_a11y = require("@wordpress/a11y");
42
+ var import_inline = __toESM(require("./inline"));
43
+ var import_utils = require("./utils");
44
+ var import_lock_unlock = require("../lock-unlock");
45
+ const { essentialFormatKey } = (0, import_lock_unlock.unlock)(import_block_editor.privateApis);
46
+ const name = "core/link";
47
+ const title = (0, import_i18n.__)("Link");
33
48
  function Edit({
34
49
  isActive,
35
50
  activeAttributes,
@@ -38,200 +53,180 @@ function Edit({
38
53
  onFocus,
39
54
  contentRef
40
55
  }) {
41
- const [addingLink, setAddingLink] = (0, _element.useState)(false);
42
-
43
- // We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.
44
- const [openedBy, setOpenedBy] = (0, _element.useState)(null);
45
- (0, _element.useEffect)(() => {
46
- // When the link becomes inactive (i.e. isActive is false), reset the editingLink state
47
- // and the creatingLink state. This means that if the Link UI is displayed and the link
48
- // becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.
56
+ const [addingLink, setAddingLink] = (0, import_element.useState)(false);
57
+ const [openedBy, setOpenedBy] = (0, import_element.useState)(null);
58
+ (0, import_element.useEffect)(() => {
49
59
  if (!isActive) {
50
60
  setAddingLink(false);
51
61
  }
52
62
  }, [isActive]);
53
- (0, _element.useLayoutEffect)(() => {
63
+ (0, import_element.useLayoutEffect)(() => {
54
64
  const editableContentElement = contentRef.current;
55
65
  if (!editableContentElement) {
56
66
  return;
57
67
  }
58
68
  function handleClick(event) {
59
- // There is a situation whereby there is an existing link in the rich text
60
- // and the user clicks on the leftmost edge of that link and fails to activate
61
- // the link format, but the click event still fires on the `<a>` element.
62
- // This causes the `editingLink` state to be set to `true` and the link UI
63
- // to be rendered in "creating" mode. We need to check isActive to see if
64
- // we have an active link format.
65
- const link = event.target.closest('[contenteditable] a');
66
- if (!link ||
67
- // other formats (e.g. bold) may be nested within the link.
69
+ const link2 = event.target.closest("[contenteditable] a");
70
+ if (!link2 || // other formats (e.g. bold) may be nested within the link.
68
71
  !isActive) {
69
72
  return;
70
73
  }
71
74
  setAddingLink(true);
72
75
  setOpenedBy({
73
- el: link,
74
- action: 'click'
76
+ el: link2,
77
+ action: "click"
75
78
  });
76
79
  }
77
- editableContentElement.addEventListener('click', handleClick);
80
+ editableContentElement.addEventListener("click", handleClick);
78
81
  return () => {
79
- editableContentElement.removeEventListener('click', handleClick);
82
+ editableContentElement.removeEventListener("click", handleClick);
80
83
  };
81
84
  }, [contentRef, isActive]);
82
85
  function addLink(target) {
83
- const text = (0, _richText.getTextContent)((0, _richText.slice)(value));
84
- if (!isActive && text && (0, _url.isURL)(text) && (0, _utils.isValidHref)(text)) {
85
- onChange((0, _richText.applyFormat)(value, {
86
- type: name,
87
- attributes: {
88
- url: text
89
- }
90
- }));
91
- } else if (!isActive && text && (0, _url.isEmail)(text)) {
92
- onChange((0, _richText.applyFormat)(value, {
93
- type: name,
94
- attributes: {
95
- url: `mailto:${text}`
96
- }
97
- }));
98
- } else if (!isActive && text && (0, _url.isPhoneNumber)(text)) {
99
- onChange((0, _richText.applyFormat)(value, {
100
- type: name,
101
- attributes: {
102
- url: `tel:${text.replace(/\D/g, '')}`
103
- }
104
- }));
86
+ const text = (0, import_rich_text.getTextContent)((0, import_rich_text.slice)(value));
87
+ if (!isActive && text && (0, import_url.isURL)(text) && (0, import_utils.isValidHref)(text)) {
88
+ onChange(
89
+ (0, import_rich_text.applyFormat)(value, {
90
+ type: name,
91
+ attributes: { url: text }
92
+ })
93
+ );
94
+ } else if (!isActive && text && (0, import_url.isEmail)(text)) {
95
+ onChange(
96
+ (0, import_rich_text.applyFormat)(value, {
97
+ type: name,
98
+ attributes: { url: `mailto:${text}` }
99
+ })
100
+ );
101
+ } else if (!isActive && text && (0, import_url.isPhoneNumber)(text)) {
102
+ onChange(
103
+ (0, import_rich_text.applyFormat)(value, {
104
+ type: name,
105
+ attributes: { url: `tel:${text.replace(/\D/g, "")}` }
106
+ })
107
+ );
105
108
  } else {
106
109
  if (target) {
107
110
  setOpenedBy({
108
111
  el: target,
109
- action: null // We don't need to distinguish between click or keyboard here
112
+ action: null
113
+ // We don't need to distinguish between click or keyboard here
110
114
  });
111
115
  }
112
116
  setAddingLink(true);
113
117
  }
114
118
  }
115
-
116
- /**
117
- * Runs when the popover is closed via escape keypress, unlinking the selected text,
118
- * but _not_ on a click outside the popover. onFocusOutside handles that.
119
- */
120
119
  function stopAddingLink() {
121
- // Don't let the click handler on the toolbar button trigger again.
122
-
123
- // There are two places for us to return focus to on Escape keypress:
124
- // 1. The rich text field.
125
- // 2. The toolbar button.
126
-
127
- // The toolbar button is the only one we need to handle returning focus to.
128
- // Otherwise, we rely on the passed in onFocus to return focus to the rich text field.
129
-
130
- // Close the popover
131
120
  setAddingLink(false);
132
-
133
- // Return focus to the toolbar button or the rich text field
134
- if (openedBy?.el?.tagName === 'BUTTON') {
121
+ if (openedBy?.el?.tagName === "BUTTON") {
135
122
  openedBy.el.focus();
136
123
  } else {
137
124
  onFocus();
138
125
  }
139
- // Remove the openedBy state
140
126
  setOpenedBy(null);
141
127
  }
142
-
143
- // Test for this:
144
- // 1. Click on the link button
145
- // 2. Click the Options button in the top right of header
146
- // 3. Focus should be in the dropdown of the Options button
147
- // 4. Press Escape
148
- // 5. Focus should be on the Options button
149
128
  function onFocusOutside() {
150
129
  setAddingLink(false);
151
130
  setOpenedBy(null);
152
131
  }
153
132
  function onRemoveFormat() {
154
- onChange((0, _richText.removeFormat)(value, name));
155
- (0, _a11y.speak)((0, _i18n.__)('Link removed.'), 'assertive');
133
+ onChange((0, import_rich_text.removeFormat)(value, name));
134
+ (0, import_a11y.speak)((0, import_i18n.__)("Link removed."), "assertive");
156
135
  }
157
-
158
- // Only autofocus if we have clicked a link within the editor
159
- const shouldAutoFocus = !(openedBy?.el?.tagName === 'A' && openedBy?.action === 'click');
160
- const hasSelection = !(0, _richText.isCollapsed)(value);
161
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
162
- children: [hasSelection && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.RichTextShortcut, {
163
- type: "primary",
164
- character: "k",
165
- onUse: addLink
166
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.RichTextShortcut, {
167
- type: "primaryShift",
168
- character: "k",
169
- onUse: onRemoveFormat
170
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockEditor.RichTextToolbarButton, {
171
- name: "link",
172
- icon: _icons.link,
173
- title: isActive ? (0, _i18n.__)('Link') : title,
174
- onClick: event => {
175
- addLink(event.currentTarget);
176
- },
177
- isActive: isActive || addingLink,
178
- shortcutType: "primary",
179
- shortcutCharacter: "k",
180
- "aria-haspopup": "true",
181
- "aria-expanded": addingLink
182
- }), addingLink && /*#__PURE__*/(0, _jsxRuntime.jsx)(_inline.default, {
183
- stopAddingLink: stopAddingLink,
184
- onFocusOutside: onFocusOutside,
185
- isActive: isActive,
186
- activeAttributes: activeAttributes,
187
- value: value,
188
- onChange: onChange,
189
- contentRef: contentRef,
190
- focusOnMount: shouldAutoFocus ? 'firstElement' : false
191
- })]
192
- });
136
+ const shouldAutoFocus = !(openedBy?.el?.tagName === "A" && openedBy?.action === "click");
137
+ const hasSelection = !(0, import_rich_text.isCollapsed)(value);
138
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
139
+ hasSelection && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
+ import_block_editor.RichTextShortcut,
141
+ {
142
+ type: "primary",
143
+ character: "k",
144
+ onUse: addLink
145
+ }
146
+ ),
147
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
148
+ import_block_editor.RichTextShortcut,
149
+ {
150
+ type: "primaryShift",
151
+ character: "k",
152
+ onUse: onRemoveFormat
153
+ }
154
+ ),
155
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
156
+ import_block_editor.RichTextToolbarButton,
157
+ {
158
+ name: "link",
159
+ icon: import_icons.link,
160
+ title: isActive ? (0, import_i18n.__)("Link") : title,
161
+ onClick: (event) => {
162
+ addLink(event.currentTarget);
163
+ },
164
+ isActive: isActive || addingLink,
165
+ shortcutType: "primary",
166
+ shortcutCharacter: "k",
167
+ "aria-haspopup": "true",
168
+ "aria-expanded": addingLink
169
+ }
170
+ ),
171
+ addingLink && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
172
+ import_inline.default,
173
+ {
174
+ stopAddingLink,
175
+ onFocusOutside,
176
+ isActive,
177
+ activeAttributes,
178
+ value,
179
+ onChange,
180
+ contentRef,
181
+ focusOnMount: shouldAutoFocus ? "firstElement" : false
182
+ }
183
+ )
184
+ ] });
193
185
  }
194
- const link = exports.link = {
186
+ const link = {
195
187
  name,
196
188
  title,
197
- tagName: 'a',
189
+ tagName: "a",
198
190
  className: null,
199
191
  attributes: {
200
- url: 'href',
201
- type: 'data-type',
202
- id: 'data-id',
203
- _id: 'id',
204
- target: 'target',
205
- rel: 'rel'
192
+ url: "href",
193
+ type: "data-type",
194
+ id: "data-id",
195
+ _id: "id",
196
+ target: "target",
197
+ rel: "rel",
198
+ class: "class"
206
199
  },
207
200
  [essentialFormatKey]: true,
208
- __unstablePasteRule(value, {
209
- html,
210
- plainText
211
- }) {
212
- const pastedText = (html || plainText).replace(/<[^>]+>/g, '').trim();
213
-
214
- // A URL was pasted, turn the selection into a link.
215
- // For the link pasting feature, allow only http(s) protocols.
216
- if (!(0, _url.isURL)(pastedText) || !/^https?:/.test(pastedText)) {
201
+ __unstablePasteRule(value, { html, plainText }) {
202
+ const pastedText = (html || plainText).replace(/<[^>]+>/g, "").trim();
203
+ if (!(0, import_url.isURL)(pastedText) || !/^https?:/.test(pastedText)) {
217
204
  return value;
218
205
  }
219
-
220
- // Allows us to ask for this information when we get a report.
221
- window.console.log('Created link:\n\n', pastedText);
206
+ window.console.log("Created link:\n\n", pastedText);
222
207
  const format = {
223
208
  type: name,
224
209
  attributes: {
225
- url: (0, _htmlEntities.decodeEntities)(pastedText)
210
+ url: (0, import_html_entities.decodeEntities)(pastedText)
226
211
  }
227
212
  };
228
- if ((0, _richText.isCollapsed)(value)) {
229
- return (0, _richText.insert)(value, (0, _richText.applyFormat)((0, _richText.create)({
230
- text: plainText
231
- }), format, 0, plainText.length));
213
+ if ((0, import_rich_text.isCollapsed)(value)) {
214
+ return (0, import_rich_text.insert)(
215
+ value,
216
+ (0, import_rich_text.applyFormat)(
217
+ (0, import_rich_text.create)({ text: plainText }),
218
+ format,
219
+ 0,
220
+ plainText.length
221
+ )
222
+ );
232
223
  }
233
- return (0, _richText.applyFormat)(value, format);
224
+ return (0, import_rich_text.applyFormat)(value, format);
234
225
  },
235
226
  edit: Edit
236
227
  };
237
- //# sourceMappingURL=index.js.map
228
+ // Annotate the CommonJS export names for ESM import in node:
229
+ 0 && (module.exports = {
230
+ link
231
+ });
232
+ //# sourceMappingURL=index.js.map
@@ -1 +1,7 @@
1
- {"version":3,"names":["_i18n","require","_element","_richText","_url","_blockEditor","_htmlEntities","_icons","_a11y","_inline","_interopRequireDefault","_utils","_lockUnlock","_jsxRuntime","essentialFormatKey","unlock","blockEditorPrivateApis","name","title","__","Edit","isActive","activeAttributes","value","onChange","onFocus","contentRef","addingLink","setAddingLink","useState","openedBy","setOpenedBy","useEffect","useLayoutEffect","editableContentElement","current","handleClick","event","link","target","closest","el","action","addEventListener","removeEventListener","addLink","text","getTextContent","slice","isURL","isValidHref","applyFormat","type","attributes","url","isEmail","isPhoneNumber","replace","stopAddingLink","tagName","focus","onFocusOutside","onRemoveFormat","removeFormat","speak","shouldAutoFocus","hasSelection","isCollapsed","jsxs","Fragment","children","jsx","RichTextShortcut","character","onUse","RichTextToolbarButton","icon","linkIcon","onClick","currentTarget","shortcutType","shortcutCharacter","default","focusOnMount","exports","className","id","_id","rel","__unstablePasteRule","html","plainText","pastedText","trim","test","window","console","log","format","decodeEntities","insert","create","length","edit"],"sources":["@wordpress/format-library/src/link/index.js"],"sourcesContent":["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect, useEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail, isPhoneNumber } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n\tprivateApis as blockEditorPrivateApis,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\nimport { unlock } from '../lock-unlock';\n\nconst { essentialFormatKey } = unlock( blockEditorPrivateApis );\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ addingLink, setAddingLink ] = useState( false );\n\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\tuseEffect( () => {\n\t\t// When the link becomes inactive (i.e. isActive is false), reset the editingLink state\n\t\t// and the creatingLink state. This means that if the Link UI is displayed and the link\n\t\t// becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.\n\t\tif ( ! isActive ) {\n\t\t\tsetAddingLink( false );\n\t\t}\n\t}, [ isActive ] );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `editingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tconst link = event.target.closest( '[contenteditable] a' );\n\t\t\tif (\n\t\t\t\t! link || // other formats (e.g. bold) may be nested within the link.\n\t\t\t\t! isActive\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetAddingLink( true );\n\t\t\tsetOpenedBy( {\n\t\t\t\tel: link,\n\t\t\t\taction: 'click',\n\t\t\t} );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isPhoneNumber( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `tel:${ text.replace( /\\D/g, '' ) }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( {\n\t\t\t\t\tel: target,\n\t\t\t\t\taction: null, // We don't need to distinguish between click or keyboard here\n\t\t\t\t} );\n\t\t\t}\n\t\t\tsetAddingLink( true );\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetAddingLink( false );\n\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.el?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.el.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetAddingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\t// Only autofocus if we have clicked a link within the editor\n\tconst shouldAutoFocus = ! (\n\t\topenedBy?.el?.tagName === 'A' && openedBy?.action === 'click'\n\t);\n\n\tconst hasSelection = ! isCollapsed( value );\n\n\treturn (\n\t\t<>\n\t\t\t{ hasSelection && (\n\t\t\t\t<RichTextShortcut\n\t\t\t\t\ttype=\"primary\"\n\t\t\t\t\tcharacter=\"k\"\n\t\t\t\t\tonUse={ addLink }\n\t\t\t\t/>\n\t\t\t) }\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || addingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ addingLink }\n\t\t\t/>\n\t\t\t{ addingLink && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t\tfocusOnMount={ shouldAutoFocus ? 'firstElement' : false }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t},\n\t[ essentialFormatKey ]: true,\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/link/index.js"],
4
+ "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { useState, useLayoutEffect, useEffect } from '@wordpress/element';\nimport {\n\tgetTextContent,\n\tapplyFormat,\n\tremoveFormat,\n\tslice,\n\tisCollapsed,\n\tinsert,\n\tcreate,\n} from '@wordpress/rich-text';\nimport { isURL, isEmail, isPhoneNumber } from '@wordpress/url';\nimport {\n\tRichTextToolbarButton,\n\tRichTextShortcut,\n\tprivateApis as blockEditorPrivateApis,\n} from '@wordpress/block-editor';\nimport { decodeEntities } from '@wordpress/html-entities';\nimport { link as linkIcon } from '@wordpress/icons';\nimport { speak } from '@wordpress/a11y';\n\n/**\n * Internal dependencies\n */\nimport InlineLinkUI from './inline';\nimport { isValidHref } from './utils';\nimport { unlock } from '../lock-unlock';\n\nconst { essentialFormatKey } = unlock( blockEditorPrivateApis );\n\nconst name = 'core/link';\nconst title = __( 'Link' );\n\nfunction Edit( {\n\tisActive,\n\tactiveAttributes,\n\tvalue,\n\tonChange,\n\tonFocus,\n\tcontentRef,\n} ) {\n\tconst [ addingLink, setAddingLink ] = useState( false );\n\n\t// We only need to store the button element that opened the popover. We can ignore the other states, as they will be handled by the onFocus prop to return to the rich text field.\n\tconst [ openedBy, setOpenedBy ] = useState( null );\n\n\tuseEffect( () => {\n\t\t// When the link becomes inactive (i.e. isActive is false), reset the editingLink state\n\t\t// and the creatingLink state. This means that if the Link UI is displayed and the link\n\t\t// becomes inactive (e.g. used arrow keys to move cursor outside of link bounds), the UI will close.\n\t\tif ( ! isActive ) {\n\t\t\tsetAddingLink( false );\n\t\t}\n\t}, [ isActive ] );\n\n\tuseLayoutEffect( () => {\n\t\tconst editableContentElement = contentRef.current;\n\t\tif ( ! editableContentElement ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfunction handleClick( event ) {\n\t\t\t// There is a situation whereby there is an existing link in the rich text\n\t\t\t// and the user clicks on the leftmost edge of that link and fails to activate\n\t\t\t// the link format, but the click event still fires on the `<a>` element.\n\t\t\t// This causes the `editingLink` state to be set to `true` and the link UI\n\t\t\t// to be rendered in \"creating\" mode. We need to check isActive to see if\n\t\t\t// we have an active link format.\n\t\t\tconst link = event.target.closest( '[contenteditable] a' );\n\t\t\tif (\n\t\t\t\t! link || // other formats (e.g. bold) may be nested within the link.\n\t\t\t\t! isActive\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tsetAddingLink( true );\n\t\t\tsetOpenedBy( {\n\t\t\t\tel: link,\n\t\t\t\taction: 'click',\n\t\t\t} );\n\t\t}\n\n\t\teditableContentElement.addEventListener( 'click', handleClick );\n\n\t\treturn () => {\n\t\t\teditableContentElement.removeEventListener( 'click', handleClick );\n\t\t};\n\t}, [ contentRef, isActive ] );\n\n\tfunction addLink( target ) {\n\t\tconst text = getTextContent( slice( value ) );\n\n\t\tif ( ! isActive && text && isURL( text ) && isValidHref( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: text },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isEmail( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `mailto:${ text }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else if ( ! isActive && text && isPhoneNumber( text ) ) {\n\t\t\tonChange(\n\t\t\t\tapplyFormat( value, {\n\t\t\t\t\ttype: name,\n\t\t\t\t\tattributes: { url: `tel:${ text.replace( /\\D/g, '' ) }` },\n\t\t\t\t} )\n\t\t\t);\n\t\t} else {\n\t\t\tif ( target ) {\n\t\t\t\tsetOpenedBy( {\n\t\t\t\t\tel: target,\n\t\t\t\t\taction: null, // We don't need to distinguish between click or keyboard here\n\t\t\t\t} );\n\t\t\t}\n\t\t\tsetAddingLink( true );\n\t\t}\n\t}\n\n\t/**\n\t * Runs when the popover is closed via escape keypress, unlinking the selected text,\n\t * but _not_ on a click outside the popover. onFocusOutside handles that.\n\t */\n\tfunction stopAddingLink() {\n\t\t// Don't let the click handler on the toolbar button trigger again.\n\n\t\t// There are two places for us to return focus to on Escape keypress:\n\t\t// 1. The rich text field.\n\t\t// 2. The toolbar button.\n\n\t\t// The toolbar button is the only one we need to handle returning focus to.\n\t\t// Otherwise, we rely on the passed in onFocus to return focus to the rich text field.\n\n\t\t// Close the popover\n\t\tsetAddingLink( false );\n\n\t\t// Return focus to the toolbar button or the rich text field\n\t\tif ( openedBy?.el?.tagName === 'BUTTON' ) {\n\t\t\topenedBy.el.focus();\n\t\t} else {\n\t\t\tonFocus();\n\t\t}\n\t\t// Remove the openedBy state\n\t\tsetOpenedBy( null );\n\t}\n\n\t// Test for this:\n\t// 1. Click on the link button\n\t// 2. Click the Options button in the top right of header\n\t// 3. Focus should be in the dropdown of the Options button\n\t// 4. Press Escape\n\t// 5. Focus should be on the Options button\n\tfunction onFocusOutside() {\n\t\tsetAddingLink( false );\n\t\tsetOpenedBy( null );\n\t}\n\n\tfunction onRemoveFormat() {\n\t\tonChange( removeFormat( value, name ) );\n\t\tspeak( __( 'Link removed.' ), 'assertive' );\n\t}\n\n\t// Only autofocus if we have clicked a link within the editor\n\tconst shouldAutoFocus = ! (\n\t\topenedBy?.el?.tagName === 'A' && openedBy?.action === 'click'\n\t);\n\n\tconst hasSelection = ! isCollapsed( value );\n\n\treturn (\n\t\t<>\n\t\t\t{ hasSelection && (\n\t\t\t\t<RichTextShortcut\n\t\t\t\t\ttype=\"primary\"\n\t\t\t\t\tcharacter=\"k\"\n\t\t\t\t\tonUse={ addLink }\n\t\t\t\t/>\n\t\t\t) }\n\t\t\t<RichTextShortcut\n\t\t\t\ttype=\"primaryShift\"\n\t\t\t\tcharacter=\"k\"\n\t\t\t\tonUse={ onRemoveFormat }\n\t\t\t/>\n\t\t\t<RichTextToolbarButton\n\t\t\t\tname=\"link\"\n\t\t\t\ticon={ linkIcon }\n\t\t\t\ttitle={ isActive ? __( 'Link' ) : title }\n\t\t\t\tonClick={ ( event ) => {\n\t\t\t\t\taddLink( event.currentTarget );\n\t\t\t\t} }\n\t\t\t\tisActive={ isActive || addingLink }\n\t\t\t\tshortcutType=\"primary\"\n\t\t\t\tshortcutCharacter=\"k\"\n\t\t\t\taria-haspopup=\"true\"\n\t\t\t\taria-expanded={ addingLink }\n\t\t\t/>\n\t\t\t{ addingLink && (\n\t\t\t\t<InlineLinkUI\n\t\t\t\t\tstopAddingLink={ stopAddingLink }\n\t\t\t\t\tonFocusOutside={ onFocusOutside }\n\t\t\t\t\tisActive={ isActive }\n\t\t\t\t\tactiveAttributes={ activeAttributes }\n\t\t\t\t\tvalue={ value }\n\t\t\t\t\tonChange={ onChange }\n\t\t\t\t\tcontentRef={ contentRef }\n\t\t\t\t\tfocusOnMount={ shouldAutoFocus ? 'firstElement' : false }\n\t\t\t\t/>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport const link = {\n\tname,\n\ttitle,\n\ttagName: 'a',\n\tclassName: null,\n\tattributes: {\n\t\turl: 'href',\n\t\ttype: 'data-type',\n\t\tid: 'data-id',\n\t\t_id: 'id',\n\t\ttarget: 'target',\n\t\trel: 'rel',\n\t\tclass: 'class',\n\t},\n\t[ essentialFormatKey ]: true,\n\t__unstablePasteRule( value, { html, plainText } ) {\n\t\tconst pastedText = ( html || plainText )\n\t\t\t.replace( /<[^>]+>/g, '' )\n\t\t\t.trim();\n\n\t\t// A URL was pasted, turn the selection into a link.\n\t\t// For the link pasting feature, allow only http(s) protocols.\n\t\tif ( ! isURL( pastedText ) || ! /^https?:/.test( pastedText ) ) {\n\t\t\treturn value;\n\t\t}\n\n\t\t// Allows us to ask for this information when we get a report.\n\t\twindow.console.log( 'Created link:\\n\\n', pastedText );\n\n\t\tconst format = {\n\t\t\ttype: name,\n\t\t\tattributes: {\n\t\t\t\turl: decodeEntities( pastedText ),\n\t\t\t},\n\t\t};\n\n\t\tif ( isCollapsed( value ) ) {\n\t\t\treturn insert(\n\t\t\t\tvalue,\n\t\t\t\tapplyFormat(\n\t\t\t\t\tcreate( { text: plainText } ),\n\t\t\t\t\tformat,\n\t\t\t\t\t0,\n\t\t\t\t\tplainText.length\n\t\t\t\t)\n\t\t\t);\n\t\t}\n\n\t\treturn applyFormat( value, format );\n\t},\n\tedit: Edit,\n};\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAmLE;AAhLF,kBAAmB;AACnB,qBAAqD;AACrD,uBAQO;AACP,iBAA8C;AAC9C,0BAIO;AACP,2BAA+B;AAC/B,mBAAiC;AACjC,kBAAsB;AAKtB,oBAAyB;AACzB,mBAA4B;AAC5B,yBAAuB;AAEvB,MAAM,EAAE,mBAAmB,QAAI,2BAAQ,oBAAAA,WAAuB;AAE9D,MAAM,OAAO;AACb,MAAM,YAAQ,gBAAI,MAAO;AAEzB,SAAS,KAAM;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACD,GAAI;AACH,QAAM,CAAE,YAAY,aAAc,QAAI,yBAAU,KAAM;AAGtD,QAAM,CAAE,UAAU,WAAY,QAAI,yBAAU,IAAK;AAEjD,gCAAW,MAAM;AAIhB,QAAK,CAAE,UAAW;AACjB,oBAAe,KAAM;AAAA,IACtB;AAAA,EACD,GAAG,CAAE,QAAS,CAAE;AAEhB,sCAAiB,MAAM;AACtB,UAAM,yBAAyB,WAAW;AAC1C,QAAK,CAAE,wBAAyB;AAC/B;AAAA,IACD;AAEA,aAAS,YAAa,OAAQ;AAO7B,YAAMC,QAAO,MAAM,OAAO,QAAS,qBAAsB;AACzD,UACC,CAAEA;AAAA,MACF,CAAE,UACD;AACD;AAAA,MACD;AAEA,oBAAe,IAAK;AACpB,kBAAa;AAAA,QACZ,IAAIA;AAAA,QACJ,QAAQ;AAAA,MACT,CAAE;AAAA,IACH;AAEA,2BAAuB,iBAAkB,SAAS,WAAY;AAE9D,WAAO,MAAM;AACZ,6BAAuB,oBAAqB,SAAS,WAAY;AAAA,IAClE;AAAA,EACD,GAAG,CAAE,YAAY,QAAS,CAAE;AAE5B,WAAS,QAAS,QAAS;AAC1B,UAAM,WAAO,qCAAgB,wBAAO,KAAM,CAAE;AAE5C,QAAK,CAAE,YAAY,YAAQ,kBAAO,IAAK,SAAK,0BAAa,IAAK,GAAI;AACjE;AAAA,YACC,8BAAa,OAAO;AAAA,UACnB,MAAM;AAAA,UACN,YAAY,EAAE,KAAK,KAAK;AAAA,QACzB,CAAE;AAAA,MACH;AAAA,IACD,WAAY,CAAE,YAAY,YAAQ,oBAAS,IAAK,GAAI;AACnD;AAAA,YACC,8BAAa,OAAO;AAAA,UACnB,MAAM;AAAA,UACN,YAAY,EAAE,KAAK,UAAW,IAAK,GAAG;AAAA,QACvC,CAAE;AAAA,MACH;AAAA,IACD,WAAY,CAAE,YAAY,YAAQ,0BAAe,IAAK,GAAI;AACzD;AAAA,YACC,8BAAa,OAAO;AAAA,UACnB,MAAM;AAAA,UACN,YAAY,EAAE,KAAK,OAAQ,KAAK,QAAS,OAAO,EAAG,CAAE,GAAG;AAAA,QACzD,CAAE;AAAA,MACH;AAAA,IACD,OAAO;AACN,UAAK,QAAS;AACb,oBAAa;AAAA,UACZ,IAAI;AAAA,UACJ,QAAQ;AAAA;AAAA,QACT,CAAE;AAAA,MACH;AACA,oBAAe,IAAK;AAAA,IACrB;AAAA,EACD;AAMA,WAAS,iBAAiB;AAWzB,kBAAe,KAAM;AAGrB,QAAK,UAAU,IAAI,YAAY,UAAW;AACzC,eAAS,GAAG,MAAM;AAAA,IACnB,OAAO;AACN,cAAQ;AAAA,IACT;AAEA,gBAAa,IAAK;AAAA,EACnB;AAQA,WAAS,iBAAiB;AACzB,kBAAe,KAAM;AACrB,gBAAa,IAAK;AAAA,EACnB;AAEA,WAAS,iBAAiB;AACzB,iBAAU,+BAAc,OAAO,IAAK,CAAE;AACtC,+BAAO,gBAAI,eAAgB,GAAG,WAAY;AAAA,EAC3C;AAGA,QAAM,kBAAkB,EACvB,UAAU,IAAI,YAAY,OAAO,UAAU,WAAW;AAGvD,QAAM,eAAe,KAAE,8BAAa,KAAM;AAE1C,SACC,4EACG;AAAA,oBACD;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAQ;AAAA;AAAA,IACT;AAAA,IAED;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,WAAU;AAAA,QACV,OAAQ;AAAA;AAAA,IACT;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACA,MAAK;AAAA,QACL,MAAO,aAAAC;AAAA,QACP,OAAQ,eAAW,gBAAI,MAAO,IAAI;AAAA,QAClC,SAAU,CAAE,UAAW;AACtB,kBAAS,MAAM,aAAc;AAAA,QAC9B;AAAA,QACA,UAAW,YAAY;AAAA,QACvB,cAAa;AAAA,QACb,mBAAkB;AAAA,QAClB,iBAAc;AAAA,QACd,iBAAgB;AAAA;AAAA,IACjB;AAAA,IACE,cACD;AAAA,MAAC,cAAAC;AAAA,MAAA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAe,kBAAkB,iBAAiB;AAAA;AAAA,IACnD;AAAA,KAEF;AAEF;AAEO,MAAM,OAAO;AAAA,EACnB;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,IACX,KAAK;AAAA,IACL,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,OAAO;AAAA,EACR;AAAA,EACA,CAAE,kBAAmB,GAAG;AAAA,EACxB,oBAAqB,OAAO,EAAE,MAAM,UAAU,GAAI;AACjD,UAAM,cAAe,QAAQ,WAC3B,QAAS,YAAY,EAAG,EACxB,KAAK;AAIP,QAAK,KAAE,kBAAO,UAAW,KAAK,CAAE,WAAW,KAAM,UAAW,GAAI;AAC/D,aAAO;AAAA,IACR;AAGA,WAAO,QAAQ,IAAK,qBAAqB,UAAW;AAEpD,UAAM,SAAS;AAAA,MACd,MAAM;AAAA,MACN,YAAY;AAAA,QACX,SAAK,qCAAgB,UAAW;AAAA,MACjC;AAAA,IACD;AAEA,YAAK,8BAAa,KAAM,GAAI;AAC3B,iBAAO;AAAA,QACN;AAAA,YACA;AAAA,cACC,yBAAQ,EAAE,MAAM,UAAU,CAAE;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,UAAU;AAAA,QACX;AAAA,MACD;AAAA,IACD;AAEA,eAAO,8BAAa,OAAO,MAAO;AAAA,EACnC;AAAA,EACA,MAAM;AACP;",
6
+ "names": ["blockEditorPrivateApis", "link", "linkIcon", "InlineLinkUI"]
7
+ }