@squiz/formatted-text-editor 1.34.1-alpha.1 → 1.34.1-alpha.11
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/lib/EditorToolbar/FloatingToolbar.js +7 -1
- package/lib/EditorToolbar/Toolbar.js +4 -2
- package/lib/EditorToolbar/Tools/ClearFormatting/ClearFormattingButton.d.ts +2 -0
- package/lib/EditorToolbar/Tools/ClearFormatting/ClearFormattingButton.js +56 -0
- package/lib/EditorToolbar/Tools/Image/ImageButton.js +1 -1
- package/lib/EditorToolbar/Tools/Link/LinkButton.js +1 -1
- package/lib/EditorToolbar/Tools/TextAlign/TextAlignButtons.js +2 -2
- package/lib/EditorToolbar/Tools/TextType/CodeBlock/CodeBlockButton.d.ts +2 -0
- package/lib/EditorToolbar/Tools/TextType/CodeBlock/CodeBlockButton.js +22 -0
- package/lib/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.js +3 -2
- package/lib/EditorToolbar/Tools/TextType/TextTypeDropdown.js +8 -2
- package/lib/Extensions/ClearFormattingExtension/ClearFormattingExtension.d.ts +5 -0
- package/lib/Extensions/ClearFormattingExtension/ClearFormattingExtension.js +63 -0
- package/lib/Extensions/CodeBlockExtension/CodeBlockExtension.d.ts +5 -0
- package/lib/Extensions/CodeBlockExtension/CodeBlockExtension.js +30 -0
- package/lib/Extensions/Extensions.d.ts +1 -0
- package/lib/Extensions/Extensions.js +5 -0
- package/lib/Extensions/PreformattedExtension/PreformattedExtension.d.ts +2 -0
- package/lib/Extensions/PreformattedExtension/PreformattedExtension.js +23 -0
- package/lib/index.css +50 -9
- package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.d.ts +2 -1
- package/lib/ui/ToolbarDropdownButton/ToolbarDropdownButton.js +6 -4
- package/lib/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.js +7 -2
- package/lib/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.js +7 -0
- package/lib/utils/getMarkNamesByGroup.d.ts +2 -0
- package/lib/utils/getMarkNamesByGroup.js +9 -0
- package/lib/utils/getNodeNamesByGroup.d.ts +2 -0
- package/lib/utils/getNodeNamesByGroup.js +9 -0
- package/package.json +4 -4
- package/postcss.config.js +1 -1
- package/src/EditorToolbar/FloatingToolbar.tsx +10 -5
- package/src/EditorToolbar/Toolbar.tsx +3 -1
- package/src/EditorToolbar/Tools/ClearFormatting/ClearFormattingButton.spec.tsx +34 -0
- package/src/EditorToolbar/Tools/ClearFormatting/ClearFormattingButton.tsx +45 -0
- package/src/EditorToolbar/Tools/Image/ImageButton.tsx +3 -2
- package/src/EditorToolbar/Tools/Link/LinkButton.tsx +3 -2
- package/src/EditorToolbar/Tools/TextAlign/TextAlignButtons.tsx +2 -2
- package/src/EditorToolbar/Tools/TextType/CodeBlock/CodeBlockButton.spec.tsx +47 -0
- package/src/EditorToolbar/Tools/TextType/CodeBlock/CodeBlockButton.tsx +32 -0
- package/src/EditorToolbar/Tools/TextType/Heading/HeadingButton.spec.tsx +2 -2
- package/src/EditorToolbar/Tools/TextType/Paragraph/ParagraphButton.spec.tsx +1 -1
- package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.spec.tsx +2 -2
- package/src/EditorToolbar/Tools/TextType/Preformatted/PreformattedButton.tsx +3 -1
- package/src/EditorToolbar/Tools/TextType/TextTypeDropdown.tsx +12 -2
- package/src/EditorToolbar/_floating-toolbar.scss +1 -1
- package/src/EditorToolbar/_toolbar.scss +2 -2
- package/src/Extensions/ClearFormattingExtension/ClearFormattingExtension.ts +57 -0
- package/src/Extensions/CodeBlockExtension/CodeBlockExtension.ts +34 -0
- package/src/Extensions/Extensions.ts +5 -0
- package/src/Extensions/PreformattedExtension/PreformattedExtension.spec.ts +4 -2
- package/src/Extensions/PreformattedExtension/PreformattedExtension.ts +31 -0
- package/src/index.scss +3 -0
- package/src/ui/ToolbarDropdownButton/ToolbarDropdownButton.tsx +8 -4
- package/src/ui/ToolbarDropdownButton/_toolbar-dropdown-button.scss +11 -0
- package/src/ui/_typography.scss +26 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.spec.ts +37 -0
- package/src/utils/converters/remirrorNodeToSquizNode/remirrorNodeToSquizNode.ts +10 -2
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.spec.ts +39 -2
- package/src/utils/converters/squizNodeToRemirrorNode/squizNodeToRemirrorNode.ts +6 -0
- package/src/utils/getMarkNamesByGroup.spec.ts +20 -0
- package/src/utils/getMarkNamesByGroup.ts +7 -0
- package/src/utils/getNodeNamesByGroup.spec.ts +20 -0
- package/src/utils/getNodeNamesByGroup.ts +7 -0
- package/tailwind.config.cjs +4 -3
@@ -39,10 +39,12 @@ const react_components_1 = require("@remirror/react-components");
|
|
39
39
|
const createToolbarPositioner_1 = require("../utils/createToolbarPositioner");
|
40
40
|
const ImageButton_1 = __importDefault(require("./Tools/Image/ImageButton"));
|
41
41
|
const Extensions_1 = require("../Extensions/Extensions");
|
42
|
+
const ClearFormattingButton_1 = __importDefault(require("./Tools/ClearFormatting/ClearFormattingButton"));
|
42
43
|
const FloatingToolbar = () => {
|
43
44
|
const watchedMarks = [Extensions_1.MarkName.Link, Extensions_1.MarkName.AssetLink];
|
44
45
|
const extensionNames = (0, hooks_1.useExtensionNames)();
|
45
46
|
const positioner = (0, react_1.useMemo)(() => (0, createToolbarPositioner_1.createToolbarPositioner)({ types: watchedMarks }), []);
|
47
|
+
const { clearFormatting } = (0, react_2.useCommands)();
|
46
48
|
const active = (0, react_2.useActive)();
|
47
49
|
const { data: { marks }, } = (0, react_2.usePositioner)(positioner, []);
|
48
50
|
let buttons = [
|
@@ -63,7 +65,11 @@ const FloatingToolbar = () => {
|
|
63
65
|
}
|
64
66
|
else if (!marks?.[Extensions_1.MarkName.Link].isActive && !marks?.[Extensions_1.MarkName.AssetLink].isActive) {
|
65
67
|
// if none of the selected text is a link show the option to create a link.
|
66
|
-
buttons.push(react_1.default.createElement(react_components_1.VerticalDivider, { key: "link-divider"
|
68
|
+
buttons.push(react_1.default.createElement(react_components_1.VerticalDivider, { key: "link-divider" }), react_1.default.createElement(LinkButton_1.default, { key: "add-link", inPopover: true }));
|
69
|
+
}
|
70
|
+
// Clear formatting will always be the last button in the toolbar
|
71
|
+
if (extensionNames.clearFormatting && clearFormatting.enabled()) {
|
72
|
+
buttons.push(react_1.default.createElement(ClearFormattingButton_1.default, { key: "clearFormatting" }));
|
67
73
|
}
|
68
74
|
return (react_1.default.createElement(react_2.FloatingToolbar, { className: "squiz-fte-scope squiz-fte-scope__floating-popover", positioner: positioner }, buttons));
|
69
75
|
};
|
@@ -17,13 +17,14 @@ const hooks_1 = require("../hooks");
|
|
17
17
|
const LinkButton_1 = __importDefault(require("./Tools/Link/LinkButton"));
|
18
18
|
const ImageButton_1 = __importDefault(require("./Tools/Image/ImageButton"));
|
19
19
|
const RemoveLinkButton_1 = __importDefault(require("./Tools/Link/RemoveLinkButton"));
|
20
|
+
const ClearFormattingButton_1 = __importDefault(require("./Tools/ClearFormatting/ClearFormattingButton"));
|
20
21
|
const Toolbar = () => {
|
21
22
|
const extensionNames = (0, hooks_1.useExtensionNames)();
|
22
23
|
return (react_1.default.createElement(react_components_1.Toolbar, { className: "remirror-toolbar editor-toolbar" },
|
23
24
|
extensionNames.history && (react_1.default.createElement(react_1.default.Fragment, null,
|
24
25
|
react_1.default.createElement(UndoButton_1.default, null),
|
25
26
|
react_1.default.createElement(RedoButton_1.default, null),
|
26
|
-
react_1.default.createElement(react_components_1.VerticalDivider,
|
27
|
+
react_1.default.createElement(react_components_1.VerticalDivider, null))),
|
27
28
|
extensionNames.heading && extensionNames.paragraph && extensionNames.preformatted && react_1.default.createElement(TextTypeDropdown_1.default, null),
|
28
29
|
extensionNames.bold && react_1.default.createElement(BoldButton_1.default, null),
|
29
30
|
extensionNames.italic && react_1.default.createElement(ItalicButton_1.default, null),
|
@@ -32,6 +33,7 @@ const Toolbar = () => {
|
|
32
33
|
extensionNames.link && (react_1.default.createElement(react_1.default.Fragment, null,
|
33
34
|
react_1.default.createElement(LinkButton_1.default, null),
|
34
35
|
react_1.default.createElement(RemoveLinkButton_1.default, null))),
|
35
|
-
extensionNames.image && react_1.default.createElement(ImageButton_1.default, null)
|
36
|
+
extensionNames.image && react_1.default.createElement(ImageButton_1.default, null),
|
37
|
+
extensionNames.clearFormatting && react_1.default.createElement(ClearFormattingButton_1.default, null)));
|
36
38
|
};
|
37
39
|
exports.Toolbar = Toolbar;
|
@@ -0,0 +1,56 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
+
}) : function(o, v) {
|
16
|
+
o["default"] = v;
|
17
|
+
});
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
+
if (mod && mod.__esModule) return mod;
|
20
|
+
var result = {};
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
+
__setModuleDefault(result, mod);
|
23
|
+
return result;
|
24
|
+
};
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
27
|
+
};
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
29
|
+
const react_1 = __importStar(require("react"));
|
30
|
+
const react_2 = require("@remirror/react");
|
31
|
+
const react_components_1 = require("@remirror/react-components");
|
32
|
+
const FormatClearRounded_1 = __importDefault(require("@mui/icons-material/FormatClearRounded"));
|
33
|
+
const Button_1 = __importDefault(require("../../../ui/Button/Button"));
|
34
|
+
const ClearFormattingButton = () => {
|
35
|
+
const { clearFormatting } = (0, react_2.useCommands)();
|
36
|
+
const { selection } = (0, react_2.useEditorState)();
|
37
|
+
// Checks wether we have specific content selected or not
|
38
|
+
const contentSelected = !selection.empty;
|
39
|
+
const handleSelect = () => {
|
40
|
+
if (clearFormatting.enabled()) {
|
41
|
+
clearFormatting();
|
42
|
+
}
|
43
|
+
};
|
44
|
+
const handleShortcut = (0, react_1.useCallback)(() => {
|
45
|
+
handleSelect();
|
46
|
+
// Prevent other key handlers being run
|
47
|
+
return true;
|
48
|
+
}, []);
|
49
|
+
// When Ctrl+\ is pressed clear formatting, only registered in the toolbar button instance to avoid the key press
|
50
|
+
// being double handled.
|
51
|
+
(0, react_2.useKeymap)('Mod-\\', handleShortcut);
|
52
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
53
|
+
react_1.default.createElement(react_components_1.VerticalDivider, null),
|
54
|
+
react_1.default.createElement(Button_1.default, { handleOnClick: handleSelect, isDisabled: false, isActive: false, icon: react_1.default.createElement(FormatClearRounded_1.default, null), label: `${contentSelected ? 'Clear formatting from selection' : 'Clear all formatting'} (cmd+\\)` })));
|
55
|
+
};
|
56
|
+
exports.default = ClearFormattingButton;
|
@@ -38,7 +38,7 @@ const ImageButton = ({ inPopover = false }) => {
|
|
38
38
|
const active = (0, react_2.useActive)();
|
39
39
|
const selection = (0, react_2.useCurrentSelection)();
|
40
40
|
// if the active selection is not an image, disable the button as it means it will be text
|
41
|
-
const disabled = !selection.empty && !active.image() && !active.assetImage();
|
41
|
+
const disabled = (!selection.empty && !active.image() && !active.assetImage()) || active.codeBlock();
|
42
42
|
const handleClick = () => {
|
43
43
|
if (!showModal) {
|
44
44
|
setShowModal(true);
|
@@ -37,7 +37,7 @@ const LinkButton = ({ inPopover = false }) => {
|
|
37
37
|
const { updateLink, updateAssetLink } = (0, react_2.useCommands)();
|
38
38
|
const active = (0, react_2.useActive)();
|
39
39
|
// If the image tool is active, disable the link tool as they shouldn't work at the same time
|
40
|
-
const disabled = active.image();
|
40
|
+
const disabled = active.image() || active.codeBlock();
|
41
41
|
const handleClick = () => {
|
42
42
|
if (!showModal) {
|
43
43
|
setShowModal(true);
|
@@ -11,11 +11,11 @@ const JustifyAlignButton_1 = __importDefault(require("./JustifyAlign/JustifyAlig
|
|
11
11
|
const react_components_1 = require("@remirror/react-components");
|
12
12
|
const TextAlignButtons = () => {
|
13
13
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
14
|
-
react_1.default.createElement(react_components_1.VerticalDivider,
|
14
|
+
react_1.default.createElement(react_components_1.VerticalDivider, null),
|
15
15
|
react_1.default.createElement(LeftAlignButton_1.default, null),
|
16
16
|
react_1.default.createElement(CenterAlignButton_1.default, null),
|
17
17
|
react_1.default.createElement(RightAlignButton_1.default, null),
|
18
18
|
react_1.default.createElement(JustifyAlignButton_1.default, null),
|
19
|
-
react_1.default.createElement(react_components_1.VerticalDivider,
|
19
|
+
react_1.default.createElement(react_components_1.VerticalDivider, null)));
|
20
20
|
};
|
21
21
|
exports.default = TextAlignButtons;
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
const react_1 = __importDefault(require("react"));
|
7
|
+
const react_2 = require("@remirror/react");
|
8
|
+
const ToolbarDropdownButton_1 = __importDefault(require("../../../../ui/ToolbarDropdownButton/ToolbarDropdownButton"));
|
9
|
+
const CodeRounded_1 = __importDefault(require("@mui/icons-material/CodeRounded"));
|
10
|
+
const CodeBlockButton = () => {
|
11
|
+
const { toggleCodeBlock } = (0, react_2.useCommands)();
|
12
|
+
const active = (0, react_2.useActive)();
|
13
|
+
const enabled = toggleCodeBlock.enabled();
|
14
|
+
const handleSelect = () => {
|
15
|
+
if (toggleCodeBlock.enabled()) {
|
16
|
+
toggleCodeBlock();
|
17
|
+
}
|
18
|
+
};
|
19
|
+
return (react_1.default.createElement(ToolbarDropdownButton_1.default, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.codeBlock(), label: "Code block", icon: react_1.default.createElement(CodeRounded_1.default, null) },
|
20
|
+
react_1.default.createElement("p", null, "Code block")));
|
21
|
+
};
|
22
|
+
exports.default = CodeBlockButton;
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
7
7
|
const react_2 = require("@remirror/react");
|
8
8
|
const ToolbarDropdownButton_1 = __importDefault(require("../../../../ui/ToolbarDropdownButton/ToolbarDropdownButton"));
|
9
|
+
const ShortTextRounded_1 = __importDefault(require("@mui/icons-material/ShortTextRounded"));
|
9
10
|
const PreformattedButton = () => {
|
10
11
|
const { togglePreformatted } = (0, react_2.useCommands)();
|
11
12
|
const active = (0, react_2.useActive)();
|
@@ -15,7 +16,7 @@ const PreformattedButton = () => {
|
|
15
16
|
togglePreformatted();
|
16
17
|
}
|
17
18
|
};
|
18
|
-
return (react_1.default.createElement(ToolbarDropdownButton_1.default, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.preformatted(), label: "Preformatted" },
|
19
|
-
react_1.default.createElement("
|
19
|
+
return (react_1.default.createElement(ToolbarDropdownButton_1.default, { handleOnClick: handleSelect, isDisabled: !enabled, isActive: active.preformatted(), label: "Preformatted", icon: react_1.default.createElement(ShortTextRounded_1.default, null) },
|
20
|
+
react_1.default.createElement("p", null, "Preformatted")));
|
20
21
|
};
|
21
22
|
exports.default = PreformattedButton;
|
@@ -7,6 +7,7 @@ const react_1 = __importDefault(require("react"));
|
|
7
7
|
const HeadingButton_1 = __importDefault(require("./Heading/HeadingButton"));
|
8
8
|
const ParagraphButton_1 = __importDefault(require("./Paragraph/ParagraphButton"));
|
9
9
|
const PreformattedButton_1 = __importDefault(require("./Preformatted/PreformattedButton"));
|
10
|
+
const CodeBlockButton_1 = __importDefault(require("./CodeBlock/CodeBlockButton"));
|
10
11
|
const ToolbarDropdown_1 = __importDefault(require("../../../ui/ToolbarDropdown/ToolbarDropdown"));
|
11
12
|
const react_2 = require("@remirror/react");
|
12
13
|
const TextTypeDropdown = () => {
|
@@ -16,6 +17,10 @@ const TextTypeDropdown = () => {
|
|
16
17
|
if (active.preformatted()) {
|
17
18
|
return 'Preformatted';
|
18
19
|
}
|
20
|
+
// Determine if codeblock is active
|
21
|
+
if (active.codeBlock()) {
|
22
|
+
return 'Code block';
|
23
|
+
}
|
19
24
|
// Determine if a heading is active
|
20
25
|
for (let i = 1; i <= 6; i++) {
|
21
26
|
if (active.heading({ level: i })) {
|
@@ -34,7 +39,8 @@ const TextTypeDropdown = () => {
|
|
34
39
|
react_1.default.createElement(HeadingButton_1.default, { level: 4 }),
|
35
40
|
react_1.default.createElement(HeadingButton_1.default, { level: 5 }),
|
36
41
|
react_1.default.createElement(HeadingButton_1.default, { level: 6 }),
|
37
|
-
react_1.default.createElement(PreformattedButton_1.default, null)
|
38
|
-
|
42
|
+
react_1.default.createElement(PreformattedButton_1.default, null),
|
43
|
+
react_1.default.createElement(CodeBlockButton_1.default, null)),
|
44
|
+
react_1.default.createElement(react_2.VerticalDivider, null)));
|
39
45
|
};
|
40
46
|
exports.default = TextTypeDropdown;
|
@@ -0,0 +1,63 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
7
|
+
};
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
9
|
+
exports.ClearFormattingExtension = void 0;
|
10
|
+
const core_1 = require("@remirror/core");
|
11
|
+
const getNodeNamesByGroup_1 = require("../../utils/getNodeNamesByGroup");
|
12
|
+
const getMarkNamesByGroup_1 = require("../../utils/getMarkNamesByGroup");
|
13
|
+
let ClearFormattingExtension = class ClearFormattingExtension extends core_1.PlainExtension {
|
14
|
+
get name() {
|
15
|
+
return 'clearFormatting';
|
16
|
+
}
|
17
|
+
clearFormatting() {
|
18
|
+
return ({ dispatch, tr, state }) => {
|
19
|
+
const { empty, ranges } = state.selection;
|
20
|
+
const schema = state.schema;
|
21
|
+
const formattingNodes = (0, getNodeNamesByGroup_1.getNodeNamesByGroup)(schema, core_1.ExtensionTag.FormattingNode);
|
22
|
+
const formattingMarks = (0, getMarkNamesByGroup_1.getMarkNamesByGroup)(schema, core_1.ExtensionTag.FormattingMark);
|
23
|
+
let isChanged = false;
|
24
|
+
ranges.forEach(({ $from, $to }) => {
|
25
|
+
// Check if there is a selection or not, if no selection use the doc content size as the range
|
26
|
+
state.doc.nodesBetween(empty ? 0 : $from.pos, empty ? state.doc.content.size : $to.pos, (node, pos) => {
|
27
|
+
// Clear marks (bold, italic, etc)
|
28
|
+
node.marks.forEach((mark) => {
|
29
|
+
if (formattingMarks.includes(mark.type.name)) {
|
30
|
+
tr.removeMark(pos, pos + node.nodeSize, mark);
|
31
|
+
isChanged = true;
|
32
|
+
}
|
33
|
+
});
|
34
|
+
// Leave non-foramtting nodes as-is
|
35
|
+
if (!formattingNodes.includes(node.type.name)) {
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
// Clear node attributes & set to paragraph by default
|
39
|
+
if (node.type.name === schema.nodes.paragraph.name) {
|
40
|
+
const { nodeTextAlignment } = node.attrs;
|
41
|
+
if (nodeTextAlignment && nodeTextAlignment !== 'left') {
|
42
|
+
tr.setNodeAttribute(pos, 'nodeTextAlignment', null);
|
43
|
+
isChanged = true;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
tr.setNodeMarkup(pos, schema.nodes.paragraph, null, node.marks);
|
48
|
+
isChanged = true;
|
49
|
+
}
|
50
|
+
});
|
51
|
+
});
|
52
|
+
dispatch?.(tr);
|
53
|
+
return isChanged;
|
54
|
+
};
|
55
|
+
}
|
56
|
+
};
|
57
|
+
__decorate([
|
58
|
+
(0, core_1.command)()
|
59
|
+
], ClearFormattingExtension.prototype, "clearFormatting", null);
|
60
|
+
ClearFormattingExtension = __decorate([
|
61
|
+
(0, core_1.extension)({})
|
62
|
+
], ClearFormattingExtension);
|
63
|
+
exports.ClearFormattingExtension = ClearFormattingExtension;
|
@@ -0,0 +1,30 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.ExtendedCodeBlockExtension = void 0;
|
4
|
+
const extension_code_block_1 = require("@remirror/extension-code-block");
|
5
|
+
class ExtendedCodeBlockExtension extends extension_code_block_1.CodeBlockExtension {
|
6
|
+
createNodeViews() {
|
7
|
+
return (node) => {
|
8
|
+
const { language } = node.attrs;
|
9
|
+
// This is the pre container for the code block
|
10
|
+
const dom = document.createElement('pre');
|
11
|
+
dom.setAttribute('spellcheck', 'false');
|
12
|
+
dom.classList.add(`code-block`);
|
13
|
+
// This is the actual code content in the code block
|
14
|
+
const contentDOM = document.createElement('code');
|
15
|
+
contentDOM.setAttribute('data-code-block-language', language);
|
16
|
+
// Divider between code block and pre container
|
17
|
+
const dividerElement = document.createElement('div');
|
18
|
+
dividerElement.classList.add('block-divider');
|
19
|
+
// The material icon to use
|
20
|
+
const codeIcon = document.createElement('svg');
|
21
|
+
codeIcon.classList.add('material-symbols-rounded');
|
22
|
+
codeIcon.textContent = 'code';
|
23
|
+
dom.append(codeIcon);
|
24
|
+
dom.append(dividerElement);
|
25
|
+
dom.append(contentDOM);
|
26
|
+
return { dom, contentDOM };
|
27
|
+
};
|
28
|
+
}
|
29
|
+
}
|
30
|
+
exports.ExtendedCodeBlockExtension = ExtendedCodeBlockExtension;
|
@@ -8,9 +8,12 @@ const LinkExtension_1 = require("./LinkExtension/LinkExtension");
|
|
8
8
|
const ImageExtension_1 = require("./ImageExtension/ImageExtension");
|
9
9
|
const CommandsExtension_1 = require("./CommandsExtension/CommandsExtension");
|
10
10
|
const AssetImageExtension_1 = require("./ImageExtension/AssetImageExtension");
|
11
|
+
const CodeBlockExtension_1 = require("./CodeBlockExtension/CodeBlockExtension");
|
12
|
+
const ClearFormattingExtension_1 = require("./ClearFormattingExtension/ClearFormattingExtension");
|
11
13
|
var NodeName;
|
12
14
|
(function (NodeName) {
|
13
15
|
NodeName["Image"] = "image";
|
16
|
+
NodeName["CodeBlock"] = "codeBlock";
|
14
17
|
NodeName["AssetImage"] = "assetImage";
|
15
18
|
NodeName["Text"] = "text";
|
16
19
|
})(NodeName = exports.NodeName || (exports.NodeName = {}));
|
@@ -29,6 +32,7 @@ const createExtensions = (context) => {
|
|
29
32
|
new extensions_1.NodeFormattingExtension({ indents: [] }),
|
30
33
|
new extensions_1.ParagraphExtension(),
|
31
34
|
new PreformattedExtension_1.PreformattedExtension(),
|
35
|
+
new CodeBlockExtension_1.ExtendedCodeBlockExtension({ defaultWrap: true }),
|
32
36
|
new extensions_1.UnderlineExtension(),
|
33
37
|
new extensions_1.HistoryExtension(),
|
34
38
|
new ImageExtension_1.ImageExtension(),
|
@@ -40,6 +44,7 @@ const createExtensions = (context) => {
|
|
40
44
|
new AssetLinkExtension_1.AssetLinkExtension({
|
41
45
|
matrixDomain: context.matrix.matrixDomain,
|
42
46
|
}),
|
47
|
+
new ClearFormattingExtension_1.ClearFormattingExtension(),
|
43
48
|
];
|
44
49
|
};
|
45
50
|
};
|
@@ -1,8 +1,10 @@
|
|
1
1
|
import { ApplySchemaAttributes, CommandFunction, NodeExtension, NodeExtensionSpec, NodeSpecOverride } from '@remirror/core';
|
2
|
+
import { NodeViewMethod } from 'remirror';
|
2
3
|
export declare class PreformattedExtension extends NodeExtension {
|
3
4
|
get name(): "preformatted";
|
4
5
|
createTags(): ("block" | "formattingNode" | "textBlock")[];
|
5
6
|
createNodeSpec(extra: ApplySchemaAttributes, override: NodeSpecOverride): NodeExtensionSpec;
|
7
|
+
createNodeViews(): NodeViewMethod;
|
6
8
|
/**
|
7
9
|
* Toggle the <pre> for the current block.
|
8
10
|
*/
|
@@ -34,6 +34,29 @@ let PreformattedExtension = class PreformattedExtension extends core_1.NodeExten
|
|
34
34
|
},
|
35
35
|
};
|
36
36
|
}
|
37
|
+
createNodeViews() {
|
38
|
+
return (node) => {
|
39
|
+
const { nodeTextAlignment } = node.attrs;
|
40
|
+
// This is the pre container for the code block
|
41
|
+
const dom = document.createElement('div');
|
42
|
+
dom.classList.add(`preformatted`);
|
43
|
+
// This is the actual code content in the code block
|
44
|
+
const contentDOM = document.createElement('pre');
|
45
|
+
contentDOM.setAttribute('data-node-text-align', nodeTextAlignment);
|
46
|
+
contentDOM.setAttribute('style', `text-align:${nodeTextAlignment}`);
|
47
|
+
// Divider between code block and pre container
|
48
|
+
const dividerElement = document.createElement('div');
|
49
|
+
dividerElement.classList.add('block-divider');
|
50
|
+
// The material icon to use
|
51
|
+
const codeIcon = document.createElement('svg');
|
52
|
+
codeIcon.classList.add('material-symbols-rounded');
|
53
|
+
codeIcon.textContent = 'short_text';
|
54
|
+
dom.append(codeIcon);
|
55
|
+
dom.append(dividerElement);
|
56
|
+
dom.append(contentDOM);
|
57
|
+
return { dom, contentDOM };
|
58
|
+
};
|
59
|
+
}
|
37
60
|
/**
|
38
61
|
* Toggle the <pre> for the current block.
|
39
62
|
*/
|
package/lib/index.css
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
@import "https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded";
|
2
|
+
|
1
3
|
/* src/index.scss */
|
2
4
|
.squiz-fte-scope *,
|
3
5
|
.squiz-fte-scope ::before,
|
@@ -674,6 +676,36 @@
|
|
674
676
|
letter-spacing: -0.2px;
|
675
677
|
line-height: 1.25rem;
|
676
678
|
}
|
679
|
+
.squiz-fte-scope .code-block,
|
680
|
+
.squiz-fte-scope .preformatted {
|
681
|
+
display: flex;
|
682
|
+
}
|
683
|
+
.squiz-fte-scope .code-block .material-symbols-rounded,
|
684
|
+
.squiz-fte-scope .preformatted .material-symbols-rounded {
|
685
|
+
font-size: 1.125rem;
|
686
|
+
--tw-text-opacity: 1;
|
687
|
+
color: rgb(79 79 79 / var(--tw-text-opacity));
|
688
|
+
pointer-events: none;
|
689
|
+
margin-right: 0.375rem;
|
690
|
+
}
|
691
|
+
.squiz-fte-scope .code-block .block-divider,
|
692
|
+
.squiz-fte-scope .preformatted .block-divider {
|
693
|
+
--tw-bg-opacity: 1;
|
694
|
+
background-color: rgb(237 237 237 / var(--tw-bg-opacity));
|
695
|
+
width: 4px;
|
696
|
+
border-radius: 0.75rem;
|
697
|
+
margin-right: 0.625rem;
|
698
|
+
}
|
699
|
+
.squiz-fte-scope .code-block code,
|
700
|
+
.squiz-fte-scope .code-block pre,
|
701
|
+
.squiz-fte-scope .preformatted code,
|
702
|
+
.squiz-fte-scope .preformatted pre {
|
703
|
+
--tw-text-opacity: 1;
|
704
|
+
color: rgb(79 79 79 / var(--tw-text-opacity));
|
705
|
+
font-size: 0.75rem;
|
706
|
+
padding-top: 0.75rem;
|
707
|
+
padding-bottom: 0.75rem;
|
708
|
+
}
|
677
709
|
.squiz-fte-scope .squiz-fte-form-group {
|
678
710
|
display: flex;
|
679
711
|
flex-direction: column;
|
@@ -812,12 +844,12 @@
|
|
812
844
|
display: flex;
|
813
845
|
justify-items: center;
|
814
846
|
}
|
815
|
-
.squiz-fte-scope .editor-toolbar > *:not(:first-child, .
|
816
|
-
.squiz-fte-
|
847
|
+
.squiz-fte-scope .editor-toolbar > *:not(:first-child, .MuiDivider-root),
|
848
|
+
.squiz-fte-scope__floating-popover > *:not(:first-child, .MuiDivider-root) {
|
817
849
|
margin: 0 0 0 2px;
|
818
850
|
}
|
819
|
-
.squiz-fte-scope .editor-toolbar .
|
820
|
-
.squiz-fte-
|
851
|
+
.squiz-fte-scope .editor-toolbar .MuiDivider-root,
|
852
|
+
.squiz-fte-scope__floating-popover .MuiDivider-root {
|
821
853
|
margin-top: -0.25rem;
|
822
854
|
margin-bottom: -0.25rem;
|
823
855
|
margin-left: 0.25rem;
|
@@ -827,12 +859,12 @@
|
|
827
859
|
height: auto;
|
828
860
|
}
|
829
861
|
.squiz-fte-scope .editor-toolbar .squiz-fte-btn,
|
830
|
-
.squiz-fte-
|
862
|
+
.squiz-fte-scope__floating-popover .squiz-fte-btn {
|
831
863
|
padding: 0.25rem;
|
832
864
|
font-weight: 700;
|
833
865
|
}
|
834
866
|
.squiz-fte-scope .editor-toolbar .squiz-fte-btn ~ .squiz-fte-btn,
|
835
|
-
.squiz-fte-
|
867
|
+
.squiz-fte-scope__floating-popover .squiz-fte-btn ~ .squiz-fte-btn {
|
836
868
|
margin-left: 2px;
|
837
869
|
}
|
838
870
|
.squiz-fte-scope__floating-popover {
|
@@ -851,7 +883,7 @@
|
|
851
883
|
var(--tw-ring-shadow, 0 0 #0000),
|
852
884
|
var(--tw-shadow);
|
853
885
|
}
|
854
|
-
.squiz-fte-
|
886
|
+
.squiz-fte-scope__floating-popover .MuiDivider-root {
|
855
887
|
margin-top: 0px;
|
856
888
|
margin-bottom: 0px;
|
857
889
|
}
|
@@ -959,6 +991,15 @@
|
|
959
991
|
.squiz-fte-scope .dropdown-button:focus {
|
960
992
|
background-color: rgba(0, 0, 0, 0.04);
|
961
993
|
}
|
994
|
+
.squiz-fte-scope .dropdown-button svg {
|
995
|
+
font-size: 18px;
|
996
|
+
}
|
997
|
+
.squiz-fte-scope .dropdown-button .dropdown-button-label {
|
998
|
+
display: flex;
|
999
|
+
align-items: center;
|
1000
|
+
font-size: 14px;
|
1001
|
+
gap: 5px;
|
1002
|
+
}
|
962
1003
|
.squiz-fte-scope .squiz-fte-checkbox {
|
963
1004
|
--tw-text-opacity: 1;
|
964
1005
|
color: rgb(61 61 61 / var(--tw-text-opacity));
|
@@ -1042,12 +1083,12 @@
|
|
1042
1083
|
font-weight: 700;
|
1043
1084
|
}
|
1044
1085
|
.squiz-fte-scope .editor-toolbar .squiz-fte-modal-footer__button,
|
1045
|
-
.squiz-fte-
|
1086
|
+
.squiz-fte-scope__floating-popover .squiz-fte-modal-footer__button {
|
1046
1087
|
padding: 0.25rem;
|
1047
1088
|
font-weight: 700;
|
1048
1089
|
}
|
1049
1090
|
.squiz-fte-scope .editor-toolbar .squiz-fte-modal-footer__button ~ .squiz-fte-btn,
|
1050
|
-
.squiz-fte-
|
1091
|
+
.squiz-fte-scope__floating-popover .squiz-fte-modal-footer__button ~ .squiz-fte-btn {
|
1051
1092
|
margin-left: 2px;
|
1052
1093
|
}
|
1053
1094
|
.squiz-fte-scope .squiz-fte-modal-footer__button {
|
@@ -4,6 +4,7 @@ type DropdownButtonProps = {
|
|
4
4
|
isDisabled: boolean;
|
5
5
|
isActive: boolean;
|
6
6
|
label: string;
|
7
|
+
icon?: JSX.Element;
|
7
8
|
};
|
8
|
-
declare const DropdownButton: ({ children, handleOnClick, isDisabled, isActive, label }: DropdownButtonProps) => JSX.Element;
|
9
|
+
declare const DropdownButton: ({ children, handleOnClick, isDisabled, isActive, label, icon }: DropdownButtonProps) => JSX.Element;
|
9
10
|
export default DropdownButton;
|
@@ -4,10 +4,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
const react_1 = __importDefault(require("react"));
|
7
|
-
const
|
8
|
-
const DropdownButton = ({ children, handleOnClick, isDisabled, isActive, label }) => {
|
7
|
+
const CheckRounded_1 = __importDefault(require("@mui/icons-material/CheckRounded"));
|
8
|
+
const DropdownButton = ({ children, handleOnClick, isDisabled, isActive, label, icon }) => {
|
9
9
|
return (react_1.default.createElement("button", { "aria-label": label, id: "dropdownMenuButton", title: label, type: "button", onClick: handleOnClick, disabled: isDisabled, className: `btn dropdown-button ${isActive ? 'is-active' : ''}` },
|
10
|
-
react_1.default.createElement("
|
11
|
-
|
10
|
+
react_1.default.createElement("div", { className: "dropdown-button-label" },
|
11
|
+
icon && icon,
|
12
|
+
children || label),
|
13
|
+
isActive && react_1.default.createElement(CheckRounded_1.default, { className: "dropdown-button-icon" })));
|
12
14
|
};
|
13
15
|
exports.default = DropdownButton;
|
@@ -4,9 +4,12 @@ exports.remirrorNodeToSquizNode = exports.resolveNodeTag = void 0;
|
|
4
4
|
const undefinedIfEmpty_1 = require("../../undefinedIfEmpty");
|
5
5
|
const Extensions_1 = require("../../../Extensions/Extensions");
|
6
6
|
const resolveNodeTag = (node) => {
|
7
|
-
if (node.type.name ===
|
7
|
+
if (node.type.name === Extensions_1.NodeName.Text) {
|
8
8
|
return 'span';
|
9
9
|
}
|
10
|
+
if (node.type.name === Extensions_1.NodeName.CodeBlock) {
|
11
|
+
return 'code';
|
12
|
+
}
|
10
13
|
if (node.type.spec?.toDOM) {
|
11
14
|
const domNode = node.type.spec.toDOM(node);
|
12
15
|
if (domNode instanceof window.Node) {
|
@@ -63,9 +66,11 @@ const transformFragment = (fragment) => {
|
|
63
66
|
return transformed;
|
64
67
|
};
|
65
68
|
const transformNode = (node) => {
|
66
|
-
const attributes = node.type.name === Extensions_1.NodeName.Image ? transformAttributes(node.attrs) : undefined;
|
67
69
|
const formattingOptions = (0, undefinedIfEmpty_1.undefinedIfEmpty)(resolveFormattingOptions(node));
|
68
70
|
const font = (0, undefinedIfEmpty_1.undefinedIfEmpty)(resolveFontOptions(node));
|
71
|
+
const attributes = node.type.name === Extensions_1.NodeName.Image || node.type.name === Extensions_1.NodeName.CodeBlock
|
72
|
+
? transformAttributes(node.attrs)
|
73
|
+
: undefined;
|
69
74
|
let transformedNode = { type: 'text', value: node.text || '' };
|
70
75
|
// Squiz "text" nodes can't have formatting/font options but Remirror "text" nodes can.
|
71
76
|
// If the node has formatting options wrap in a tag.
|
@@ -21,6 +21,7 @@ const getNodeType = (node) => {
|
|
21
21
|
p: 'paragraph',
|
22
22
|
a: Extensions_1.NodeName.Text,
|
23
23
|
span: Extensions_1.NodeName.Text,
|
24
|
+
code: Extensions_1.NodeName.CodeBlock,
|
24
25
|
};
|
25
26
|
if (typeMap[node.type]) {
|
26
27
|
return typeMap[node.type];
|
@@ -43,6 +44,12 @@ const getNodeAttributes = (node) => {
|
|
43
44
|
title: node.attributes?.title,
|
44
45
|
};
|
45
46
|
}
|
47
|
+
else if (node.type === 'tag' && node.tag === 'code') {
|
48
|
+
return {
|
49
|
+
language: node.attributes?.language || 'markup',
|
50
|
+
wrap: node.attributes?.wrap || true,
|
51
|
+
};
|
52
|
+
}
|
46
53
|
else if (node.type === 'matrix-image') {
|
47
54
|
return {
|
48
55
|
matrixAssetId: node.matrixAssetId,
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getMarkNamesByGroup = void 0;
|
4
|
+
const getMarkNamesByGroup = (schema, group) => {
|
5
|
+
return Object.values(schema.marks)
|
6
|
+
.filter((mark) => mark.spec.group?.includes(group))
|
7
|
+
.map((mark) => mark.name);
|
8
|
+
};
|
9
|
+
exports.getMarkNamesByGroup = getMarkNamesByGroup;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getNodeNamesByGroup = void 0;
|
4
|
+
const getNodeNamesByGroup = (schema, group) => {
|
5
|
+
return Object.values(schema.nodes)
|
6
|
+
.filter((node) => node.spec.group?.includes(group))
|
7
|
+
.map((node) => node.name);
|
8
|
+
};
|
9
|
+
exports.getNodeNamesByGroup = getNodeNamesByGroup;
|