-
-
Save Demian1996/2eec10e30ef130d61ce0d7512ecd0ebb to your computer and use it in GitHub Desktop.
yuque-markdown-download
This file contains hidden or 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/"; | |
| // 效果: ->  | |
| const MARKDOWN_IMAGE_PATH = ""; | |
| // 知识库,没配置就下载全部知识库,配置了就只下载该知识库 | |
| const KNOWLEDGES = ['算法小结']; | |
| 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"); | |
| }); | |
| // 筛选特定知识库 | |
| if (KNOWLEDGES.length > 0 && !KNOWLEDGES.includes(name)) { | |
| continue; | |
| } | |
| 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