Skip to content

Commit

Permalink
Add option to specify external CSS
Browse files Browse the repository at this point in the history
Closes #10
  • Loading branch information
bfirsh committed Jul 4, 2018
1 parent 051e0bc commit 4beb984
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 14 deletions.
7 changes: 6 additions & 1 deletion bin/engrafo
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ program
"--no-post-processing",
"Raw LaTeXML output, without filters or postprocessors (for debugging)"
)
.option(
"--css <path>",
"URL or path to external CSS to use instead of the default CSS. If passed, the defaut CSS is not copied to the output directory."
)
.parse(process.argv);

if (program.args.length != 1) {
Expand All @@ -28,7 +32,8 @@ var output =
var options = {
input: input,
output: output,
postProcessing: program.postProcessing
postProcessing: program.postProcessing,
externalCSS: program.css
};

converter
Expand Down
19 changes: 13 additions & 6 deletions src/converter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ const math = require("./math");
const postprocessors = require("./postprocessor");

// Run postprocessing against a string of HTML
function postprocess(htmlString) {
function postprocess(htmlString, options) {
var dom = jsdom.jsdom(htmlString, {
features: { ProcessExternalResources: false, FetchExternalResources: false }
});

// Run all processing on document.
postprocessors.css(dom, options);
postprocessors.figures(dom);
postprocessors.headings(dom);
postprocessors.links(dom);
Expand All @@ -22,17 +23,17 @@ function postprocess(htmlString) {
}

// Do all processing on the file that LaTeXML produces
async function processHTML(htmlPath) {
async function processHTML(htmlPath, options) {
let htmlString = await fs.readFile(htmlPath, "utf8");
htmlString = postprocess(htmlString);
htmlString = postprocess(htmlString, options);
htmlString = await math.renderMath(htmlString);
await fs.writeFile(htmlPath, htmlString);
}

// Render and postprocess a LaTeX file into outputDir (created if does not
// exist). Calls callback with an error on failure or a path to an HTML file
// on success.
async function render({ input, output, postProcessing }) {
async function render({ input, output, postProcessing, externalCSS }) {
if (postProcessing === undefined) {
postProcessing = true;
}
Expand All @@ -41,10 +42,16 @@ async function render({ input, output, postProcessing }) {
const texPath = await io.pickLatexFile(inputDir);
const outputDir = await io.prepareOutputDirectory(output);

// If there are external assets, don't let LaTeXML copy it to the output
// directory - we will handle it ourselves
// Otherwise, link directly to the built asset. Absolute path, assuming
// latexml is always run in Docker.
const cssPath = externalCSS ? null : "/app/dist/css/index.css";

console.log(`Rendering tex file ${texPath} to ${outputDir}`);
const htmlPath = await latexml.render({ texPath, outputDir });
const htmlPath = await latexml.render({ texPath, outputDir, cssPath });

await processHTML(htmlPath);
await processHTML(htmlPath, { externalCSS });

if (output.startsWith("s3://")) {
await io.uploadOutputToS3(outputDir, output);
Expand Down
20 changes: 14 additions & 6 deletions src/converter/latexml.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ function unlinkIfExists(path) {
}
}

function createChildProcess({ htmlPath, texPath, outputDir }) {
function createChildProcess({ cssPath, htmlPath, texPath, outputDir }) {
// prettier-ignore
const latexmlArgs = [
"--format", "html5",
"--nodefaultresources",
"--css", "/app/dist/index.css",
"--mathtex",
"--svg",
"--verbose",
Expand All @@ -27,6 +26,10 @@ function createChildProcess({ htmlPath, texPath, outputDir }) {
"--preload", "/usr/src/latexml/lib/LaTeXML/Package/hyperref.sty.ltxml",
];

if (cssPath) {
latexmlArgs.push("--css", cssPath);
}

latexmlArgs.push(path.basename(texPath));

if (process.env.LATEXML_DOCKER) {
Expand Down Expand Up @@ -55,14 +58,19 @@ function createChildProcess({ htmlPath, texPath, outputDir }) {
}

// render a document with latexml
function render({ texPath, outputDir }) {
function render({ texPath, outputDir, cssPath }) {
const htmlPath = path.join(outputDir, "index.html");

const latexmlc = createChildProcess({ texPath, outputDir, htmlPath });
const latexmlc = createChildProcess({
texPath,
outputDir,
htmlPath,
cssPath
});

var stdoutReadline = readline.createInterface({ input: latexmlc.stdout });
const stdoutReadline = readline.createInterface({ input: latexmlc.stdout });
stdoutReadline.on("line", console.log);
var stderrReadline = readline.createInterface({ input: latexmlc.stderr });
const stderrReadline = readline.createInterface({ input: latexmlc.stderr });
stderrReadline.on("line", console.error);

return new Promise((resolve, reject) => {
Expand Down
13 changes: 13 additions & 0 deletions src/converter/postprocessor/css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const utils = require("./utils");

module.exports = function(dom, { externalCSS }) {
if (externalCSS) {
const head = dom.querySelector("head");
const link = utils.nodeFromString(
dom,
'<link type="text/css" rel="stylesheet">'
);
link.setAttribute("href", externalCSS);
head.appendChild(link);
}
};
1 change: 1 addition & 0 deletions src/converter/postprocessor/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = {
css: require("./css"),
figures: require("./figures"),
headings: require("./headings"),
links: require("./links"),
Expand Down
14 changes: 14 additions & 0 deletions src/converter/postprocessor/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
exports.removeAll = function(els) {
Array.from(els).forEach(el => {
el.parentNode.removeChild(el);
});
};

exports.nodeFromString = function(dom, str) {
var div = dom.createElement("div");
div.innerHTML = str;
if (!div.firstChild) {
throw new Error("Invalid HTML passed to nodeFromString");
}
return div.firstChild;
};
5 changes: 4 additions & 1 deletion src/converter/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ module.exports.start = async input => {
const tmpDir = await tmp.dir();
const htmlPath = await render({
input: input,
output: tmpDir.path
output: tmpDir.path,
// This absolute filesystem path will be passed unmodified through
// to the parcel bundler, which will compile the SCSS
externalCSS: path.join(__dirname, "../assets/css/index.scss")
});

console.log("💅 Starting server at http://localhost:8000");
Expand Down

0 comments on commit 4beb984

Please sign in to comment.