Last active
August 3, 2024 07:27
-
-
Save Aaron-Bird/30a16c162218db4315dfd2d11f5c2f0b to your computer and use it in GitHub Desktop.
yuque-markdown-download
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!(async () => { | |
// 配置 | |
//是否下载储存在语雀上的图片 | |
const DOWNLOAD_IMAGE = true; | |
// 修改 markdown 的图片路径 | |
// 示例:MARKDOWN_IMAGE_PATH = "/image/"; | |
// 效果:![](foo.png) -> ![](/image/foo.png) | |
const MARKDOWN_IMAGE_PATH = ""; | |
class YuqueMarkdownDownload { | |
sleep(time) { | |
return new Promise((resolve) => setTimeout(resolve, time)); | |
} | |
randomNumStr() { | |
return "" + Date.now() + Math.ceil(Math.random() * 100000); | |
} | |
getBooks() { | |
return fetch("https://www.yuque.com/api/mine/book_stacks") | |
.then((resp) => resp.json()) | |
.then(({ data: [{ books }] }) => books); | |
} | |
getDocs(bookId) { | |
return fetch(`https://www.yuque.com/api/docs?book_id=${bookId}`) | |
.then((resp) => resp.json()) | |
.then(({ data }) => data); | |
} | |
downloadDoc({ login, bookSlug, slug }) { | |
return fetch( | |
`https://www.yuque.com/${login}/${bookSlug}/${slug}/markdown?plain=true&linebreak=false&anchor=false` | |
).then((resp) => resp.text()); | |
} | |
downloadBlob(blob, filename) { | |
const link = document.createElement("a"); | |
link.href = window.URL.createObjectURL(blob); | |
link.download = filename; | |
link.click(); | |
window.URL.revokeObjectURL(link.href); | |
} | |
async processMarkdownImage(markdown) { | |
const reg = /\!\[.*?\]\((https:\/\/cdn\.nlark.com\/yuque\/.*?)\)/gi; | |
const imgs = [...markdown.matchAll(reg)]; | |
for (const img of imgs) { | |
const url = img?.[1]; | |
const filename = | |
this.randomNumStr() + | |
"-" + | |
url.match(/[^\/]*?\.([^\.]*?)(?=#)/i)?.[0]; | |
const imgBlob = await fetch(url).then((res) => res.blob()); | |
this.downloadBlob(imgBlob, filename); | |
markdown = markdown.replace(img[0], (match) => | |
match.replace(url, MARKDOWN_IMAGE_PATH + filename) | |
); | |
} | |
return markdown; | |
} | |
async downloadDocAll() { | |
const books = await this.getBooks(); | |
for (const book of books) { | |
const { | |
id: bookId, | |
user: { login }, | |
slug: bookSlug, | |
items_count, | |
name, | |
} = book; | |
const docs = await this.getDocs(bookId).then((docs) => { | |
return docs.filter((i) => i.type === "Doc"); | |
}); | |
console.log(`正在下载 ${name}, 共 ${docs.length} 篇文章`); | |
for (const doc of docs) { | |
const { slug, title } = doc; | |
try { | |
let markdown = await this.downloadDoc({ login, bookSlug, slug }); | |
if (DOWNLOAD_IMAGE) { | |
markdown = await this.processMarkdownImage(markdown); | |
} | |
const markdownBlob = new Blob([markdown], { type: "text/plain" }); | |
this.downloadBlob(markdownBlob, `${title}.md`); | |
} catch (err) { | |
console.log(err); | |
} | |
await this.sleep(1000 * Math.ceil(Math.random() * 10)); | |
} | |
} | |
console.log("end"); | |
} | |
} | |
const yuque = new YuqueMarkdownDownload(); | |
yuque.downloadDocAll(); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
md+assets的方式保存图片也许会更方便