Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function isOpenAPIFile(content: any, filePath?: string): boolean {
}

// Check file path patterns for common OpenAPI file structures
// Only accept files in OpenAPI-related directories
// Only accept files in OpenAPI-related directories, but validate content first
if (filePath) {
const path = filePath.toLowerCase();

Expand All @@ -155,7 +155,33 @@ function isOpenAPIFile(content: any, filePath?: string): boolean {
path.includes("/webhooks/") ||
path.includes("/paths/")
) {
return true;
// Fast-path: if filepath matches, still validate content to prevent
// generic JSON from being misclassified as OpenAPI
const keys = Object.keys(content);
const hasOnlyGenericProperties = keys.every(
(key) =>
!key.startsWith("x-") && // Not a custom extension
![
"openapi",
"swagger",
"info",
"paths",
"components",
"definitions",
"parameters",
"responses",
"securityDefinitions",
"tags",
"servers",
"webhooks",
].includes(key)
);

// Only accept if content doesn't have only generic properties
if (!hasOnlyGenericProperties) {
return true;
}
// If it has only generic properties, fall through to continue validation
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down
2 changes: 1 addition & 1 deletion src/prettier-markdown/adapter-prettier-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ if (!utils) {
const hasSingle = str.includes("'");
const hasDouble = str.includes('"');
if (hasSingle && !hasDouble) return '"';
return "'";
return '"';
},
};
}
Expand Down
7 changes: 7 additions & 0 deletions src/prettier-markdown/embed.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ import getMaxContinuousCount from "../utils/get-max-continuous-count.js";
import inferParser from "../utils/infer-parser.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) {
const { node } = path;

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 });
if (parser) {
return async (textToDoc) => {
Expand Down
54 changes: 41 additions & 13 deletions src/prettier-markdown/parser-markdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,49 @@ import wikiLink from "./unified-plugins/wiki-link.js";
* interface Sentence { children: Array<Word | Whitespace> }
* 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 }) {
return (text) => {
const processor = unified()
.use(remarkParse, {
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.run(processor.parse(text));
const features = detectFeatures(text);
const processor = getProcessor({ isMDX, features });
return processor.runSync(processor.parse(text));
};
}

Expand Down
12 changes: 10 additions & 2 deletions src/prettier-markdown/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,17 @@ function getOrderedListItemInfo(orderListItem, options) {
orderListItem.position.end.offset,
);

const { numberText, leadingSpaces } = text.match(
const m = text.match(
/^\s*(?<numberText>\d+)(\.|\))(?<leadingSpaces>\s*)/u,
).groups;
);

if (!m) {
throw new Error(
`Failed to parse ordered list item: expected pattern matching /^\\s*(?<numberText>\\d+)(\\.|\\))(?<leadingSpaces>\\s*)/u, but got: ${JSON.stringify(text)}`,
);
}

const { numberText, leadingSpaces } = m.groups;

return { number: Number(numberText), leadingSpaces };
}
Expand Down
Loading