UNPKG

@telefonica/markdown-confluence-sync

Version:

Creates/updates/deletes Confluence pages based on markdown files in a directory. Supports Mermaid diagrams and per-page configuration using frontmatter metadata. Works great with Docusaurus

114 lines (113 loc) 4.24 kB
// SPDX-FileCopyrightText: 2024 Telefónica Innovación Digital // SPDX-License-Identifier: Apache-2.0 import { basename, dirname, join } from "node:path"; import { globSync } from "glob"; import { readSync, toVFile } from "to-vfile"; import { PathNotExistException } from "../pages/errors/PathNotExistException.js"; /** * Checked if file is valid in docusaurus * @param path - Page path * @returns {boolean} */ export function isValidFile(path) { return isSupportedFile(path) && isNotIndexFile(path); } /** * Check if file ended with md or mdx * @param path - Page path * @returns {boolean} */ export function isSupportedFile(path) { return /mdx?$/.test(path); } /** * Check if file is not an index file * index files are the following: * - index.md * - index.mdx * - README.md * - README.mdx * - [directory-name].md * - [directory-name].mdx * @param path - Page path * @returns {boolean} */ export function isNotIndexFile(path) { const dirnamePath = basename(dirname(path)); const pattern = buildIndexFileRegExp("", dirnamePath); return !pattern.test(path); } /** * Replace docusaurus admonitions titles to a valid remark-directive * @param {string} path - Path to the docs directory * @param options - Options with {LoggerInterface} logger * @returns {VFile} - File */ export function readMarkdownAndPatchDocusaurusAdmonitions(path, options) { const file = toVFile(readSync(path)); // HACK: fix docusaurus directive syntax // Docusaurus directive syntax is not compatible with remark-directive. // Docusaurus allows title following directive type, but remark-directive does not. // So, we replace `:::type title` to `:::type[title]` here. const fileContent = file.value.toString(); const processedContent = options?.contentPreprocessor ? options.contentPreprocessor(fileContent, path) : fileContent; file.value = processedContent.replace(/^:::([a-z]+) +(.+)$/gm, (_match, type, title) => { options?.logger?.debug(`Fix docusaurus directive syntax: "${_match}" => ":::${type}[${title}]"`); return `:::${type}[${title}]`; }); return file; } /** * Search for index file in the path * @param {string} path - Path to the docs directory * @param options - Options with {LoggerInterface} logger * @returns {string} - Index file path */ export function getIndexFile(path, options) { const indexFilesGlob = `{index,README,Readme,${basename(path)}}.{md,mdx}`; const indexFilesFounded = globSync(indexFilesGlob, { cwd: path }); if (indexFilesFounded.length === 0) { throw new PathNotExistException(`Index file does not exist in this path ${path}`); } if (indexFilesFounded.length > 1) { options?.logger?.warn(`Multiple index files found in ${basename(path)} directory. Using ${indexFilesFounded[0]} as index file. Ignoring the rest.`); } return join(path, indexFilesFounded[0]); } /** * Search for index file in the path from a list of paths * @param {string} path - Path to search * @param {string[]} paths - Available paths * @returns {string} - Index file path */ export function getIndexFileFromPaths(path, paths) { const indexFiles = [ "index.md", "index.mdx", "README.md", "Readme.md", "README.mdx", "Readme.mdx", `${basename(path)}.md`, `${basename(path)}.mdx`, ]; const indexFilesFounded = indexFiles.find((indexFile) => paths.includes(join(path, indexFile))); // This should never happen, because we are checking if the path exists before // istanbul ignore next if (!indexFilesFounded) throw new PathNotExistException(`Index file does not exist in this path ${path}`); return join(path, indexFilesFounded); } /** * Build index file regexp * @param sep - Separator * @param dirnamePath - Directory name * @returns {RegExp} - RegExp to match with any index file */ export function buildIndexFileRegExp(sep, dirnamePath) { //HACK Use this check to correct an irregular expression when executing unit tests in windows when using parentheses. const pathSep = sep === "\\" ? "\\\\" : sep; return new RegExp(pathSep + `(index|README|${dirnamePath}).mdx?$`); }