diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2021-11-12 02:02:25 +0900 |
| commit | 0e4a111f81cceed275d9bec2695f6e401fb654d8 (patch) | |
| tree | 40874799472fa07416f17b50a398ac33b7771905 /src/mfm | |
| parent | update deps (diff) | |
| download | misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.gz misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.tar.bz2 misskey-0e4a111f81cceed275d9bec2695f6e401fb654d8.zip | |
refactoring
Resolve #7779
Diffstat (limited to 'src/mfm')
| -rw-r--r-- | src/mfm/fn-name-list.ts | 23 | ||||
| -rw-r--r-- | src/mfm/from-html.ts | 209 | ||||
| -rw-r--r-- | src/mfm/to-html.ts | 159 |
3 files changed, 0 insertions, 391 deletions
diff --git a/src/mfm/fn-name-list.ts b/src/mfm/fn-name-list.ts deleted file mode 100644 index 1203bfffde..0000000000 --- a/src/mfm/fn-name-list.ts +++ /dev/null @@ -1,23 +0,0 @@ -// NOTE: client/components/autocomplete.vueにも関数のリスト(MFM_TAGS)があるので統合? - -const fnNameList = [ - 'tada', - 'jelly', - 'twitch', - 'shake', - 'spin', - 'jump', - 'bounce', - 'flip', - 'x2', - 'x3', - 'x4', - 'font', - 'blur', - 'rainbow', - 'sparkle', -]; - -export { - fnNameList -}; diff --git a/src/mfm/from-html.ts b/src/mfm/from-html.ts deleted file mode 100644 index de6aa3d0cc..0000000000 --- a/src/mfm/from-html.ts +++ /dev/null @@ -1,209 +0,0 @@ -import * as parse5 from 'parse5'; -import treeAdapter = require('parse5/lib/tree-adapters/default'); -import { URL } from 'url'; - -const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; -const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; - -export function fromHtml(html: string, hashtagNames?: string[]): string | null { - if (html == null) return null; - - const dom = parse5.parseFragment(html); - - let text = ''; - - for (const n of dom.childNodes) { - analyze(n); - } - - return text.trim(); - - function getText(node: parse5.Node): string { - if (treeAdapter.isTextNode(node)) return node.value; - if (!treeAdapter.isElementNode(node)) return ''; - if (node.nodeName === 'br') return '\n'; - - if (node.childNodes) { - return node.childNodes.map(n => getText(n)).join(''); - } - - return ''; - } - - function appendChildren(childNodes: parse5.ChildNode[]): void { - if (childNodes) { - for (const n of childNodes) { - analyze(n); - } - } - } - - function analyze(node: parse5.Node) { - if (treeAdapter.isTextNode(node)) { - text += node.value; - return; - } - - // Skip comment or document type node - if (!treeAdapter.isElementNode(node)) return; - - switch (node.nodeName) { - case 'br': - text += '\n'; - break; - - case 'a': - { - const txt = getText(node); - const rel = node.attrs.find(x => x.name === 'rel'); - const href = node.attrs.find(x => x.name === 'href'); - - // ハッシュタグ - if (hashtagNames && href && hashtagNames.map(x => x.toLowerCase()).includes(txt.toLowerCase())) { - text += txt; - // メンション - } else if (txt.startsWith('@') && !(rel && rel.value.match(/^me /))) { - const part = txt.split('@'); - - if (part.length === 2 && href) { - //#region ホスト名部分が省略されているので復元する - const acct = `${txt}@${(new URL(href.value)).hostname}`; - text += acct; - //#endregion - } else if (part.length === 3) { - text += txt; - } - // その他 - } else { - const generateLink = () => { - if (!href && !txt) { - return ''; - } - if (!href) { - return txt; - } - if (!txt || txt === href.value) { // #6383: Missing text node - if (href.value.match(urlRegexFull)) { - return href.value; - } else { - return `<${href.value}>`; - } - } - if (href.value.match(urlRegex) && !href.value.match(urlRegexFull)) { - return `[${txt}](<${href.value}>)`; // #6846 - } else { - return `[${txt}](${href.value})`; - } - }; - - text += generateLink(); - } - break; - } - - case 'h1': - { - text += '【'; - appendChildren(node.childNodes); - text += '】\n'; - break; - } - - case 'b': - case 'strong': - { - text += '**'; - appendChildren(node.childNodes); - text += '**'; - break; - } - - case 'small': - { - text += '<small>'; - appendChildren(node.childNodes); - text += '</small>'; - break; - } - - case 's': - case 'del': - { - text += '~~'; - appendChildren(node.childNodes); - text += '~~'; - break; - } - - case 'i': - case 'em': - { - text += '<i>'; - appendChildren(node.childNodes); - text += '</i>'; - break; - } - - // block code (<pre><code>) - case 'pre': { - if (node.childNodes.length === 1 && node.childNodes[0].nodeName === 'code') { - text += '\n```\n'; - text += getText(node.childNodes[0]); - text += '\n```\n'; - } else { - appendChildren(node.childNodes); - } - break; - } - - // inline code (<code>) - case 'code': { - text += '`'; - appendChildren(node.childNodes); - text += '`'; - break; - } - - case 'blockquote': { - const t = getText(node); - if (t) { - text += '> '; - text += t.split('\n').join(`\n> `); - } - break; - } - - case 'p': - case 'h2': - case 'h3': - case 'h4': - case 'h5': - case 'h6': - { - text += '\n\n'; - appendChildren(node.childNodes); - break; - } - - // other block elements - case 'div': - case 'header': - case 'footer': - case 'article': - case 'li': - case 'dt': - case 'dd': - { - text += '\n'; - appendChildren(node.childNodes); - break; - } - - default: // includes inline elements - { - appendChildren(node.childNodes); - break; - } - } - } -} diff --git a/src/mfm/to-html.ts b/src/mfm/to-html.ts deleted file mode 100644 index b3678a0dda..0000000000 --- a/src/mfm/to-html.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { JSDOM } from 'jsdom'; -import * as mfm from 'mfm-js'; -import config from '@/config/index'; -import { intersperse } from '@/prelude/array'; -import { IMentionedRemoteUsers } from '@/models/entities/note'; -import { wellKnownServices } from '../well-known-services'; - -export function toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = []) { - if (nodes == null) { - return null; - } - - const { window } = new JSDOM(''); - - const doc = window.document; - - function appendChildren(children: mfm.MfmNode[], targetElement: any): void { - if (children) { - for (const child of children.map(x => (handlers as any)[x.type](x))) targetElement.appendChild(child); - } - } - - const handlers: { [K in mfm.MfmNode['type']]: (node: mfm.NodeType<K>) => any } = { - bold(node) { - const el = doc.createElement('b'); - appendChildren(node.children, el); - return el; - }, - - small(node) { - const el = doc.createElement('small'); - appendChildren(node.children, el); - return el; - }, - - strike(node) { - const el = doc.createElement('del'); - appendChildren(node.children, el); - return el; - }, - - italic(node) { - const el = doc.createElement('i'); - appendChildren(node.children, el); - return el; - }, - - fn(node) { - const el = doc.createElement('i'); - appendChildren(node.children, el); - return el; - }, - - blockCode(node) { - const pre = doc.createElement('pre'); - const inner = doc.createElement('code'); - inner.textContent = node.props.code; - pre.appendChild(inner); - return pre; - }, - - center(node) { - const el = doc.createElement('div'); - appendChildren(node.children, el); - return el; - }, - - emojiCode(node) { - return doc.createTextNode(`\u200B:${node.props.name}:\u200B`); - }, - - unicodeEmoji(node) { - return doc.createTextNode(node.props.emoji); - }, - - hashtag(node) { - const a = doc.createElement('a'); - a.href = `${config.url}/tags/${node.props.hashtag}`; - a.textContent = `#${node.props.hashtag}`; - a.setAttribute('rel', 'tag'); - return a; - }, - - inlineCode(node) { - const el = doc.createElement('code'); - el.textContent = node.props.code; - return el; - }, - - mathInline(node) { - const el = doc.createElement('code'); - el.textContent = node.props.formula; - return el; - }, - - mathBlock(node) { - const el = doc.createElement('code'); - el.textContent = node.props.formula; - return el; - }, - - link(node) { - const a = doc.createElement('a'); - a.href = node.props.url; - appendChildren(node.children, a); - return a; - }, - - mention(node) { - const a = doc.createElement('a'); - const { username, host, acct } = node.props; - const wellKnown = wellKnownServices.find(x => x[0] === host); - if (wellKnown) { - a.href = wellKnown[1](username); - } else { - const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host); - a.href = remoteUserInfo ? (remoteUserInfo.url ? remoteUserInfo.url : remoteUserInfo.uri) : `${config.url}/${acct}`; - a.className = 'u-url mention'; - } - a.textContent = acct; - return a; - }, - - quote(node) { - const el = doc.createElement('blockquote'); - appendChildren(node.children, el); - return el; - }, - - text(node) { - const el = doc.createElement('span'); - const nodes = node.props.text.split(/\r\n|\r|\n/).map(x => doc.createTextNode(x)); - - for (const x of intersperse<FIXME | 'br'>('br', nodes)) { - el.appendChild(x === 'br' ? doc.createElement('br') : x); - } - - return el; - }, - - url(node) { - const a = doc.createElement('a'); - a.href = node.props.url; - a.textContent = node.props.url; - return a; - }, - - search(node) { - const a = doc.createElement('a'); - a.href = `https://www.google.com/search?q=${node.props.query}`; - a.textContent = node.props.content; - return a; - } - }; - - appendChildren(nodes, doc.body); - - return `<p>${doc.body.innerHTML}</p>`; -} |