Skip to content

Commit b63409d

Browse files
committed
fix lint issues
1 parent 55e3231 commit b63409d

7 files changed

Lines changed: 94 additions & 99 deletions

File tree

packages/module/src/ConsoleInternal/components/markdown-view.tsx

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -87,58 +87,65 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
8787

8888
// Fix malformed HTML entities early in the process
8989
let preprocessedMarkdown = markdownWithSubstitutedCodeFences;
90-
preprocessedMarkdown = preprocessedMarkdown.replace(/&nbsp([^;])/g, ' $1').replace(/ /g, ' ');
90+
preprocessedMarkdown = preprocessedMarkdown
91+
.replace(/&nbsp([^;])/g, ' $1')
92+
.replace(/ /g, ' ');
9193
preprocessedMarkdown = preprocessedMarkdown.replace(/&nbsp(?![;])/g, ' ');
9294

9395
// Process content in segments to ensure markdown parsing continues after HTML blocks
94-
const htmlBlockRegex = /(<(?:details|div|section|article)[^>]*>[\s\S]*?<\/(?:details|div|section|article)>)/g;
95-
96+
const htmlBlockRegex =
97+
/(<(?:details|div|section|article)[^>]*>[\s\S]*?<\/(?:details|div|section|article)>)/g;
98+
9699
let parsedMarkdown = '';
97-
100+
98101
// Check if there are any HTML blocks
99102
if (htmlBlockRegex.test(preprocessedMarkdown)) {
100103
// Reset regex for actual processing
101104
htmlBlockRegex.lastIndex = 0;
102-
105+
103106
let lastIndex = 0;
104107
let match;
105-
108+
106109
while ((match = htmlBlockRegex.exec(preprocessedMarkdown)) !== null) {
107110
// Process markdown before the HTML block
108111
const markdownBefore = preprocessedMarkdown.slice(lastIndex, match.index).trim();
109112
if (markdownBefore) {
110113
const parsed = await marked.parse(markdownBefore);
111114
parsedMarkdown += parsed;
112115
}
113-
116+
114117
// Process the HTML block: parse markdown content inside while preserving HTML structure
115118
let htmlBlock = match[1];
116-
119+
117120
// Find and process markdown content inside HTML tags
118121
const contentRegex = />(\s*[\s\S]*?)\s*</g;
119122
const contentMatches = [];
120123
let contentMatch;
121-
122-
while ((contentMatch = contentRegex.exec(htmlBlock)) !== null) {
123-
const content = contentMatch[1];
124-
// Only process content that has markdown formatting but no extension syntax
125-
if (content.trim() && !content.includes('{{') && (content.includes('**') || content.includes('- ') || content.includes('\n'))) {
126-
// This looks like markdown content without extensions - parse it as block content
127-
const parsedContent = await marked.parse(content.trim());
128-
// Remove wrapping <p> tags if they exist since we're inside HTML already
129-
const cleanedContent = parsedContent.replace(/^<p[^>]*>([\s\S]*)<\/p>[\s]*$/g, '$1');
130-
contentMatches.push({
131-
original: contentMatch[0],
132-
replacement: `>${cleanedContent}<`
133-
});
134-
}
135-
}
136-
124+
125+
while ((contentMatch = contentRegex.exec(htmlBlock)) !== null) {
126+
const content = contentMatch[1];
127+
// Only process content that has markdown formatting but no extension syntax
128+
if (
129+
content.trim() &&
130+
!content.includes('{{') &&
131+
(content.includes('**') || content.includes('- ') || content.includes('\n'))
132+
) {
133+
// This looks like markdown content without extensions - parse it as block content
134+
const parsedContent = await marked.parse(content.trim());
135+
// Remove wrapping <p> tags if they exist since we're inside HTML already
136+
const cleanedContent = parsedContent.replace(/^<p[^>]*>([\s\S]*)<\/p>[\s]*$/g, '$1');
137+
contentMatches.push({
138+
original: contentMatch[0],
139+
replacement: `>${cleanedContent}<`,
140+
});
141+
}
142+
}
143+
137144
// Apply the content replacements
138145
contentMatches.forEach(({ original, replacement }) => {
139146
htmlBlock = htmlBlock.replace(original, replacement);
140147
});
141-
148+
142149
// Apply extensions (like admonitions) to the processed HTML block
143150
if (extensions) {
144151
extensions.forEach(({ regex, replace }) => {
@@ -147,11 +154,11 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
147154
}
148155
});
149156
}
150-
157+
151158
parsedMarkdown += htmlBlock;
152159
lastIndex = htmlBlockRegex.lastIndex;
153160
}
154-
161+
155162
// Process any remaining markdown after the last HTML block
156163
const markdownAfter = preprocessedMarkdown.slice(lastIndex).trim();
157164
if (markdownAfter) {
@@ -169,16 +176,16 @@ export const markdownConvert = async (markdown: string, extensions?: ShowdownExt
169176
// Convert code spans back to md format before we run the custom extension regexes
170177
md = md.replace(/<code>(.*)<\/code>/g, '`$1`');
171178

172-
extensions.forEach(({ regex, replace }, index) => {
179+
extensions.forEach(({ regex, replace }, _index) => {
173180
if (regex) {
174181
md = md.replace(regex, replace);
175182
}
176183
});
177184

178185
// Convert any remaining backticks back into code spans
179186
md = md.replace(/`(.*)`/g, '<code>$1</code>');
180-
}
181-
187+
}
188+
182189
return DOMPurify.sanitize(md);
183190
};
184191

@@ -287,7 +294,10 @@ const InlineMarkdownView: FC<InnerSyncMarkdownProps> = ({
287294
const id = useMemo(() => uniqueId('markdown'), []);
288295
return (
289296
<div className={css({ 'is-empty': isEmpty } as any, className)} id={id}>
290-
<div style={{ marginBlockEnd: 'var(--pf-t-global--spacer--md)' }} dangerouslySetInnerHTML={{ __html: markup }} />
297+
<div
298+
style={{ marginBlockEnd: 'var(--pf-t-global--spacer--md)' }}
299+
dangerouslySetInnerHTML={{ __html: markup }}
300+
/>
291301
{renderExtension && (
292302
<RenderExtension renderExtension={renderExtension} selector={`#${id}`} markup={markup} />
293303
)}
@@ -376,6 +386,7 @@ const IFrameMarkdownView: FC<InnerSyncMarkdownProps> = ({
376386
return (
377387
<>
378388
<iframe
389+
title="Markdown content preview"
379390
sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin"
380391
srcDoc={contents}
381392
style={{ border: '0px', display: 'block', width: '100%', height: '0' }}

packages/module/src/ConsoleShared/src/components/markdown-extensions/__tests__/accordion-extension.spec.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,34 +34,36 @@ describe('useAccordionShowdownExtension', () => {
3434
it('should match accordion syntax with HTML-encoded quotes', () => {
3535
const { result } = renderHook(() => useAccordionShowdownExtension());
3636
const { regex } = result.current;
37-
37+
3838
const testText = '[Some content]{{accordion &quot;My Title&quot;}}';
3939
const matches = regex.exec(testText);
40-
40+
4141
expect(matches).not.toBeNull();
42-
expect(matches![1]).toBe('Some content');
43-
expect(matches![2]).toBe('accordion');
44-
expect(matches![4]).toBe('My Title');
42+
if (matches) {
43+
expect(matches[1]).toBe('Some content');
44+
expect(matches[2]).toBe('accordion');
45+
expect(matches[4]).toBe('My Title');
46+
}
4547
});
4648

4749
it('should not match accordion syntax with regular quotes', () => {
4850
const { result } = renderHook(() => useAccordionShowdownExtension());
4951
const { regex } = result.current;
50-
52+
5153
const testText = '[Some content]{{accordion "My Title"}}';
5254
expect(testText.match(regex)).toBeNull();
5355
});
5456

5557
it('should generate correct accordion HTML structure', () => {
5658
const { result } = renderHook(() => useAccordionShowdownExtension());
5759
const { replace } = result.current;
58-
60+
5961
const html = replace(
6062
'[Test content]{{accordion &quot;Test Title&quot;}}',
6163
'Test content',
6264
'accordion',
6365
'&quot;Test Title&quot;',
64-
'Test Title'
66+
'Test Title',
6567
);
6668

6769
expect(html).toContain('pf-v6-c-accordion');
@@ -74,13 +76,13 @@ describe('useAccordionShowdownExtension', () => {
7476
it('should process content through marked and sanitize HTML', () => {
7577
const { result } = renderHook(() => useAccordionShowdownExtension());
7678
const { replace } = result.current;
77-
79+
7880
replace(
7981
'[**Bold text**]{{accordion &quot;Title&quot;}}',
8082
'**Bold text**',
8183
'accordion',
8284
'&quot;Title&quot;',
83-
'Title'
85+
'Title',
8486
);
8587

8688
expect(marked.parseInline).toHaveBeenCalledWith('**Bold text**');
@@ -89,15 +91,15 @@ describe('useAccordionShowdownExtension', () => {
8991
it('should handle titles with spaces in IDs', () => {
9092
const { result } = renderHook(() => useAccordionShowdownExtension());
9193
const { replace } = result.current;
92-
94+
9395
const html = replace(
9496
'[Content]{{accordion &quot;My Test Title&quot;}}',
9597
'Content',
9698
'accordion',
9799
'&quot;My Test Title&quot;',
98-
'My Test Title'
100+
'My Test Title',
99101
);
100102

101103
expect(html).toContain(`${ACCORDION_MARKDOWN_BUTTON_ID}-My-Test-Title`);
102104
});
103-
});
105+
});

packages/module/src/ConsoleShared/src/components/markdown-extensions/__tests__/admonition-extension.spec.tsx

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -31,48 +31,45 @@ describe('useAdmonitionShowdownExtension', () => {
3131
it('should match different admonition types', () => {
3232
const { result } = renderHook(() => useAdmonitionShowdownExtension());
3333
const { regex } = result.current;
34-
34+
3535
const admonitionTypes = ['note', 'tip', 'important', 'warning', 'caution', 'custom-type'];
36-
37-
admonitionTypes.forEach(type => {
36+
37+
admonitionTypes.forEach((type) => {
3838
const testText = `[Content for ${type}]{{admonition ${type}}}`;
3939
// Reset regex state for global flag
4040
regex.lastIndex = 0;
4141
const matches = regex.exec(testText);
42-
42+
4343
expect(matches).not.toBeNull();
44-
expect(matches![1]).toBe(`Content for ${type}`);
45-
expect(matches![2]).toBe('admonition');
46-
expect(matches![3]).toBe(type);
44+
if (matches) {
45+
expect(matches[1]).toBe(`Content for ${type}`);
46+
expect(matches[2]).toBe('admonition');
47+
expect(matches[3]).toBe(type);
48+
}
4749
});
4850
});
4951

5052
it('should not match malformed admonition syntax', () => {
5153
const { result } = renderHook(() => useAdmonitionShowdownExtension());
5254
const { regex } = result.current;
53-
55+
5456
const malformedCases = [
5557
'Content]{{admonition note}}',
5658
'[Content{{admonition note}}',
5759
'[Content]{{admonition}}',
5860
'[Content]{{notadmonition note}}',
5961
];
6062

61-
malformedCases.forEach(testCase => {
63+
malformedCases.forEach((testCase) => {
6264
expect(testCase.match(regex)).toBeNull();
6365
});
6466
});
6567

6668
it('should generate correct alert HTML structure', () => {
6769
const { result } = renderHook(() => useAdmonitionShowdownExtension());
6870
const { replace } = result.current;
69-
70-
const html = replace(
71-
'[Test message]{{admonition note}}',
72-
'Test message',
73-
'admonition',
74-
'note'
75-
);
71+
72+
const html = replace('[Test message]{{admonition note}}', 'Test message', 'admonition', 'note');
7673

7774
expect(html).toContain('pf-v6-c-alert');
7875
expect(html).toContain('pf-m-info'); // note maps to info variant
@@ -84,20 +81,15 @@ describe('useAdmonitionShowdownExtension', () => {
8481
it('should handle different admonition types with correct variants', () => {
8582
const { result } = renderHook(() => useAdmonitionShowdownExtension());
8683
const { replace } = result.current;
87-
84+
8885
const testCases = [
8986
{ type: 'note', expectedClass: 'pf-m-info' },
9087
{ type: 'warning', expectedClass: 'pf-m-warning' },
9188
{ type: 'important', expectedClass: 'pf-m-danger' },
9289
];
9390

9491
testCases.forEach(({ type, expectedClass }) => {
95-
const html = replace(
96-
`[Content]{{admonition ${type}}}`,
97-
'Content',
98-
'admonition',
99-
type
100-
);
92+
const html = replace(`[Content]{{admonition ${type}}}`, 'Content', 'admonition', type);
10193

10294
expect(html).toContain(expectedClass);
10395
expect(html).toContain(type.toUpperCase());
@@ -107,28 +99,23 @@ describe('useAdmonitionShowdownExtension', () => {
10799
it('should process content through marked', () => {
108100
const { result } = renderHook(() => useAdmonitionShowdownExtension());
109101
const { replace } = result.current;
110-
111-
replace(
112-
'[**Bold text**]{{admonition note}}',
113-
'**Bold text**',
114-
'admonition',
115-
'note'
116-
);
102+
103+
replace('[**Bold text**]{{admonition note}}', '**Bold text**', 'admonition', 'note');
117104

118105
expect(marked.parseInline).toHaveBeenCalledWith('**Bold text**');
119106
});
120107

121108
it('should return original text for invalid cases', () => {
122109
const { result } = renderHook(() => useAdmonitionShowdownExtension());
123110
const { replace } = result.current;
124-
111+
125112
// Missing content
126113
const originalText = '[Content]{{admonition note}}';
127114
const result1 = replace(originalText, '', 'admonition', 'note');
128115
expect(result1).toBe(originalText);
129-
116+
130117
// Wrong command
131118
const result2 = replace(originalText, 'Content', 'not-admonition', 'note');
132119
expect(result2).toBe(originalText);
133120
});
134-
});
121+
});

packages/module/src/ConsoleShared/src/components/markdown-extensions/accordion-extension.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ const useAccordionShowdownExtension = () =>
2424
_command: string,
2525
_quotedHeading: string,
2626
accordionHeading: string,
27-
): string => {
28-
const accordionId = String(accordionHeading).replace(/\s/g, '-');
29-
27+
): string => {
28+
const accordionId = String(accordionHeading).replace(/\s/g, '-');
29+
3030
// Process accordion content with markdown
3131
const processedContent = marked.parseInline(accordionContent);
3232
const sanitizedContent = DOMPurify.sanitize(processedContent);
@@ -35,19 +35,14 @@ const useAccordionShowdownExtension = () =>
3535
renderToStaticMarkup(
3636
<Accordion>
3737
<AccordionItem>
38-
<AccordionToggle
39-
id={`${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}`}
40-
>
38+
<AccordionToggle id={`${ACCORDION_MARKDOWN_BUTTON_ID}-${accordionId}`}>
4139
{accordionHeading}
4240
</AccordionToggle>
43-
<AccordionContent
44-
id={`${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`}
45-
hidden
46-
>
41+
<AccordionContent id={`${ACCORDION_MARKDOWN_CONTENT_ID}-${accordionId}`} hidden>
4742
<div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
4843
</AccordionContent>
4944
</AccordionItem>
50-
</Accordion>
45+
</Accordion>,
5146
),
5247
);
5348
},

0 commit comments

Comments
 (0)