From 57e687efa2f3c9adb4e0966caf555039028b5ad6 Mon Sep 17 00:00:00 2001
From: marihachi <marihachi0620@gmail.com>
Date: Sat, 27 Mar 2021 22:09:18 +0900
Subject: [PATCH] #34

---
 src/node.ts |  5 +++++
 src/util.ts | 48 +++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/src/node.ts b/src/node.ts
index 9470cc3..0455693 100644
--- a/src/node.ts
+++ b/src/node.ts
@@ -2,6 +2,11 @@ export type MfmNode = MfmBlock | MfmInline;
 
 export type MfmBlock = MfmQuote | MfmSearch | MfmCodeBlock | MfmMathBlock | MfmCenter;
 
+const blockTypes: MfmNode['type'][] = [ 'quote', 'search', 'blockCode', 'mathBlock', 'center' ];
+export function isMfmBlock(node: MfmNode): node is MfmBlock {
+	return blockTypes.includes(node.type);
+}
+
 export type MfmQuote = {
 	type: 'quote';
 	props?: { };
diff --git a/src/util.ts b/src/util.ts
index 45f328d..12a21e8 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -1,4 +1,4 @@
-import { MfmNode } from './node';
+import { isMfmBlock, MfmNode } from './node';
 
 export function createNode(type: string, props?: Record<string, any>, children?: MfmNode[]): MfmNode {
 	const node: any = { type };
@@ -45,7 +45,7 @@ export function stringifyNode(node: MfmNode): string {
 	switch(node.type) {
 		// block
 		case 'quote': {
-			return stringifyTree(node.children).split('\n').map(line => `>${line}`).join('\n');
+			return stringifyTree(node.children).split('\n').map(line => `> ${line}`).join('\n');
 		}
 		case 'search': {
 			return node.props.content;
@@ -57,7 +57,7 @@ export function stringifyNode(node: MfmNode): string {
 			return `\\[\n${ node.props.formula }\n\\]`;
 		}
 		case 'center': {
-			return `<center>${ stringifyTree(node.children) }</center>`;
+			return `<center>\n${ stringifyTree(node.children) }\n</center>`;
 		}
 		// inline
 		case 'emoji': {
@@ -122,8 +122,46 @@ export function stringifyNode(node: MfmNode): string {
 	throw new Error('unknown mfm node');
 }
 
-export function stringifyTree(tree: MfmNode[]): string {
-	return tree.map(n => stringifyNode(n)).join('');
+enum stringifyState {
+	none = 0,
+	inline,
+	block
+};
+
+export function stringifyTree(nodes: MfmNode[]): string {
+	let dest: MfmNode[] = [];
+	let state: stringifyState = stringifyState.none;
+
+	for (const node of nodes) {
+		// 文脈に合わせて改行を追加する。
+		// none -> inline   : No
+		// none -> block    : No
+		// inline -> inline : No
+		// inline -> block  : Yes
+		// block -> inline  : Yes
+		// block -> block   : Yes
+
+		let pushLf: boolean = true;
+		if (isMfmBlock(node)) {
+			if (state == stringifyState.none) {
+				pushLf = false;
+			}
+			state = stringifyState.block;
+		}
+		else {
+			if (state == stringifyState.none || state == stringifyState.inline) {
+				pushLf = false;
+			}
+			state = stringifyState.inline;
+		}
+		if (pushLf) {
+			dest.push(createNode('text', { text: '\n' }));
+		}
+
+		dest.push(node);
+	}
+
+	return dest.map(n => stringifyNode(n)).join('');
 }
 
 //
-- 
GitLab