
import { marked } from 'marked';
import katex = require('katex');
import type { KatexOptions } from 'katex';
import { MarkdownOptions } from './render';

export interface KatexToken extends marked.Tokens.Generic {
	text: string;
}

export function katex_block_ext(renderer: marked.Renderer, opts: MarkdownOptions) : marked.TokenizerExtension & marked.RendererExtension {
	return {
		name: 'katex_block',
		level: 'block',
		start: (src) => src.match(/^\$\$/)?.index,
		tokenizer(src, tokens) {
			const rule = /^\$\$((?:[^\$]|\$(?!\$))+)\$\$/;
			const match = rule.exec(src);

			if (match) {
				return {
					type: 'katex_block',
					raw: match[0],
					text: match[1]
				};
			}
		},
		renderer(token: KatexToken) {
			const katex_opts: KatexOptions = {
				displayMode: true,  // true == "block"
				output: 'html',
				macros: opts.katex_macros,
			};

			return (katex as any).renderToString(token.text, katex_opts);
		}
	};
}

export function katex_inline_ext(renderer: marked.Renderer, opts: MarkdownOptions) : marked.TokenizerExtension & marked.RendererExtension {
	return {
		name: 'katex_inline',
		level: 'inline',
		start: (src) => src.match(/\$/)?.index,
		tokenizer(src, tokens) {
			const rule = /^\$([^\n\s](?:[^\n\$]*[^\n\s])?)\$/;
			const match = rule.exec(src);

			if (match) {
				return {
					type: 'katex_inline',
					raw: match[0],
					text: match[1]
				};
			}
		},
		renderer(token: KatexToken) {
			const katex_opts: KatexOptions = {
				displayMode: false,  // false == "inline"
				output: 'html',
				macros: opts.katex_macros,
			};

			return (katex as any).renderToString(token.text, katex_opts);
		}
	};
}
