@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clidey/dory",
3
3
  "private": false,
4
- "version": "0.13.0",
4
+ "version": "0.15.0",
5
5
  "type": "module",
6
6
  "description": "A CLI tool for building and previewing documentation sites",
7
7
  "keywords": [
@@ -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
- // Allow <service> and any <[a-z][a-z0-9]*> tag inside code blocks to be left as-is (not parsed as JSX).
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
- // If known component, leave as-is
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
- // If tag is 'service', always leave as-is (do not wrap in backticks)
68
- if (tag === 'service') {
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