@eventuras/scribo 0.8.2 → 0.10.7
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/dist/App.d.ts +11 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/MarkdownEditor.d.ts +18 -0
- package/dist/MarkdownEditor.d.ts.map +1 -0
- package/dist/MarkdownEditor2.js +111 -0
- package/dist/MarkdownEditor2.js.map +1 -0
- package/dist/MarkdownInput.d.ts +27 -0
- package/dist/MarkdownInput.d.ts.map +1 -0
- package/dist/MarkdownInput.js +57 -0
- package/dist/MarkdownInput.js.map +1 -0
- package/dist/callout.js +5 -0
- package/dist/context/SharedHistoryContext.d.ts +11 -0
- package/dist/context/SharedHistoryContext.d.ts.map +1 -0
- package/dist/context/SharedHistoryContext.js +12 -0
- package/dist/context/SharedHistoryContext.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +4 -0
- package/dist/nodes/EditorNodes.d.ts +4 -0
- package/dist/nodes/EditorNodes.d.ts.map +1 -0
- package/dist/nodes/EditorNodes.js +39 -0
- package/dist/nodes/EditorNodes.js.map +1 -0
- package/dist/nodes/callout/CalloutComponent.d.ts +6 -0
- package/dist/nodes/callout/CalloutComponent.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutComponent.js +53 -0
- package/dist/nodes/callout/CalloutComponent.js.map +1 -0
- package/dist/nodes/callout/CalloutNode.d.ts +27 -0
- package/dist/nodes/callout/CalloutNode.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutNode.js +153 -0
- package/dist/nodes/callout/CalloutNode.js.map +1 -0
- package/dist/nodes/callout/CalloutTransformer.d.ts +3 -0
- package/dist/nodes/callout/CalloutTransformer.d.ts.map +1 -0
- package/dist/nodes/callout/CalloutTransformer.js +48 -0
- package/dist/nodes/callout/CalloutTransformer.js.map +1 -0
- package/dist/nodes/callout/calloutPlugin.d.ts +3 -0
- package/dist/nodes/callout/calloutPlugin.d.ts.map +1 -0
- package/dist/nodes/callout/calloutPlugin.js +34 -0
- package/dist/nodes/callout/calloutPlugin.js.map +1 -0
- package/dist/nodes/callout/index.d.ts +6 -0
- package/dist/nodes/callout/index.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemComponent.d.ts +9 -0
- package/dist/nodes/schedule/ScheduleItemComponent.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemComponent.js +167 -0
- package/dist/nodes/schedule/ScheduleItemComponent.js.map +1 -0
- package/dist/nodes/schedule/ScheduleItemNode.d.ts +31 -0
- package/dist/nodes/schedule/ScheduleItemNode.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleItemNode.js +94 -0
- package/dist/nodes/schedule/ScheduleItemNode.js.map +1 -0
- package/dist/nodes/schedule/ScheduleTransformer.d.ts +22 -0
- package/dist/nodes/schedule/ScheduleTransformer.d.ts.map +1 -0
- package/dist/nodes/schedule/ScheduleTransformer.js +60 -0
- package/dist/nodes/schedule/ScheduleTransformer.js.map +1 -0
- package/dist/nodes/schedule/index.d.ts +5 -0
- package/dist/nodes/schedule/index.d.ts.map +1 -0
- package/dist/nodes/schedule/schedulePlugin.d.ts +3 -0
- package/dist/nodes/schedule/schedulePlugin.d.ts.map +1 -0
- package/dist/nodes/schedule/schedulePlugin.js +33 -0
- package/dist/nodes/schedule/schedulePlugin.js.map +1 -0
- package/dist/plugins/AutoLinkPlugin.d.ts +3 -0
- package/dist/plugins/AutoLinkPlugin.d.ts.map +1 -0
- package/dist/plugins/AutoLinkPlugin.js +22 -0
- package/dist/plugins/AutoLinkPlugin.js.map +1 -0
- package/dist/plugins/FloatingLinkEditorPlugin.d.ts +7 -0
- package/dist/plugins/FloatingLinkEditorPlugin.d.ts.map +1 -0
- package/dist/plugins/FloatingLinkEditorPlugin2.js +302 -0
- package/dist/plugins/FloatingLinkEditorPlugin2.js.map +1 -0
- package/dist/plugins/HistoryPlugin.d.ts +26 -0
- package/dist/plugins/HistoryPlugin.d.ts.map +1 -0
- package/dist/plugins/LinkPlugin.d.ts +3 -0
- package/dist/plugins/LinkPlugin.d.ts.map +1 -0
- package/dist/plugins/LinkPlugin.js +18 -0
- package/dist/plugins/LinkPlugin.js.map +1 -0
- package/dist/plugins/ToolbarPlugin.d.ts +7 -0
- package/dist/plugins/ToolbarPlugin.d.ts.map +1 -0
- package/dist/plugins/ToolbarPlugin.js +372 -0
- package/dist/plugins/ToolbarPlugin.js.map +1 -0
- package/dist/schedule.js +4 -0
- package/dist/scribo.css +1977 -0
- package/dist/themes/EditorTheme.d.ts +4 -0
- package/dist/themes/EditorTheme.d.ts.map +1 -0
- package/dist/themes/EditorTheme2.js +107 -0
- package/dist/themes/EditorTheme2.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/ui/ContentEditable.d.ts +6 -0
- package/dist/ui/ContentEditable.d.ts.map +1 -0
- package/dist/ui/ContentEditable2.js +14 -0
- package/dist/ui/ContentEditable2.js.map +1 -0
- package/dist/ui/DropDown.d.ts +18 -0
- package/dist/ui/DropDown.d.ts.map +1 -0
- package/dist/ui/DropDown.js +162 -0
- package/dist/ui/DropDown.js.map +1 -0
- package/dist/ui/Placeholder.d.ts +6 -0
- package/dist/ui/Placeholder.d.ts.map +1 -0
- package/dist/ui/Placeholder2.js +13 -0
- package/dist/ui/Placeholder2.js.map +1 -0
- package/dist/utils/environment.d.ts +24 -0
- package/dist/utils/environment.d.ts.map +1 -0
- package/dist/utils/environment.js +20 -0
- package/dist/utils/environment.js.map +1 -0
- package/dist/utils/getSelectedNode.d.ts +3 -0
- package/dist/utils/getSelectedNode.d.ts.map +1 -0
- package/dist/utils/getSelectedNode.js +23 -0
- package/dist/utils/getSelectedNode.js.map +1 -0
- package/dist/utils/setFloatingElemPosition.d.ts +2 -0
- package/dist/utils/setFloatingElemPosition.d.ts.map +1 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts +2 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.d.ts.map +1 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.js +33 -0
- package/dist/utils/setFloatingElemPositionForLinkEditor.js.map +1 -0
- package/dist/utils/url.d.ts +11 -0
- package/dist/utils/url.d.ts.map +1 -0
- package/dist/utils/url.js +33 -0
- package/dist/utils/url.js.map +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +57 -39
- package/src/MarkdownEditor.css +130 -27
- package/src/MarkdownEditor.tsx +82 -31
- package/src/MarkdownInput.tsx +9 -10
- package/src/context/SharedHistoryContext.tsx +8 -16
- package/src/main.tsx +3 -3
- package/src/nodes/EditorNodes.ts +10 -10
- package/src/nodes/callout/Callout.css +94 -0
- package/src/nodes/callout/CalloutComponent.tsx +61 -0
- package/src/nodes/callout/CalloutNode.ts +197 -0
- package/src/nodes/callout/CalloutTransformer.ts +87 -0
- package/src/nodes/callout/calloutPlugin.ts +37 -0
- package/src/nodes/callout/index.ts +5 -0
- package/src/nodes/schedule/ScheduleItem.css +140 -0
- package/src/nodes/schedule/ScheduleItemComponent.tsx +195 -0
- package/src/nodes/schedule/ScheduleItemNode.ts +135 -0
- package/src/nodes/schedule/ScheduleTransformer.ts +80 -0
- package/src/nodes/schedule/index.ts +4 -0
- package/src/nodes/schedule/schedulePlugin.ts +33 -0
- package/src/plugins/AutoLinkPlugin.tsx +5 -10
- package/src/plugins/FloatingLinkEditorPlugin.tsx +42 -66
- package/src/plugins/HistoryPlugin.tsx +20 -30
- package/src/plugins/LinkPlugin.tsx +2 -3
- package/src/plugins/ToolbarPlugin.tsx +129 -141
- package/src/themes/EditorTheme.css +82 -62
- package/src/themes/EditorTheme.ts +89 -90
- package/src/types.ts +27 -0
- package/src/ui/ContentEditable.tsx +5 -5
- package/src/ui/DropDown.tsx +23 -41
- package/src/ui/Placeholder.tsx +21 -21
- package/src/utils/environment.ts +6 -12
- package/src/utils/getSelectedNode.ts +3 -5
- package/src/utils/setFloatingElemPosition.ts +2 -5
- package/src/utils/setFloatingElemPositionForLinkEditor.ts +1 -1
- package/src/utils/url.ts +4 -10
- package/tsconfig.json +8 -0
- package/CHANGELOG.md +0 -59
- package/README.md +0 -126
- package/RELEASE.md +0 -102
- package/eslint.config.js +0 -4
- package/src/App.css +0 -35
- package/src/App.tsx +0 -42
- package/src/index.tsx +0 -13
- package/tsconfig.node.json +0 -11
- package/vite.config.site.ts +0 -19
- package/vite.config.ts +0 -33
- /package/{src → dist}/vite-env.d.ts +0 -0
package/src/ui/DropDown.tsx
CHANGED
|
@@ -6,19 +6,11 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import {isDOMNode} from 'lexical';
|
|
9
|
+
import { isDOMNode } from 'lexical';
|
|
10
|
+
import type { JSX } from 'react';
|
|
12
11
|
import * as React from 'react';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
useCallback,
|
|
16
|
-
useEffect,
|
|
17
|
-
useMemo,
|
|
18
|
-
useRef,
|
|
19
|
-
useState,
|
|
20
|
-
} from 'react';
|
|
21
|
-
import {createPortal} from 'react-dom';
|
|
12
|
+
import { type ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
+
import { createPortal } from 'react-dom';
|
|
22
14
|
|
|
23
15
|
type DropDownContextType = {
|
|
24
16
|
registerItem: (ref: React.RefObject<HTMLButtonElement>) => void;
|
|
@@ -47,21 +39,16 @@ export function DropDownItem({
|
|
|
47
39
|
throw new Error('DropDownItem must be used within a DropDown');
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
const {registerItem} = dropDownContext;
|
|
42
|
+
const { registerItem } = dropDownContext;
|
|
51
43
|
|
|
52
44
|
useEffect(() => {
|
|
53
|
-
if (ref
|
|
45
|
+
if (ref?.current) {
|
|
54
46
|
registerItem(ref as React.RefObject<HTMLButtonElement>);
|
|
55
47
|
}
|
|
56
48
|
}, [ref, registerItem]);
|
|
57
49
|
|
|
58
50
|
return (
|
|
59
|
-
<button
|
|
60
|
-
className={className}
|
|
61
|
-
onClick={onClick}
|
|
62
|
-
ref={ref}
|
|
63
|
-
title={title}
|
|
64
|
-
type="button">
|
|
51
|
+
<button className={className} onClick={onClick} ref={ref} title={title} type="button">
|
|
65
52
|
{children}
|
|
66
53
|
</button>
|
|
67
54
|
);
|
|
@@ -71,20 +58,19 @@ function DropDownItems({
|
|
|
71
58
|
children,
|
|
72
59
|
dropDownRef,
|
|
73
60
|
onClose,
|
|
74
|
-
}: {
|
|
61
|
+
}: Readonly<{
|
|
75
62
|
children: React.ReactNode;
|
|
76
63
|
dropDownRef: React.Ref<HTMLDivElement>;
|
|
77
64
|
onClose: () => void;
|
|
78
|
-
}) {
|
|
65
|
+
}>) {
|
|
79
66
|
const [items, setItems] = useState<React.RefObject<HTMLButtonElement>[]>();
|
|
80
|
-
const [highlightedItem, setHighlightedItem] =
|
|
81
|
-
useState<React.RefObject<HTMLButtonElement>>();
|
|
67
|
+
const [highlightedItem, setHighlightedItem] = useState<React.RefObject<HTMLButtonElement>>();
|
|
82
68
|
|
|
83
69
|
const registerItem = useCallback(
|
|
84
70
|
(itemRef: React.RefObject<HTMLButtonElement>) => {
|
|
85
71
|
setItems((prev) => (prev ? [...prev, itemRef] : [itemRef]));
|
|
86
72
|
},
|
|
87
|
-
[setItems]
|
|
73
|
+
[setItems]
|
|
88
74
|
);
|
|
89
75
|
|
|
90
76
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
@@ -122,7 +108,7 @@ function DropDownItems({
|
|
|
122
108
|
() => ({
|
|
123
109
|
registerItem,
|
|
124
110
|
}),
|
|
125
|
-
[registerItem]
|
|
111
|
+
[registerItem]
|
|
126
112
|
);
|
|
127
113
|
|
|
128
114
|
useEffect(() => {
|
|
@@ -130,7 +116,7 @@ function DropDownItems({
|
|
|
130
116
|
setHighlightedItem(items[0]);
|
|
131
117
|
}
|
|
132
118
|
|
|
133
|
-
if (highlightedItem
|
|
119
|
+
if (highlightedItem?.current) {
|
|
134
120
|
highlightedItem.current.focus();
|
|
135
121
|
}
|
|
136
122
|
}, [items, highlightedItem]);
|
|
@@ -167,7 +153,7 @@ export default function DropDown({
|
|
|
167
153
|
|
|
168
154
|
const handleClose = () => {
|
|
169
155
|
setShowDropDown(false);
|
|
170
|
-
if (buttonRef
|
|
156
|
+
if (buttonRef?.current) {
|
|
171
157
|
buttonRef.current.focus();
|
|
172
158
|
}
|
|
173
159
|
};
|
|
@@ -177,12 +163,9 @@ export default function DropDown({
|
|
|
177
163
|
const dropDown = dropDownRef.current;
|
|
178
164
|
|
|
179
165
|
if (showDropDown && button !== null && dropDown !== null) {
|
|
180
|
-
const {top, left} = button.getBoundingClientRect();
|
|
166
|
+
const { top, left } = button.getBoundingClientRect();
|
|
181
167
|
dropDown.style.top = `${top + button.offsetHeight + dropDownPadding}px`;
|
|
182
|
-
dropDown.style.left = `${Math.min(
|
|
183
|
-
left,
|
|
184
|
-
window.innerWidth - dropDown.offsetWidth - 20,
|
|
185
|
-
)}px`;
|
|
168
|
+
dropDown.style.left = `${Math.min(left, window.innerWidth - dropDown.offsetWidth - 20)}px`;
|
|
186
169
|
}
|
|
187
170
|
}, [dropDownRef, buttonRef, showDropDown]);
|
|
188
171
|
|
|
@@ -196,7 +179,7 @@ export default function DropDown({
|
|
|
196
179
|
return;
|
|
197
180
|
}
|
|
198
181
|
if (stopCloseOnClickSelf) {
|
|
199
|
-
if (dropDownRef.current
|
|
182
|
+
if (dropDownRef.current?.contains(target)) {
|
|
200
183
|
return;
|
|
201
184
|
}
|
|
202
185
|
}
|
|
@@ -218,7 +201,7 @@ export default function DropDown({
|
|
|
218
201
|
const button = buttonRef.current;
|
|
219
202
|
const dropDown = dropDownRef.current;
|
|
220
203
|
if (button !== null && dropDown !== null) {
|
|
221
|
-
const {top} = button.getBoundingClientRect();
|
|
204
|
+
const { top } = button.getBoundingClientRect();
|
|
222
205
|
const newPosition = top + button.offsetHeight + dropDownPadding;
|
|
223
206
|
if (newPosition !== dropDown.getBoundingClientRect().top) {
|
|
224
207
|
dropDown.style.top = `${newPosition}px`;
|
|
@@ -242,11 +225,10 @@ export default function DropDown({
|
|
|
242
225
|
aria-label={buttonAriaLabel || buttonLabel}
|
|
243
226
|
className={buttonClassName}
|
|
244
227
|
onClick={() => setShowDropDown(!showDropDown)}
|
|
245
|
-
ref={buttonRef}
|
|
228
|
+
ref={buttonRef}
|
|
229
|
+
>
|
|
246
230
|
{buttonIconClassName && <span className={buttonIconClassName} />}
|
|
247
|
-
{buttonLabel &&
|
|
248
|
-
<span className="text dropdown-button-text">{buttonLabel}</span>
|
|
249
|
-
)}
|
|
231
|
+
{buttonLabel && <span className="text dropdown-button-text">{buttonLabel}</span>}
|
|
250
232
|
<i className="chevron-down" />
|
|
251
233
|
</button>
|
|
252
234
|
|
|
@@ -255,8 +237,8 @@ export default function DropDown({
|
|
|
255
237
|
<DropDownItems dropDownRef={dropDownRef} onClose={handleClose}>
|
|
256
238
|
{children}
|
|
257
239
|
</DropDownItems>,
|
|
258
|
-
document.body
|
|
240
|
+
document.body
|
|
259
241
|
)}
|
|
260
242
|
</>
|
|
261
243
|
);
|
|
262
|
-
}
|
|
244
|
+
}
|
package/src/ui/Placeholder.tsx
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
import type {JSX} from 'react';
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import { ReactNode } from
|
|
12
|
-
|
|
13
|
-
export default function Placeholder({
|
|
14
|
-
children,
|
|
15
|
-
className,
|
|
16
|
-
}: {
|
|
17
|
-
children: ReactNode;
|
|
18
|
-
className?: string;
|
|
19
|
-
}): JSX.Element {
|
|
20
|
-
return <div className={className ||
|
|
21
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { JSX } from 'react';
|
|
9
|
+
import './Placeholder.css';
|
|
10
|
+
|
|
11
|
+
import type { ReactNode } from 'react';
|
|
12
|
+
|
|
13
|
+
export default function Placeholder({
|
|
14
|
+
children,
|
|
15
|
+
className,
|
|
16
|
+
}: Readonly<{
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
className?: string;
|
|
19
|
+
}>): JSX.Element {
|
|
20
|
+
return <div className={className || 'Placeholder__root'}>{children}</div>;
|
|
21
|
+
}
|
package/src/utils/environment.ts
CHANGED
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
export const CAN_USE_DOM: boolean =
|
|
10
|
-
typeof window !==
|
|
11
|
-
typeof window.document !== "undefined" &&
|
|
12
|
-
typeof window.document.createElement !== "undefined";
|
|
10
|
+
typeof window !== 'undefined' && typeof window.document?.createElement !== 'undefined';
|
|
13
11
|
|
|
14
12
|
declare global {
|
|
15
13
|
interface Document {
|
|
@@ -21,8 +19,7 @@ declare global {
|
|
|
21
19
|
}
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
const documentMode =
|
|
25
|
-
CAN_USE_DOM && "documentMode" in document ? document.documentMode : null;
|
|
22
|
+
const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
|
|
26
23
|
|
|
27
24
|
//TODO forcing false on this to stop mismatch render between ssr and clientside
|
|
28
25
|
export const IS_APPLE = false;
|
|
@@ -32,22 +29,19 @@ export const IS_FIREFOX: boolean =
|
|
|
32
29
|
CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
|
|
33
30
|
|
|
34
31
|
export const CAN_USE_BEFORE_INPUT: boolean =
|
|
35
|
-
CAN_USE_DOM &&
|
|
36
|
-
?
|
|
32
|
+
CAN_USE_DOM && 'InputEvent' in window && !documentMode
|
|
33
|
+
? 'getTargetRanges' in new window.InputEvent('input')
|
|
37
34
|
: false;
|
|
38
35
|
|
|
39
36
|
export const IS_SAFARI: boolean =
|
|
40
37
|
CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent);
|
|
41
38
|
|
|
42
39
|
export const IS_IOS: boolean =
|
|
43
|
-
CAN_USE_DOM &&
|
|
44
|
-
/iPad|iPhone|iPod/.test(navigator.userAgent) &&
|
|
45
|
-
!window.MSStream;
|
|
40
|
+
CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
|
46
41
|
|
|
47
42
|
// Keep these in case we need to use them in the future.
|
|
48
43
|
// export const IS_WINDOWS: boolean = CAN_USE_DOM && /Win/.test(navigator.platform);
|
|
49
|
-
export const IS_CHROME: boolean =
|
|
50
|
-
CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
|
|
44
|
+
export const IS_CHROME: boolean = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
|
|
51
45
|
// export const canUseTextInputEvent: boolean = CAN_USE_DOM && 'TextEvent' in window && !documentMode;
|
|
52
46
|
|
|
53
47
|
export const IS_APPLE_WEBKIT =
|
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* source: https://github.com/facebook/lexical/blob/main/packages/lexical-playground/src/utils/getSelectedNode.ts
|
|
8
8
|
*/
|
|
9
|
-
import { $isAtNodeEnd } from
|
|
10
|
-
import { ElementNode, RangeSelection, TextNode } from
|
|
9
|
+
import { $isAtNodeEnd } from '@lexical/selection';
|
|
10
|
+
import type { ElementNode, RangeSelection, TextNode } from 'lexical';
|
|
11
11
|
|
|
12
|
-
export function getSelectedNode(
|
|
13
|
-
selection: RangeSelection,
|
|
14
|
-
): TextNode | ElementNode {
|
|
12
|
+
export function getSelectedNode(selection: RangeSelection): TextNode | ElementNode {
|
|
15
13
|
const anchor = selection.anchor;
|
|
16
14
|
const focus = selection.focus;
|
|
17
15
|
const anchorNode = selection.anchor.getNode();
|
|
@@ -14,7 +14,7 @@ export function setFloatingElemPosition(
|
|
|
14
14
|
anchorElem: HTMLElement,
|
|
15
15
|
isLink: boolean = false,
|
|
16
16
|
verticalGap: number = VERTICAL_GAP,
|
|
17
|
-
horizontalOffset: number = HORIZONTAL_OFFSET
|
|
17
|
+
horizontalOffset: number = HORIZONTAL_OFFSET
|
|
18
18
|
): void {
|
|
19
19
|
const scrollerElem = anchorElem.parentElement;
|
|
20
20
|
|
|
@@ -33,10 +33,7 @@ export function setFloatingElemPosition(
|
|
|
33
33
|
|
|
34
34
|
if (top < editorScrollerRect.top) {
|
|
35
35
|
// adjusted height for link element if the element is at top
|
|
36
|
-
top +=
|
|
37
|
-
floatingElemRect.height +
|
|
38
|
-
targetRect.height +
|
|
39
|
-
verticalGap * (isLink ? 9 : 2);
|
|
36
|
+
top += floatingElemRect.height + targetRect.height + verticalGap * (isLink ? 9 : 2);
|
|
40
37
|
}
|
|
41
38
|
|
|
42
39
|
if (left + floatingElemRect.width > editorScrollerRect.right) {
|
|
@@ -13,7 +13,7 @@ export function setFloatingElemPositionForLinkEditor(
|
|
|
13
13
|
floatingElem: HTMLElement,
|
|
14
14
|
anchorElem: HTMLElement,
|
|
15
15
|
verticalGap: number = VERTICAL_GAP,
|
|
16
|
-
horizontalOffset: number = HORIZONTAL_OFFSET
|
|
16
|
+
horizontalOffset: number = HORIZONTAL_OFFSET
|
|
17
17
|
): void {
|
|
18
18
|
const scrollerElem = anchorElem.parentElement;
|
|
19
19
|
|
package/src/utils/url.ts
CHANGED
|
@@ -7,20 +7,14 @@
|
|
|
7
7
|
* Source: https://github.com/facebook/lexical/blob/main/packages/lexical-playground/src/utils/url.ts
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
const SUPPORTED_URL_PROTOCOLS = new Set([
|
|
11
|
-
"http:",
|
|
12
|
-
"https:",
|
|
13
|
-
"mailto:",
|
|
14
|
-
"sms:",
|
|
15
|
-
"tel:",
|
|
16
|
-
]);
|
|
10
|
+
const SUPPORTED_URL_PROTOCOLS = new Set(['http:', 'https:', 'mailto:', 'sms:', 'tel:']);
|
|
17
11
|
|
|
18
12
|
export function sanitizeUrl(url: string): string {
|
|
19
13
|
try {
|
|
20
14
|
const parsedUrl = new URL(url);
|
|
21
15
|
// eslint-disable-next-line no-script-url
|
|
22
16
|
if (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {
|
|
23
|
-
return
|
|
17
|
+
return 'about:blank';
|
|
24
18
|
}
|
|
25
19
|
} catch {
|
|
26
20
|
return url;
|
|
@@ -30,10 +24,10 @@ export function sanitizeUrl(url: string): string {
|
|
|
30
24
|
|
|
31
25
|
// Source: https://stackoverflow.com/a/8234912/2013580
|
|
32
26
|
const urlRegExp = new RegExp(
|
|
33
|
-
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-
|
|
27
|
+
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-]*)?\??(?:[-+=&;%@.\w]*)#?(?:\w*))?)/
|
|
34
28
|
);
|
|
35
29
|
export function validateUrl(url: string): boolean {
|
|
36
30
|
// TODO Fix UI for link insertion; it should never default to an invalid URL such as https://.
|
|
37
31
|
// Maybe show a dialog where they user can type the URL before inserting it.
|
|
38
|
-
return url ===
|
|
32
|
+
return url === 'https://' || urlRegExp.test(url);
|
|
39
33
|
}
|
package/tsconfig.json
ADDED
package/CHANGELOG.md
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# @eventuras/scribo
|
|
2
|
-
|
|
3
|
-
## 0.8.2
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- chore: update deps
|
|
8
|
-
|
|
9
|
-
## 0.8.1
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- chore: update dependencies across frontend packages
|
|
14
|
-
|
|
15
|
-
## 0.8.0
|
|
16
|
-
|
|
17
|
-
### Minor Changes
|
|
18
|
-
|
|
19
|
-
### 🧱 Features
|
|
20
|
-
|
|
21
|
-
- feat(scribo): auto heigh expanding (6ca2322) [@eventuras/scribo]
|
|
22
|
-
|
|
23
|
-
### 🐞 Bug Fixes
|
|
24
|
-
|
|
25
|
-
- fix(scribo): import MarkdownEditor.css for styling (d1eec7a) [@eventuras/scribo]
|
|
26
|
-
- fix(scribo): disable swc in scribo (ebce6db) [@eventuras/scribo]
|
|
27
|
-
|
|
28
|
-
### ♻️ Refactoring
|
|
29
|
-
|
|
30
|
-
- refactor(scribo): merge markdowninput into scribo with flexible styling (373587e) [@eventuras/scribo]
|
|
31
|
-
|
|
32
|
-
### 🧹 Maintenance
|
|
33
|
-
|
|
34
|
-
- chore(scribo): externalize Lexical packages in build configuration (7c7caaf) [@eventuras/scribo]
|
|
35
|
-
- chore(convertoapi,docsite,web,markdown,scribo,sdk): upgrade deps (b2de638) [@eventuras/scribo]
|
|
36
|
-
|
|
37
|
-
### ⚙️ CI/CD
|
|
38
|
-
|
|
39
|
-
- ci(scribo): implement automated release workflow for Scribo (36d6ba1) [@eventuras/scribo]
|
|
40
|
-
|
|
41
|
-
## 0.7.1
|
|
42
|
-
|
|
43
|
-
### Patch Changes
|
|
44
|
-
|
|
45
|
-
- - chore(convertoapi,docsite,web,markdown,scribo,sdk): upgrade deps (51e931b) [@eventuras/scribo]
|
|
46
|
-
|
|
47
|
-
## 0.7.0
|
|
48
|
-
|
|
49
|
-
### Minor Changes
|
|
50
|
-
|
|
51
|
-
- ## Initial history (pre-Changesets)
|
|
52
|
-
- chore(scribo): upgrade lexical (f78dfa1)
|
|
53
|
-
- chore(scribo): update packages (3475e0f)
|
|
54
|
-
- feat(scribo): use readme as default content of editor page (428fc2b)
|
|
55
|
-
- fix(scribo): add dependency (101954b)
|
|
56
|
-
- feat(scribo): cache npm files for scribo build (a065b61)
|
|
57
|
-
- feat(scribo): add undo/redo to markdown editor (b2482cc)
|
|
58
|
-
- feat(scribo): adds links and link editing to editor (afe159d)
|
|
59
|
-
- feat(scribo): set up scribo demo site (a467bc2)
|
package/README.md
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
# Scribo markdown editor
|
|
2
|
-
|
|
3
|
-
Markdown editor built on [Lexical framework](https://lexical.dev/). Intended to be used as part of eventuras, but also packed as a standalone component. Scribo is a WYSIWYG editor with markdown export.
|
|
4
|
-
|
|
5
|
-
The editor should provide simple and intuitive editing of markdown text, with a focus on the most common use cases.
|
|
6
|
-
|
|
7
|
-
Test the [scribo editor online demo](https://scribo.losol.no/).
|
|
8
|
-
|
|
9
|
-
> **Lexical version**: we are keeping the lexical version in sync with the [lexical version used in Payload CMS](https://github.com/payloadcms/payload/blob/main/packages/richtext-lexical/package.json), to prevent multiple versions making trouble.
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
pnpm add @eventuras/scribo
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Usage
|
|
18
|
-
|
|
19
|
-
**Important**: You must import the CSS file for Scribo to display correctly:
|
|
20
|
-
|
|
21
|
-
### MarkdownEditor (WYSIWYG Editor)
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
import "@eventuras/scribo/style.css";
|
|
25
|
-
import { MarkdownEditor } from "@eventuras/scribo";
|
|
26
|
-
|
|
27
|
-
function MyComponent() {
|
|
28
|
-
return <MarkdownEditor defaultValue="# Hello World" />;
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
### MarkdownInput (Form-ready Input)
|
|
33
|
-
|
|
34
|
-
For use with native HTML forms (FormData API):
|
|
35
|
-
|
|
36
|
-
```tsx
|
|
37
|
-
import "@eventuras/scribo/style.css";
|
|
38
|
-
import { MarkdownInput } from "@eventuras/scribo";
|
|
39
|
-
|
|
40
|
-
function MyForm() {
|
|
41
|
-
return (
|
|
42
|
-
<form>
|
|
43
|
-
<MarkdownInput
|
|
44
|
-
name="description"
|
|
45
|
-
label="Description"
|
|
46
|
-
placeholder="Enter markdown..."
|
|
47
|
-
defaultValue="# Hello"
|
|
48
|
-
maxLength={500}
|
|
49
|
-
className="mb-4"
|
|
50
|
-
labelClassName="font-bold"
|
|
51
|
-
editorClassName="border rounded"
|
|
52
|
-
errorClassName="text-red-500"
|
|
53
|
-
/>
|
|
54
|
-
<button type="submit">Submit</button>
|
|
55
|
-
</form>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
The `MarkdownInput` component is framework-agnostic and provides:
|
|
61
|
-
|
|
62
|
-
- Hidden input for FormData submission
|
|
63
|
-
- Optional label and validation
|
|
64
|
-
- Flexible styling via className props
|
|
65
|
-
- Character limit validation
|
|
66
|
-
|
|
67
|
-
### Peer Dependencies
|
|
68
|
-
|
|
69
|
-
Scribo requires the following peer dependencies:
|
|
70
|
-
|
|
71
|
-
```bash
|
|
72
|
-
pnpm add react react-dom lexical @lexical/code @lexical/hashtag @lexical/link @lexical/list @lexical/mark @lexical/markdown @lexical/overflow @lexical/react @lexical/rich-text @lexical/selection @lexical/table @lexical/utils prismjs
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Prism.js for syntax highlighting:**
|
|
76
|
-
Scribo uses Prism.js for code syntax highlighting but does not bundle it. You need to install `prismjs` and import the language grammars you need in your application.
|
|
77
|
-
|
|
78
|
-
Example:
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
import "prismjs";
|
|
82
|
-
import "prismjs/components/prism-javascript";
|
|
83
|
-
import "prismjs/components/prism-typescript";
|
|
84
|
-
import "prismjs/components/prism-css";
|
|
85
|
-
// Import other languages as needed
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
## Develop
|
|
89
|
-
|
|
90
|
-
To start developing Scribo, run the following commands:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
pnpm install
|
|
94
|
-
vite dev
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
## Release
|
|
98
|
-
|
|
99
|
-
Quick release process:
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
# 1. Create changeset (choose one)
|
|
103
|
-
pnpm changeset # Manual (recommended)
|
|
104
|
-
pnpm changeset:suggest # Auto-generate from commits
|
|
105
|
-
|
|
106
|
-
# 2. Version package
|
|
107
|
-
pnpm changeset:version
|
|
108
|
-
|
|
109
|
-
# 3. Commit and push (create PR to main)
|
|
110
|
-
git checkout -b release/scribo-v0.x.x
|
|
111
|
-
git add .
|
|
112
|
-
git commit -m "chore(scribo): release v0.x.x"
|
|
113
|
-
git push origin release/scribo-v0.x.x
|
|
114
|
-
|
|
115
|
-
# 4. Merge PR to main, then automated workflow will publish to npm and create GitHub release
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
For detailed release instructions, including setup and troubleshooting, see [RELEASE.md](./RELEASE.md).
|
|
119
|
-
|
|
120
|
-
## Credits
|
|
121
|
-
|
|
122
|
-
Scribo is built on the [Lexical framework](https://lexical.dev/), and most of the code in the repo is done by [Meta under MIT license](https://github.com/facebook/lexical).
|
|
123
|
-
|
|
124
|
-
## Learn More
|
|
125
|
-
|
|
126
|
-
- [Lexical](https://lexical.dev/)
|
package/RELEASE.md
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# Release Instructions for @eventuras/scribo
|
|
2
|
-
|
|
3
|
-
This document explains how to configure the automated release workflow for `@eventuras/scribo`.
|
|
4
|
-
|
|
5
|
-
## Release Process
|
|
6
|
-
|
|
7
|
-
### Standard Release
|
|
8
|
-
|
|
9
|
-
1. **Create changesets** for your changes:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
# Option A: Manual (recommended for better changelog messages)
|
|
13
|
-
pnpm changeset
|
|
14
|
-
|
|
15
|
-
# Option B: Auto-generate from commits (review and edit after)
|
|
16
|
-
pnpm changeset:suggest
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
> **Tip**: `changeset:suggest` analyzes your git commits since the last release and automatically generates changeset files. Review the generated changesets and edit them for clarity if needed.
|
|
20
|
-
|
|
21
|
-
2. **Version the package** when ready:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
pnpm changeset:version
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
3. **Commit and push** the version bump:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
git add .
|
|
31
|
-
git commit -m "chore(scribo): release v0.x.x"
|
|
32
|
-
git push origin main
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
4. **Automated workflow** will:
|
|
36
|
-
- ✅ Build the package
|
|
37
|
-
- ✅ Publish to npm with provenance
|
|
38
|
-
- ✅ Create Git tag `@eventuras/scribo@x.x.x`
|
|
39
|
-
- ✅ Create GitHub Release with changelog
|
|
40
|
-
|
|
41
|
-
### Manual Release
|
|
42
|
-
|
|
43
|
-
If the automated workflow fails or you need to publish manually:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
cd libs/scribo
|
|
47
|
-
pnpm build
|
|
48
|
-
npm login --scope @eventuras --auth-type web
|
|
49
|
-
npm publish --access public
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Release Setup
|
|
53
|
-
|
|
54
|
-
### NPM Trusted Publishing Setup (Recommended)
|
|
55
|
-
|
|
56
|
-
Scribo uses **npm trusted publishing with OIDC** for secure, token-free publishing.
|
|
57
|
-
|
|
58
|
-
#### Configure Trusted Publisher on npmjs.com
|
|
59
|
-
|
|
60
|
-
1. Log in to [npmjs.com](https://www.npmjs.com)
|
|
61
|
-
2. Navigate to `@eventuras/scribo` package settings
|
|
62
|
-
3. Find **Trusted Publisher** section
|
|
63
|
-
4. Click **GitHub Actions**
|
|
64
|
-
5. Configure:
|
|
65
|
-
- **Organization or user**: `losol`
|
|
66
|
-
- **Repository**: `eventuras`
|
|
67
|
-
- **Workflow filename**: `scribo-release.yml` (include `.yml` extension)
|
|
68
|
-
- **Environment name**: `scribo-npm`
|
|
69
|
-
6. Click **Add trusted publisher**
|
|
70
|
-
|
|
71
|
-
#### Set Up GitHub Environment
|
|
72
|
-
|
|
73
|
-
The workflow uses a GitHub environment for deployment protection (optional but recommended):
|
|
74
|
-
|
|
75
|
-
1. Go to your GitHub repository
|
|
76
|
-
2. Navigate to **Settings** → **Environments**
|
|
77
|
-
3. Click **New environment**
|
|
78
|
-
4. Name: `scribo-npm`
|
|
79
|
-
5. (Optional) Add protection rules:
|
|
80
|
-
- Required reviewers if you want manual approval
|
|
81
|
-
- Deployment branches: Select "Selected branches" and add `main`
|
|
82
|
-
6. Click **Create environment**
|
|
83
|
-
|
|
84
|
-
> **Note**: With trusted publishing, you don't need to add any secrets to this environment. The workflow uses OIDC authentication automatically.
|
|
85
|
-
|
|
86
|
-
### Legacy: Token-Based Publishing (Not Recommended)
|
|
87
|
-
|
|
88
|
-
If you cannot use trusted publishing, you can fall back to traditional npm tokens:
|
|
89
|
-
|
|
90
|
-
1. Create a granular access token on npmjs.com with write access to `@eventuras/scribo`
|
|
91
|
-
2. Add it as `NODE_AUTH_TOKEN` secret in the `scribo-npm` environment
|
|
92
|
-
3. Update the workflow to include `NODE_AUTH_TOKEN` environment variable in the publish step
|
|
93
|
-
|
|
94
|
-
However, trusted publishing is strongly recommended for better security.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
## Workflow Trigger
|
|
98
|
-
|
|
99
|
-
The release workflow (`.github/workflows/scribo-release.yml`) triggers automatically when:
|
|
100
|
-
|
|
101
|
-
- Changes are pushed to the `main` branch
|
|
102
|
-
- The file `libs/scribo/package.json` is modified
|
package/eslint.config.js
DELETED
package/src/App.css
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
body {
|
|
2
|
-
margin: 0;
|
|
3
|
-
background: #eee;
|
|
4
|
-
font-family: Arial, Helvetica, sans-serif;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
h1 {
|
|
8
|
-
text-align: center;
|
|
9
|
-
margin: 20px 0;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.editor-container {
|
|
13
|
-
display: flex;
|
|
14
|
-
flex-direction: column;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.markdown-output {
|
|
18
|
-
white-space: pre-wrap;
|
|
19
|
-
overflow: auto;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@media (min-width: 768px) {
|
|
23
|
-
.editor-container {
|
|
24
|
-
flex-direction: row;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.markdown-editor,
|
|
28
|
-
.markdown-output {
|
|
29
|
-
flex: 1;
|
|
30
|
-
margin: 10px;
|
|
31
|
-
padding: 20px;
|
|
32
|
-
border: 1px solid #ccc;
|
|
33
|
-
border-radius: 5px;
|
|
34
|
-
}
|
|
35
|
-
}
|