summaryrefslogtreecommitdiff
path: root/src/mfm/parse/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/mfm/parse/index.ts')
-rw-r--r--src/mfm/parse/index.ts99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/mfm/parse/index.ts b/src/mfm/parse/index.ts
new file mode 100644
index 0000000000..2b6a459b1e
--- /dev/null
+++ b/src/mfm/parse/index.ts
@@ -0,0 +1,99 @@
+/**
+ * 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[]);
+};