UNPKG

4.56 kBJavaScriptView Raw
1#!/usr/bin/env node
2// Simple CLI for KaTeX.
3// Reads TeX from stdin, outputs HTML to stdout.
4// To run this from the repository, you must first build KaTeX by running
5// `yarn` and `yarn build`.
6
7/* eslint no-console:0 */
8
9let katex;
10try {
11 katex = require("./");
12} catch (e) {
13 console.error(
14 "KaTeX could not import, likely because dist/katex.js is missing.");
15 console.error("Please run 'yarn' and 'yarn build' before running");
16 console.error("cli.js from the KaTeX repository.");
17 console.error();
18 throw e;
19}
20const {version} = require("./package.json");
21const fs = require("fs");
22
23const program = require("commander")
24 .version(version)
25 .option("-d, --display-mode",
26 "Render math in display mode, which puts the math in display style " +
27 "(so \\int and \\sum are large, for example), and centers the math " +
28 "on the page on its own line.")
29 .option("--leqno",
30 "Render display math in leqno style (left-justified tags).")
31 .option("--fleqn",
32 "Render display math flush left.")
33 .option("-t, --no-throw-on-error",
34 "Render errors (in the color given by --error-color) instead of " +
35 "throwing a ParseError exception when encountering an error.")
36 .option("-c, --error-color <color>",
37 "A color string given in the format 'rgb' or 'rrggbb' (no #). " +
38 "This option determines the color of errors rendered by the -t option.",
39 "#cc0000",
40 (color) => "#" + color)
41 .option("-b, --color-is-text-color",
42 "Makes \\color behave like LaTeX's 2-argument \\textcolor, " +
43 "instead of LaTeX's one-argument \\color mode change.")
44 .option("-S, --strict",
45 "Turn on strict / LaTeX faithfulness mode, which throws an error " +
46 "if the input uses features that are not supported by LaTeX")
47 .option("-s, --max-size <n>",
48 "If non-zero, all user-specified sizes, e.g. in " +
49 "\\rule{500em}{500em}, will be capped to maxSize ems. " +
50 "Otherwise, elements and spaces can be arbitrarily large",
51 Infinity, parseInt)
52 .option("-e, --max-expand <n>",
53 "Limit the number of macro expansions to the specified number, to " +
54 "prevent e.g. infinite macro loops. If set to Infinity, the macro " +
55 "expander will try to fully expand as in LaTeX.",
56 (n) => (n === "Infinity" ? Infinity : parseInt(n)))
57 .option("-m, --macro <def>",
58 "Define custom macro of the form '\\foo:expansion' (use multiple -m " +
59 "arguments for multiple macros).",
60 (def, defs) => {
61 defs.push(def);
62 return defs;
63 }, [])
64 .option("-f, --macro-file <path>",
65 "Read macro definitions, one per line, from the given file.")
66 .option("-i, --input <path>", "Read LaTeX input from the given file.")
67 .option("-o, --output <path>", "Write html output to the given file.");
68
69if (require.main !== module) {
70 module.exports = program;
71 return;
72}
73
74const options = program.parse(process.argv);
75
76function readMacros() {
77 if (options.macroFile) {
78 fs.readFile(options.macroFile, "utf-8", function(err, data) {
79 if (err) {throw err;}
80 splitMacros(data.toString().split('\n'));
81 });
82 } else {
83 splitMacros([]);
84 }
85}
86
87function splitMacros(macroStrings) {
88 // Override macros from macro file (if any)
89 // with macros from command line (if any)
90 macroStrings = macroStrings.concat(options.macro);
91
92 const macros = {};
93
94 for (const m of macroStrings) {
95 const i = m.search(":");
96 if (i !== -1) {
97 macros[m.substring(0, i).trim()] = m.substring(i + 1).trim();
98 }
99 }
100
101 options.macros = macros;
102 readInput();
103}
104
105function readInput() {
106 let input = "";
107
108 if (options.input) {
109 fs.readFile(options.input, "utf-8", function(err, data) {
110 if (err) {throw err;}
111 input = data.toString();
112 writeOutput(input);
113 });
114 } else {
115 process.stdin.on("data", function(chunk) {
116 input += chunk.toString();
117 });
118
119 process.stdin.on("end", function() {
120 writeOutput(input);
121 });
122 }
123}
124
125function writeOutput(input) {
126 const output = katex.renderToString(input, options) + "\n";
127
128 if (options.output) {
129 fs.writeFile(options.output, output, function(err) {
130 if (err) {
131 return console.log(err);
132 }
133 });
134 } else {
135 console.log(output);
136 }
137}
138
139readMacros();