Repository: nhn/tui.editor
Pull request #2598 (2022-07-12 00:50:44)

fix: keep empty line between lists
<!-- EDIT TITLE PLEASE -->
<!-- It should be one of them
  <ISSUE TYPE>: Short Description (<CLOSING TYPE> #<ISSUE NUMBERS>)
  ex)
  feat: add new feature (close #111)
  fix: wrong behavior (fix #111)
  chore: change build tool (ref #111)
-->

<!-- SPECIFY A ISSUE TYPE AT HEAD
  feat: A new feature
  fix: A bug fix
  docs: Documentation only changes
  style: Changes that do not affect the meaning of the code (white-space, formatting etc)
  refactor: A code change that neither fixes a bug or adds a feature
  perf: A code change that improves performance
  test: Adding missing tests
  chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
-->

<!-- ADD CLOSING TYPE AND ISSUE NUMBER AT TAIL
  (<CLOSING TYPE> #<ISSUE NUMBERS>)
  close: resolve not a bug(feature, docs, etc) completely
  fix: resolve a bug completely
  ref: not fully resolved or related to
-->

### Please check if the PR fulfills these requirements
- [x] It's the right issue type on the title
- [ ] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] The commit message follows our guidelines
- [x] Tests for the changes have been added (for bug fixes/features)
- [ ] Docs have been added/updated (for bug fixes/features)
- [ ] It does not introduce a breaking change or has a description of the breaking change

### Description

* Fixed an issue that removes empty line between lists when convert to markdown.
  * If there is an empty line, it keeps to `<br>`.

**As-Is**

![](https://user-images.githubusercontent.com/41339744/178384527-e87a2b63-0fbe-4a59-97d7-989efddbad1a.gif)

**To-Be**

![](https://user-images.githubusercontent.com/41339744/178384545-867c25a5-6fb0-417c-b177-1b1e817025b9.gif)

---
Thank you for your contribution to TOAST UI product. 🎉 😘 ✨



Patch:
diff --git a/apps/editor/src/convertors/toMarkdown/toMdConvertorState.ts b/apps/editor/src/convertors/toMarkdown/toMdConvertorState.ts
index 99991a34..b402f797 100644
--- a/apps/editor/src/convertors/toMarkdown/toMdConvertorState.ts
+++ b/apps/editor/src/convertors/toMarkdown/toMdConvertorState.ts
@@ -78,6 +78,14 @@ export default class ToMdConvertorState {
     return '';
   }
 
+  setDelim(delim: string) {
+    this.delim = delim;
+  }
+
+  getDelim() {
+    return this.delim;
+  }
+
   flushClose(size?: number) {
     if (!this.stopNewline && this.closed) {
       if (!this.isInBlank()) {
@@ -106,12 +114,12 @@ export default class ToMdConvertorState {
   }
 
   wrapBlock(delim: string, firstDelim: string | null, node: Node, fn: () => void) {
-    const old = this.delim;
+    const old = this.getDelim();
 
     this.write(firstDelim || delim);
-    this.delim += delim;
+    this.setDelim(this.getDelim() + delim);
     fn();
-    this.delim = old;
+    this.setDelim(old);
     this.closeBlock(node);
   }
 
diff --git a/apps/editor/src/convertors/toMarkdown/toMdNodeTypeWriters.ts b/apps/editor/src/convertors/toMarkdown/toMdNodeTypeWriters.ts
index 3c4aeb04..2cf7e16e 100644
--- a/apps/editor/src/convertors/toMarkdown/toMdNodeTypeWriters.ts
+++ b/apps/editor/src/convertors/toMarkdown/toMdNodeTypeWriters.ts
@@ -83,6 +83,14 @@ export const nodeTypeWriters: ToMdNodeTypeWriterMap = {
       if (emptyNode && prevEmptyNode) {
         state.write('<br>\n');
       } else if (emptyNode && !prevEmptyNode && !firstChildNode) {
+        if (parent?.type.name === 'listItem') {
+          const prevDelim = state.getDelim();
+
+          state.setDelim('');
+          state.write('<br>');
+
+          state.setDelim(prevDelim);
+        }
         state.write('\n');
       } else {
         state.convertInline(node);
diff --git a/apps/editor/types/convertor.d.ts b/apps/editor/types/convertor.d.ts
index d44db7d0..a3cb6bac 100644
--- a/apps/editor/types/convertor.d.ts
+++ b/apps/editor/types/convertor.d.ts
@@ -45,6 +45,8 @@ export type FirstDelimFn = (index: number) => string;
 export interface ToMdConvertorState {
   stopNewline: boolean;
   inTable: boolean;
+  getDelim(): string;
+  setDelim(delim: string): void;
   flushClose(size?: number): void;
   wrapBlock(delim: string, firstDelim: string | null, node: ProsemirrorNode, fn: () => void): void;
   ensureNewLine(): void;


Test patch:
diff --git a/apps/editor/src/__test__/unit/convertor.spec.ts b/apps/editor/src/__test__/unit/convertor.spec.ts
index 6b98f6e0..2ed8cdd3 100644
--- a/apps/editor/src/__test__/unit/convertor.spec.ts
+++ b/apps/editor/src/__test__/unit/convertor.spec.ts
@@ -1099,6 +1099,36 @@ describe('Convertor', () => {
     expect(result).toBe(`<strong>"test"</strong>a`);
   });
 
+  it('should convert empty line between lists of wysiwig to <br>', () => {
+    const wwNodeJson = {
+      type: 'doc',
+      content: [
+        {
+          type: 'bulletList',
+          content: [
+            {
+              type: 'listItem',
+              content: [
+                { type: 'paragraph', content: [{ type: 'text', text: 'test_1' }] },
+                { type: 'paragraph', content: [] },
+              ],
+            },
+            {
+              type: 'listItem',
+              content: [{ type: 'paragraph', content: [{ type: 'text', text: 'test_2' }] }],
+            },
+          ],
+        },
+      ],
+    };
+
+    const wwNode = Node.fromJSON(schema, wwNodeJson);
+
+    const result = convertor.toMarkdownText(wwNode);
+
+    expect(result).toBe(`* test\\_1\n<br>\n* test\\_2`);
+  });
+
   it('should escape the backslash, which is a plain chracter in the middle of a sentence', () => {
     const markdown = source`
       backslash \\in the middle of a sentence