Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e5a9b7e
Restructured text & heading blocks (excluding drag handle add impleme…
matthewlipski Nov 16, 2022
72bb83b
Small cleanup
matthewlipski Nov 16, 2022
99a3a09
Cleaned up drag handle code
matthewlipski Nov 17, 2022
034c6f6
Added basic list item implementation
matthewlipski Nov 17, 2022
73ae9ef
Updated block commands and keyboard handling
matthewlipski Nov 17, 2022
ef94e88
Added ordered list item indexing
matthewlipski Nov 18, 2022
0a57bb5
Finished block manipulation logic
matthewlipski Nov 21, 2022
d079e53
Fixed bug causing suggestion menu to not work properly in list item b…
matthewlipski Nov 21, 2022
a1ae764
Refactoring changes
matthewlipski Nov 25, 2022
a10632d
Minor fix
matthewlipski Nov 25, 2022
e7ba0ec
fix animations for headings and indents (#67)
YousefED Nov 28, 2022
5b0bfa7
Fixed bug where splitting a block created an additional empty block
matthewlipski Nov 28, 2022
ad77216
Cleaned up drag handle code
matthewlipski Nov 28, 2022
28c2de9
Fixed bug where the suggestion plugin tried to process transactions c…
matthewlipski Nov 28, 2022
eb3650c
Improvements to block content naming and file structure
matthewlipski Nov 28, 2022
7ef8a3b
Code style changes and small fix to block keyboard shortcuts
matthewlipski Nov 28, 2022
fdc9fb6
Fixed bugs regarding selection when deleting blocks and using the sug…
matthewlipski Nov 28, 2022
f072459
Block content attribute naming fixes
matthewlipski Nov 28, 2022
0287cb2
Fixed list item copy/pasting within the editor
matthewlipski Nov 28, 2022
c077ed9
Updated element selectors for tests
matthewlipski Nov 28, 2022
ff27520
Updated snapshots for copy/paste and drag/drop tests
matthewlipski Nov 28, 2022
00bbd64
Adjusted enter key handler behavior
matthewlipski Nov 29, 2022
c33ff76
Changed ordered list item indices to start at 1 instead of 0
matthewlipski Nov 29, 2022
9e6e07f
Fixed list styling (no animations)
matthewlipski Nov 29, 2022
b9db5d1
Updated remaining test snapshots
matthewlipski Nov 29, 2022
f052b4a
try clean playwright cache
YousefED Nov 29, 2022
8be0efc
Fixed bug where splitting a block duplicates its ID
matthewlipski Nov 30, 2022
88592c3
Merge remote-tracking branch 'origin/block-restructuring' into block-…
matthewlipski Nov 30, 2022
4a1f5bd
Fixed bug where ordered list item indices were being updated unnecess…
matthewlipski Nov 30, 2022
16c483f
clean up OrderedListItemIndexPlugin
YousefED Nov 30, 2022
be05939
Fixed animation issue caused by change in naming convention
Nov 30, 2022
e8f7918
Merge remote-tracking branch 'origin/block-restructuring' into block-…
Nov 30, 2022
7c6835a
Added animations for unordered lists
matthewlipski Nov 30, 2022
2ba14b1
Added animations for ordered lists
matthewlipski Nov 30, 2022
3c8d3eb
Added dispatch to block commands
matthewlipski Dec 1, 2022
cea2919
Made backspace revert all block typing instead of just list items
matthewlipski Dec 1, 2022
641ac1d
Removed redundant conditions in block keyboard handlers
matthewlipski Dec 1, 2022
218e6fe
Changed ordered list index type from number to string in plugin
matthewlipski Dec 1, 2022
a1a2760
Optimized `getPosFromBlock` function
matthewlipski Dec 1, 2022
4ce84a6
Fixed multiple block dragging
matthewlipski Dec 1, 2022
ab69670
Improved transaction filtering for `PreviousBlockTypePlugin`
matthewlipski Dec 2, 2022
d763e03
Improved paste behaviour for content outside the editor
matthewlipski Dec 2, 2022
16bdfb8
Removed dispatch calls from block commands
matthewlipski Dec 2, 2022
d1750a2
Added edge cases for block commands (not currently being triggered)
matthewlipski Dec 2, 2022
bcf39f6
Added test for Enter keyboard handler with selection spanning multipl…
matthewlipski Dec 2, 2022
a01ad22
Added functions to allow testing block IDs
matthewlipski Dec 5, 2022
5954897
Tests in which blocks are deleted/moved now verify block IDs
matthewlipski Dec 5, 2022
c773302
Added updated snapshots
matthewlipski Dec 5, 2022
f5252ca
Added updated screenshots for drag handle menu
matthewlipski Dec 5, 2022
35c4b4a
Removed `joinBackward` as it is no longer used
matthewlipski Dec 5, 2022
91774ca
Improved paste reliability from other sites, broke inline styles.
matthewlipski Dec 5, 2022
5c5c448
Improved paste reliability from other sites, broke inline styles.
matthewlipski Dec 5, 2022
ba69c31
Merge remote-tracking branch 'origin/block-restructuring' into block-…
matthewlipski Dec 5, 2022
4fc50f5
Revert "Improved paste reliability from other sites, broke inline sty…
matthewlipski Dec 5, 2022
c522016
Small fixes
matthewlipski Dec 6, 2022
b17f060
Improved block ID mocking implementation.
matthewlipski Dec 6, 2022
623089b
Updated snapshot
matthewlipski Dec 6, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
uses: actions/cache@v2
with:
path: ~/.cache/ms-playwright
key: pw-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
key: pw-new-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

- name: Install Dependencies
run: npm install
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/extensions/Blocks/BlockAttributes.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Object containing all possible block attributes.
const BlockAttributes: Record<string, string> = {
listType: "data-list-type",
blockColor: "data-block-color",
blockStyle: "data-block-style",
headingType: "data-heading-type",
id: "data-id",
depth: "data-depth",
depthChange: "data-depth-change",
};

export default BlockAttributes;
export default BlockAttributes;
57 changes: 0 additions & 57 deletions packages/core/src/extensions/Blocks/OrderedListPlugin.ts

This file was deleted.

89 changes: 71 additions & 18 deletions packages/core/src/extensions/Blocks/PreviousBlockTypePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import {
} from "@tiptap/core";
import { Plugin, PluginKey } from "prosemirror-state";
import { Decoration, DecorationSet } from "prosemirror-view";
import BlockAttributes from "./BlockAttributes";

const PLUGIN_KEY = new PluginKey(`previous-blocks`);

// Inserts "prev-" string into an HTML attribute name with a "data-" prefix, e.g. "data-depth" -> "data-prev-depth".
// Assumes "data-" prefix is in the attribute name.
const insertPrev = (attr: string) => attr.slice(0, 5) + "prev-" + attr.slice(5);
const nodeAttributes: Record<string, string> = {
listItemType: "list-item-type",
listItemIndex: "list-item-index",
headingLevel: "heading-level",
type: "type",
depth: "depth",
"depth-change": "depth-change",
};

/**
* This plugin tracks transformation of Block node attributes, so we can support CSS transitions.
*
* Problem it solves: Prosemirror recreates the DOM when transactions happen. So when a transaction changes an Node attribute,
* Problem it solves: ProseMirror recreates the DOM when transactions happen. So when a transaction changes a Node attribute,
* it results in a completely new DOM element. This means CSS transitions don't work.
*
* Solution: When attributes change on a node, this plugin sets a data-* attribute with the "previous" value. This way we can still use CSS transitions. (See block.module.css)
Expand Down Expand Up @@ -75,7 +79,6 @@ export const PreviousBlockTypePlugin = () => {

changes.forEach(() => {
const oldNodes = findChildren(oldState.doc, (node) => node.attrs.id);

const oldNodesById = new Map(
oldNodes.map((node) => [node.node.attrs.id, node])
);
Expand All @@ -84,28 +87,68 @@ export const PreviousBlockTypePlugin = () => {

for (let node of newNodes) {
const oldNode = oldNodesById.get(node.node.attrs.id);
if (oldNode) {
const oldContentNode = oldNode?.node.firstChild;
const newContentNode = node.node.firstChild;
if (oldNode && oldContentNode && newContentNode) {
const newAttrs = {
listType: node.node.attrs.listType,
blockColor: node.node.attrs.blockColor,
blockStyle: node.node.attrs.blockStyle,
headingType: node.node.attrs.headingType,
listItemType: newContentNode.attrs.listItemType,
listItemIndex: newContentNode.attrs.listItemIndex,
headingLevel: newContentNode.attrs.headingLevel,
type: newContentNode.type.name,
depth: newState.doc.resolve(node.pos).depth,
};

const oldAttrs = {
listType: oldNode.node.attrs.listType,
blockColor: oldNode.node.attrs.blockColor,
blockStyle: oldNode.node.attrs.blockStyle,
headingType: oldNode.node.attrs.headingType,
listItemType: oldContentNode.attrs.listItemType,
listItemIndex: oldContentNode.attrs.listItemIndex,
headingLevel: oldContentNode.attrs.headingLevel,
type: oldContentNode.type.name,
depth: oldState.doc.resolve(oldNode.pos).depth,
};

// Hacky fix to avoid processing certain transactions created by ordered list indexing plugin.
Comment thread
matthewlipski marked this conversation as resolved.

// True when an existing ordered list item is assigned an index for the first time, which happens
// immediately after it's created. Using this condition to start an animation ensures it's not
// immediately overridden by a different transaction created by the ordered list indexing plugin.
const indexInitialized =
oldAttrs.listItemIndex === null &&
newAttrs.listItemIndex !== null;

// True when an existing ordered list item changes nesting levels, before its index is updated by the
// ordered list indexing plugin. This condition ensures that animations for indentation still work with
// ordered list items, while preventing unnecessary animations being done when dragging/dropping them.
const depthChanged =
oldAttrs.listItemIndex !== null &&
newAttrs.listItemIndex !== null &&
oldAttrs.listItemIndex === newAttrs.listItemIndex;

// Only false for transactions in which the block remains an ordered list item before & after, but neither
// of the previous conditions apply.
const shouldUpdate =
oldAttrs.listItemType === "ordered" &&
newAttrs.listItemType === "ordered"
? indexInitialized || depthChanged
: true;

if (
JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) // TODO: faster deep equal?
JSON.stringify(oldAttrs) !== JSON.stringify(newAttrs) && // TODO: faster deep equal?
shouldUpdate
) {
(oldAttrs as any).depthChange = oldAttrs.depth - newAttrs.depth;
(oldAttrs as any)["depth-change"] =
oldAttrs.depth - newAttrs.depth;
prev.prevBlockAttrs[node.node.attrs.id] = oldAttrs;

// for debugging:
console.log(
"id:",
node.node.attrs.id,
"previousBlockTypePlugin changes detected, oldAttrs",
oldAttrs,
"new",
newAttrs
);

prev.needsUpdate = true;
}
}
Expand All @@ -119,25 +162,35 @@ export const PreviousBlockTypePlugin = () => {
decorations(state) {
const pluginState = (this as Plugin).getState(state);
if (!pluginState.needsUpdate) {
// console.log("0");
return undefined;
}

const decorations: Decoration[] = [];

state.doc.descendants((node, pos) => {
if (!node.attrs.id) {
// console.log("1");
return;
}
const prevAttrs = pluginState.prevBlockAttrs[node.attrs.id];
if (!prevAttrs) {
// console.log("2");
return;
}

const decorationAttributes: any = {};
for (let [nodeAttr, val] of Object.entries(prevAttrs)) {
decorationAttributes[insertPrev(BlockAttributes[nodeAttr])] =
decorationAttributes["data-prev-" + nodeAttributes[nodeAttr]] =
val || "none";
}

// for debugging:
console.log(
"previousBlockTypePlugin committing decorations",
decorationAttributes
);

const decoration = Decoration.node(pos, pos + node.nodeSize, {
...decorationAttributes,
});
Expand Down
Loading