diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-06-21 01:21:57 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-06-21 01:21:57 +0900 |
| commit | 79d1bf30a49e1fd1ef1f8b743a9aff84d104fb89 (patch) | |
| tree | ed8f50f01cc50cf851dc0d0f399ed7e0f514f6c6 /src/text/parse | |
| parent | Disable transitions to avoid memory leak (diff) | |
| download | sharkey-79d1bf30a49e1fd1ef1f8b743a9aff84d104fb89.tar.gz sharkey-79d1bf30a49e1fd1ef1f8b743a9aff84d104fb89.tar.bz2 sharkey-79d1bf30a49e1fd1ef1f8b743a9aff84d104fb89.zip | |
リモートユーザーのHTMLで表現されたプロフィールをMFMに変換するように
Diffstat (limited to 'src/text/parse')
| -rw-r--r-- | src/text/parse/core/syntax-highlighter.ts | 341 | ||||
| -rw-r--r-- | src/text/parse/elements/bold.ts | 20 | ||||
| -rw-r--r-- | src/text/parse/elements/code.ts | 24 | ||||
| -rw-r--r-- | src/text/parse/elements/emoji.ts | 20 | ||||
| -rw-r--r-- | src/text/parse/elements/hashtag.ts | 25 | ||||
| -rw-r--r-- | src/text/parse/elements/inline-code.ts | 24 | ||||
| -rw-r--r-- | src/text/parse/elements/link.ts | 27 | ||||
| -rw-r--r-- | src/text/parse/elements/mention.ts | 24 | ||||
| -rw-r--r-- | src/text/parse/elements/quote.ts | 20 | ||||
| -rw-r--r-- | src/text/parse/elements/search.ts | 19 | ||||
| -rw-r--r-- | src/text/parse/elements/title.ts | 20 | ||||
| -rw-r--r-- | src/text/parse/elements/url.ts | 20 | ||||
| -rw-r--r-- | src/text/parse/index.ts | 99 |
13 files changed, 0 insertions, 683 deletions
diff --git a/src/text/parse/core/syntax-highlighter.ts b/src/text/parse/core/syntax-highlighter.ts deleted file mode 100644 index 3fb7a3b73d..0000000000 --- a/src/text/parse/core/syntax-highlighter.ts +++ /dev/null @@ -1,341 +0,0 @@ -function escape(text: string) { - return text - .replace(/>/g, '>') - .replace(/</g, '<'); -} - -// 文字数が多い順にソートします -// そうしないと、「function」という文字列が与えられたときに「func」が先にマッチしてしまう可能性があるためです -const _keywords = [ - 'true', - 'false', - 'null', - 'nil', - 'undefined', - 'void', - 'var', - 'const', - 'let', - 'mut', - 'dim', - 'if', - 'then', - 'else', - 'switch', - 'match', - 'case', - 'default', - 'for', - 'each', - 'in', - 'while', - 'loop', - 'continue', - 'break', - 'do', - 'goto', - 'next', - 'end', - 'sub', - 'throw', - 'try', - 'catch', - 'finally', - 'enum', - 'delegate', - 'function', - 'func', - 'fun', - 'fn', - 'return', - 'yield', - 'async', - 'await', - 'require', - 'include', - 'import', - 'imports', - 'export', - 'exports', - 'from', - 'as', - 'using', - 'use', - 'internal', - 'module', - 'namespace', - 'where', - 'select', - 'struct', - 'union', - 'new', - 'delete', - 'this', - 'super', - 'base', - 'class', - 'interface', - 'abstract', - 'static', - 'public', - 'private', - 'protected', - 'virtual', - 'partial', - 'override', - 'extends', - 'implements', - 'constructor' -]; - -const keywords = _keywords - .concat(_keywords.map(k => k[0].toUpperCase() + k.substr(1))) - .concat(_keywords.map(k => k.toUpperCase())) - .sort((a, b) => b.length - a.length); - -const symbols = [ - '=', - '+', - '-', - '*', - '/', - '%', - '~', - '^', - '&', - '|', - '>', - '<', - '!', - '?' -]; - -type Token = { - html: string - next: number -}; - -type Element = (code: string, i: number, source: string) => (Token | null); - -const elements: Element[] = [ - // comment - code => { - if (code.substr(0, 2) != '//') return null; - const match = code.match(/^\/\/(.+?)(\n|$)/); - if (!match) return null; - const comment = match[0]; - return { - html: `<span class="comment">${escape(comment)}</span>`, - next: comment.length - }; - }, - - // block comment - code => { - const match = code.match(/^\/\*([\s\S]+?)\*\//); - if (!match) return null; - return { - html: `<span class="comment">${escape(match[0])}</span>`, - next: match[0].length - }; - }, - - // string - code => { - if (!/^['"`]/.test(code)) return null; - const begin = code[0]; - let str = begin; - let thisIsNotAString = false; - for (let i = 1; i < code.length; i++) { - const char = code[i]; - if (char == '\\') { - str += char; - str += code[i + 1] || ''; - i++; - continue; - } else if (char == begin) { - str += char; - break; - } else if (char == '\n' || i == (code.length - 1)) { - thisIsNotAString = true; - break; - } else { - str += char; - } - } - if (thisIsNotAString) { - return null; - } else { - return { - html: `<span class="string">${escape(str)}</span>`, - next: str.length - }; - } - }, - - // regexp - code => { - if (code[0] != '/') return null; - let regexp = ''; - let thisIsNotARegexp = false; - for (let i = 1; i < code.length; i++) { - const char = code[i]; - if (char == '\\') { - regexp += char; - regexp += code[i + 1] || ''; - i++; - continue; - } else if (char == '/') { - break; - } else if (char == '\n' || i == (code.length - 1)) { - thisIsNotARegexp = true; - break; - } else { - regexp += char; - } - } - - if (thisIsNotARegexp) return null; - if (regexp == '') return null; - if (regexp[0] == ' ' && regexp[regexp.length - 1] == ' ') return null; - - return { - html: `<span class="regexp">/${escape(regexp)}/</span>`, - next: regexp.length + 2 - }; - }, - - // label - code => { - if (code[0] != '@') return null; - const match = code.match(/^@([a-zA-Z_-]+?)\n/); - if (!match) return null; - const label = match[0]; - return { - html: `<span class="label">${label}</span>`, - next: label.length - }; - }, - - // number - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - if (!/^[\-\+]?[0-9\.]+/.test(code)) return null; - const match = code.match(/^[\-\+]?[0-9\.]+/)[0]; - if (match) { - return { - html: `<span class="number">${match}</span>`, - next: match.length - }; - } else { - return null; - } - }, - - // nan - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - if (code.substr(0, 3) == 'NaN') { - return { - html: `<span class="nan">NaN</span>`, - next: 3 - }; - } else { - return null; - } - }, - - // method - code => { - const match = code.match(/^([a-zA-Z_-]+?)\(/); - if (!match) return null; - - if (match[1] == '-') return null; - - return { - html: `<span class="method">${match[1]}</span>`, - next: match[1].length - }; - }, - - // property - (code, i, source) => { - const prev = source[i - 1]; - if (prev != '.') return null; - - const match = code.match(/^[a-zA-Z0-9_-]+/); - if (!match) return null; - - return { - html: `<span class="property">${match[0]}</span>`, - next: match[0].length - }; - }, - - // keyword - (code, i, source) => { - const prev = source[i - 1]; - if (prev && /[a-zA-Z]/.test(prev)) return null; - - const match = keywords.filter(k => code.substr(0, k.length) == k)[0]; - if (match) { - if (/^[a-zA-Z]/.test(code.substr(match.length))) return null; - return { - html: `<span class="keyword ${match}">${match}</span>`, - next: match.length - }; - } else { - return null; - } - }, - - // symbol - code => { - const match = symbols.filter(s => code[0] == s)[0]; - if (match) { - return { - html: `<span class="symbol">${match}</span>`, - next: 1 - }; - } else { - return null; - } - } -]; - -// specify lang is todo -export default (source: string, lang?: string) => { - let code = source; - let html = ''; - - let i = 0; - - function push(token: Token) { - html += token.html; - code = code.substr(token.next); - i += token.next; - } - - while (code != '') { - const parsed = elements.some(el => { - const e = el(code, i, source); - if (e) { - push(e); - return true; - } else { - return false; - } - }); - - if (!parsed) { - push({ - html: escape(code[0]), - next: 1 - }); - } - } - - return html; -}; diff --git a/src/text/parse/elements/bold.ts b/src/text/parse/elements/bold.ts deleted file mode 100644 index cf615cd3cc..0000000000 --- a/src/text/parse/elements/bold.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Bold - */ - -export type TextElementBold = { - type: 'bold' - content: string - bold: string -}; - -export default function(text: string) { - const match = text.match(/^\*\*(.+?)\*\*/); - if (!match) return null; - const bold = match[0]; - return { - type: 'bold', - content: bold, - bold: bold.substr(2, bold.length - 4) - } as TextElementBold; -} diff --git a/src/text/parse/elements/code.ts b/src/text/parse/elements/code.ts deleted file mode 100644 index f48e945048..0000000000 --- a/src/text/parse/elements/code.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Code (block) - */ - -import genHtml from '../core/syntax-highlighter'; - -export type TextElementCode = { - type: 'code' - content: string - code: string - html: string -}; - -export default function(text: string) { - const match = text.match(/^```([\s\S]+?)```/); - if (!match) return null; - const code = match[0]; - return { - type: 'code', - content: code, - code: code.substr(3, code.length - 6).trim(), - html: genHtml(code.substr(3, code.length - 6).trim()) - } as TextElementCode; -} diff --git a/src/text/parse/elements/emoji.ts b/src/text/parse/elements/emoji.ts deleted file mode 100644 index 83d3effef5..0000000000 --- a/src/text/parse/elements/emoji.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Emoji - */ - -export type TextElementEmoji = { - type: 'emoji' - content: string - emoji: string -}; - -export default function(text: string) { - const match = text.match(/^:[a-zA-Z0-9+-_]+:/); - if (!match) return null; - const emoji = match[0]; - return { - type: 'emoji', - content: emoji, - emoji: emoji.substr(1, emoji.length - 2) - } as TextElementEmoji; -} diff --git a/src/text/parse/elements/hashtag.ts b/src/text/parse/elements/hashtag.ts deleted file mode 100644 index 129041774f..0000000000 --- a/src/text/parse/elements/hashtag.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Hashtag - */ - -export type TextElementHashtag = { - type: 'hashtag' - content: string - hashtag: string -}; - -export default function(text: string, i: number) { - if (!(/^\s#[^\s]+/.test(text) || (i == 0 && /^#[^\s]+/.test(text)))) return null; - const isHead = text[0] == '#'; - const hashtag = text.match(/^\s?#[^\s]+/)[0]; - const res: any[] = !isHead ? [{ - type: 'text', - content: text[0] - }] : []; - res.push({ - type: 'hashtag', - content: isHead ? hashtag : hashtag.substr(1), - hashtag: isHead ? hashtag.substr(1) : hashtag.substr(2) - }); - return res as TextElementHashtag[]; -} diff --git a/src/text/parse/elements/inline-code.ts b/src/text/parse/elements/inline-code.ts deleted file mode 100644 index 1dd5affa51..0000000000 --- a/src/text/parse/elements/inline-code.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Code (inline) - */ - -import genHtml from '../core/syntax-highlighter'; - -export type TextElementInlineCode = { - type: 'inline-code' - content: string - code: string - html: string -}; - -export default function(text: string) { - const match = text.match(/^`(.+?)`/); - if (!match) return null; - const code = match[0]; - return { - type: 'inline-code', - content: code, - code: code.substr(1, code.length - 2).trim(), - html: genHtml(code.substr(1, code.length - 2).trim()) - } as TextElementInlineCode; -} diff --git a/src/text/parse/elements/link.ts b/src/text/parse/elements/link.ts deleted file mode 100644 index b353aebc5c..0000000000 --- a/src/text/parse/elements/link.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Link - */ - -export type TextElementLink = { - type: 'link' - content: string - title: string - url: string - silent: boolean -}; - -export default function(text: string) { - const match = text.match(/^\??\[([^\[\]]+?)\]\((https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+?)\)/); - if (!match) return null; - const silent = text[0] == '?'; - const link = match[0]; - const title = match[1]; - const url = match[2]; - return { - type: 'link', - content: link, - title: title, - url: url, - silent: silent - } as TextElementLink; -} diff --git a/src/text/parse/elements/mention.ts b/src/text/parse/elements/mention.ts deleted file mode 100644 index eda60b530a..0000000000 --- a/src/text/parse/elements/mention.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Mention - */ -import parseAcct from '../../../acct/parse'; - -export type TextElementMention = { - type: 'mention' - content: string - username: string - host: string -}; - -export default function(text: string) { - const match = text.match(/^@[a-z0-9_]+(?:@[a-z0-9\.\-]+[a-z0-9])?/i); - if (!match) return null; - const mention = match[0]; - const { username, host } = parseAcct(mention.substr(1)); - return { - type: 'mention', - content: mention, - username, - host - } as TextElementMention; -} diff --git a/src/text/parse/elements/quote.ts b/src/text/parse/elements/quote.ts deleted file mode 100644 index bef9ad4988..0000000000 --- a/src/text/parse/elements/quote.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Quoted text - */ - -export type TextElementQuote = { - type: 'quote' - content: string - quote: string -}; - -export default function(text: string) { - const match = text.match(/^"([\s\S]+?)\n"/); - if (!match) return null; - const quote = match[0]; - return { - type: 'quote', - content: quote, - quote: quote.substr(1, quote.length - 2).trim(), - } as TextElementQuote; -} diff --git a/src/text/parse/elements/search.ts b/src/text/parse/elements/search.ts deleted file mode 100644 index e5d9b9f0c2..0000000000 --- a/src/text/parse/elements/search.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Search - */ - -export type TextElementSearch = { - type: 'search' - content: string - query: string -}; - -export default function(text: string) { - const match = text.match(/^(.+?) 検索(\n|$)/); - if (!match) return null; - return { - type: 'search', - content: match[0], - query: match[1] - }; -} diff --git a/src/text/parse/elements/title.ts b/src/text/parse/elements/title.ts deleted file mode 100644 index b89739a7c5..0000000000 --- a/src/text/parse/elements/title.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Title - */ - -export type TextElementTitle = { - type: 'title' - content: string - title: string -}; - -export default function(text: string) { - const match = text.match(/^【(.+?)】\n/); - if (!match) return null; - const title = match[0]; - return { - type: 'title', - content: title, - title: title.substr(1, title.length - 3) - } as TextElementTitle; -} diff --git a/src/text/parse/elements/url.ts b/src/text/parse/elements/url.ts deleted file mode 100644 index 78b9b1f2f1..0000000000 --- a/src/text/parse/elements/url.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * URL - */ - -export type TextElementUrl = { - type: 'url' - content: string - url: string -}; - -export default function(text: string) { - const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+/); - if (!match) return null; - const url = match[0]; - return { - type: 'url', - content: url, - url: url - } as TextElementUrl; -} diff --git a/src/text/parse/index.ts b/src/text/parse/index.ts deleted file mode 100644 index 2b6a459b1e..0000000000 --- a/src/text/parse/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Misskey Text Analyzer - */ - -import { TextElementBold } from './elements/bold'; -import { TextElementCode } from './elements/code'; -import { TextElementEmoji } from './elements/emoji'; -import { TextElementHashtag } from './elements/hashtag'; -import { TextElementInlineCode } from './elements/inline-code'; -import { TextElementLink } from './elements/link'; -import { TextElementMention } from './elements/mention'; -import { TextElementQuote } from './elements/quote'; -import { TextElementSearch } from './elements/search'; -import { TextElementTitle } from './elements/title'; -import { TextElementUrl } from './elements/url'; - -const elements = [ - require('./elements/bold'), - require('./elements/title'), - require('./elements/url'), - require('./elements/link'), - require('./elements/mention'), - require('./elements/hashtag'), - require('./elements/code'), - require('./elements/inline-code'), - require('./elements/quote'), - require('./elements/emoji'), - require('./elements/search') -].map(element => element.default as TextElementProcessor); - -export type TextElement = { type: 'text', content: string } - | TextElementBold - | TextElementCode - | TextElementEmoji - | TextElementHashtag - | TextElementInlineCode - | TextElementLink - | TextElementMention - | TextElementQuote - | TextElementSearch - | TextElementTitle - | TextElementUrl; -export type TextElementProcessor = (text: string, i: number) => TextElement | TextElement[]; - -export default (source: string): TextElement[] => { - - if (source == '') { - return null; - } - - const tokens: TextElement[] = []; - - function push(token: TextElement) { - if (token != null) { - tokens.push(token); - source = source.substr(token.content.length); - } - } - - let i = 0; - - // パース - while (source != '') { - const parsed = elements.some(el => { - let _tokens = el(source, i); - if (_tokens) { - if (!Array.isArray(_tokens)) { - _tokens = [_tokens]; - } - _tokens.forEach(push); - return true; - } else { - return false; - } - }); - - if (!parsed) { - push({ - type: 'text', - content: source[0] - }); - } - - i++; - } - - // テキストを纏める - return tokens.reduce((a, b) => { - if (a.length && a[a.length - 1].type == 'text' && b.type == 'text') { - const tail = a.pop(); - return a.concat({ - type: 'text', - content: tail.content + b.content - }); - } else { - return a.concat(b); - } - }, [] as TextElement[]); -}; |