summaryrefslogtreecommitdiff
path: root/src/text/parse
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-06-21 01:21:57 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-06-21 01:21:57 +0900
commit79d1bf30a49e1fd1ef1f8b743a9aff84d104fb89 (patch)
treeed8f50f01cc50cf851dc0d0f399ed7e0f514f6c6 /src/text/parse
parentDisable transitions to avoid memory leak (diff)
downloadsharkey-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.ts341
-rw-r--r--src/text/parse/elements/bold.ts20
-rw-r--r--src/text/parse/elements/code.ts24
-rw-r--r--src/text/parse/elements/emoji.ts20
-rw-r--r--src/text/parse/elements/hashtag.ts25
-rw-r--r--src/text/parse/elements/inline-code.ts24
-rw-r--r--src/text/parse/elements/link.ts27
-rw-r--r--src/text/parse/elements/mention.ts24
-rw-r--r--src/text/parse/elements/quote.ts20
-rw-r--r--src/text/parse/elements/search.ts19
-rw-r--r--src/text/parse/elements/title.ts20
-rw-r--r--src/text/parse/elements/url.ts20
-rw-r--r--src/text/parse/index.ts99
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, '&gt;')
- .replace(/</g, '&lt;');
-}
-
-// 文字数が多い順にソートします
-// そうしないと、「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[]);
-};