146 lines
3.2 KiB
JavaScript
146 lines
3.2 KiB
JavaScript
const fs = require("fs");
|
|
const jsdom = require("jsdom");
|
|
const fetch = require("node-fetch");
|
|
const { JSDOM } = jsdom;
|
|
const { window } = new JSDOM("");
|
|
global.window = window;
|
|
var showdown = require("showdown");
|
|
const converter = new showdown.Converter();
|
|
const libxmljs = require("libxmljs");
|
|
|
|
const MIRROR_URL = "http://mirror.csclub.uwaterloo.ca/csclub/";
|
|
|
|
try {
|
|
fs.mkdirSync("./markdown-talks/");
|
|
} catch (e) {
|
|
if (e.code !== "EEXIST") {
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
const file = fs
|
|
.readFileSync("../../media/index.xml", "utf8")
|
|
.replace(/<!DOCTYPE.*>/, "");
|
|
|
|
const xml = libxmljs.parseHtml(file);
|
|
const talks = xml.find("//mediaitem");
|
|
|
|
(async () => {
|
|
const all = await Promise.all(
|
|
talks.map(async (talk, idx) => {
|
|
const { filename, markdown } = await xml2md(talk, idx);
|
|
|
|
await fs.promises.writeFile(`./markdown-talks/${filename}.md`, markdown);
|
|
}),
|
|
);
|
|
|
|
console.log(all.length);
|
|
|
|
process.exit(0);
|
|
})();
|
|
|
|
/**
|
|
*
|
|
* @param {libxmljs.Element} talk
|
|
*/
|
|
async function xml2md(talk, index) {
|
|
const title = talk.attr("title").value();
|
|
|
|
const abstract = talk
|
|
.get("abstract")
|
|
?.childNodes()
|
|
.reduce((str, node) => str + node.toString(), "")
|
|
.trim();
|
|
|
|
const presentors = talk
|
|
.get("presentor")
|
|
.childNodes()
|
|
.toString()
|
|
.split(",")
|
|
.map((s) => s.trim());
|
|
|
|
const thumbSmall = MIRROR_URL + talk.get("thumbnail").attr("file").value();
|
|
|
|
/** @type{string | undefined} */
|
|
let thumbLarge = thumbSmall.replace("-thumb-small", "-thumb-large");
|
|
|
|
if (!(await resourceExists(thumbLarge))) {
|
|
thumbLarge = undefined;
|
|
}
|
|
|
|
const links = talk
|
|
.find("mediafile")
|
|
.map((mf) => ({
|
|
/** @type{string} */
|
|
file: MIRROR_URL + mf.attr("file").value(),
|
|
|
|
/** @type{string} */
|
|
type: mf.attr("type").value(),
|
|
|
|
/** @type{string | undefined} */
|
|
size: mf.attr("size")?.value() ?? undefined,
|
|
}))
|
|
.map(
|
|
({ file, type, size }) =>
|
|
" " +
|
|
`
|
|
- file: '${file.replaceAll("'", "''")}'
|
|
type: '${type.replaceAll("'", "''")}'
|
|
${size == null ? "" : `size: '${size.replaceAll("'", "''")}'`}
|
|
`.trim(),
|
|
);
|
|
|
|
const markdown =
|
|
`
|
|
---
|
|
index: ${index}
|
|
title: '${title.replaceAll("'", "''")}'
|
|
presentors:
|
|
- ${presentors.join("\n - ").replaceAll("'", "''")}
|
|
thumbnails:
|
|
small: '${thumbSmall}'${thumbLarge ? `\n large: '${thumbLarge}'` : ""}
|
|
links:
|
|
${links.join("\n")}
|
|
---
|
|
|
|
${converter.makeMarkdown(abstract ?? "")}
|
|
`.trim() + "\n";
|
|
|
|
return {
|
|
filename: title
|
|
.toLowerCase()
|
|
.replaceAll(" ", "-")
|
|
.replaceAll(":", "")
|
|
.replaceAll("=", "")
|
|
.replaceAll(",", "-")
|
|
.replaceAll("'", "-")
|
|
.replaceAll("+", "-plus-")
|
|
.replaceAll(/-+/g, "-"),
|
|
markdown,
|
|
};
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param {string} url
|
|
*/
|
|
async function resourceExists(url) {
|
|
|
|
const time = Math.trunc(Math.random() * 10000);
|
|
await sleep(time);
|
|
|
|
const timer = setTimeout(() => console.log("not done", time, url), time + 3000);
|
|
const response = await fetch(url);
|
|
|
|
clearTimeout(timer)
|
|
|
|
return (
|
|
response.status.toString().startsWith("2") ||
|
|
response.status.toString().startsWith("3")
|
|
);
|
|
}
|
|
|
|
function sleep(time) {
|
|
return new Promise((resolve) => setTimeout(resolve, time));
|
|
}
|