UNPKG

single-page-markdown-website

Version:

Create a nice single-page documentation website from one or more Markdown files

101 lines 4.18 kB
import fs from 'fs-extra'; import { globby } from 'globby'; import isUrl from 'is-url'; import path from 'path'; import remarkParse from 'remark-parse'; import stringify from 'remark-stringify'; import { unified } from 'unified'; import { visit } from 'unist-util-visit'; import { VFile } from 'vfile'; import { resolveNewImageFilePath } from './resolve-new-image-file-path.js'; export async function readMarkdownFilesAsync(globs, images = {}) { const files = []; const filePaths = await globby(globs); if (filePaths.length === 0) { throw new Error(`No files found for: ${globs.join(', ')}`); } for (const filePath of filePaths) { const { fileContent, fileImages } = await readMarkdownFileAsync(filePath, images); files.push(fileContent); for (const originalFilePath in fileImages) { images[originalFilePath] = fileImages[originalFilePath]; } } return { files, images }; } async function readMarkdownFileAsync(filePath, images) { const value = await fs.readFile(filePath, 'utf8'); const file = await unified() .use(remarkParse) .use(remarkReplaceLocalImageFilePaths, { images }) .use(remarkTransclude) .use(stringify) .process(new VFile({ path: filePath, value })); return { fileContent: file.toString(), fileImages: file.data.images }; } const imageElementSrcRegex = /(<img src=)"([^"]+)"/g; const remarkReplaceLocalImageFilePaths = function (options) { return function (node, file) { const directory = path.dirname(file.path); function createNewFilePath(imageSrc) { const originalFilePath = path.join(imageSrc[0] === '/' ? process.cwd() : directory, imageSrc); const newFilePath = resolveNewImageFilePath(imageSrc, Object.values(options.images)); options.images[originalFilePath] = newFilePath; return newFilePath; } visit(node, ['html', 'image'], function (node) { if (node.type === 'image') { const imageSrc = node.url; if (isUrl(imageSrc) === true) { return; } node.url = createNewFilePath(imageSrc); return; } if (node.type === 'html') { const html = node.value; node.value = html.replace(imageElementSrcRegex, function (match, prefix, imageSrc) { if (isUrl(imageSrc) === true) { return match; } const filePath = createNewFilePath(imageSrc); return `${prefix}"${filePath}"`; }); } }); file.data.images = options.images; }; }; const remarkTransclude = function () { return async function (node, file) { if (typeof file.data.images === 'undefined') { throw new Error('`file.data.images` is `undefined`'); } const fileImages = file.data.images; let result = []; for (const childNode of node.children) { if (childNode.type === 'paragraph' && childNode.children.length === 1 && childNode.children[0].type === 'text') { const value = childNode.children[0].value; if (value.indexOf('./') === 0 || value[0] === '/') { const directory = value[0] === '/' ? process.cwd() : path.dirname(file.path); const glob = path.join(directory, value.slice(1)); const { files, images } = await readMarkdownFilesAsync([glob], fileImages); const tree = unified().use(remarkParse).parse(files.join('\n')); result = result.concat(tree.children); for (const originalFilePath in images) { fileImages[originalFilePath] = images[originalFilePath]; } continue; } } result.push(childNode); } node.children = result; }; }; //# sourceMappingURL=read-markdown-files-async.js.map