CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/project/formatters/xml-format.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { writeFile, readFile, unlink } from "fs";
7
import * as tmp from "tmp";
8
import { callback } from "awaiting";
9
import { executeCode } from "@cocalc/backend/execute-code";
10
11
interface ParserOptions {
12
parser: string;
13
}
14
15
// ref: http://tidy.sourceforge.net/docs/quickref.html
16
17
async function tidy(input_path) {
18
const args = [
19
"-modify",
20
"-xml",
21
"--indent",
22
"yes",
23
"--vertical-space",
24
"yes",
25
"--indent-spaces",
26
"2", // tune that if we let users ever choose the indentation
27
"--wrap",
28
"80",
29
"--sort-attributes",
30
"alpha",
31
"--quiet",
32
"yes",
33
"--write-back",
34
"yes",
35
"--show-warnings",
36
"no", // enable it, if we want to show warnings upon exit code == 1
37
"--tidy-mark",
38
"no",
39
input_path,
40
];
41
42
return await executeCode({
43
command: "tidy",
44
args: args,
45
err_on_exit: false,
46
bash: false,
47
timeout: 15,
48
});
49
}
50
51
export async function xml_format(
52
input: string,
53
options: ParserOptions,
54
logger: any
55
): Promise<string> {
56
// create input temp file
57
const input_path: string = await callback(tmp.file);
58
try {
59
await callback(writeFile, input_path, input);
60
61
// spawn the html formatter
62
let xml_formatter;
63
try {
64
switch (options.parser) {
65
case "xml-tidy":
66
xml_formatter = await tidy(input_path);
67
break;
68
default:
69
throw Error(`Unknown XML formatter utility '${options.parser}'`);
70
}
71
} catch (e) {
72
logger.debug(`Calling XML formatter raised ${e}`);
73
throw new Error(
74
`XML formatter broken or not available. Is '${options.parser}' installed?`
75
);
76
}
77
78
const { exit_code, stdout, stderr } = xml_formatter;
79
const code = exit_code;
80
81
const problem = options.parser === "xml-tidy" ? code >= 2 : code >= 1;
82
if (problem) {
83
const msg = `XML formatter "${options.parser}" exited with code ${code}\nOutput:\n${stdout}\n${stderr}`;
84
throw Error(msg);
85
}
86
87
// all fine, we read from the temp file
88
const output: Buffer = await callback(readFile, input_path);
89
const s: string = output.toString("utf-8");
90
return s;
91
} finally {
92
// logger.debug(`xml formatter done, unlinking ${input_path}`);
93
unlink(input_path, () => {});
94
}
95
}
96
97