mirror of
https://github.com/LukeHagar/prettier-plugin-openapi.git
synced 2025-12-07 12:47:48 +00:00
Implement code block size limit and optimize markdown processor caching for performance
This commit is contained in:
@@ -4,10 +4,17 @@ import getMaxContinuousCount from "../utils/get-max-continuous-count.js";
|
|||||||
import inferParser from "../utils/infer-parser.js";
|
import inferParser from "../utils/infer-parser.js";
|
||||||
import { getFencedCodeBlockValue } from "./utils.js";
|
import { getFencedCodeBlockValue } from "./utils.js";
|
||||||
|
|
||||||
|
// Skip embedding extremely large code blocks to avoid expensive formatting passes
|
||||||
|
const MAX_EMBED_CODE_SIZE = 32 * 1024; // 32KB
|
||||||
|
|
||||||
function embed(path, options) {
|
function embed(path, options) {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
|
|
||||||
if (node.type === "code" && node.lang !== null) {
|
if (node.type === "code" && node.lang !== null) {
|
||||||
|
// Fast path: large code blocks are printed as-is without embedding
|
||||||
|
if (typeof node.value === "string" && node.value.length > MAX_EMBED_CODE_SIZE) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const parser = inferParser(options, { language: node.lang });
|
const parser = inferParser(options, { language: node.lang });
|
||||||
if (parser) {
|
if (parser) {
|
||||||
return async (textToDoc) => {
|
return async (textToDoc) => {
|
||||||
|
|||||||
@@ -24,20 +24,48 @@ import wikiLink from "./unified-plugins/wiki-link.js";
|
|||||||
* interface Sentence { children: Array<Word | Whitespace> }
|
* interface Sentence { children: Array<Word | Whitespace> }
|
||||||
* interface InlineCode { children: Array<Sentence> }
|
* interface InlineCode { children: Array<Sentence> }
|
||||||
*/
|
*/
|
||||||
|
// Memoized processors keyed by feature signature to avoid rebuilding pipelines
|
||||||
|
const processorCache = new Map();
|
||||||
|
|
||||||
|
function detectFeatures(text) {
|
||||||
|
// Cheap checks to decide whether to enable heavier plugins
|
||||||
|
const hasMath = /(\$\$|\\\[|\\\(|\$)/u.test(text);
|
||||||
|
const hasLiquid = /(\{\{|\{%)/u.test(text);
|
||||||
|
const hasWiki = /\[\[/u.test(text);
|
||||||
|
return { hasMath, hasLiquid, hasWiki };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProcessor({ isMDX, features }) {
|
||||||
|
const key = `${isMDX ? 1 : 0}:${features.hasMath ? 1 : 0}${features.hasLiquid ? 1 : 0}${features.hasWiki ? 1 : 0}`;
|
||||||
|
const cached = processorCache.get(key);
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
const processor = unified()
|
||||||
|
.use(remarkParse, {
|
||||||
|
commonmark: true,
|
||||||
|
...(isMDX && { blocks: [BLOCKS_REGEX] }),
|
||||||
|
})
|
||||||
|
// inexpensive plugins first
|
||||||
|
.use(footnotes)
|
||||||
|
.use(frontMatter)
|
||||||
|
.use(isMDX ? esSyntax : noop)
|
||||||
|
// conditional heavy plugins
|
||||||
|
.use(features.hasMath ? remarkMath : noop)
|
||||||
|
.use(features.hasLiquid ? liquid : noop)
|
||||||
|
// html -> jsx only matters in MDX
|
||||||
|
.use(isMDX ? htmlToJsx : noop)
|
||||||
|
.use(features.hasWiki ? wikiLink : noop);
|
||||||
|
|
||||||
|
processorCache.set(key, processor);
|
||||||
|
return processor;
|
||||||
|
}
|
||||||
|
|
||||||
function createParse({ isMDX }) {
|
function createParse({ isMDX }) {
|
||||||
return (text) => {
|
return (text) => {
|
||||||
const processor = unified()
|
const features = detectFeatures(text);
|
||||||
.use(remarkParse, {
|
const processor = getProcessor({ isMDX, features });
|
||||||
commonmark: true,
|
|
||||||
...(isMDX && { blocks: [BLOCKS_REGEX] }),
|
|
||||||
})
|
|
||||||
.use(footnotes)
|
|
||||||
.use(frontMatter)
|
|
||||||
.use(remarkMath)
|
|
||||||
.use(isMDX ? esSyntax : noop)
|
|
||||||
.use(liquid)
|
|
||||||
.use(isMDX ? htmlToJsx : noop)
|
|
||||||
.use(wikiLink);
|
|
||||||
return processor.runSync(processor.parse(text));
|
return processor.runSync(processor.parse(text));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user