import { error, info } from "../deno_ral/log.ts";
import { join } from "../deno_ral/path.ts";
import { ensureDirSync, existsSync } from "../deno_ral/fs.ts";
import { md5HashSync } from "./hash.ts";
import { quartoConfig } from "./quarto.ts";
import { normalizePath } from "./path.ts";
import { isWindows } from "../deno_ral/platform.ts";
const kDevConfig = "dev-config";
export interface DevConfig {
deno: string;
deno_dom: string;
pandoc: string;
dartsass: string;
esbuild: string;
typst: string;
script: string;
importMap: string;
}
export function createDevConfig(
deno: string,
deno_dom: string,
pandoc: string,
dartsass: string,
esbuild: string,
typst: string,
scriptDir: string,
): DevConfig {
const scriptPath = join(scriptDir, "quarto" + (isWindows ? ".cmd" : ""));
const srcDir = Deno.env.get("QUARTO_SRC_PATH") ||
join(quartoConfig.sharePath(), "../../src");
return {
deno,
deno_dom,
pandoc,
dartsass,
esbuild,
typst,
script: md5HashSync(Deno.readTextFileSync(scriptPath)),
importMap: md5HashSync(
Deno.readTextFileSync(
join(srcDir, "import_map.json"),
),
),
};
}
export function writeDevConfig(config: DevConfig, binPath: string) {
const configPath = join(binPath, "..", "config");
ensureDirSync(configPath);
Deno.writeTextFileSync(
join(configPath, kDevConfig),
JSON.stringify(config, undefined, 2),
);
}
export function readInstalledDevConfig(): DevConfig | null {
const binPath = quartoConfig.binPath();
const configPath = join(binPath, "..", "config", kDevConfig);
if (existsSync(configPath)) {
return JSON.parse(Deno.readTextFileSync(configPath)) as DevConfig;
} else {
return null;
}
}
export function readSourceDevConfig(): DevConfig {
const rootDir = Deno.env.get("QUARTO_ROOT") ||
join(quartoConfig.sharePath(), "../..");
const configurationScript = join(
rootDir,
"configuration",
);
const configurationScriptSrc = Deno.readTextFileSync(configurationScript);
const readConfig = (key: string) => {
const regex = new RegExp(`${key}=(\\S+)`);
const match = configurationScriptSrc.match(regex);
if (match) {
return match[1];
} else {
return "";
}
};
return createDevConfig(
readConfig("DENO"),
readConfig("DENO_DOM"),
readConfig("PANDOC"),
readConfig("DARTSASS"),
readConfig("ESBUILD"),
readConfig("TYPST"),
quartoConfig.binPath(),
);
}
export function devConfigsEqual(a: DevConfig, b: DevConfig) {
return a.deno === b.deno &&
a.deno_dom === b.deno_dom &&
a.pandoc === b.pandoc &&
a.dartsass == b.dartsass &&
a.esbuild == b.esbuild &&
a.typst === b.typst &&
a.script == b.script &&
a.importMap === b.importMap;
}
export async function reconfigureQuarto(
installed: DevConfig | null,
source: DevConfig,
) {
if (isWindows) {
error(
`Quarto requires reconfiguration to ${
reconfigureReason(installed, source)
}. Please run \`./configure.cmd\` command.\n`,
);
return;
}
const configureScript = isWindows
? ["cmd", "/c", ".\\configure.cmd"]
: ["./configure.sh"];
const quartoDir = normalizePath(
join(quartoConfig.sharePath(), "..", ".."),
);
const process = new Deno.Command(configureScript[0], {
args: configureScript.slice(1),
cwd: quartoDir,
});
await process.output();
info("");
error(
`Quarto required reconfiguration to ${
reconfigureReason(installed, source)
}. Please try command again.\n`,
);
}
function reconfigureReason(
installed: DevConfig | null,
source: DevConfig,
) {
const versionMessage = (dep: string, version: string) => {
return `install ${dep} version ${version}`;
};
if (installed === null || installed.deno !== source.deno) {
return versionMessage("Deno", source.deno);
} else if (installed.deno_dom !== source.deno_dom) {
return versionMessage("Deno Dom", source.deno_dom);
} else if (installed.pandoc !== source.pandoc) {
return versionMessage("Pandoc", source.pandoc);
} else if (installed.dartsass !== source.dartsass) {
return versionMessage("Dart Sass", source.dartsass);
} else if (installed.esbuild !== source.esbuild) {
return versionMessage("Esbuild", source.esbuild);
} else if (installed.typst !== source.typst) {
return versionMessage("Typst", source.typst);
} else if (installed.script !== source.script) {
return "update Quarto wrapper script";
} else if (
installed.importMap !== source.importMap
) {
return "update dev import map";
}
}