mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-17 04:07:51 +01:00
Revert "Merge pull request #8493 from 01zulfi/editor/collapsible-headings"
This reverts commit7241dce7a6, reversing changes made toae5b422965.
This commit is contained in:
@@ -704,10 +704,8 @@ function EditorChrome(props: PropsWithChildren<EditorProps>) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
if (!isMobile() && !isTablet()) {
|
editor.style.marginLeft = `-${negativeSpace}px`;
|
||||||
editor.style.marginLeft = `-${negativeSpace}px`;
|
editor.style.marginRight = `-${negativeSpace}px`;
|
||||||
editor.style.marginRight = `-${negativeSpace}px`;
|
|
||||||
}
|
|
||||||
editor.style.paddingLeft = `${negativeSpace}px`;
|
editor.style.paddingLeft = `${negativeSpace}px`;
|
||||||
editor.style.paddingRight = `${negativeSpace}px`;
|
editor.style.paddingRight = `${negativeSpace}px`;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,11 +16,13 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
import { getParentAttributes } from "../../utils/prosemirror.js";
|
||||||
import {
|
import {
|
||||||
getParentAttributes,
|
InputRule,
|
||||||
isClickWithinBounds
|
Node,
|
||||||
} from "../../utils/prosemirror.js";
|
findParentNodeClosestToPos,
|
||||||
import { InputRule, Node, mergeAttributes } from "@tiptap/core";
|
mergeAttributes
|
||||||
|
} from "@tiptap/core";
|
||||||
import { Paragraph } from "../paragraph/index.js";
|
import { Paragraph } from "../paragraph/index.js";
|
||||||
import { Heading } from "../heading/index.js";
|
import { Heading } from "../heading/index.js";
|
||||||
import { TextSelection } from "@tiptap/pm/state";
|
import { TextSelection } from "@tiptap/pm/state";
|
||||||
@@ -233,9 +235,37 @@ export const Callout = Node.create({
|
|||||||
|
|
||||||
const pos = typeof getPos === "function" ? getPos() : 0;
|
const pos = typeof getPos === "function" ? getPos() : 0;
|
||||||
if (typeof pos !== "number") return;
|
if (typeof pos !== "number") return;
|
||||||
|
|
||||||
const resolvedPos = editor.state.doc.resolve(pos);
|
const resolvedPos = editor.state.doc.resolve(pos);
|
||||||
if (isClickWithinBounds(e, resolvedPos, "right")) {
|
|
||||||
|
const { x, y, width } = e.target.getBoundingClientRect();
|
||||||
|
|
||||||
|
const clientX =
|
||||||
|
e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
||||||
|
|
||||||
|
const clientY =
|
||||||
|
e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
||||||
|
|
||||||
|
const hitArea = { width: 40, height: 40 };
|
||||||
|
|
||||||
|
const isRtl =
|
||||||
|
e.target.dir === "rtl" ||
|
||||||
|
findParentNodeClosestToPos(
|
||||||
|
resolvedPos,
|
||||||
|
(node) => !!node.attrs.textDirection
|
||||||
|
)?.node.attrs.textDirection === "rtl";
|
||||||
|
|
||||||
|
let xEnd = clientX <= x + width;
|
||||||
|
let xStart = clientX >= x + width - hitArea.width;
|
||||||
|
|
||||||
|
const yStart = clientY >= y;
|
||||||
|
const yEnd = clientY <= y + hitArea.height;
|
||||||
|
|
||||||
|
if (isRtl) {
|
||||||
|
xStart = clientX >= x;
|
||||||
|
xEnd = clientX <= x + hitArea.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xStart && xEnd && yStart && yEnd) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopImmediatePropagation();
|
e.stopImmediatePropagation();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`collapse heading > heading collapsed 1`] = `"<h1 data-collapsed="true">Main Heading</h1><p>paragraph.</p><h2>Subheading</h2><p>subheading paragraph</p><h1>Main heading 2</h1><p>paragraph another</p>"`;
|
|
||||||
|
|
||||||
exports[`collapse heading > heading uncollapsed 1`] = `"<h1>Main Heading</h1><p>paragraph.</p><h2>Subheading</h2><p>subheading paragraph</p><h1>Main heading 2</h1><p>paragraph another</p>"`;
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of the Notesnook project (https://notesnook.com/)
|
|
||||||
|
|
||||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { test, expect } from "vitest";
|
|
||||||
import { createEditor } from "../../../../test-utils/index.js";
|
|
||||||
import { Heading } from "../heading.js";
|
|
||||||
|
|
||||||
test("collapse heading", () => {
|
|
||||||
const { editor } = createEditor({
|
|
||||||
extensions: {
|
|
||||||
heading: Heading.configure({ levels: [1, 2, 3, 4, 5, 6] })
|
|
||||||
},
|
|
||||||
initialContent: `
|
|
||||||
<h1>Main Heading</h1>
|
|
||||||
<p>paragraph.</p>
|
|
||||||
<h2>Subheading</h2>
|
|
||||||
<p>subheading paragraph</p>
|
|
||||||
<h1>Main heading 2</h1>
|
|
||||||
<p>paragraph another</p>
|
|
||||||
`
|
|
||||||
});
|
|
||||||
|
|
||||||
const headingPos = 0;
|
|
||||||
|
|
||||||
editor.commands.command(({ tr }) => {
|
|
||||||
tr.setNodeAttribute(headingPos, "collapsed", true);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(editor.getHTML()).toMatchSnapshot("heading collapsed");
|
|
||||||
|
|
||||||
editor.commands.command(({ tr }) => {
|
|
||||||
tr.setNodeAttribute(headingPos, "collapsed", false);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(editor.getHTML()).toMatchSnapshot("heading uncollapsed");
|
|
||||||
});
|
|
||||||
@@ -18,31 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { tiptapKeys } from "@notesnook/common";
|
import { tiptapKeys } from "@notesnook/common";
|
||||||
import {
|
import { textblockTypeInputRule } from "@tiptap/core";
|
||||||
textblockTypeInputRule,
|
|
||||||
findParentNodeClosestToPos
|
|
||||||
} from "@tiptap/core";
|
|
||||||
import { Heading as TiptapHeading } from "@tiptap/extension-heading";
|
import { Heading as TiptapHeading } from "@tiptap/extension-heading";
|
||||||
import { Plugin, PluginKey } from "@tiptap/pm/state";
|
|
||||||
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
||||||
import { isClickWithinBounds } from "../../utils/prosemirror.js";
|
|
||||||
|
|
||||||
const HEADING_REGEX = /^(#{1,6})\s$/;
|
const HEADING_REGEX = /^(#{1,6})\s$/;
|
||||||
export const Heading = TiptapHeading.extend({
|
export const Heading = TiptapHeading.extend({
|
||||||
addAttributes() {
|
|
||||||
return {
|
|
||||||
...this.parent?.(),
|
|
||||||
collapsed: {
|
|
||||||
default: false,
|
|
||||||
keepOnSplit: false,
|
|
||||||
parseHTML: (element) => element.dataset.collapsed === "true",
|
|
||||||
renderHTML: (attributes) => ({
|
|
||||||
"data-collapsed": attributes.collapsed === true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
addCommands() {
|
addCommands() {
|
||||||
return {
|
return {
|
||||||
...this.parent?.(),
|
...this.parent?.(),
|
||||||
@@ -61,16 +41,6 @@ export const Heading = TiptapHeading.extend({
|
|||||||
textAlign,
|
textAlign,
|
||||||
textDirection
|
textDirection
|
||||||
});
|
});
|
||||||
},
|
|
||||||
toggleHeadingCollapse:
|
|
||||||
(pos: number) =>
|
|
||||||
({ tr }: { tr: any }) => {
|
|
||||||
const node = tr.doc.nodeAt(pos);
|
|
||||||
if (node && node.type === this.type) {
|
|
||||||
tr.setNodeAttribute(pos, "collapsed", !node.attrs.collapsed);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -101,114 +71,5 @@ export const Heading = TiptapHeading.extend({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
},
|
|
||||||
|
|
||||||
addProseMirrorPlugins() {
|
|
||||||
return [
|
|
||||||
new Plugin({
|
|
||||||
key: new PluginKey("collapsibleHeadings"),
|
|
||||||
props: {
|
|
||||||
decorations: (state) => {
|
|
||||||
const decorations: Decoration[] = [];
|
|
||||||
const { doc } = state;
|
|
||||||
|
|
||||||
doc.descendants((node, pos) => {
|
|
||||||
if (node.type.name === "heading" && node.attrs.collapsed) {
|
|
||||||
const headingLevel = node.attrs.level;
|
|
||||||
let nextPos = pos + node.nodeSize;
|
|
||||||
|
|
||||||
while (nextPos < doc.content.size) {
|
|
||||||
const nextNode = doc.nodeAt(nextPos);
|
|
||||||
if (!nextNode) break;
|
|
||||||
if (
|
|
||||||
nextNode.type.name === "heading" &&
|
|
||||||
nextNode.attrs.level <= headingLevel
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
decorations.push(
|
|
||||||
Decoration.node(nextPos, nextPos + nextNode.nodeSize, {
|
|
||||||
style: "display: none;"
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
nextPos += nextNode.nodeSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return DecorationSet.create(doc, decorations);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
addNodeView() {
|
|
||||||
return ({ node, getPos, editor, HTMLAttributes }) => {
|
|
||||||
const heading = document.createElement(`h${node.attrs.level}`);
|
|
||||||
|
|
||||||
for (const attr in HTMLAttributes) {
|
|
||||||
heading.setAttribute(attr, HTMLAttributes[attr]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.attrs.collapsed) heading.dataset.collapsed = "true";
|
|
||||||
else delete heading.dataset.collapsed;
|
|
||||||
|
|
||||||
function onClick(e: MouseEvent | TouchEvent) {
|
|
||||||
if (e instanceof MouseEvent && e.button !== 0) return;
|
|
||||||
if (!(e.target instanceof HTMLHeadingElement)) return;
|
|
||||||
|
|
||||||
const pos = typeof getPos === "function" ? getPos() : 0;
|
|
||||||
if (typeof pos !== "number") return;
|
|
||||||
|
|
||||||
const resolvedPos = editor.state.doc.resolve(pos);
|
|
||||||
const calloutAncestor = findParentNodeClosestToPos(
|
|
||||||
resolvedPos,
|
|
||||||
(node) => node.type.name === "callout"
|
|
||||||
);
|
|
||||||
if (calloutAncestor) return;
|
|
||||||
|
|
||||||
if (isClickWithinBounds(e, resolvedPos, "left")) {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopImmediatePropagation();
|
|
||||||
|
|
||||||
editor.commands.command(({ tr }) => {
|
|
||||||
const currentNode = tr.doc.nodeAt(pos);
|
|
||||||
if (currentNode) {
|
|
||||||
tr.setNodeAttribute(
|
|
||||||
pos,
|
|
||||||
"collapsed",
|
|
||||||
!currentNode.attrs.collapsed
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
heading.onmousedown = onClick;
|
|
||||||
heading.ontouchstart = onClick;
|
|
||||||
|
|
||||||
return {
|
|
||||||
dom: heading,
|
|
||||||
contentDOM: heading,
|
|
||||||
update: (updatedNode) => {
|
|
||||||
if (updatedNode.type !== this.type) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedNode.attrs.level !== node.attrs.level) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (updatedNode.attrs.collapsed) heading.dataset.collapsed = "true";
|
|
||||||
else delete heading.dataset.collapsed;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,11 +17,12 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Node, mergeAttributes } from "@tiptap/core";
|
|
||||||
import {
|
import {
|
||||||
findParentNodeOfTypeClosestToPos,
|
Node,
|
||||||
isClickWithinBounds
|
mergeAttributes,
|
||||||
} from "../../utils/prosemirror.js";
|
findParentNodeClosestToPos
|
||||||
|
} from "@tiptap/core";
|
||||||
|
import { findParentNodeOfTypeClosestToPos } from "../../utils/prosemirror.js";
|
||||||
import { OutlineList } from "../outline-list/outline-list.js";
|
import { OutlineList } from "../outline-list/outline-list.js";
|
||||||
import { keybindings, tiptapKeys } from "@notesnook/common";
|
import { keybindings, tiptapKeys } from "@notesnook/common";
|
||||||
|
|
||||||
@@ -128,9 +129,36 @@ export const OutlineListItem = Node.create<ListItemOptions>({
|
|||||||
|
|
||||||
const pos = typeof getPos === "function" ? getPos() : 0;
|
const pos = typeof getPos === "function" ? getPos() : 0;
|
||||||
if (typeof pos !== "number") return;
|
if (typeof pos !== "number") return;
|
||||||
|
|
||||||
const resolvedPos = editor.state.doc.resolve(pos);
|
const resolvedPos = editor.state.doc.resolve(pos);
|
||||||
if (isClickWithinBounds(e, resolvedPos, "left")) {
|
|
||||||
|
const { x, y, right } = li.getBoundingClientRect();
|
||||||
|
|
||||||
|
const clientX =
|
||||||
|
e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
||||||
|
|
||||||
|
const clientY =
|
||||||
|
e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
||||||
|
|
||||||
|
const hitArea = { width: 40, height: 40 };
|
||||||
|
|
||||||
|
const isRtl =
|
||||||
|
e.target.dir === "rtl" ||
|
||||||
|
findParentNodeClosestToPos(
|
||||||
|
resolvedPos,
|
||||||
|
(node) => !!node.attrs.textDirection
|
||||||
|
)?.node.attrs.textDirection === "rtl";
|
||||||
|
|
||||||
|
let xStart = clientX >= x - hitArea.width;
|
||||||
|
let xEnd = clientX <= x;
|
||||||
|
const yStart = clientY >= y;
|
||||||
|
const yEnd = clientY <= y + hitArea.height;
|
||||||
|
|
||||||
|
if (isRtl) {
|
||||||
|
xEnd = clientX <= right + hitArea.width;
|
||||||
|
xStart = clientX >= right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xStart && xEnd && yStart && yEnd) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
editor.commands.command(({ tr }) => {
|
editor.commands.command(({ tr }) => {
|
||||||
tr.setNodeAttribute(
|
tr.setNodeAttribute(
|
||||||
|
|||||||
@@ -345,52 +345,3 @@ export function getDeletedNodes(
|
|||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isClickWithinBounds(
|
|
||||||
e: MouseEvent | TouchEvent,
|
|
||||||
pos: ResolvedPos,
|
|
||||||
hitPosition: "left" | "right",
|
|
||||||
hitArea: { width: number; height: number } = { width: 40, height: 40 }
|
|
||||||
) {
|
|
||||||
const { target } = e;
|
|
||||||
if (!(target instanceof HTMLElement)) return false;
|
|
||||||
|
|
||||||
const { x, y, right, width } = target.getBoundingClientRect();
|
|
||||||
const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
|
||||||
const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
|
||||||
const isRtl =
|
|
||||||
target.dir === "rtl" ||
|
|
||||||
findParentNodeClosestToPos(pos, (node) => !!node.attrs.textDirection)?.node
|
|
||||||
.attrs.textDirection === "rtl";
|
|
||||||
|
|
||||||
switch (hitPosition) {
|
|
||||||
case "left": {
|
|
||||||
let xStart = clientX >= x - hitArea.width;
|
|
||||||
let xEnd = clientX <= x;
|
|
||||||
const yStart = clientY >= y;
|
|
||||||
const yEnd = clientY <= y + hitArea.height;
|
|
||||||
|
|
||||||
if (isRtl) {
|
|
||||||
xEnd = clientX <= x + hitArea.width;
|
|
||||||
xStart = clientX >= right;
|
|
||||||
}
|
|
||||||
|
|
||||||
return xStart && xEnd && yStart && yEnd;
|
|
||||||
}
|
|
||||||
case "right": {
|
|
||||||
let xEnd = clientX <= x + width;
|
|
||||||
let xStart = clientX >= x + width - hitArea.width;
|
|
||||||
const yStart = clientY >= y;
|
|
||||||
const yEnd = clientY <= y + hitArea.height;
|
|
||||||
|
|
||||||
if (isRtl) {
|
|
||||||
xStart = clientX >= x;
|
|
||||||
xEnd = clientX <= x + hitArea.width;
|
|
||||||
}
|
|
||||||
|
|
||||||
return xStart && xEnd && yStart && yEnd;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -800,70 +800,6 @@ del.diffdel {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ProseMirror h1,
|
|
||||||
.ProseMirror h2,
|
|
||||||
.ProseMirror h3,
|
|
||||||
.ProseMirror h4,
|
|
||||||
.ProseMirror h5,
|
|
||||||
.ProseMirror h6 {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror h1::before,
|
|
||||||
.ProseMirror h2::before,
|
|
||||||
.ProseMirror h3::before,
|
|
||||||
.ProseMirror h4::before,
|
|
||||||
.ProseMirror h5::before,
|
|
||||||
.ProseMirror h6::before {
|
|
||||||
position: absolute;
|
|
||||||
cursor: pointer;
|
|
||||||
content: "";
|
|
||||||
background-size: 18px;
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
|
|
||||||
background-color: var(--icon);
|
|
||||||
mask: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxZW0iIGhlaWdodD0iMWVtIiB2aWV3Qm94PSIwIDAgMjQgMjQiPjxwYXRoIGZpbGw9IiM4ODg4ODgiIGQ9Ik03LjQxIDguNThMMTIgMTMuMTdsNC41OS00LjU5TDE4IDEwbC02IDZsLTYtNmwxLjQxLTEuNDJaIi8+PC9zdmc+)
|
|
||||||
no-repeat 50% 50%;
|
|
||||||
mask-size: cover;
|
|
||||||
border: 1px solid var(--background);
|
|
||||||
|
|
||||||
transform: rotate(0);
|
|
||||||
transition: transform 250ms ease, opacity 200ms ease;
|
|
||||||
left: -22px;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror h1[data-collapsed="true"]::before,
|
|
||||||
.ProseMirror h2[data-collapsed="true"]::before,
|
|
||||||
.ProseMirror h3[data-collapsed="true"]::before,
|
|
||||||
.ProseMirror h4[data-collapsed="true"]::before,
|
|
||||||
.ProseMirror h5[data-collapsed="true"]::before,
|
|
||||||
.ProseMirror h6[data-collapsed="true"]::before {
|
|
||||||
transform: rotate(-90deg);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror h1:hover::before,
|
|
||||||
.ProseMirror h2:hover::before,
|
|
||||||
.ProseMirror h3:hover::before,
|
|
||||||
.ProseMirror h4:hover::before,
|
|
||||||
.ProseMirror h5:hover::before,
|
|
||||||
.ProseMirror h6:hover::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ProseMirror div.callout h1::before,
|
|
||||||
.ProseMirror div.callout h2::before,
|
|
||||||
.ProseMirror div.callout h3::before,
|
|
||||||
.ProseMirror div.callout h4::before,
|
|
||||||
.ProseMirror div.callout h5::before,
|
|
||||||
.ProseMirror div.callout h6::before {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* simplebar */
|
/* simplebar */
|
||||||
.simplebar-track {
|
.simplebar-track {
|
||||||
height: 9px !important;
|
height: 9px !important;
|
||||||
|
|||||||
Reference in New Issue
Block a user