summaryrefslogtreecommitdiff
path: root/src/mfm/to-string.ts
blob: 107929164cca19b7db1addcb074474fbba3c82e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { MfmForest, MfmTree } from './prelude';
import { nyaize } from '../misc/nyaize';

export type RestoreOptions = {
	doNyaize?: boolean;
};

export function toString(tokens: MfmForest | null, opts?: RestoreOptions): string {

	if (tokens === null) return '';

	function appendChildren(children: MfmForest, opts?: RestoreOptions): string {
		return children.map(t => handlers[t.node.type](t, opts)).join('');
	}

	const handlers: { [key: string]: (token: MfmTree, opts?: RestoreOptions) => string } = {
		bold(token, opts) {
			return `**${appendChildren(token.children, opts)}**`;
		},

		big(token, opts) {
			return `***${appendChildren(token.children, opts)}***`;
		},

		small(token, opts) {
			return `<small>${appendChildren(token.children, opts)}</small>`;
		},

		strike(token, opts) {
			return `~~${appendChildren(token.children, opts)}~~`;
		},

		italic(token, opts) {
			return `<i>${appendChildren(token.children, opts)}</i>`;
		},

		motion(token, opts) {
			return `<motion>${appendChildren(token.children, opts)}</motion>`;
		},

		spin(token, opts) {
			const attr = token.node.props?.attr;
			const post = attr ? ` ${attr}` : '';
			return `<spin${post}>${appendChildren(token.children, opts)}</spin>`;
		},

		jump(token, opts) {
			return `<jump>${appendChildren(token.children, opts)}</jump>`;
		},

		flip(token, opts) {
			return `<flip>${appendChildren(token.children, opts)}</flip>`;
		},

		blockCode(token) {
			return `\`\`\`${token.node.props.lang || ''}\n${token.node.props.code}\n\`\`\`\n`;
		},

		center(token, opts) {
			return `<center>${appendChildren(token.children, opts)}</center>`;
		},

		emoji(token) {
			return (token.node.props.emoji ? token.node.props.emoji : `:${token.node.props.name}:`);
		},

		hashtag(token) {
			return `#${token.node.props.hashtag}`;
		},

		inlineCode(token) {
			return `\`${token.node.props.code}\``;
		},

		mathInline(token) {
			return `\\(${token.node.props.formula}\\)`;
		},

		mathBlock(token) {
			return `\\[${token.node.props.formula}\\]`;
		},

		link(token, opts) {
			if (token.node.props.silent) {
				return `?[${appendChildren(token.children, opts)}](${token.node.props.url})`;
			} else {
				return `[${appendChildren(token.children, opts)}](${token.node.props.url})`;
			}
		},

		mention(token) {
			return token.node.props.canonical;
		},

		quote(token) {
			return `${appendChildren(token.children, {doNyaize: false}).replace(/^/gm,'>').trim()}\n`;
		},

		title(token, opts) {
			return `[${appendChildren(token.children, opts)}]\n`;
		},

		text(token, opts) {
			return (opts && opts.doNyaize) ? nyaize(token.node.props.text) : token.node.props.text;
		},

		url(token) {
			return `<${token.node.props.url}>`;
		},

		search(token, opts) {
			const query = token.node.props.query;
			return `${(opts && opts.doNyaize ? nyaize(query) : query)} [search]\n`;
		}
	};

	return appendChildren(tokens, { doNyaize: (opts && opts.doNyaize) || false }).trim();
}