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:
		
							parent
							
								
									0f65b1bcc5
								
							
						
					
					
						commit
						38656103c0
					
				
					 10 changed files with 37 additions and 13 deletions
				
			
		|  | @ -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', () => { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue