diff --git a/src/mfm/from-html.ts b/src/mfm/from-html.ts index 1eca3fc6c..4c27c2cbb 100644 --- a/src/mfm/from-html.ts +++ b/src/mfm/from-html.ts @@ -1,5 +1,5 @@ import { parseFragment, DefaultTreeDocumentFragment } from 'parse5'; -import { urlRegex } from './prelude'; +import { urlRegexFull } from './prelude'; export function fromHtml(html: string, hashtagNames?: string[]): string { const dom = parseFragment(html) as DefaultTreeDocumentFragment; @@ -54,7 +54,11 @@ export function fromHtml(html: string, hashtagNames?: string[]): string { } // その他 } else { - text += (!href || (txt === href.value && txt.match(urlRegex))) ? txt : `[${txt}](${href.value})`; + text += !href ? txt + : txt === href.value + ? txt.match(urlRegexFull) ? txt + : `<${txt}>` + : `[${txt}](${href.value})`; } break; diff --git a/src/mfm/prelude.ts b/src/mfm/prelude.ts index e18625bc7..a8b52eb31 100644 --- a/src/mfm/prelude.ts +++ b/src/mfm/prelude.ts @@ -36,4 +36,5 @@ export function createTree(type: string, children: MfmForest, props: any): MfmTr return T.createTree({ type, props }, children); } -export const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; +export const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; +export const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; diff --git a/test/mfm.ts b/test/mfm.ts index 6244263a3..650fabcb8 100644 --- a/test/mfm.ts +++ b/test/mfm.ts @@ -12,6 +12,7 @@ import * as assert from 'assert'; import { parse, parsePlain } from '../src/mfm/parse'; import { toHtml } from '../src/mfm/to-html'; +import { fromHtml } from '../src/mfm/from-html'; import { toString } from '../src/mfm/to-string'; import { createTree as tree, createLeaf as leaf, MfmTree } from '../src/mfm/prelude'; import { removeOrphanedBrackets } from '../src/mfm/language'; @@ -1199,3 +1200,37 @@ describe('MFM', () => { }); }); }); + +describe('fromHtml', () => { + it('br', () => { + assert.deepStrictEqual(fromHtml('

abc

d

'), 'abc\n\nd'); + }); + + it('link with different text', () => { + assert.deepStrictEqual(fromHtml('

a c d

'), 'a [c](https://example.com/b) d'); + }); + + it('link with same text', () => { + assert.deepStrictEqual(fromHtml('

a https://example.com/b d

'), 'a https://example.com/b d'); + }); + + it('link with same text, but not encoded', () => { + assert.deepStrictEqual(fromHtml('

a https://example.com/ä d

'), 'a d'); + }); + + it('link with no url', () => { + assert.deepStrictEqual(fromHtml('

a c d

'), 'a [c](b) d'); + }); + + it('link without href', () => { + assert.deepStrictEqual(fromHtml('

a c d

'), 'a c d'); + }); + + it('mention', () => { + assert.deepStrictEqual(fromHtml('

a @user d

'), 'a @user@example.com d'); + }); + + it('hashtag', () => { + assert.deepStrictEqual(fromHtml('

a #a d

', ['#a']), 'a #a d'); + }); +});