@clidey/dory 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/plugins/sanitize.ts +47 -4
package/package.json
CHANGED
package/src/plugins/sanitize.ts
CHANGED
|
@@ -42,7 +42,37 @@ function isInsideCodeBlock(code: string, idx: number): boolean {
|
|
|
42
42
|
return codeBlockMatches ? codeBlockMatches.length % 2 === 1 : false;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
//
|
|
45
|
+
// Helper: checks if a known component tag has a matching closing tag
|
|
46
|
+
function hasMatchingClosingTag(code: string, tagName: string, openingTagOffset: number): boolean {
|
|
47
|
+
// Simple approach: look for the next occurrence of either an opening or closing tag of the same type
|
|
48
|
+
const afterOpening = code.slice(openingTagOffset + `<${tagName}>`.length);
|
|
49
|
+
|
|
50
|
+
// Find the first occurrence of either opening or closing tag
|
|
51
|
+
const nextOpeningMatch = afterOpening.match(new RegExp(`<${tagName}>`, 'i'));
|
|
52
|
+
const nextClosingMatch = afterOpening.match(new RegExp(`</${tagName}>`, 'i'));
|
|
53
|
+
|
|
54
|
+
// If no closing tag found at all
|
|
55
|
+
if (!nextClosingMatch) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const nextOpeningIndex = nextOpeningMatch ? nextOpeningMatch.index! : Infinity;
|
|
60
|
+
const nextClosingIndex = nextClosingMatch ? nextClosingMatch.index! : Infinity;
|
|
61
|
+
|
|
62
|
+
// If the closing tag comes before any other opening tag, this tag is properly closed
|
|
63
|
+
if (nextClosingIndex < nextOpeningIndex) {
|
|
64
|
+
// Check if the closing tag is inside a code block
|
|
65
|
+
const closingTagOffset = openingTagOffset + `<${tagName}>`.length + nextClosingIndex;
|
|
66
|
+
if (isInsideCodeBlock(code, closingTagOffset)) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return false; // Another opening tag comes before the closing tag, so this one is not properly closed
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Allow any <[a-z][a-z0-9]*> tag inside code blocks to be left as-is (not parsed as JSX).
|
|
46
76
|
export function preprocessMdxTags() {
|
|
47
77
|
return {
|
|
48
78
|
name: 'preprocess-mdx-tags',
|
|
@@ -60,12 +90,25 @@ export function preprocessMdxTags() {
|
|
|
60
90
|
if (isInsideCodeBlock(processed, offset)) {
|
|
61
91
|
return match;
|
|
62
92
|
}
|
|
63
|
-
|
|
93
|
+
|
|
94
|
+
// If known component, check if it has a closing tag
|
|
64
95
|
if (KNOWN_COMPONENTS.includes(tag)) {
|
|
96
|
+
// If it doesn't have a matching closing tag, treat it as text
|
|
97
|
+
if (!hasMatchingClosingTag(processed, tag, offset)) {
|
|
98
|
+
return `\`<${tag}>\``;
|
|
99
|
+
}
|
|
100
|
+
// Otherwise, leave as-is for proper JSX parsing
|
|
65
101
|
return match;
|
|
66
102
|
}
|
|
67
|
-
|
|
68
|
-
|
|
103
|
+
|
|
104
|
+
// If already inside backticks, do not wrap again
|
|
105
|
+
// Find the start of the line up to the match
|
|
106
|
+
const before = processed.slice(0, offset);
|
|
107
|
+
// Count the number of backticks before this tag
|
|
108
|
+
const backtickMatches = before.match(/`+/g);
|
|
109
|
+
// If the number of backticks is odd, we're inside a backtick span
|
|
110
|
+
const insideBackticks = backtickMatches ? backtickMatches.reduce((acc, s) => acc + s.length, 0) % 2 === 1 : false;
|
|
111
|
+
if (insideBackticks) {
|
|
69
112
|
return match;
|
|
70
113
|
}
|
|
71
114
|
// Otherwise, wrap in backticks to prevent JSX parsing
|