summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-12-01 10:40:09 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-12-01 10:40:09 +0900
commitfe707f88a47e80a52e1ba54a1c8ae873061c6a62 (patch)
tree222a0c14c3a77ba6f6d15653ce98eb912627c3fc
parent:art: (diff)
downloadmisskey-fe707f88a47e80a52e1ba54a1c8ae873061c6a62.tar.gz
misskey-fe707f88a47e80a52e1ba54a1c8ae873061c6a62.tar.bz2
misskey-fe707f88a47e80a52e1ba54a1c8ae873061c6a62.zip
[MFM] Better MFM parsing
-rw-r--r--src/mfm/parse.ts41
-rw-r--r--src/mfm/parser.ts2
-rw-r--r--test/mfm.ts29
3 files changed, 25 insertions, 47 deletions
diff --git a/src/mfm/parse.ts b/src/mfm/parse.ts
index ee434d8dd9..01c8cc7d7a 100644
--- a/src/mfm/parse.ts
+++ b/src/mfm/parse.ts
@@ -26,45 +26,6 @@ export default (source: string): Node[] => {
nodes = concatText(nodes);
concatTextRecursive(nodes);
- function getBeforeTextNode(node: Node): Node {
- if (node == null) return null;
- if (node.name == 'text') return node;
- if (node.children) return getBeforeTextNode(node.children[node.children.length - 1]);
- return null;
- }
-
- function getAfterTextNode(node: Node): Node {
- if (node == null) return null;
- if (node.name == 'text') return node;
- if (node.children) return getBeforeTextNode(node.children[0]);
- return null;
- }
-
- function isBlockNode(node: Node): boolean {
- return ['blockCode', 'center', 'quote', 'title'].includes(node.name);
- }
-
- /**
- * ブロック要素の前後にある改行を削除します
- * (ブロック要素自体が改行の役割を果たすため、余計に改行されてしまう)
- * @param nodes
- */
- const removeNeedlessLineBreaks = (nodes: Node[]) => {
- nodes.forEach((node, i) => {
- if (node.children) removeNeedlessLineBreaks(node.children);
- if (isBlockNode(node)) {
- const before = getBeforeTextNode(nodes[i - 1]);
- const after = getAfterTextNode(nodes[i + 1]);
- if (before && before.props.text.endsWith('\n')) {
- before.props.text = before.props.text.substring(0, before.props.text.length - 1);
- }
- if (after && after.props.text.startsWith('\n')) {
- after.props.text = after.props.text.substring(1);
- }
- }
- });
- };
-
const removeEmptyTextNodes = (nodes: Node[]) => {
nodes.forEach(n => {
if (n.children) {
@@ -74,8 +35,6 @@ export default (source: string): Node[] => {
return nodes.filter(n => !(n.name == 'text' && n.props.text == ''));
};
- removeNeedlessLineBreaks(nodes);
-
nodes = removeEmptyTextNodes(nodes);
return nodes;
diff --git a/src/mfm/parser.ts b/src/mfm/parser.ts
index 9e47baf893..467097d4f1 100644
--- a/src/mfm/parser.ts
+++ b/src/mfm/parser.ts
@@ -254,7 +254,7 @@ const mfm = P.createLanguage({
const qInner = quote.join('\n').replace(/^>/gm, '').replace(/^ /gm, '');
if (qInner == '') return P.makeFailure(i, 'not a quote');
const contents = r.root.tryParse(qInner);
- return P.makeSuccess(i + quote.join('\n').length, makeNodeWithChildren('quote', contents));
+ return P.makeSuccess(i + quote.join('\n').length + 1, makeNodeWithChildren('quote', contents));
})),
//#endregion
diff --git a/test/mfm.ts b/test/mfm.ts
index c89152f8a2..bfbf595f1c 100644
--- a/test/mfm.ts
+++ b/test/mfm.ts
@@ -299,6 +299,7 @@ describe('Text', () => {
nodeWithChildren('quote', [
text('foo')
]),
+ text('\n'),
nodeWithChildren('quote', [
text('bar')
]),
@@ -358,7 +359,7 @@ describe('Text', () => {
it('with before and after texts', () => {
const tokens = analyze('before\n> foo\nafter');
assert.deepEqual([
- text('before'),
+ text('before\n'),
nodeWithChildren('quote', [
text('foo')
]),
@@ -366,6 +367,24 @@ describe('Text', () => {
], tokens);
});
+ it('multiple quotes', () => {
+ const tokens = analyze('> foo\nbar\n\n> foo\nbar\n\n> foo\nbar');
+ assert.deepEqual([
+ nodeWithChildren('quote', [
+ text('foo')
+ ]),
+ text('bar\n\n'),
+ nodeWithChildren('quote', [
+ text('foo')
+ ]),
+ text('bar\n\n'),
+ nodeWithChildren('quote', [
+ text('foo')
+ ]),
+ text('bar'),
+ ], tokens);
+ });
+
it('require line break before ">"', () => {
const tokens = analyze('foo>bar');
assert.deepEqual([
@@ -388,11 +407,11 @@ describe('Text', () => {
it('trim line breaks', () => {
const tokens = analyze('foo\n\n>a\n>>b\n>>\n>>>\n>>>c\n>>>\n>d\n\n');
assert.deepEqual([
- text('foo\n'),
+ text('foo\n\n'),
nodeWithChildren('quote', [
- text('a'),
+ text('a\n'),
nodeWithChildren('quote', [
- text('b\n'),
+ text('b\n\n'),
nodeWithChildren('quote', [
text('\nc\n')
])
@@ -664,7 +683,7 @@ describe('Text', () => {
it('with before and after texts', () => {
const tokens = analyze('before\n【foo】\nafter');
assert.deepEqual([
- text('before'),
+ text('before\n'),
nodeWithChildren('title', [
text('foo')
]),