-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutil.ts
More file actions
92 lines (78 loc) · 2.66 KB
/
util.ts
File metadata and controls
92 lines (78 loc) · 2.66 KB
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
import { AttachmentBuilder, TextBasedChannel } from 'discord.js';
// Type for channels that have a send method
type SendableChannel = TextBasedChannel & {
send: (options: string | { content?: string; files?: any[] }) => Promise<any>;
};
// MathJax (mathjax-full) setup (render TeX -> SVG)
import { mathjax } from 'mathjax-full/js/mathjax';
import { TeX } from 'mathjax-full/js/input/tex';
import { SVG } from 'mathjax-full/js/output/svg';
import { liteAdaptor } from 'mathjax-full/js/adaptors/liteAdaptor';
import { RegisterHTMLHandler } from 'mathjax-full/js/handlers/html';
import { AllPackages } from 'mathjax-full/js/input/tex/AllPackages';
// For converting SVG output from MathJax into PNG
import sharp from 'sharp';
// Set up a lite adaptor and MathJax document once at startup
const adaptor = liteAdaptor();
RegisterHTMLHandler(adaptor);
const texInput = new TeX({
packages: AllPackages
});
const svgOutput = new SVG({ fontCache: 'none' });
const html = mathjax.document('', { InputJax: texInput, OutputJax: svgOutput });
// The colour to typeset in; gray works in both light and dark mode.
const typesetColour = 'gray';
/**
* Typesets LaTeX using MathJax, into a PNG buffer.
*
* @param tex The LaTeX text to typeset.
* @return A promise that resolves with the typeset PNG buffer.
*/
export const typeset = async (tex: string): Promise<Buffer> => {
const math = `\\color{${typesetColour}}{${tex}}`;
// Convert TeX -> SVG using MathJax
const node = html.convert(math, { display: true });
// Extract just the <svg> element; sharp expects an SVG root
const svgNode = adaptor.firstChild(node) as any;
const svgString = adaptor.outerHTML(svgNode);
// Convert SVG -> PNG buffer
const image = await sharp(Buffer.from(svgString))
.png()
.toBuffer();
return image;
};
/**
* Sends one or more images, preceded by an optional message.
*
* @param channel The channel to send to.
* @param images The images to send.
* @param message The message to send, optional.
*/
export const attachImages = (
channel: SendableChannel,
images: Buffer[],
message: string | false = false
): void => {
const files = images.map(
(elem, index) => new AttachmentBuilder(elem, { name: `file${index}.png` })
);
if (!message) {
channel.send({ files });
} else {
channel.send({ content: message, files });
}
};
/**
* Sends an image, preceded by an optional message.
*
* @param channel The channel to send to.
* @param image The image to send.
* @param message The message to send, optional.
*/
export const attachImage = (
channel: SendableChannel,
image: Buffer,
message: string | false = false
): void => {
attachImages(channel, [image], message);
};