import { basename, dirname, join } from "../../deno_ral/path.ts";
import { readPartials } from "../../command/render/template.ts";
import {
kCellFormat,
kCellRawMimeType,
kDefaultImageExtension,
kIPynbTitleBlockTemplate,
} from "../../config/constants.ts";
import { Format, PandocFlags } from "../../config/types.ts";
import {
jupyterFromFile,
kQuartoMimeType,
} from "../../core/jupyter/jupyter.ts";
import {
kApplicationRtf,
kRestructuredText,
kTextHtml,
kTextLatex,
} from "../../core/mime.ts";
import { formatResourcePath } from "../../core/resources.ts";
import { createFormat } from "../formats-shared.ts";
import { decodeBase64 as base64decode } from "encoding/base64";
import {
JupyterOutput,
JupyterOutputDisplayData,
} from "../../core/jupyter/types.ts";
export function ipynbTitleTemplatePath() {
return formatResourcePath(
"ipynb",
join("templates", "title-block.md"),
);
}
export function ipynbFormat(): Format {
return createFormat("Jupyter", "ipynb", {
pandoc: {
standalone: true,
[kDefaultImageExtension]: "png",
},
formatExtras: (
input: string,
_markdown: string,
_flags: PandocFlags,
format: Format,
) => {
const resolveTemplate = () => {
const titleTemplate = ipynbTitleTemplatePath();
const partials = readPartials(format.metadata, dirname(input));
if (partials.length > 0) {
const userTitleTemplate = partials.find((part) => {
return basename(part) === "title-block.md";
});
if (userTitleTemplate) {
return userTitleTemplate;
} else {
return titleTemplate;
}
} else {
return titleTemplate;
}
};
return {
metadata: {
[kIPynbTitleBlockTemplate]: resolveTemplate(),
},
postprocessors: [(output: string) => {
const nb = jupyterFromFile(output);
const widgets = nb.metadata.widgets as unknown;
if (widgets && typeof widgets === "string") {
nb.metadata.widgets = JSON.parse(
new TextDecoder().decode(base64decode(widgets)),
);
}
nb.cells = nb.cells.map((cell) => {
if (cell.cell_type == "raw") {
if (cell.metadata[kCellFormat]) {
const format = cell.metadata[kCellFormat];
delete cell.metadata[kCellFormat];
if (format === kTextHtml) {
cell.metadata[kCellRawMimeType] = format;
} else if (format === "tex") {
cell.metadata[kCellRawMimeType] = kTextLatex;
} else if (format === "rst") {
cell.metadata[kCellRawMimeType] = kRestructuredText;
} else if (format === "rtf") {
cell.metadata[kCellRawMimeType] = kApplicationRtf;
} else {
cell.metadata[kCellFormat] = format;
}
}
}
cell.outputs?.forEach((output) => {
const cellOutput = output as JupyterOutput;
if (cellOutput.output_type === "display_data") {
const cellDisplayOutput =
cellOutput as JupyterOutputDisplayData;
if (cellDisplayOutput.data["application/json"]) {
const jsonData = cellDisplayOutput
.data["application/json"] as Record<
string,
unknown
>;
if (jsonData[kQuartoMimeType]) {
const realMimetype = jsonData[kQuartoMimeType] as string;
delete jsonData[kQuartoMimeType];
cellDisplayOutput.data[realMimetype] = jsonData;
delete cellDisplayOutput.data["application/json"];
}
}
}
});
return cell;
});
Deno.writeTextFileSync(output, JSON.stringify(nb, null, 2));
return Promise.resolve();
}],
};
},
});
}