const fetchJSON = async (url, startAt = 0) => {
const response = await fetch(url);
const text = await response.text();
const json = JSON.parse(text.slice(startAt));
return json;
};
export const mediumToMarkdown = async (mediumLink) => {
const raw = await fetchJSON(mediumLink + "?format=json", 16);
if (raw.error) {
throw new Error(raw.error);
}
const {
firstPublishedAt,
latestPublishedAt,
slug,
title,
} = raw.payload.value;
const { paragraphs, sections } = raw.payload.value.content.bodyModel;
const blocks = await Promise.all(
paragraphs.map(async (paragraph, i) => {
const { iframe, metadata, mixtapeMetadata, name, text, type } = paragraph;
let markups = JSON.parse(JSON.stringify(paragraph.markups));
markups.sort((a, b) => {
return a.start - b.start || a.end - b.end;
});
let formatted = text;
while (markups.length) {
const markup = markups.shift();
let prefix = "";
let suffix = "";
switch (markup.type) {
case 1:
prefix = "**";
suffix = "**";
break;
case 2:
prefix = "*";
suffix = "*";
break;
case 3:
prefix = `[`;
switch (markup.anchorType) {
case 0:
suffix = `](${markup.href})`;
break;
case 2:
suffix = `](https://medium.com/u/${markup.userId})`;
break;
default:
console.error(paragraph);
throw new Error(`Unsupported anchorType: ${markup.anchorType}`);
}
break;
case 10:
prefix = "`";
suffix = "`";
break;
default:
console.error(paragraph);
throw new Error(`Unsupported markup type: ${markup.type}`);
}
formatted = [
formatted.slice(0, markup.start),
prefix,
formatted.slice(markup.start, markup.end),
suffix,
formatted.slice(markup.end),
].join("");
markups.forEach((next) => {
if (next.end <= markup.start) {
return;
}
if (next.start >= markup.end) {
next.start += prefix.length + suffix.length;
next.end += prefix.length + suffix.length;