@liveblocks/react-ui 1.12.0-initial1
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.
- package/README.md +65 -0
- package/dist/components/Comment.js +473 -0
- package/dist/components/Comment.js.map +1 -0
- package/dist/components/Comment.mjs +447 -0
- package/dist/components/Comment.mjs.map +1 -0
- package/dist/components/Composer.js +299 -0
- package/dist/components/Composer.js.map +1 -0
- package/dist/components/Composer.mjs +297 -0
- package/dist/components/Composer.mjs.map +1 -0
- package/dist/components/InboxNotification.js +374 -0
- package/dist/components/InboxNotification.js.map +1 -0
- package/dist/components/InboxNotification.mjs +372 -0
- package/dist/components/InboxNotification.mjs.map +1 -0
- package/dist/components/InboxNotificationList.js +19 -0
- package/dist/components/InboxNotificationList.js.map +1 -0
- package/dist/components/InboxNotificationList.mjs +17 -0
- package/dist/components/InboxNotificationList.mjs.map +1 -0
- package/dist/components/Thread.js +188 -0
- package/dist/components/Thread.js.map +1 -0
- package/dist/components/Thread.mjs +167 -0
- package/dist/components/Thread.mjs.map +1 -0
- package/dist/components/internal/Attribution.js +26 -0
- package/dist/components/internal/Attribution.js.map +1 -0
- package/dist/components/internal/Attribution.mjs +24 -0
- package/dist/components/internal/Attribution.mjs.map +1 -0
- package/dist/components/internal/Avatar.js +40 -0
- package/dist/components/internal/Avatar.js.map +1 -0
- package/dist/components/internal/Avatar.mjs +38 -0
- package/dist/components/internal/Avatar.mjs.map +1 -0
- package/dist/components/internal/Button.js +24 -0
- package/dist/components/internal/Button.js.map +1 -0
- package/dist/components/internal/Button.mjs +22 -0
- package/dist/components/internal/Button.mjs.map +1 -0
- package/dist/components/internal/Dropdown.js +72 -0
- package/dist/components/internal/Dropdown.js.map +1 -0
- package/dist/components/internal/Dropdown.mjs +47 -0
- package/dist/components/internal/Dropdown.mjs.map +1 -0
- package/dist/components/internal/Emoji.js +18 -0
- package/dist/components/internal/Emoji.js.map +1 -0
- package/dist/components/internal/Emoji.mjs +16 -0
- package/dist/components/internal/Emoji.mjs.map +1 -0
- package/dist/components/internal/EmojiPicker.js +186 -0
- package/dist/components/internal/EmojiPicker.js.map +1 -0
- package/dist/components/internal/EmojiPicker.mjs +162 -0
- package/dist/components/internal/EmojiPicker.mjs.map +1 -0
- package/dist/components/internal/Icon.js +28 -0
- package/dist/components/internal/Icon.js.map +1 -0
- package/dist/components/internal/Icon.mjs +24 -0
- package/dist/components/internal/Icon.mjs.map +1 -0
- package/dist/components/internal/InboxNotificationThread.js +116 -0
- package/dist/components/internal/InboxNotificationThread.js.map +1 -0
- package/dist/components/internal/InboxNotificationThread.mjs +112 -0
- package/dist/components/internal/InboxNotificationThread.mjs.map +1 -0
- package/dist/components/internal/List.js +34 -0
- package/dist/components/internal/List.js.map +1 -0
- package/dist/components/internal/List.mjs +32 -0
- package/dist/components/internal/List.mjs.map +1 -0
- package/dist/components/internal/Room.js +22 -0
- package/dist/components/internal/Room.js.map +1 -0
- package/dist/components/internal/Room.mjs +20 -0
- package/dist/components/internal/Room.mjs.map +1 -0
- package/dist/components/internal/Tooltip.js +91 -0
- package/dist/components/internal/Tooltip.js.map +1 -0
- package/dist/components/internal/Tooltip.mjs +65 -0
- package/dist/components/internal/Tooltip.mjs.map +1 -0
- package/dist/components/internal/User.js +41 -0
- package/dist/components/internal/User.js.map +1 -0
- package/dist/components/internal/User.mjs +39 -0
- package/dist/components/internal/User.mjs.map +1 -0
- package/dist/components.js +64 -0
- package/dist/components.js.map +1 -0
- package/dist/components.mjs +41 -0
- package/dist/components.mjs.map +1 -0
- package/dist/config.js +33 -0
- package/dist/config.js.map +1 -0
- package/dist/config.mjs +30 -0
- package/dist/config.mjs.map +1 -0
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -0
- package/dist/constants.mjs +6 -0
- package/dist/constants.mjs.map +1 -0
- package/dist/icons/ArrowDown.js +15 -0
- package/dist/icons/ArrowDown.js.map +1 -0
- package/dist/icons/ArrowDown.mjs +13 -0
- package/dist/icons/ArrowDown.mjs.map +1 -0
- package/dist/icons/Check.js +15 -0
- package/dist/icons/Check.js.map +1 -0
- package/dist/icons/Check.mjs +13 -0
- package/dist/icons/Check.mjs.map +1 -0
- package/dist/icons/Cross.js +17 -0
- package/dist/icons/Cross.js.map +1 -0
- package/dist/icons/Cross.mjs +15 -0
- package/dist/icons/Cross.mjs.map +1 -0
- package/dist/icons/Delete.js +15 -0
- package/dist/icons/Delete.js.map +1 -0
- package/dist/icons/Delete.mjs +13 -0
- package/dist/icons/Delete.mjs.map +1 -0
- package/dist/icons/Edit.js +15 -0
- package/dist/icons/Edit.js.map +1 -0
- package/dist/icons/Edit.mjs +13 -0
- package/dist/icons/Edit.mjs.map +1 -0
- package/dist/icons/Ellipsis.js +26 -0
- package/dist/icons/Ellipsis.js.map +1 -0
- package/dist/icons/Ellipsis.mjs +24 -0
- package/dist/icons/Ellipsis.mjs.map +1 -0
- package/dist/icons/Emoji.js +27 -0
- package/dist/icons/Emoji.js.map +1 -0
- package/dist/icons/Emoji.mjs +25 -0
- package/dist/icons/Emoji.mjs.map +1 -0
- package/dist/icons/EmojiAdd.js +29 -0
- package/dist/icons/EmojiAdd.js.map +1 -0
- package/dist/icons/EmojiAdd.mjs +27 -0
- package/dist/icons/EmojiAdd.mjs.map +1 -0
- package/dist/icons/Mention.js +17 -0
- package/dist/icons/Mention.js.map +1 -0
- package/dist/icons/Mention.mjs +15 -0
- package/dist/icons/Mention.mjs.map +1 -0
- package/dist/icons/Missing.js +19 -0
- package/dist/icons/Missing.js.map +1 -0
- package/dist/icons/Missing.mjs +17 -0
- package/dist/icons/Missing.mjs.map +1 -0
- package/dist/icons/Resolve.js +19 -0
- package/dist/icons/Resolve.js.map +1 -0
- package/dist/icons/Resolve.mjs +17 -0
- package/dist/icons/Resolve.mjs.map +1 -0
- package/dist/icons/Resolved.js +21 -0
- package/dist/icons/Resolved.js.map +1 -0
- package/dist/icons/Resolved.mjs +19 -0
- package/dist/icons/Resolved.mjs.map +1 -0
- package/dist/icons/Search.js +15 -0
- package/dist/icons/Search.js.map +1 -0
- package/dist/icons/Search.mjs +13 -0
- package/dist/icons/Search.mjs.map +1 -0
- package/dist/icons/Send.js +15 -0
- package/dist/icons/Send.js.map +1 -0
- package/dist/icons/Send.mjs +13 -0
- package/dist/icons/Send.mjs.map +1 -0
- package/dist/icons/Spinner.js +22 -0
- package/dist/icons/Spinner.js.map +1 -0
- package/dist/icons/Spinner.mjs +20 -0
- package/dist/icons/Spinner.mjs.map +1 -0
- package/dist/index.d.mts +476 -0
- package/dist/index.d.ts +476 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +11 -0
- package/dist/index.mjs.map +1 -0
- package/dist/overrides.js +100 -0
- package/dist/overrides.js.map +1 -0
- package/dist/overrides.mjs +77 -0
- package/dist/overrides.mjs.map +1 -0
- package/dist/primitives/Comment/index.js +113 -0
- package/dist/primitives/Comment/index.js.map +1 -0
- package/dist/primitives/Comment/index.mjs +109 -0
- package/dist/primitives/Comment/index.mjs.map +1 -0
- package/dist/primitives/Comment/utils.js +25 -0
- package/dist/primitives/Comment/utils.js.map +1 -0
- package/dist/primitives/Comment/utils.mjs +20 -0
- package/dist/primitives/Comment/utils.mjs.map +1 -0
- package/dist/primitives/Composer/contexts.js +34 -0
- package/dist/primitives/Composer/contexts.js.map +1 -0
- package/dist/primitives/Composer/contexts.mjs +27 -0
- package/dist/primitives/Composer/contexts.mjs.map +1 -0
- package/dist/primitives/Composer/index.js +771 -0
- package/dist/primitives/Composer/index.js.map +1 -0
- package/dist/primitives/Composer/index.mjs +762 -0
- package/dist/primitives/Composer/index.mjs.map +1 -0
- package/dist/primitives/Composer/utils.js +102 -0
- package/dist/primitives/Composer/utils.js.map +1 -0
- package/dist/primitives/Composer/utils.mjs +93 -0
- package/dist/primitives/Composer/utils.mjs.map +1 -0
- package/dist/primitives/EmojiPicker/contexts.js +19 -0
- package/dist/primitives/EmojiPicker/contexts.js.map +1 -0
- package/dist/primitives/EmojiPicker/contexts.mjs +16 -0
- package/dist/primitives/EmojiPicker/contexts.mjs.map +1 -0
- package/dist/primitives/EmojiPicker/index.js +434 -0
- package/dist/primitives/EmojiPicker/index.js.map +1 -0
- package/dist/primitives/EmojiPicker/index.mjs +430 -0
- package/dist/primitives/EmojiPicker/index.mjs.map +1 -0
- package/dist/primitives/EmojiPicker/utils.js +329 -0
- package/dist/primitives/EmojiPicker/utils.js.map +1 -0
- package/dist/primitives/EmojiPicker/utils.mjs +325 -0
- package/dist/primitives/EmojiPicker/utils.mjs.map +1 -0
- package/dist/primitives/Timestamp.js +121 -0
- package/dist/primitives/Timestamp.js.map +1 -0
- package/dist/primitives/Timestamp.mjs +119 -0
- package/dist/primitives/Timestamp.mjs.map +1 -0
- package/dist/primitives/index.d.mts +502 -0
- package/dist/primitives/index.d.ts +502 -0
- package/dist/primitives/index.js +16 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/primitives/index.mjs +9 -0
- package/dist/primitives/index.mjs.map +1 -0
- package/dist/primitives/internal/Emoji.js +30 -0
- package/dist/primitives/internal/Emoji.js.map +1 -0
- package/dist/primitives/internal/Emoji.mjs +28 -0
- package/dist/primitives/internal/Emoji.mjs.map +1 -0
- package/dist/shared.js +21 -0
- package/dist/shared.js.map +1 -0
- package/dist/shared.mjs +19 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/slate/plugins/auto-formatting.js +83 -0
- package/dist/slate/plugins/auto-formatting.js.map +1 -0
- package/dist/slate/plugins/auto-formatting.mjs +81 -0
- package/dist/slate/plugins/auto-formatting.mjs.map +1 -0
- package/dist/slate/plugins/auto-links.js +175 -0
- package/dist/slate/plugins/auto-links.js.map +1 -0
- package/dist/slate/plugins/auto-links.mjs +172 -0
- package/dist/slate/plugins/auto-links.mjs.map +1 -0
- package/dist/slate/plugins/empty-clear-formatting.js +18 -0
- package/dist/slate/plugins/empty-clear-formatting.js.map +1 -0
- package/dist/slate/plugins/empty-clear-formatting.mjs +16 -0
- package/dist/slate/plugins/empty-clear-formatting.mjs.map +1 -0
- package/dist/slate/plugins/mentions.js +112 -0
- package/dist/slate/plugins/mentions.js.map +1 -0
- package/dist/slate/plugins/mentions.mjs +105 -0
- package/dist/slate/plugins/mentions.mjs.map +1 -0
- package/dist/slate/utils/get-character.js +50 -0
- package/dist/slate/utils/get-character.js.map +1 -0
- package/dist/slate/utils/get-character.mjs +47 -0
- package/dist/slate/utils/get-character.mjs.map +1 -0
- package/dist/slate/utils/get-dom-range.js +17 -0
- package/dist/slate/utils/get-dom-range.js.map +1 -0
- package/dist/slate/utils/get-dom-range.mjs +15 -0
- package/dist/slate/utils/get-dom-range.mjs.map +1 -0
- package/dist/slate/utils/get-match-range.js +53 -0
- package/dist/slate/utils/get-match-range.js.map +1 -0
- package/dist/slate/utils/get-match-range.mjs +51 -0
- package/dist/slate/utils/get-match-range.mjs.map +1 -0
- package/dist/slate/utils/is-empty-string.js +8 -0
- package/dist/slate/utils/is-empty-string.js.map +1 -0
- package/dist/slate/utils/is-empty-string.mjs +6 -0
- package/dist/slate/utils/is-empty-string.mjs.map +1 -0
- package/dist/slate/utils/is-empty.js +10 -0
- package/dist/slate/utils/is-empty.js.map +1 -0
- package/dist/slate/utils/is-empty.mjs +8 -0
- package/dist/slate/utils/is-empty.mjs.map +1 -0
- package/dist/slate/utils/is-selection-collapsed.js +10 -0
- package/dist/slate/utils/is-selection-collapsed.js.map +1 -0
- package/dist/slate/utils/is-selection-collapsed.mjs +8 -0
- package/dist/slate/utils/is-selection-collapsed.mjs.map +1 -0
- package/dist/slate/utils/marks.js +43 -0
- package/dist/slate/utils/marks.js.map +1 -0
- package/dist/slate/utils/marks.mjs +38 -0
- package/dist/slate/utils/marks.mjs.map +1 -0
- package/dist/utils/Persist.js +85 -0
- package/dist/utils/Persist.js.map +1 -0
- package/dist/utils/Persist.mjs +81 -0
- package/dist/utils/Persist.mjs.map +1 -0
- package/dist/utils/Portal.js +27 -0
- package/dist/utils/Portal.js.map +1 -0
- package/dist/utils/Portal.mjs +25 -0
- package/dist/utils/Portal.mjs.map +1 -0
- package/dist/utils/capitalize.js +8 -0
- package/dist/utils/capitalize.js.map +1 -0
- package/dist/utils/capitalize.mjs +6 -0
- package/dist/utils/capitalize.mjs.map +1 -0
- package/dist/utils/chunk.js +12 -0
- package/dist/utils/chunk.js.map +1 -0
- package/dist/utils/chunk.mjs +10 -0
- package/dist/utils/chunk.mjs.map +1 -0
- package/dist/utils/clamp.js +8 -0
- package/dist/utils/clamp.js.map +1 -0
- package/dist/utils/clamp.mjs +6 -0
- package/dist/utils/clamp.mjs.map +1 -0
- package/dist/utils/class-names.js +8 -0
- package/dist/utils/class-names.js.map +1 -0
- package/dist/utils/class-names.mjs +6 -0
- package/dist/utils/class-names.mjs.map +1 -0
- package/dist/utils/exists.js +8 -0
- package/dist/utils/exists.js.map +1 -0
- package/dist/utils/exists.mjs +6 -0
- package/dist/utils/exists.mjs.map +1 -0
- package/dist/utils/find-last-index.js +15 -0
- package/dist/utils/find-last-index.js.map +1 -0
- package/dist/utils/find-last-index.mjs +13 -0
- package/dist/utils/find-last-index.mjs.map +1 -0
- package/dist/utils/flush-sync.js +12 -0
- package/dist/utils/flush-sync.js.map +1 -0
- package/dist/utils/flush-sync.mjs +10 -0
- package/dist/utils/flush-sync.mjs.map +1 -0
- package/dist/utils/get-initials.js +13 -0
- package/dist/utils/get-initials.js.map +1 -0
- package/dist/utils/get-initials.mjs +11 -0
- package/dist/utils/get-initials.mjs.map +1 -0
- package/dist/utils/intl.js +24 -0
- package/dist/utils/intl.js.map +1 -0
- package/dist/utils/intl.mjs +20 -0
- package/dist/utils/intl.mjs.map +1 -0
- package/dist/utils/is-apple.js +9 -0
- package/dist/utils/is-apple.js.map +1 -0
- package/dist/utils/is-apple.mjs +7 -0
- package/dist/utils/is-apple.mjs.map +1 -0
- package/dist/utils/is-key.js +26 -0
- package/dist/utils/is-key.js.map +1 -0
- package/dist/utils/is-key.mjs +24 -0
- package/dist/utils/is-key.mjs.map +1 -0
- package/dist/utils/memoize.js +19 -0
- package/dist/utils/memoize.js.map +1 -0
- package/dist/utils/memoize.mjs +17 -0
- package/dist/utils/memoize.mjs.map +1 -0
- package/dist/utils/pluralize.js +8 -0
- package/dist/utils/pluralize.js.map +1 -0
- package/dist/utils/pluralize.mjs +6 -0
- package/dist/utils/pluralize.mjs.map +1 -0
- package/dist/utils/request-idle-callback.js +15 -0
- package/dist/utils/request-idle-callback.js.map +1 -0
- package/dist/utils/request-idle-callback.mjs +12 -0
- package/dist/utils/request-idle-callback.mjs.map +1 -0
- package/dist/utils/request-submit.js +20 -0
- package/dist/utils/request-submit.js.map +1 -0
- package/dist/utils/request-submit.mjs +18 -0
- package/dist/utils/request-submit.mjs.map +1 -0
- package/dist/utils/url.js +22 -0
- package/dist/utils/url.js.map +1 -0
- package/dist/utils/url.mjs +20 -0
- package/dist/utils/url.mjs.map +1 -0
- package/dist/utils/use-controllable-state.js +34 -0
- package/dist/utils/use-controllable-state.js.map +1 -0
- package/dist/utils/use-controllable-state.mjs +32 -0
- package/dist/utils/use-controllable-state.mjs.map +1 -0
- package/dist/utils/use-id.js +29 -0
- package/dist/utils/use-id.js.map +1 -0
- package/dist/utils/use-id.mjs +27 -0
- package/dist/utils/use-id.mjs.map +1 -0
- package/dist/utils/use-index.js +32 -0
- package/dist/utils/use-index.js.map +1 -0
- package/dist/utils/use-index.mjs +30 -0
- package/dist/utils/use-index.mjs.map +1 -0
- package/dist/utils/use-initial.js +10 -0
- package/dist/utils/use-initial.js.map +1 -0
- package/dist/utils/use-initial.mjs +8 -0
- package/dist/utils/use-initial.mjs.map +1 -0
- package/dist/utils/use-interval.js +24 -0
- package/dist/utils/use-interval.js.map +1 -0
- package/dist/utils/use-interval.mjs +22 -0
- package/dist/utils/use-interval.mjs.map +1 -0
- package/dist/utils/use-latest.js +14 -0
- package/dist/utils/use-latest.js.map +1 -0
- package/dist/utils/use-latest.mjs +12 -0
- package/dist/utils/use-latest.mjs.map +1 -0
- package/dist/utils/use-layout-effect.js +8 -0
- package/dist/utils/use-layout-effect.js.map +1 -0
- package/dist/utils/use-layout-effect.mjs +6 -0
- package/dist/utils/use-layout-effect.mjs.map +1 -0
- package/dist/utils/use-refs.js +24 -0
- package/dist/utils/use-refs.js.map +1 -0
- package/dist/utils/use-refs.mjs +22 -0
- package/dist/utils/use-refs.mjs.map +1 -0
- package/dist/utils/use-rerender.js +14 -0
- package/dist/utils/use-rerender.js.map +1 -0
- package/dist/utils/use-rerender.mjs +12 -0
- package/dist/utils/use-rerender.mjs.map +1 -0
- package/dist/utils/use-transition.js +12 -0
- package/dist/utils/use-transition.js.map +1 -0
- package/dist/utils/use-transition.mjs +10 -0
- package/dist/utils/use-transition.mjs.map +1 -0
- package/dist/utils/use-visible.js +48 -0
- package/dist/utils/use-visible.js.map +1 -0
- package/dist/utils/use-visible.mjs +46 -0
- package/dist/utils/use-visible.mjs.map +1 -0
- package/dist/utils/visually-hidden.js +17 -0
- package/dist/utils/visually-hidden.js.map +1 -0
- package/dist/utils/visually-hidden.mjs +15 -0
- package/dist/utils/visually-hidden.mjs.map +1 -0
- package/dist/utils/wrap.js +9 -0
- package/dist/utils/wrap.js.map +1 -0
- package/dist/utils/wrap.mjs +7 -0
- package/dist/utils/wrap.mjs.map +1 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/dist/version.mjs +6 -0
- package/dist/version.mjs.map +1 -0
- package/package.json +142 -0
- package/primitives/README.md +5 -0
- package/primitives/package.json +4 -0
- package/src/styles/constants.css +17 -0
- package/src/styles/dark/attributes.css +8 -0
- package/src/styles/dark/index.css +29 -0
- package/src/styles/dark/media-query.css +7 -0
- package/src/styles/index.css +1437 -0
- package/src/styles/utils.css +36 -0
- package/styles/dark/attributes.css +1 -0
- package/styles/dark/attributes.css.d.ts +1 -0
- package/styles/dark/attributes.css.map +1 -0
- package/styles/dark/media-query.css +1 -0
- package/styles/dark/media-query.css.d.ts +1 -0
- package/styles/dark/media-query.css.map +1 -0
- package/styles.css +1 -0
- package/styles.css.d.ts +1 -0
- package/styles.css.map +1 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var slate = require('slate');
|
|
4
|
+
var getCharacter = require('../utils/get-character.js');
|
|
5
|
+
var getMatchRange = require('../utils/get-match-range.js');
|
|
6
|
+
var isEmptyString = require('../utils/is-empty-string.js');
|
|
7
|
+
var isSelectionCollapsed = require('../utils/is-selection-collapsed.js');
|
|
8
|
+
|
|
9
|
+
const formatters = [
|
|
10
|
+
{
|
|
11
|
+
type: "mark",
|
|
12
|
+
mark: "bold",
|
|
13
|
+
character: "*"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: "mark",
|
|
17
|
+
mark: "italic",
|
|
18
|
+
character: "_"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: "mark",
|
|
22
|
+
mark: "strikethrough",
|
|
23
|
+
character: "~"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "mark",
|
|
27
|
+
mark: "code",
|
|
28
|
+
character: "`"
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
const markFormattingCharacters = formatters.filter((formatter) => formatter.type === "mark").map((formatter) => formatter.character);
|
|
32
|
+
function formatMark(editor, text, formatter) {
|
|
33
|
+
if (text !== formatter.character) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
const match = getMatchRange.getMatchRange(editor, editor.selection, [formatter.character]);
|
|
37
|
+
if (!match || slate.Range.isCollapsed(match)) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const formattingCharacter = getCharacter.getCharacterBefore(editor, match);
|
|
41
|
+
if (!formattingCharacter || formattingCharacter.text !== formatter.character) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
const beforeCharacter = getCharacter.getCharacterBefore(editor, formattingCharacter.range);
|
|
45
|
+
if (beforeCharacter && !markFormattingCharacters.includes(beforeCharacter.text) && !isEmptyString.isEmptyString(beforeCharacter.text)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const matchText = slate.Editor.string(editor, match);
|
|
49
|
+
if (matchText.trim() !== matchText) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
slate.Transforms.select(editor, match);
|
|
53
|
+
editor.addMark(formatter.mark, true);
|
|
54
|
+
slate.Transforms.collapse(editor, { edge: "end" });
|
|
55
|
+
editor.removeMark(formatter.mark);
|
|
56
|
+
slate.Transforms.delete(editor, {
|
|
57
|
+
at: formattingCharacter.range
|
|
58
|
+
});
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
function withAutoFormatting(editor) {
|
|
62
|
+
const { insertText } = editor;
|
|
63
|
+
editor.insertText = (text, options) => {
|
|
64
|
+
if (!isSelectionCollapsed.isSelectionCollapsed(editor.selection)) {
|
|
65
|
+
return insertText(text, options);
|
|
66
|
+
}
|
|
67
|
+
let shouldInsertText = true;
|
|
68
|
+
for (const formatter of formatters) {
|
|
69
|
+
if (formatter.type === "mark") {
|
|
70
|
+
if (formatMark(editor, text, formatter)) {
|
|
71
|
+
shouldInsertText = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (shouldInsertText) {
|
|
76
|
+
insertText(text, options);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
return editor;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
exports.withAutoFormatting = withAutoFormatting;
|
|
83
|
+
//# sourceMappingURL=auto-formatting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-formatting.js","sources":["../../../src/slate/plugins/auto-formatting.ts"],"sourcesContent":["import type { EditorMarks } from \"slate\";\nimport {\n Editor as SlateEditor,\n Range,\n Transforms as SlateTransforms,\n} from \"slate\";\n\nimport { getCharacterBefore } from \"../utils/get-character\";\nimport { getMatchRange } from \"../utils/get-match-range\";\nimport { isEmptyString } from \"../utils/is-empty-string\";\nimport { isSelectionCollapsed } from \"../utils/is-selection-collapsed\";\n\ninterface MarkFormatter {\n type: \"mark\";\n mark: keyof EditorMarks;\n character: string;\n}\n\ntype Formatter = MarkFormatter;\n\nconst formatters: Formatter[] = [\n {\n type: \"mark\",\n mark: \"bold\",\n character: \"*\",\n },\n {\n type: \"mark\",\n mark: \"italic\",\n character: \"_\",\n },\n {\n type: \"mark\",\n mark: \"strikethrough\",\n character: \"~\",\n },\n {\n type: \"mark\",\n mark: \"code\",\n character: \"`\",\n },\n];\nconst markFormattingCharacters = formatters\n .filter((formatter) => formatter.type === \"mark\")\n .map((formatter) => formatter.character);\n\nfunction formatMark<T extends SlateEditor>(\n editor: T,\n text: string,\n formatter: MarkFormatter\n): boolean {\n if (text !== formatter.character) {\n return false;\n }\n\n const match = getMatchRange(editor, editor.selection!, [formatter.character]);\n\n // Check if the match exists and is not empty\n if (!match || Range.isCollapsed(match)) {\n return false;\n }\n\n const formattingCharacter = getCharacterBefore(editor, match);\n\n // Check if the match is preceded by the formatting character\n if (\n !formattingCharacter ||\n formattingCharacter.text !== formatter.character\n ) {\n return false;\n }\n\n const beforeCharacter = getCharacterBefore(editor, formattingCharacter.range);\n\n // Check if the formatting character is preceded by a non-whitespace character (or another formatting character)\n if (\n beforeCharacter &&\n !markFormattingCharacters.includes(beforeCharacter.text) &&\n !isEmptyString(beforeCharacter.text)\n ) {\n return false;\n }\n\n const matchText = SlateEditor.string(editor, match);\n\n // Check if the match has leading/trailing whitespace\n if (matchText.trim() !== matchText) {\n return false;\n }\n\n // Set the match to the expected mark\n SlateTransforms.select(editor, match);\n editor.addMark(formatter.mark, true);\n\n // Set the selection at the end of the match and reset formatting\n SlateTransforms.collapse(editor, { edge: \"end\" });\n editor.removeMark(formatter.mark);\n\n // Delete the formatting character\n SlateTransforms.delete(editor, {\n at: formattingCharacter.range,\n });\n\n return true;\n}\n\nexport function withAutoFormatting<T extends SlateEditor>(editor: T): T {\n const { insertText } = editor;\n\n editor.insertText = (text, options) => {\n if (!isSelectionCollapsed(editor.selection)) {\n return insertText(text, options);\n }\n\n let shouldInsertText = true;\n\n for (const formatter of formatters) {\n if (formatter.type === \"mark\") {\n if (formatMark(editor, text, formatter)) {\n shouldInsertText = false;\n }\n }\n }\n\n if (shouldInsertText) {\n insertText(text, options);\n }\n };\n\n return editor;\n}\n"],"names":["getMatchRange","Range","getCharacterBefore","isEmptyString","SlateEditor","SlateTransforms","isSelectionCollapsed"],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Range, Editor, Transforms } from 'slate';
|
|
2
|
+
import { getCharacterBefore } from '../utils/get-character.mjs';
|
|
3
|
+
import { getMatchRange } from '../utils/get-match-range.mjs';
|
|
4
|
+
import { isEmptyString } from '../utils/is-empty-string.mjs';
|
|
5
|
+
import { isSelectionCollapsed } from '../utils/is-selection-collapsed.mjs';
|
|
6
|
+
|
|
7
|
+
const formatters = [
|
|
8
|
+
{
|
|
9
|
+
type: "mark",
|
|
10
|
+
mark: "bold",
|
|
11
|
+
character: "*"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
type: "mark",
|
|
15
|
+
mark: "italic",
|
|
16
|
+
character: "_"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
type: "mark",
|
|
20
|
+
mark: "strikethrough",
|
|
21
|
+
character: "~"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
type: "mark",
|
|
25
|
+
mark: "code",
|
|
26
|
+
character: "`"
|
|
27
|
+
}
|
|
28
|
+
];
|
|
29
|
+
const markFormattingCharacters = formatters.filter((formatter) => formatter.type === "mark").map((formatter) => formatter.character);
|
|
30
|
+
function formatMark(editor, text, formatter) {
|
|
31
|
+
if (text !== formatter.character) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const match = getMatchRange(editor, editor.selection, [formatter.character]);
|
|
35
|
+
if (!match || Range.isCollapsed(match)) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const formattingCharacter = getCharacterBefore(editor, match);
|
|
39
|
+
if (!formattingCharacter || formattingCharacter.text !== formatter.character) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
const beforeCharacter = getCharacterBefore(editor, formattingCharacter.range);
|
|
43
|
+
if (beforeCharacter && !markFormattingCharacters.includes(beforeCharacter.text) && !isEmptyString(beforeCharacter.text)) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const matchText = Editor.string(editor, match);
|
|
47
|
+
if (matchText.trim() !== matchText) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
Transforms.select(editor, match);
|
|
51
|
+
editor.addMark(formatter.mark, true);
|
|
52
|
+
Transforms.collapse(editor, { edge: "end" });
|
|
53
|
+
editor.removeMark(formatter.mark);
|
|
54
|
+
Transforms.delete(editor, {
|
|
55
|
+
at: formattingCharacter.range
|
|
56
|
+
});
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
function withAutoFormatting(editor) {
|
|
60
|
+
const { insertText } = editor;
|
|
61
|
+
editor.insertText = (text, options) => {
|
|
62
|
+
if (!isSelectionCollapsed(editor.selection)) {
|
|
63
|
+
return insertText(text, options);
|
|
64
|
+
}
|
|
65
|
+
let shouldInsertText = true;
|
|
66
|
+
for (const formatter of formatters) {
|
|
67
|
+
if (formatter.type === "mark") {
|
|
68
|
+
if (formatMark(editor, text, formatter)) {
|
|
69
|
+
shouldInsertText = false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (shouldInsertText) {
|
|
74
|
+
insertText(text, options);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
return editor;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { withAutoFormatting };
|
|
81
|
+
//# sourceMappingURL=auto-formatting.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-formatting.mjs","sources":["../../../src/slate/plugins/auto-formatting.ts"],"sourcesContent":["import type { EditorMarks } from \"slate\";\nimport {\n Editor as SlateEditor,\n Range,\n Transforms as SlateTransforms,\n} from \"slate\";\n\nimport { getCharacterBefore } from \"../utils/get-character\";\nimport { getMatchRange } from \"../utils/get-match-range\";\nimport { isEmptyString } from \"../utils/is-empty-string\";\nimport { isSelectionCollapsed } from \"../utils/is-selection-collapsed\";\n\ninterface MarkFormatter {\n type: \"mark\";\n mark: keyof EditorMarks;\n character: string;\n}\n\ntype Formatter = MarkFormatter;\n\nconst formatters: Formatter[] = [\n {\n type: \"mark\",\n mark: \"bold\",\n character: \"*\",\n },\n {\n type: \"mark\",\n mark: \"italic\",\n character: \"_\",\n },\n {\n type: \"mark\",\n mark: \"strikethrough\",\n character: \"~\",\n },\n {\n type: \"mark\",\n mark: \"code\",\n character: \"`\",\n },\n];\nconst markFormattingCharacters = formatters\n .filter((formatter) => formatter.type === \"mark\")\n .map((formatter) => formatter.character);\n\nfunction formatMark<T extends SlateEditor>(\n editor: T,\n text: string,\n formatter: MarkFormatter\n): boolean {\n if (text !== formatter.character) {\n return false;\n }\n\n const match = getMatchRange(editor, editor.selection!, [formatter.character]);\n\n // Check if the match exists and is not empty\n if (!match || Range.isCollapsed(match)) {\n return false;\n }\n\n const formattingCharacter = getCharacterBefore(editor, match);\n\n // Check if the match is preceded by the formatting character\n if (\n !formattingCharacter ||\n formattingCharacter.text !== formatter.character\n ) {\n return false;\n }\n\n const beforeCharacter = getCharacterBefore(editor, formattingCharacter.range);\n\n // Check if the formatting character is preceded by a non-whitespace character (or another formatting character)\n if (\n beforeCharacter &&\n !markFormattingCharacters.includes(beforeCharacter.text) &&\n !isEmptyString(beforeCharacter.text)\n ) {\n return false;\n }\n\n const matchText = SlateEditor.string(editor, match);\n\n // Check if the match has leading/trailing whitespace\n if (matchText.trim() !== matchText) {\n return false;\n }\n\n // Set the match to the expected mark\n SlateTransforms.select(editor, match);\n editor.addMark(formatter.mark, true);\n\n // Set the selection at the end of the match and reset formatting\n SlateTransforms.collapse(editor, { edge: \"end\" });\n editor.removeMark(formatter.mark);\n\n // Delete the formatting character\n SlateTransforms.delete(editor, {\n at: formattingCharacter.range,\n });\n\n return true;\n}\n\nexport function withAutoFormatting<T extends SlateEditor>(editor: T): T {\n const { insertText } = editor;\n\n editor.insertText = (text, options) => {\n if (!isSelectionCollapsed(editor.selection)) {\n return insertText(text, options);\n }\n\n let shouldInsertText = true;\n\n for (const formatter of formatters) {\n if (formatter.type === \"mark\") {\n if (formatMark(editor, text, formatter)) {\n shouldInsertText = false;\n }\n }\n }\n\n if (shouldInsertText) {\n insertText(text, options);\n }\n };\n\n return editor;\n}\n"],"names":["SlateEditor","SlateTransforms"],"mappings":"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"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var slate = require('slate');
|
|
4
|
+
|
|
5
|
+
function withAutoLinks(editor) {
|
|
6
|
+
const { isInline, normalizeNode, deleteBackward } = editor;
|
|
7
|
+
editor.isInline = (element) => {
|
|
8
|
+
return element.type === "auto-link" ? true : isInline(element);
|
|
9
|
+
};
|
|
10
|
+
editor.normalizeNode = (entry) => {
|
|
11
|
+
const [node, path] = entry;
|
|
12
|
+
if (slate.Text.isText(node)) {
|
|
13
|
+
const parentNode = slate.Node.parent(editor, path);
|
|
14
|
+
if (isComposerBodyAutoLink(parentNode)) {
|
|
15
|
+
const parentPath = slate.Path.parent(path);
|
|
16
|
+
handleLinkEdit(editor, [parentNode, parentPath]);
|
|
17
|
+
} else {
|
|
18
|
+
handleLinkCreate(editor, [node, path]);
|
|
19
|
+
handleNeighbours(editor, [node, path]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
normalizeNode(entry);
|
|
23
|
+
};
|
|
24
|
+
editor.deleteBackward = (unit) => {
|
|
25
|
+
deleteBackward(unit);
|
|
26
|
+
const { selection } = editor;
|
|
27
|
+
if (!selection)
|
|
28
|
+
return;
|
|
29
|
+
if (!slate.Range.isCollapsed(selection))
|
|
30
|
+
return;
|
|
31
|
+
const [match] = slate.Editor.nodes(editor, {
|
|
32
|
+
at: selection,
|
|
33
|
+
match: isComposerBodyAutoLink,
|
|
34
|
+
mode: "lowest"
|
|
35
|
+
});
|
|
36
|
+
if (!match)
|
|
37
|
+
return;
|
|
38
|
+
slate.Transforms.unwrapNodes(editor, {
|
|
39
|
+
match: isComposerBodyAutoLink
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
return editor;
|
|
43
|
+
}
|
|
44
|
+
function isComposerBodyAutoLink(node) {
|
|
45
|
+
return slate.Element.isElement(node) && node.type === "auto-link";
|
|
46
|
+
}
|
|
47
|
+
const URL_REGEX = /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9().@:%_+~#?&//=]*)/;
|
|
48
|
+
const PUNCTUATION_OR_SPACE = /[.,;!?\s]/;
|
|
49
|
+
const PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC = /^[.?][a-zA-Z0-9]+/;
|
|
50
|
+
function isSeparator(char) {
|
|
51
|
+
return PUNCTUATION_OR_SPACE.test(char);
|
|
52
|
+
}
|
|
53
|
+
function endsWithSeparator(textContent) {
|
|
54
|
+
return isSeparator(textContent[textContent.length - 1]);
|
|
55
|
+
}
|
|
56
|
+
function startsWithSeparator(textContent) {
|
|
57
|
+
return isSeparator(textContent[0]);
|
|
58
|
+
}
|
|
59
|
+
function endsWithPeriodOrQuestionMark(textContent) {
|
|
60
|
+
return textContent[textContent.length - 1] === "." || textContent[textContent.length - 1] === "?";
|
|
61
|
+
}
|
|
62
|
+
function isPreviousNodeValid(editor, path) {
|
|
63
|
+
const entry = slate.Editor.previous(editor, { at: path });
|
|
64
|
+
if (!entry)
|
|
65
|
+
return true;
|
|
66
|
+
return slate.Text.isText(entry[0]) && (endsWithSeparator(entry[0].text) || entry[0].text === "");
|
|
67
|
+
}
|
|
68
|
+
function isNextNodeValid(editor, path) {
|
|
69
|
+
const entry = slate.Editor.next(editor, { at: path });
|
|
70
|
+
if (!entry)
|
|
71
|
+
return true;
|
|
72
|
+
return slate.Text.isText(entry[0]) && (startsWithSeparator(entry[0].text) || entry[0].text === "");
|
|
73
|
+
}
|
|
74
|
+
function isContentAroundValid(editor, entry, start, end) {
|
|
75
|
+
const [node, path] = entry;
|
|
76
|
+
const text = node.text;
|
|
77
|
+
const contentBeforeIsValid = start > 0 ? isSeparator(text[start - 1]) : isPreviousNodeValid(editor, path);
|
|
78
|
+
const contentAfterIsValid = end < text.length ? isSeparator(text[end]) : isNextNodeValid(editor, path);
|
|
79
|
+
return contentBeforeIsValid && contentAfterIsValid;
|
|
80
|
+
}
|
|
81
|
+
const handleLinkEdit = (editor, entry) => {
|
|
82
|
+
const [node, path] = entry;
|
|
83
|
+
const children = slate.Node.children(editor, path);
|
|
84
|
+
for (const [child] of children) {
|
|
85
|
+
if (slate.Text.isText(child))
|
|
86
|
+
continue;
|
|
87
|
+
slate.Transforms.unwrapNodes(editor, { at: path });
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const text = slate.Node.string(node);
|
|
91
|
+
const match = URL_REGEX.exec(text);
|
|
92
|
+
if (!match || match[0] !== text) {
|
|
93
|
+
slate.Transforms.unwrapNodes(editor, { at: path });
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (endsWithPeriodOrQuestionMark(text)) {
|
|
97
|
+
slate.Transforms.unwrapNodes(editor, { at: path });
|
|
98
|
+
const textBeforePeriod = text.slice(0, text.length - 1);
|
|
99
|
+
slate.Transforms.wrapNodes(
|
|
100
|
+
editor,
|
|
101
|
+
{
|
|
102
|
+
type: "auto-link",
|
|
103
|
+
url: textBeforePeriod,
|
|
104
|
+
children: []
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
at: {
|
|
108
|
+
anchor: { path, offset: 0 },
|
|
109
|
+
focus: { path, offset: textBeforePeriod.length }
|
|
110
|
+
},
|
|
111
|
+
split: true
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (!isPreviousNodeValid(editor, path) || !isNextNodeValid(editor, path)) {
|
|
117
|
+
slate.Transforms.unwrapNodes(editor, { at: path });
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (node.url !== text) {
|
|
121
|
+
slate.Transforms.setNodes(editor, { url: match[0] }, { at: path });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const handleLinkCreate = (editor, entry) => {
|
|
126
|
+
const [node, path] = entry;
|
|
127
|
+
const match = URL_REGEX.exec(node.text);
|
|
128
|
+
if (!match)
|
|
129
|
+
return;
|
|
130
|
+
const start = match.index;
|
|
131
|
+
const end = start + match[0].length;
|
|
132
|
+
if (!isContentAroundValid(editor, entry, start, end))
|
|
133
|
+
return;
|
|
134
|
+
slate.Transforms.wrapNodes(
|
|
135
|
+
editor,
|
|
136
|
+
{
|
|
137
|
+
type: "auto-link",
|
|
138
|
+
url: match[0],
|
|
139
|
+
children: []
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
at: {
|
|
143
|
+
anchor: { path, offset: start },
|
|
144
|
+
focus: { path, offset: end }
|
|
145
|
+
},
|
|
146
|
+
split: true
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
return;
|
|
150
|
+
};
|
|
151
|
+
const handleNeighbours = (editor, entry) => {
|
|
152
|
+
const [node, path] = entry;
|
|
153
|
+
const text = node.text;
|
|
154
|
+
const previousSibling = slate.Editor.previous(editor, { at: path });
|
|
155
|
+
if (previousSibling && isComposerBodyAutoLink(previousSibling[0])) {
|
|
156
|
+
if (PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC.test(text)) {
|
|
157
|
+
slate.Transforms.unwrapNodes(editor, { at: previousSibling[1] });
|
|
158
|
+
slate.Transforms.mergeNodes(editor, { at: path });
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (!startsWithSeparator(text)) {
|
|
162
|
+
slate.Transforms.unwrapNodes(editor, { at: previousSibling[1] });
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const nextSibling = slate.Editor.next(editor, { at: path });
|
|
167
|
+
if (nextSibling && isComposerBodyAutoLink(nextSibling[0]) && !endsWithSeparator(text)) {
|
|
168
|
+
slate.Transforms.unwrapNodes(editor, { at: nextSibling[1] });
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
exports.isComposerBodyAutoLink = isComposerBodyAutoLink;
|
|
174
|
+
exports.withAutoLinks = withAutoLinks;
|
|
175
|
+
//# sourceMappingURL=auto-links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-links.js","sources":["../../../src/slate/plugins/auto-links.ts"],"sourcesContent":["import type { NodeEntry } from \"slate\";\nimport { Editor, Element, Node, Path, Range, Text, Transforms } from \"slate\";\n\nimport type { ComposerBodyAutoLink } from \"../../types\";\n\n/**\n * This implementation is inspired by Lexical's AutoLink plugin.\n * Additional modifications and features were added to adapt it to our specific needs.\n *\n * Original Lexical AutoLink plugin can be found at [Lexical's Github Repository](https://github.com/facebook/lexical/blob/main/packages/lexical-react/src/LexicalAutoLinkPlugin.ts)\n */\nexport function withAutoLinks(editor: Editor): Editor {\n const { isInline, normalizeNode, deleteBackward } = editor;\n\n editor.isInline = (element) => {\n return element.type === \"auto-link\" ? true : isInline(element);\n };\n\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n if (Text.isText(node)) {\n const parentNode = Node.parent(editor, path);\n\n if (isComposerBodyAutoLink(parentNode)) {\n const parentPath = Path.parent(path);\n handleLinkEdit(editor, [parentNode, parentPath]);\n } else {\n handleLinkCreate(editor, [node, path]);\n handleNeighbours(editor, [node, path]);\n }\n }\n\n normalizeNode(entry);\n };\n\n editor.deleteBackward = (unit) => {\n deleteBackward(unit);\n const { selection } = editor;\n if (!selection) return;\n\n if (!Range.isCollapsed(selection)) return;\n\n const [match] = Editor.nodes(editor, {\n at: selection,\n match: isComposerBodyAutoLink,\n mode: \"lowest\",\n });\n\n if (!match) return;\n\n Transforms.unwrapNodes(editor, {\n match: isComposerBodyAutoLink,\n });\n };\n\n return editor;\n}\n\nexport function isComposerBodyAutoLink(\n node: Node\n): node is ComposerBodyAutoLink {\n return Element.isElement(node) && node.type === \"auto-link\";\n}\n\n/**\n * 1. ((https?:\\/\\/(www\\.)?)|(www\\.))\n * - Matches 'http://' or 'https://' optionally followed by 'www.', or just 'www.'\n *\n * 2. [-a-zA-Z0-9@:%._+~#=]{1,256}\n * - Matches any character in the set [-a-zA-Z0-9@:%._+~#=] between 1 and 256 times, often found in the domain and subdomain part of the URL\n *\n * 3. \\.[a-zA-Z0-9()]{1,6}\n * - Matches a period followed by any character in the set [a-zA-Z0-9()] between 1 and 6 times, usually indicating the domain extension like .com, .org, etc.\n *\n * 4. \\b\n * - Represents a word boundary, ensuring that the characters following cannot be part of a different word\n *\n * 5. ([-a-zA-Z0-9().@:%_+~#?&//=]*)\n * - Matches any character in the set [-a-zA-Z0-9().@:%_+~#?&//=] between 0 and unlimited times, often found in the path, query parameters, or anchor part of the URL\n *\n * Matching URLs:\n * - http://www.example.com\n * - https://www.example.com\n * - www.example.com\n * - https://example.com/path?query=param#anchor\n *\n * Non-Matching URLs:\n * - http:/example.com (malformed scheme)\n * - example (missing scheme and domain extension)\n * - ftp://example.com (ftp scheme is not supported)\n * - example.com (missing scheme)\n */\nconst URL_REGEX =\n /((https?:\\/\\/(www\\.)?)|(www\\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9().@:%_+~#?&//=]*)/;\n\nconst PUNCTUATION_OR_SPACE = /[.,;!?\\s]/;\n\nconst PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC = /^[.?][a-zA-Z0-9]+/;\n\n/**\n * Helper function to check if a character is a separator (punctuation or space)\n * @param char The character to check\n * @returns Whether the character is a separator or not\n */\nfunction isSeparator(char: string): boolean {\n return PUNCTUATION_OR_SPACE.test(char);\n}\n\n/**\n * Helper function to check if a text content ends with a separator (punctuation or space)\n * @param textContent The text content to check\n * @returns Whether the text content ends with a separator or not\n */\nfunction endsWithSeparator(textContent: string): boolean {\n return isSeparator(textContent[textContent.length - 1]);\n}\n\n/**\n * Helper function to check if a text content starts with a separator (punctuation or space)\n * @param textContent The text content to check\n * @returns Whether the text content starts with a separator or not\n */\nfunction startsWithSeparator(textContent: string): boolean {\n return isSeparator(textContent[0]);\n}\n\n/**\n * Helper function to check if a text content ends with a period or question mark\n * @param textContent The text content to check\n * @returns Whether the text content ends with a period or not\n */\nfunction endsWithPeriodOrQuestionMark(textContent: string): boolean {\n return (\n textContent[textContent.length - 1] === \".\" ||\n textContent[textContent.length - 1] === \"?\"\n );\n}\n\n/**\n * Helper function to check if the previous node is valid (text node that ends with a separator or is empty)\n */\nfunction isPreviousNodeValid(editor: Editor, path: Path): boolean {\n const entry = Editor.previous(editor, { at: path });\n if (!entry) return true;\n\n return (\n Text.isText(entry[0]) &&\n (endsWithSeparator(entry[0].text) || entry[0].text === \"\")\n );\n}\n\n/**\n * Helper function to check if the next node is valid (text node that starts with a separator or is empty)\n */\nfunction isNextNodeValid(editor: Editor, path: Path): boolean {\n const entry = Editor.next(editor, { at: path });\n if (!entry) return true;\n\n return (\n Text.isText(entry[0]) &&\n (startsWithSeparator(entry[0].text) || entry[0].text === \"\")\n );\n}\n\n/**\n * Helper function to check if the content around a text node is valid.\n * @param editor\n * @param entry\n * @param start\n * @param end\n * @returns\n */\nfunction isContentAroundValid(\n editor: Editor,\n entry: NodeEntry<Text>,\n start: number,\n end: number\n): boolean {\n const [node, path] = entry;\n const text = node.text;\n\n const contentBeforeIsValid =\n start > 0\n ? isSeparator(text[start - 1])\n : isPreviousNodeValid(editor, path);\n\n const contentAfterIsValid =\n end < text.length ? isSeparator(text[end]) : isNextNodeValid(editor, path);\n\n return contentBeforeIsValid && contentAfterIsValid;\n}\n\nconst handleLinkEdit = (\n editor: Editor,\n entry: NodeEntry<ComposerBodyAutoLink>\n) => {\n const [node, path] = entry;\n\n // Step 1: Ensure that the Link node only contains text nodes as children\n const children = Node.children(editor, path);\n for (const [child] of children) {\n if (Text.isText(child)) continue;\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n // Attempt to match the text content (of the Link node) against the URL regex\n const text = Node.string(node);\n const match = URL_REGEX.exec(text);\n\n // Step 2: Ensure that the text content of the Link node matches the URL regex and is identical to the match\n if (!match || match[0] !== text) {\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n\n // Step 3: Ensure that if the text content of the Link node ends with a period, we unwrap the Link node and wrap the text before the period in a new Link node\n if (endsWithPeriodOrQuestionMark(text)) {\n Transforms.unwrapNodes(editor, { at: path });\n\n const textBeforePeriod = text.slice(0, text.length - 1);\n\n // Remove the last character from the link text and wrap the remaining text in a new link node\n Transforms.wrapNodes<ComposerBodyAutoLink>(\n editor,\n {\n type: \"auto-link\",\n url: textBeforePeriod,\n children: [],\n },\n {\n at: {\n anchor: { path, offset: 0 },\n focus: { path, offset: textBeforePeriod.length },\n },\n split: true,\n }\n );\n return;\n }\n\n // Step 4: Ensure that the text content of the Link node is surrounded by separators or the start/end of the text content\n if (!isPreviousNodeValid(editor, path) || !isNextNodeValid(editor, path)) {\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n\n // Step 5: Ensure that the url attribute of the Link node is identical to its text content\n if (node.url !== text) {\n Transforms.setNodes(editor, { url: match[0] }, { at: path });\n return;\n }\n};\n\nconst handleLinkCreate = (editor: Editor, entry: NodeEntry<Text>) => {\n const [node, path] = entry;\n\n // Step 1: Ensure that the text content of the node matches the URL regex\n const match = URL_REGEX.exec(node.text);\n if (!match) return;\n\n const start = match.index;\n const end = start + match[0].length;\n\n // Step 2: Ensure that the content around the node is valid\n if (!isContentAroundValid(editor, entry, start, end)) return;\n\n Transforms.wrapNodes<ComposerBodyAutoLink>(\n editor,\n {\n type: \"auto-link\",\n url: match[0],\n children: [],\n },\n {\n at: {\n anchor: { path, offset: start },\n focus: { path, offset: end },\n },\n split: true,\n }\n );\n return;\n};\n\nconst handleNeighbours = (editor: Editor, entry: NodeEntry<Text>) => {\n const [node, path] = entry;\n const text = node.text;\n\n const previousSibling = Editor.previous(editor, { at: path });\n\n if (previousSibling && isComposerBodyAutoLink(previousSibling[0])) {\n if (PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC.test(text)) {\n Transforms.unwrapNodes(editor, { at: previousSibling[1] });\n Transforms.mergeNodes(editor, { at: path });\n return;\n }\n\n if (!startsWithSeparator(text)) {\n Transforms.unwrapNodes(editor, { at: previousSibling[1] });\n return;\n }\n }\n\n const nextSibling = Editor.next(editor, { at: path });\n if (\n nextSibling &&\n isComposerBodyAutoLink(nextSibling[0]) &&\n !endsWithSeparator(text)\n ) {\n Transforms.unwrapNodes(editor, { at: nextSibling[1] });\n return;\n }\n};\n"],"names":["Text","Node","Path","Range","Editor","Transforms","Element"],"mappings":"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"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Element, Text, Node, Path, Range, Editor, Transforms } from 'slate';
|
|
2
|
+
|
|
3
|
+
function withAutoLinks(editor) {
|
|
4
|
+
const { isInline, normalizeNode, deleteBackward } = editor;
|
|
5
|
+
editor.isInline = (element) => {
|
|
6
|
+
return element.type === "auto-link" ? true : isInline(element);
|
|
7
|
+
};
|
|
8
|
+
editor.normalizeNode = (entry) => {
|
|
9
|
+
const [node, path] = entry;
|
|
10
|
+
if (Text.isText(node)) {
|
|
11
|
+
const parentNode = Node.parent(editor, path);
|
|
12
|
+
if (isComposerBodyAutoLink(parentNode)) {
|
|
13
|
+
const parentPath = Path.parent(path);
|
|
14
|
+
handleLinkEdit(editor, [parentNode, parentPath]);
|
|
15
|
+
} else {
|
|
16
|
+
handleLinkCreate(editor, [node, path]);
|
|
17
|
+
handleNeighbours(editor, [node, path]);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
normalizeNode(entry);
|
|
21
|
+
};
|
|
22
|
+
editor.deleteBackward = (unit) => {
|
|
23
|
+
deleteBackward(unit);
|
|
24
|
+
const { selection } = editor;
|
|
25
|
+
if (!selection)
|
|
26
|
+
return;
|
|
27
|
+
if (!Range.isCollapsed(selection))
|
|
28
|
+
return;
|
|
29
|
+
const [match] = Editor.nodes(editor, {
|
|
30
|
+
at: selection,
|
|
31
|
+
match: isComposerBodyAutoLink,
|
|
32
|
+
mode: "lowest"
|
|
33
|
+
});
|
|
34
|
+
if (!match)
|
|
35
|
+
return;
|
|
36
|
+
Transforms.unwrapNodes(editor, {
|
|
37
|
+
match: isComposerBodyAutoLink
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
return editor;
|
|
41
|
+
}
|
|
42
|
+
function isComposerBodyAutoLink(node) {
|
|
43
|
+
return Element.isElement(node) && node.type === "auto-link";
|
|
44
|
+
}
|
|
45
|
+
const URL_REGEX = /((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9().@:%_+~#?&//=]*)/;
|
|
46
|
+
const PUNCTUATION_OR_SPACE = /[.,;!?\s]/;
|
|
47
|
+
const PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC = /^[.?][a-zA-Z0-9]+/;
|
|
48
|
+
function isSeparator(char) {
|
|
49
|
+
return PUNCTUATION_OR_SPACE.test(char);
|
|
50
|
+
}
|
|
51
|
+
function endsWithSeparator(textContent) {
|
|
52
|
+
return isSeparator(textContent[textContent.length - 1]);
|
|
53
|
+
}
|
|
54
|
+
function startsWithSeparator(textContent) {
|
|
55
|
+
return isSeparator(textContent[0]);
|
|
56
|
+
}
|
|
57
|
+
function endsWithPeriodOrQuestionMark(textContent) {
|
|
58
|
+
return textContent[textContent.length - 1] === "." || textContent[textContent.length - 1] === "?";
|
|
59
|
+
}
|
|
60
|
+
function isPreviousNodeValid(editor, path) {
|
|
61
|
+
const entry = Editor.previous(editor, { at: path });
|
|
62
|
+
if (!entry)
|
|
63
|
+
return true;
|
|
64
|
+
return Text.isText(entry[0]) && (endsWithSeparator(entry[0].text) || entry[0].text === "");
|
|
65
|
+
}
|
|
66
|
+
function isNextNodeValid(editor, path) {
|
|
67
|
+
const entry = Editor.next(editor, { at: path });
|
|
68
|
+
if (!entry)
|
|
69
|
+
return true;
|
|
70
|
+
return Text.isText(entry[0]) && (startsWithSeparator(entry[0].text) || entry[0].text === "");
|
|
71
|
+
}
|
|
72
|
+
function isContentAroundValid(editor, entry, start, end) {
|
|
73
|
+
const [node, path] = entry;
|
|
74
|
+
const text = node.text;
|
|
75
|
+
const contentBeforeIsValid = start > 0 ? isSeparator(text[start - 1]) : isPreviousNodeValid(editor, path);
|
|
76
|
+
const contentAfterIsValid = end < text.length ? isSeparator(text[end]) : isNextNodeValid(editor, path);
|
|
77
|
+
return contentBeforeIsValid && contentAfterIsValid;
|
|
78
|
+
}
|
|
79
|
+
const handleLinkEdit = (editor, entry) => {
|
|
80
|
+
const [node, path] = entry;
|
|
81
|
+
const children = Node.children(editor, path);
|
|
82
|
+
for (const [child] of children) {
|
|
83
|
+
if (Text.isText(child))
|
|
84
|
+
continue;
|
|
85
|
+
Transforms.unwrapNodes(editor, { at: path });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const text = Node.string(node);
|
|
89
|
+
const match = URL_REGEX.exec(text);
|
|
90
|
+
if (!match || match[0] !== text) {
|
|
91
|
+
Transforms.unwrapNodes(editor, { at: path });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (endsWithPeriodOrQuestionMark(text)) {
|
|
95
|
+
Transforms.unwrapNodes(editor, { at: path });
|
|
96
|
+
const textBeforePeriod = text.slice(0, text.length - 1);
|
|
97
|
+
Transforms.wrapNodes(
|
|
98
|
+
editor,
|
|
99
|
+
{
|
|
100
|
+
type: "auto-link",
|
|
101
|
+
url: textBeforePeriod,
|
|
102
|
+
children: []
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
at: {
|
|
106
|
+
anchor: { path, offset: 0 },
|
|
107
|
+
focus: { path, offset: textBeforePeriod.length }
|
|
108
|
+
},
|
|
109
|
+
split: true
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
if (!isPreviousNodeValid(editor, path) || !isNextNodeValid(editor, path)) {
|
|
115
|
+
Transforms.unwrapNodes(editor, { at: path });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (node.url !== text) {
|
|
119
|
+
Transforms.setNodes(editor, { url: match[0] }, { at: path });
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const handleLinkCreate = (editor, entry) => {
|
|
124
|
+
const [node, path] = entry;
|
|
125
|
+
const match = URL_REGEX.exec(node.text);
|
|
126
|
+
if (!match)
|
|
127
|
+
return;
|
|
128
|
+
const start = match.index;
|
|
129
|
+
const end = start + match[0].length;
|
|
130
|
+
if (!isContentAroundValid(editor, entry, start, end))
|
|
131
|
+
return;
|
|
132
|
+
Transforms.wrapNodes(
|
|
133
|
+
editor,
|
|
134
|
+
{
|
|
135
|
+
type: "auto-link",
|
|
136
|
+
url: match[0],
|
|
137
|
+
children: []
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
at: {
|
|
141
|
+
anchor: { path, offset: start },
|
|
142
|
+
focus: { path, offset: end }
|
|
143
|
+
},
|
|
144
|
+
split: true
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
return;
|
|
148
|
+
};
|
|
149
|
+
const handleNeighbours = (editor, entry) => {
|
|
150
|
+
const [node, path] = entry;
|
|
151
|
+
const text = node.text;
|
|
152
|
+
const previousSibling = Editor.previous(editor, { at: path });
|
|
153
|
+
if (previousSibling && isComposerBodyAutoLink(previousSibling[0])) {
|
|
154
|
+
if (PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC.test(text)) {
|
|
155
|
+
Transforms.unwrapNodes(editor, { at: previousSibling[1] });
|
|
156
|
+
Transforms.mergeNodes(editor, { at: path });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (!startsWithSeparator(text)) {
|
|
160
|
+
Transforms.unwrapNodes(editor, { at: previousSibling[1] });
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const nextSibling = Editor.next(editor, { at: path });
|
|
165
|
+
if (nextSibling && isComposerBodyAutoLink(nextSibling[0]) && !endsWithSeparator(text)) {
|
|
166
|
+
Transforms.unwrapNodes(editor, { at: nextSibling[1] });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export { isComposerBodyAutoLink, withAutoLinks };
|
|
172
|
+
//# sourceMappingURL=auto-links.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-links.mjs","sources":["../../../src/slate/plugins/auto-links.ts"],"sourcesContent":["import type { NodeEntry } from \"slate\";\nimport { Editor, Element, Node, Path, Range, Text, Transforms } from \"slate\";\n\nimport type { ComposerBodyAutoLink } from \"../../types\";\n\n/**\n * This implementation is inspired by Lexical's AutoLink plugin.\n * Additional modifications and features were added to adapt it to our specific needs.\n *\n * Original Lexical AutoLink plugin can be found at [Lexical's Github Repository](https://github.com/facebook/lexical/blob/main/packages/lexical-react/src/LexicalAutoLinkPlugin.ts)\n */\nexport function withAutoLinks(editor: Editor): Editor {\n const { isInline, normalizeNode, deleteBackward } = editor;\n\n editor.isInline = (element) => {\n return element.type === \"auto-link\" ? true : isInline(element);\n };\n\n editor.normalizeNode = (entry) => {\n const [node, path] = entry;\n\n if (Text.isText(node)) {\n const parentNode = Node.parent(editor, path);\n\n if (isComposerBodyAutoLink(parentNode)) {\n const parentPath = Path.parent(path);\n handleLinkEdit(editor, [parentNode, parentPath]);\n } else {\n handleLinkCreate(editor, [node, path]);\n handleNeighbours(editor, [node, path]);\n }\n }\n\n normalizeNode(entry);\n };\n\n editor.deleteBackward = (unit) => {\n deleteBackward(unit);\n const { selection } = editor;\n if (!selection) return;\n\n if (!Range.isCollapsed(selection)) return;\n\n const [match] = Editor.nodes(editor, {\n at: selection,\n match: isComposerBodyAutoLink,\n mode: \"lowest\",\n });\n\n if (!match) return;\n\n Transforms.unwrapNodes(editor, {\n match: isComposerBodyAutoLink,\n });\n };\n\n return editor;\n}\n\nexport function isComposerBodyAutoLink(\n node: Node\n): node is ComposerBodyAutoLink {\n return Element.isElement(node) && node.type === \"auto-link\";\n}\n\n/**\n * 1. ((https?:\\/\\/(www\\.)?)|(www\\.))\n * - Matches 'http://' or 'https://' optionally followed by 'www.', or just 'www.'\n *\n * 2. [-a-zA-Z0-9@:%._+~#=]{1,256}\n * - Matches any character in the set [-a-zA-Z0-9@:%._+~#=] between 1 and 256 times, often found in the domain and subdomain part of the URL\n *\n * 3. \\.[a-zA-Z0-9()]{1,6}\n * - Matches a period followed by any character in the set [a-zA-Z0-9()] between 1 and 6 times, usually indicating the domain extension like .com, .org, etc.\n *\n * 4. \\b\n * - Represents a word boundary, ensuring that the characters following cannot be part of a different word\n *\n * 5. ([-a-zA-Z0-9().@:%_+~#?&//=]*)\n * - Matches any character in the set [-a-zA-Z0-9().@:%_+~#?&//=] between 0 and unlimited times, often found in the path, query parameters, or anchor part of the URL\n *\n * Matching URLs:\n * - http://www.example.com\n * - https://www.example.com\n * - www.example.com\n * - https://example.com/path?query=param#anchor\n *\n * Non-Matching URLs:\n * - http:/example.com (malformed scheme)\n * - example (missing scheme and domain extension)\n * - ftp://example.com (ftp scheme is not supported)\n * - example.com (missing scheme)\n */\nconst URL_REGEX =\n /((https?:\\/\\/(www\\.)?)|(www\\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9().@:%_+~#?&//=]*)/;\n\nconst PUNCTUATION_OR_SPACE = /[.,;!?\\s]/;\n\nconst PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC = /^[.?][a-zA-Z0-9]+/;\n\n/**\n * Helper function to check if a character is a separator (punctuation or space)\n * @param char The character to check\n * @returns Whether the character is a separator or not\n */\nfunction isSeparator(char: string): boolean {\n return PUNCTUATION_OR_SPACE.test(char);\n}\n\n/**\n * Helper function to check if a text content ends with a separator (punctuation or space)\n * @param textContent The text content to check\n * @returns Whether the text content ends with a separator or not\n */\nfunction endsWithSeparator(textContent: string): boolean {\n return isSeparator(textContent[textContent.length - 1]);\n}\n\n/**\n * Helper function to check if a text content starts with a separator (punctuation or space)\n * @param textContent The text content to check\n * @returns Whether the text content starts with a separator or not\n */\nfunction startsWithSeparator(textContent: string): boolean {\n return isSeparator(textContent[0]);\n}\n\n/**\n * Helper function to check if a text content ends with a period or question mark\n * @param textContent The text content to check\n * @returns Whether the text content ends with a period or not\n */\nfunction endsWithPeriodOrQuestionMark(textContent: string): boolean {\n return (\n textContent[textContent.length - 1] === \".\" ||\n textContent[textContent.length - 1] === \"?\"\n );\n}\n\n/**\n * Helper function to check if the previous node is valid (text node that ends with a separator or is empty)\n */\nfunction isPreviousNodeValid(editor: Editor, path: Path): boolean {\n const entry = Editor.previous(editor, { at: path });\n if (!entry) return true;\n\n return (\n Text.isText(entry[0]) &&\n (endsWithSeparator(entry[0].text) || entry[0].text === \"\")\n );\n}\n\n/**\n * Helper function to check if the next node is valid (text node that starts with a separator or is empty)\n */\nfunction isNextNodeValid(editor: Editor, path: Path): boolean {\n const entry = Editor.next(editor, { at: path });\n if (!entry) return true;\n\n return (\n Text.isText(entry[0]) &&\n (startsWithSeparator(entry[0].text) || entry[0].text === \"\")\n );\n}\n\n/**\n * Helper function to check if the content around a text node is valid.\n * @param editor\n * @param entry\n * @param start\n * @param end\n * @returns\n */\nfunction isContentAroundValid(\n editor: Editor,\n entry: NodeEntry<Text>,\n start: number,\n end: number\n): boolean {\n const [node, path] = entry;\n const text = node.text;\n\n const contentBeforeIsValid =\n start > 0\n ? isSeparator(text[start - 1])\n : isPreviousNodeValid(editor, path);\n\n const contentAfterIsValid =\n end < text.length ? isSeparator(text[end]) : isNextNodeValid(editor, path);\n\n return contentBeforeIsValid && contentAfterIsValid;\n}\n\nconst handleLinkEdit = (\n editor: Editor,\n entry: NodeEntry<ComposerBodyAutoLink>\n) => {\n const [node, path] = entry;\n\n // Step 1: Ensure that the Link node only contains text nodes as children\n const children = Node.children(editor, path);\n for (const [child] of children) {\n if (Text.isText(child)) continue;\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n // Attempt to match the text content (of the Link node) against the URL regex\n const text = Node.string(node);\n const match = URL_REGEX.exec(text);\n\n // Step 2: Ensure that the text content of the Link node matches the URL regex and is identical to the match\n if (!match || match[0] !== text) {\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n\n // Step 3: Ensure that if the text content of the Link node ends with a period, we unwrap the Link node and wrap the text before the period in a new Link node\n if (endsWithPeriodOrQuestionMark(text)) {\n Transforms.unwrapNodes(editor, { at: path });\n\n const textBeforePeriod = text.slice(0, text.length - 1);\n\n // Remove the last character from the link text and wrap the remaining text in a new link node\n Transforms.wrapNodes<ComposerBodyAutoLink>(\n editor,\n {\n type: \"auto-link\",\n url: textBeforePeriod,\n children: [],\n },\n {\n at: {\n anchor: { path, offset: 0 },\n focus: { path, offset: textBeforePeriod.length },\n },\n split: true,\n }\n );\n return;\n }\n\n // Step 4: Ensure that the text content of the Link node is surrounded by separators or the start/end of the text content\n if (!isPreviousNodeValid(editor, path) || !isNextNodeValid(editor, path)) {\n Transforms.unwrapNodes(editor, { at: path });\n return;\n }\n\n // Step 5: Ensure that the url attribute of the Link node is identical to its text content\n if (node.url !== text) {\n Transforms.setNodes(editor, { url: match[0] }, { at: path });\n return;\n }\n};\n\nconst handleLinkCreate = (editor: Editor, entry: NodeEntry<Text>) => {\n const [node, path] = entry;\n\n // Step 1: Ensure that the text content of the node matches the URL regex\n const match = URL_REGEX.exec(node.text);\n if (!match) return;\n\n const start = match.index;\n const end = start + match[0].length;\n\n // Step 2: Ensure that the content around the node is valid\n if (!isContentAroundValid(editor, entry, start, end)) return;\n\n Transforms.wrapNodes<ComposerBodyAutoLink>(\n editor,\n {\n type: \"auto-link\",\n url: match[0],\n children: [],\n },\n {\n at: {\n anchor: { path, offset: start },\n focus: { path, offset: end },\n },\n split: true,\n }\n );\n return;\n};\n\nconst handleNeighbours = (editor: Editor, entry: NodeEntry<Text>) => {\n const [node, path] = entry;\n const text = node.text;\n\n const previousSibling = Editor.previous(editor, { at: path });\n\n if (previousSibling && isComposerBodyAutoLink(previousSibling[0])) {\n if (PERIOD_OR_QUESTION_MARK_FOLLOWED_BY_ALPHANUMERIC.test(text)) {\n Transforms.unwrapNodes(editor, { at: previousSibling[1] });\n Transforms.mergeNodes(editor, { at: path });\n return;\n }\n\n if (!startsWithSeparator(text)) {\n Transforms.unwrapNodes(editor, { at: previousSibling[1] });\n return;\n }\n }\n\n const nextSibling = Editor.next(editor, { at: path });\n if (\n nextSibling &&\n isComposerBodyAutoLink(nextSibling[0]) &&\n !endsWithSeparator(text)\n ) {\n Transforms.unwrapNodes(editor, { at: nextSibling[1] });\n return;\n }\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var isEmpty = require('../utils/is-empty.js');
|
|
4
|
+
var marks = require('../utils/marks.js');
|
|
5
|
+
|
|
6
|
+
function withEmptyClearFormatting(editor) {
|
|
7
|
+
const { onChange } = editor;
|
|
8
|
+
editor.onChange = (options) => {
|
|
9
|
+
if (isEmpty.isEmpty(editor, editor.children)) {
|
|
10
|
+
marks.removeMarks(editor);
|
|
11
|
+
}
|
|
12
|
+
onChange(options);
|
|
13
|
+
};
|
|
14
|
+
return editor;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
exports.withEmptyClearFormatting = withEmptyClearFormatting;
|
|
18
|
+
//# sourceMappingURL=empty-clear-formatting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-clear-formatting.js","sources":["../../../src/slate/plugins/empty-clear-formatting.ts"],"sourcesContent":["import type { Editor as SlateEditor } from \"slate\";\n\nimport { isEmpty } from \"../utils/is-empty\";\nimport { removeMarks } from \"../utils/marks\";\n\n// This plugins clears formatting on empty blocks\n// https://github.com/ianstormtaylor/slate/issues/2908\nexport function withEmptyClearFormatting<T extends SlateEditor>(editor: T): T {\n const { onChange } = editor;\n\n editor.onChange = (options) => {\n if (isEmpty(editor, editor.children)) {\n removeMarks(editor);\n }\n\n onChange(options);\n };\n\n return editor;\n}\n"],"names":["isEmpty","removeMarks"],"mappings":";;;;;AAOO,SAAS,yBAAgD,MAAc,EAAA;AAC5E,EAAM,MAAA,EAAE,UAAa,GAAA,MAAA,CAAA;AAErB,EAAO,MAAA,CAAA,QAAA,GAAW,CAAC,OAAY,KAAA;AAC7B,IAAA,IAAIA,eAAQ,CAAA,MAAA,EAAQ,MAAO,CAAA,QAAQ,CAAG,EAAA;AACpC,MAAAC,iBAAA,CAAY,MAAM,CAAA,CAAA;AAAA,KACpB;AAEA,IAAA,QAAA,CAAS,OAAO,CAAA,CAAA;AAAA,GAClB,CAAA;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isEmpty } from '../utils/is-empty.mjs';
|
|
2
|
+
import { removeMarks } from '../utils/marks.mjs';
|
|
3
|
+
|
|
4
|
+
function withEmptyClearFormatting(editor) {
|
|
5
|
+
const { onChange } = editor;
|
|
6
|
+
editor.onChange = (options) => {
|
|
7
|
+
if (isEmpty(editor, editor.children)) {
|
|
8
|
+
removeMarks(editor);
|
|
9
|
+
}
|
|
10
|
+
onChange(options);
|
|
11
|
+
};
|
|
12
|
+
return editor;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { withEmptyClearFormatting };
|
|
16
|
+
//# sourceMappingURL=empty-clear-formatting.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"empty-clear-formatting.mjs","sources":["../../../src/slate/plugins/empty-clear-formatting.ts"],"sourcesContent":["import type { Editor as SlateEditor } from \"slate\";\n\nimport { isEmpty } from \"../utils/is-empty\";\nimport { removeMarks } from \"../utils/marks\";\n\n// This plugins clears formatting on empty blocks\n// https://github.com/ianstormtaylor/slate/issues/2908\nexport function withEmptyClearFormatting<T extends SlateEditor>(editor: T): T {\n const { onChange } = editor;\n\n editor.onChange = (options) => {\n if (isEmpty(editor, editor.children)) {\n removeMarks(editor);\n }\n\n onChange(options);\n };\n\n return editor;\n}\n"],"names":[],"mappings":";;;AAOO,SAAS,yBAAgD,MAAc,EAAA;AAC5E,EAAM,MAAA,EAAE,UAAa,GAAA,MAAA,CAAA;AAErB,EAAO,MAAA,CAAA,QAAA,GAAW,CAAC,OAAY,KAAA;AAC7B,IAAA,IAAI,OAAQ,CAAA,MAAA,EAAQ,MAAO,CAAA,QAAQ,CAAG,EAAA;AACpC,MAAA,WAAA,CAAY,MAAM,CAAA,CAAA;AAAA,KACpB;AAEA,IAAA,QAAA,CAAS,OAAO,CAAA,CAAA;AAAA,GAClB,CAAA;AAEA,EAAO,OAAA,MAAA,CAAA;AACT;;;;"}
|