Skip to content

Commit

Permalink
fix: the editor breaks converting when tables have invalid list HTML (n…
Browse files Browse the repository at this point in the history
…hn#1780)

* fix: close unmatched html inline node

* chore: add test case(table with unmatched html list)

* chore: fix broken test case

* chore: use element with cached var

* chore: apply code review

* chore: add missing jsdoc
  • Loading branch information
js87zz committed Aug 31, 2021
1 parent 105c296 commit 4bb1d7f
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 8 deletions.
14 changes: 8 additions & 6 deletions src/__test__/integration/ui/layout.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ function getMdPreviewTab() {
}

function getScrollSyncWrapper() {
return getElement('.scroll-sync')!.parentElement;
const scrollSync = getElement('.scroll-sync');

return scrollSync ? scrollSync.parentElement : null;
}

function clickMdWriteTab() {
Expand Down Expand Up @@ -168,14 +170,14 @@ describe('layout component', () => {
expect(wwSwitch).not.toHaveClass('active');
});

it('should hide scrollSync when previewStyle is tab regardless of changing editor mode', () => {
it('should not render scrollSync when previewStyle is tab regardless of changing editor mode', () => {
const scrollSyncWrapper = getScrollSyncWrapper();

expect(scrollSyncWrapper).toHaveStyle({ display: 'none' });
expect(scrollSyncWrapper).toBeNull();

em.emit('changeMode', 'wysiwyg');

expect(scrollSyncWrapper).toHaveStyle({ display: 'none' });
expect(scrollSyncWrapper).toBeNull();
});

it('should show scrollSync when previewStyle is vertical on only markdown mode', () => {
Expand Down Expand Up @@ -255,12 +257,12 @@ describe('layout component', () => {

clickMdPreviewTab();

expect(scrollSyncWrapper).toHaveStyle({ display: 'none' });
expect(scrollSyncWrapper).toBeNull();
expect(getElement(`.${cls('toolbar-icons')}`)).toBeDisabled();

clickMdWriteTab();

expect(scrollSyncWrapper).toHaveStyle({ display: 'none' });
expect(scrollSyncWrapper).toBeNull();
expect(getElement(`.${cls('toolbar-icons')}`)).not.toBeDisabled();
});

Expand Down
19 changes: 19 additions & 0 deletions src/__test__/unit/convertor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,25 @@ describe('Convertor', () => {

assertConverting(markdown, `${markdown}\n`);
});

it('table with unmatched html list', () => {
const markdown = source`
| thead |
| ----- |
| <ul><li>bullet</li><ul> |
| <ol><li>ordered</li><ol> |
| <ul><li>nested<ul><li>nested</li><ul><li><ul> |
`;
const expected = source`
| thead |
| ----- |
| <ul><li>bullet</li></ul> |
| <ol><li>ordered</li></ol> |
| <ul><li>nested<ul><li>nested</li></ul></li></ul> |
`;

assertConverting(markdown, `${expected}\n`);
});
});

describe('convert block html', () => {
Expand Down
22 changes: 22 additions & 0 deletions src/convertors/toWysiwyg/toWwConvertorState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,27 @@ export default class ToWwConvertorState {
doc.content.forEach((node) => this.push(node));
}

private closeUnmatchedHTMLInline(node: MdNode, entering: boolean) {
if (!entering && node.type !== 'htmlInline') {
const length = this.stack.length - 1;

for (let i = length; i >= 0; i -= 1) {
const nodeInfo = this.stack[i];

if (nodeInfo.attrs?.rawHTML) {
if (nodeInfo.content.length) {
this.closeNode();
} else {
// just pop useless unmatched html inline node
this.stack.pop();
}
} else {
break;
}
}
}
}

private convert(mdNode: MdNode, infoForPosSync?: InfoForPosSync) {
const walker = mdNode.walker();
let event = walker.next();
Expand All @@ -117,6 +138,7 @@ export default class ToWwConvertorState {
},
};

this.closeUnmatchedHTMLInline(node, entering);
convertor(this, node, context);

if (infoForPosSync?.node === node) {
Expand Down
2 changes: 2 additions & 0 deletions src/editorCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,13 +414,15 @@ class ToastUIEditorCore {

/**
* Set cursor position to end
* @param {boolean} [focus] - automatically focus the editor
*/
moveCursorToEnd(focus = true) {
this.getCurrentModeEditor().moveCursorToEnd(focus);
}

/**
* Set cursor position to start
* @param {boolean} [focus] - automatically focus the editor
*/
moveCursorToStart(focus = true) {
this.getCurrentModeEditor().moveCursorToStart(focus);
Expand Down
4 changes: 2 additions & 2 deletions types/editor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,9 @@ export interface Base {

destroy(): void;

moveCursorToStart(focus?: boolean): void;
moveCursorToStart(focus: boolean): void;

moveCursorToEnd(focus?: boolean): void;
moveCursorToEnd(focus: boolean): void;

setScrollTop(top: number): void;

Expand Down

0 comments on commit 4bb1d7f

Please sign in to comment.