UNPKG

@mintlify/common

Version:

Commonly shared code within Mintlify

111 lines (110 loc) 5.42 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { fromMarkdown } from 'mdast-util-from-markdown'; import { gfmFromMarkdown } from 'mdast-util-gfm'; import { mdxFromMarkdown } from 'mdast-util-mdx'; import { gfm } from 'micromark-extension-gfm'; import { mdxjs } from 'micromark-extension-mdxjs'; import { coreRemark, remarkMdxInjectSnippets } from '../../../index.js'; export function createSnippetTreeMap(snippets) { return __awaiter(this, void 0, void 0, function* () { var _a; if (snippets.length === 0) { return {}; } const orderedSnippets = orderSnippetsByNumberOfSnippetsInContent(snippets); let treeMap = {}; // If the lowest number of references is greater than 0, then there will be cyclical references that will never resolve. // In these cases we do not try to replace snippets in snippets // TODO: Better error handling for cyclical references if (((_a = orderedSnippets[0]) === null || _a === void 0 ? void 0 : _a.numSnippetsInContent) === 0) { orderedSnippets.forEach((snippet) => { treeMap = parseSnippetContentToMap(snippet, treeMap); }); return treeMap; } let failedParseArr = []; orderedSnippets.forEach((snippet) => __awaiter(this, void 0, void 0, function* () { if (snippet.numSnippetsInContent === 0) { // No need to remove references if none exist treeMap = parseSnippetContentToMap(snippet, treeMap); } if (failedParseArr.length > 0) { let prevArrLength = failedParseArr.length + 1; // We try to resolve the failed snippets which likely failed because it was referencing // another snippet that has not been resolved yet. // We loop while snippets continue to be resolved. while (prevArrLength > failedParseArr.length && prevArrLength !== 0) { const newlyParsedSnippets = []; for (const failedParse of failedParseArr) { try { treeMap = yield addParsedSnippetTreeToMap(failedParse, treeMap); newlyParsedSnippets.push(failedParse); } catch (_a) { } } prevArrLength = failedParseArr.length; failedParseArr = failedParseArr.filter((elem) => !newlyParsedSnippets.includes(elem)); } } try { treeMap = yield addParsedSnippetTreeToMap(snippet, treeMap); } catch (_b) { // TODO - find exact error message for when inner snippet doesn't exist failedParseArr.push(snippet); } })); return treeMap; }); } function parseSnippetContentToMap(snippet, map) { try { const tree = fromMarkdown(snippet.content, { extensions: [gfm(), mdxjs()], mdastExtensions: [gfmFromMarkdown(), mdxFromMarkdown()], }); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: Please fix this violation when you can! map = Object.assign(Object.assign({}, map), { [snippet.snippetFileLocation]: tree }); } catch (_a) { // TODO: Better error handling } return map; } function addParsedSnippetTreeToMap(snippet, treeMap) { return __awaiter(this, void 0, void 0, function* () { const parsedContent = yield preparseSnippet(snippet, treeMap); return parseSnippetContentToMap(Object.assign(Object.assign({}, snippet), { content: parsedContent }), treeMap); }); } /* * We order the snippets by increasing number of references to other snippets in an attempt to avoid * trying to parse a snippet that references another snippet that has not been resolved yet. */ function orderSnippetsByNumberOfSnippetsInContent(snippets) { const snippetsWithNumSnippets = snippets.map((snippet) => { return Object.assign(Object.assign({}, snippet), { // Note: It's possible the regex might not be enough numSnippetsInContent: (snippet.content.match(/<Snippet/g) || []).length }); }); snippetsWithNumSnippets.sort(function (first, second) { return first.numSnippetsInContent - second.numSnippetsInContent; }); return snippetsWithNumSnippets; } function preparseSnippet(snippet, snippetTreeMap) { return __awaiter(this, void 0, void 0, function* () { const file = yield coreRemark() .use([remarkMdxInjectSnippets, snippetTreeMap]) .process(snippet.content); return String(file); }); }