Add angle bracket covered url syntax to mfm (#4483)
* Add angle bracket covered url syntax to mfm * Fix path * Fix match * Fix index
This commit is contained in:
		 Acid Chicken (硫酸鶏)
					Acid Chicken (硫酸鶏)
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						GitHub
					
				
			
						parent
						
							0f65b1bcc5
						
					
				
				
					commit
					38656103c0
				
			| @@ -1,5 +1,6 @@ | ||||
| import { parseFragment, DefaultTreeDocumentFragment } from 'parse5'; | ||||
| import { URL } from 'url'; | ||||
| import { urlRegex } from './prelude'; | ||||
|  | ||||
| export function fromHtml(html: string): string { | ||||
| 	if (html == null) return null; | ||||
| @@ -14,7 +15,7 @@ export function fromHtml(html: string): string { | ||||
|  | ||||
| 	return text.trim(); | ||||
|  | ||||
| 	function getText(node: any) { | ||||
| 	function getText(node: any): string { | ||||
| 		if (node.nodeName == '#text') return node.value; | ||||
|  | ||||
| 		if (node.childNodes) { | ||||
| @@ -41,7 +42,7 @@ export function fromHtml(html: string): string { | ||||
|  | ||||
| 				// ハッシュタグ / hrefがない / txtがURL | ||||
| 				if ((rel && rel.value.match('tag') !== null) || !href || href.value == txt) { | ||||
| 					text += txt; | ||||
| 					text += txt.match(urlRegex) ? txt : `<${txt}>`; | ||||
| 				// メンション | ||||
| 				} else if (txt.startsWith('@') && !(rel && rel.value.match(/^me /))) { | ||||
| 					const part = txt.split('@'); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import * as P from 'parsimmon'; | ||||
| import { createLeaf, createTree } from './types'; | ||||
| import { createLeaf, createTree, urlRegex } from './prelude'; | ||||
| import { takeWhile, cumulativeSum } from '../prelude/array'; | ||||
| import parseAcct from '../misc/acct/parse'; | ||||
| import { toUnicode } from 'punycode'; | ||||
| @@ -154,9 +154,16 @@ export const mfmLanguage = P.createLanguage({ | ||||
| 	url: () => { | ||||
| 		return P((input, i) => { | ||||
| 			const text = input.substr(i); | ||||
| 			const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/); | ||||
| 			if (!match) return P.makeFailure(i, 'not a url'); | ||||
| 			let url = match[0]; | ||||
| 			const match = text.match(urlRegex); | ||||
| 			let url: string; | ||||
| 			if (!match) { | ||||
| 				const match = text.match(/^<(https?:\/\/.*?)>/); | ||||
| 				if (!match) | ||||
| 					return P.makeFailure(i, 'not a url'); | ||||
| 				url = match[1]; | ||||
| 				i += 2; | ||||
| 			} else | ||||
| 				url = match[0]; | ||||
| 			url = removeOrphanedBrackets(url); | ||||
| 			if (url.endsWith('.')) url = url.substr(0, url.lastIndexOf('.')); | ||||
| 			if (url.endsWith(',')) url = url.substr(0, url.lastIndexOf(',')); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import * as A from '../prelude/array'; | ||||
| import * as S from '../prelude/string'; | ||||
| import { MfmForest, MfmTree } from './types'; | ||||
| import { MfmForest, MfmTree } from './prelude'; | ||||
| import { createTree, createLeaf } from '../prelude/tree'; | ||||
|  | ||||
| function isEmptyTextTree(t: MfmTree): boolean { | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { mfmLanguage } from './language'; | ||||
| import { MfmForest } from './types'; | ||||
| import { MfmForest } from './prelude'; | ||||
| import { normalize } from './normalize'; | ||||
|  | ||||
| export function parse(source: string): MfmForest { | ||||
|   | ||||
| @@ -35,3 +35,5 @@ export function createLeaf(type: string, props: any): MfmTree { | ||||
| export function createTree(type: string, children: MfmForest, props: any): MfmTree { | ||||
| 	return T.createTree({ type, props }, children); | ||||
| } | ||||
| 
 | ||||
| export const urlRegex = /^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.,=\+\-]+/; | ||||
| @@ -2,7 +2,7 @@ import { JSDOM } from 'jsdom'; | ||||
| import config from '../config'; | ||||
| import { INote } from '../models/note'; | ||||
| import { intersperse } from '../prelude/array'; | ||||
| import { MfmForest, MfmTree } from './types'; | ||||
| import { MfmForest, MfmTree } from './prelude'; | ||||
|  | ||||
| export function toHtml(tokens: MfmForest, mentionedRemoteUsers: INote['mentionedRemoteUsers'] = []) { | ||||
| 	if (tokens == null) { | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { EmojiNode, MfmForest } from '../mfm/types'; | ||||
| import { EmojiNode, MfmForest } from '../mfm/prelude'; | ||||
| import { preorderF } from '../prelude/tree'; | ||||
| import { unique } from '../prelude/array'; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { HashtagNode, MfmForest } from '../mfm/types'; | ||||
| import { HashtagNode, MfmForest } from '../mfm/prelude'; | ||||
| import { preorderF } from '../prelude/tree'; | ||||
| import { unique } from '../prelude/array'; | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| // test is located in test/extract-mentions | ||||
|  | ||||
| import { MentionNode, MfmForest } from '../mfm/types'; | ||||
| import { MentionNode, MfmForest } from '../mfm/prelude'; | ||||
| import { preorderF } from '../prelude/tree'; | ||||
|  | ||||
| export default function(mfmForest: MfmForest): MentionNode['props'][] { | ||||
|   | ||||
							
								
								
									
										16
									
								
								test/mfm.ts
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								test/mfm.ts
									
									
									
									
									
								
							| @@ -12,7 +12,7 @@ import * as assert from 'assert'; | ||||
|  | ||||
| import { parse, parsePlain } from '../src/mfm/parse'; | ||||
| import { toHtml } from '../src/mfm/toHtml'; | ||||
| import { createTree as tree, createLeaf as leaf, MfmTree } from '../src/mfm/types'; | ||||
| import { createTree as tree, createLeaf as leaf, MfmTree } from '../src/mfm/prelude'; | ||||
| import { removeOrphanedBrackets } from '../src/mfm/language'; | ||||
|  | ||||
| function text(text: string): MfmTree { | ||||
| @@ -840,6 +840,20 @@ describe('MFM', () => { | ||||
| 					text(')') | ||||
| 				]); | ||||
| 			}); | ||||
|  | ||||
| 			it('ignore non-ascii characters contained url without angle brackets', () => { | ||||
| 				const tokens = parse('https://大石泉すき.example.com'); | ||||
| 				assert.deepStrictEqual(tokens, [ | ||||
| 					text('https://大石泉すき.example.com') | ||||
| 				]); | ||||
| 			}); | ||||
|  | ||||
| 			it('match non-ascii characters contained url with angle brackets', () => { | ||||
| 				const tokens = parse('<https://大石泉すき.example.com>'); | ||||
| 				assert.deepStrictEqual(tokens, [ | ||||
| 					leaf('url', { url: 'https://大石泉すき.example.com' }) | ||||
| 				]); | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		describe('link', () => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user