Path: blob/main/src/command/editor-support/crossref.ts
3583 views
/*1* command.ts2*3* Copyright (C) 2020-2022 Posit Software, PBC4*/56import { join } from "../../deno_ral/path.ts";7import { readAll } from "../../deno_ral/io.ts";8import { error } from "../../deno_ral/log.ts";9import { encodeBase64 } from "../../deno_ral/encoding.ts";1011import { Command } from "cliffy/command/mod.ts";1213import { execProcess } from "../../core/process.ts";14import { pandocBinaryPath, resourcePath } from "../../core/resources.ts";15import { globalTempContext } from "../../core/temp.ts";1617function parseCrossrefFlags(options: any, args: string[]): {18input?: string;19output?: string;20} {21let input: string | undefined, output: string | undefined;2223// stop early with no input seems wonky in Cliffy so we need to undo the damage here24// by inspecting partially-parsed input...25if (options.input && args[0]) {26input = args.shift();27} else if (options.output && args[0]) {28output = args.shift();29}30const argsStack = [...args];31let arg = argsStack.shift();32while (arg !== undefined) {33switch (arg) {34case "-i":35case "--input":36arg = argsStack.shift();37if (arg) {38input = arg;39}40break;4142case "-o":43case "--output":44arg = argsStack.shift();45if (arg) {46output = arg;47}48break;49default:50arg = argsStack.shift();51break;52}53}54return { input, output };55}5657const makeCrossrefCommand = () => {58return new Command()59.description("Index cross references for content")60.stopEarly()61.arguments("[...args]")62.option(63"-i, --input",64"Use FILE as input (default: stdin).",65)66.option(67"-o, --output",68"Write output to FILE (default: stdout).",69)70.action(async (options, ...args: string[]) => {71const flags = parseCrossrefFlags(options, args);72const getInput = async () => {73if (flags.input) {74return Deno.readTextFileSync(flags.input);75} else {76// read input77const stdinContent = await readAll(Deno.stdin);78return new TextDecoder().decode(stdinContent);79}80};81const getOutputFile: () => string = () => (flags.output || "stdout");8283const input = await getInput();8485// create directory for indexing and write input into it86const indexingDir = globalTempContext().createDir();8788// setup index file and input type89const indexFile = join(indexingDir, "index.json");90Deno.env.set("QUARTO_CROSSREF_INDEX_PATH", indexFile);91Deno.env.set("QUARTO_CROSSREF_INPUT_TYPE", "qmd");9293// build command94const cmd = pandocBinaryPath();95const cmdArgs = ["+RTS", "-K512m", "-RTS"];96cmdArgs.push(...[97"--from",98resourcePath("filters/qmd-reader.lua"),99"--to",100"native",101"--data-dir",102resourcePath("pandoc/datadir"),103"--lua-filter",104resourcePath("filters/quarto-init/quarto-init.lua"),105"--lua-filter",106resourcePath("filters/crossref/crossref.lua"),107]);108109// create filter params110const filterParams = encodeBase64(111JSON.stringify({112["crossref-index-file"]: "index.json",113["crossref-input-type"]: "qmd",114}),115);116117// run pandoc118const result = await execProcess(119{120cmd,121args: cmdArgs,122cwd: indexingDir,123env: {124"QUARTO_FILTER_PARAMS": filterParams,125"QUARTO_SHARE_PATH": resourcePath(),126},127stdout: "piped",128},129input,130undefined, // mergeOutput?: "stderr>stdout" | "stdout>stderr",131undefined, // stderrFilter?: (output: string) => string,132undefined, // respectStreams?: boolean,1335000,134);135136// check for error137if (!result.success) {138error("Error running Pandoc: " + result.stderr);139throw new Error(result.stderr);140}141142const outputFile = getOutputFile();143if (outputFile === "stdout") {144// write back the index145Deno.stdout.writeSync(Deno.readFileSync(indexFile));146} else {147Deno.writeTextFileSync(outputFile, Deno.readTextFileSync(indexFile));148}149});150};151152export const crossrefCommand = makeCrossrefCommand();153154155