Skip to content

Commit

Permalink
fix(plugin-basic): lost list type when paste content is from outside
Browse files Browse the repository at this point in the history
fix #68
  • Loading branch information
lastnigtic committed Sep 28, 2021
1 parent 53bec64 commit 441d455
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/adapter/src/basic/basic-ctrl/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const BasicCtrlPlugin = (config: IBasicCtrlConfig, _editable = true) => {
const { state, dispatch } = view;
const { $from } = state.selection;
if (
$from.depth &&
$from.depth === 1 &&
state.selection instanceof TextSelection &&
!$from.parent.content.size &&
isOriginAttrs($from.parent)
Expand Down
3 changes: 3 additions & 0 deletions packages/plugin-basic/src/block/list-item/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const LIST_ITEM_NAME = 'list_item';

export { LIST_ITEM_NAME };
30 changes: 22 additions & 8 deletions packages/plugin-basic/src/block/list-item/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Block, getTypesetDOMStyle, parseTypesetStyle, SylApi, SylController, SylPlugin } from '@syllepsis/adapter';
import { DOMOutputSpecArray, Node as ProseMirrorNode } from 'prosemirror-model';
import { DOMOutputSpecArray, Fragment, Node as ProseMirrorNode, Slice } from 'prosemirror-model';
import { EditorState, Transaction } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';

Expand All @@ -11,10 +11,12 @@ import {
IUserAttrsConfig,
setDOMAttrByConfig,
} from '../../utils';
import { LIST_ITEM_NAME } from './const';
import {
checkAndMergeList,
checkOutMaxNestedLevel,
filterKeymap,
getListItem,
liftListItem,
liftListItemAtHead,
sinkListItem,
Expand Down Expand Up @@ -46,8 +48,6 @@ interface IListItemAttrs {
lineHeight: number | string;
}

const NAME = 'list_item';

class ListItem extends Block<IListItemAttrs> {
public formatAttrs: ReturnType<typeof constructTypesetParseDOM>['formatAttrs'] = v => v;
public defaultFontSize = 16;
Expand Down Expand Up @@ -103,7 +103,7 @@ class ListItem extends Block<IListItemAttrs> {
}
}

public name = NAME;
public name = LIST_ITEM_NAME;

public tagName = () => 'li';

Expand All @@ -127,7 +127,7 @@ class ListItem extends Block<IListItemAttrs> {

public inline = false;

public defining = true;
public defining = false;

public parseDOM = [
{
Expand Down Expand Up @@ -160,7 +160,21 @@ class ListItem extends Block<IListItemAttrs> {
}

class ListItemController extends SylController<IListItemProps> {
public name = NAME;
public name = LIST_ITEM_NAME;

public eventHandler = {
transformPasted: (editor: SylApi, slice: Slice) => {
const { $from } = editor.view.state.selection;
if ($from.parent.type.name === LIST_ITEM_NAME && $from.pos === $from.start()) {
// hack when paste at start of list_item
const listNode = getListItem(slice);
if (!listNode) return slice;
slice.openStart += 1;
if (!slice.size) return new Slice(Fragment.from(listNode), 1, 1);
}
return slice;
},
};

public command = {
getMaxNestedLevel: () => this.props.maxNestedLevel,
Expand All @@ -184,9 +198,9 @@ class ListItemController extends SylController<IListItemProps> {
}

class ListItemPlugin extends SylPlugin<IListItemProps> {
public name = NAME;
public name = LIST_ITEM_NAME;
public Controller = ListItemController;
public Schema = ListItem;
}

export { NAME as LIST_ITEM_NAME, ListItem, ListItemController, ListItemPlugin };
export { LIST_ITEM_NAME, ListItem, ListItemController, ListItemPlugin };
19 changes: 18 additions & 1 deletion packages/plugin-basic/src/block/list-item/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { SylApi } from '@syllepsis/adapter';
import { Node as ProsemirrorNode, NodeType } from 'prosemirror-model';
import { Node as ProsemirrorNode, NodeType, Slice } from 'prosemirror-model';
import { EditorState, Transaction } from 'prosemirror-state';
import { canJoin, liftTarget } from 'prosemirror-transform';
import { EditorView } from 'prosemirror-view';

import { LIST_ITEM_NAME } from './const';

const getListItemType = (doc: ProsemirrorNode) => doc.type.schema.nodes.list_item as NodeType;

const isInList = (state: EditorState | Transaction) => {
Expand Down Expand Up @@ -185,10 +187,25 @@ const filterKeymap = (fn: (state: EditorState, dispatch?: EditorView['dispatch']
dispatch?: EditorView['dispatch'],
) => fn(state, dispatch);

const getListItem = (slice: Slice) => {
let listNode: ProsemirrorNode | null = null;

slice.content.descendants(node => {
if (node.type.name === LIST_ITEM_NAME) {
listNode = node;
return false;
}
if (listNode) return false;
});

return listNode as ProsemirrorNode | null;
};

export {
checkAndMergeList,
checkOutMaxNestedLevel,
filterKeymap,
getListItem,
liftListItem,
liftListItemAtHead,
sinkListItem,
Expand Down
18 changes: 9 additions & 9 deletions packages/plugin-basic/src/block/ordered-list/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,38 +19,38 @@ class OrderedList extends Block<IOrderedListAttrs> {

public attrs = {
start: {
default: 1
}
default: 1,
},
};

public textMatcher = [
{
matcher: /^(\d+)\.\s$/,
handler(match: RegExpExecArray) {
return {
start: match[1]
start: match[1],
};
}
}
},
},
];

public parseDOM = [
{
tag: 'ol',
getAttrs(dom: HTMLOListElement) {
return {
start: dom.hasAttribute('start') ? +dom.getAttribute('start')! : 1
start: dom.hasAttribute('start') ? +dom.getAttribute('start')! : 1,
};
}
}
},
},
];
}

class OrderedListController extends SylController {
public name = NAME;
public toolbar = {
className: 'ordered_list',
tooltip: 'ordered_list'
tooltip: 'ordered_list',
};
}

Expand Down
9 changes: 9 additions & 0 deletions test/case/adapter/list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,4 +350,13 @@ describe('list - Backspace', () => {
});
expect(html1).toEqual('<ul><li>1</li><li>c2</li></ul>');
});

test('can paste list from outside', async () => {
const html = await page.evaluate(() => {
editor.setHTML('');
editor.pasteContent(`<ul><li>1</li><li>2</li></ul>`);
return editor.getHTML();
});
expect(html).toEqual('<ul><li>1</li><li>2</li></ul>');
});
});
38 changes: 19 additions & 19 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1620,12 +1620,12 @@
"@sinonjs/commons" "^1.7.0"

"@syllepsis/access-react@file:packages/access-react":
version "0.0.11"
version "0.0.19"
dependencies:
"@icon-park/react" "^1.3.3"
"@syllepsis/adapter" "^0.0.11"
"@syllepsis/editor" "^0.0.11"
"@syllepsis/plugin-basic" "^0.0.11"
"@syllepsis/adapter" "^0.0.19"
"@syllepsis/editor" "^0.0.19"
"@syllepsis/plugin-basic" "^0.0.19"
"@types/classnames" "^2.2.6"
"@types/emoji-mart" "<2.11.2"
"@types/lodash.debounce" "^4.0.0"
Expand All @@ -1637,7 +1637,7 @@
react-tooltip-lite "^1.12.0"

"@syllepsis/adapter@file:packages/adapter":
version "0.0.11"
version "0.0.19"
dependencies:
"@types/lodash.clonedeep" "^4.0.0"
"@types/lodash.isequal" "^4.0.0"
Expand All @@ -1664,18 +1664,18 @@
prosemirror-view "^1.13.4"

"@syllepsis/editor@file:packages/editor":
version "0.0.11"
version "0.0.19"
dependencies:
"@syllepsis/adapter" "^0.0.11"
"@syllepsis/adapter" "^0.0.19"
"@types/lodash.debounce" "^4.0.0"
"@types/lodash.throttle" "^4.0.0"
lodash.debounce "^4.0.0"
lodash.throttle "^4.0.0"

"@syllepsis/plugin-basic@file:packages/plugin-basic":
version "0.0.11"
version "0.0.19"
dependencies:
"@syllepsis/adapter" "^0.0.11"
"@syllepsis/adapter" "^0.0.19"
"@types/color" "^3.0.2"
"@types/lodash.debounce" "^4.0.0"
"@types/lodash.isequal" "^4.0.0"
Expand All @@ -1686,18 +1686,18 @@
lodash.merge "^4.0.0"

"@syllepsis/plugin-code-block@file:packages/plugin-code-block":
version "0.0.11"
version "0.0.19"
dependencies:
"@syllepsis/adapter" "^0.0.11"
"@syllepsis/adapter" "^0.0.19"
"@types/codemirror" "^5.60.2"
"@types/lodash.debounce" "^4.0.0"
codemirror "^5.54.0"
lodash.debounce "^4.0.0"

"@syllepsis/plugin-table@file:packages/plugin-table":
version "0.0.11"
version "0.0.19"
dependencies:
"@syllepsis/adapter" "^0.0.11"
"@syllepsis/adapter" "^0.0.19"
"@types/lodash.clonedeep" "^4.0.0"
"@types/lodash.debounce" "^4.0.0"
"@types/lodash.merge" "^4.0.0"
Expand Down Expand Up @@ -8465,9 +8465,9 @@ prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.3:
w3c-keyname "^2.2.0"

prosemirror-model@^1.0.0, prosemirror-model@^1.1.0, prosemirror-model@^1.10.0, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
version "1.11.2"
resolved "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.11.2.tgz#3ce08172b465bc725c8808c18c2e9378fe69418d"
integrity sha1-POCBcrRlvHJciAjBjC6TeP5pQY0=
version "1.14.3"
resolved "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.14.3.tgz#a9c250d3c4023ddf10ecb41a0a7a130e9741d37e"
integrity sha512-yzZlBaSxfUPIIP6U5Edh5zKxJPZ5f7bwZRhiCuH3UYkWhj+P3d8swHsbuAMOu/iDatDc5J/Qs5Mb3++mZf+CvQ==
dependencies:
orderedmap "^1.1.0"

Expand Down Expand Up @@ -8515,9 +8515,9 @@ prosemirror-test-builder@^1.0.1:
prosemirror-schema-list "^1.0.0"

prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transform@^1.2.1, prosemirror-transform@^1.2.3:
version "1.2.3"
resolved "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.2.3.tgz#239d17591af24d39ef3f1999daa09e1f1c76b06a"
integrity sha1-I50XWRryTTnvPxmZ2qCeHxx2sGo=
version "1.3.2"
resolved "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.2.tgz#5620ebe7379e6fae4f34ecc881886cb22ce96579"
integrity sha512-/G6d/u9Mf6Bv3H1XR8VxhpjmUO75LYmnvj+s3ZfZpakU1hnQbsvCEybml1B3f2IWUAAQRFkbO1PnsbFhLZsYsw==
dependencies:
prosemirror-model "^1.0.0"

Expand Down

0 comments on commit 441d455

Please sign in to comment.