mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-26 01:46:26 +00:00
Markdown editor fix (#19732)
* fix block editor escaping html elements * add unit tests
This commit is contained in:
parent
fcbe9241bc
commit
442b58b0e7
@ -14,6 +14,7 @@ import {
|
|||||||
formatValueBasedOnContent,
|
formatValueBasedOnContent,
|
||||||
getHtmlStringFromMarkdownString,
|
getHtmlStringFromMarkdownString,
|
||||||
getTextFromHtmlString,
|
getTextFromHtmlString,
|
||||||
|
isHTMLString,
|
||||||
} from './BlockEditorUtils';
|
} from './BlockEditorUtils';
|
||||||
|
|
||||||
describe('getTextFromHtmlString', () => {
|
describe('getTextFromHtmlString', () => {
|
||||||
@ -132,3 +133,59 @@ describe('formatValueBasedOnContent', () => {
|
|||||||
expect(formatValueBasedOnContent(input)).toBe('');
|
expect(formatValueBasedOnContent(input)).toBe('');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('isHTMLString', () => {
|
||||||
|
it('should return true for simple HTML content', () => {
|
||||||
|
const htmlContent = '<p>This is a paragraph</p>';
|
||||||
|
|
||||||
|
expect(isHTMLString(htmlContent)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for complex HTML content', () => {
|
||||||
|
const htmlContent = `
|
||||||
|
<div class="container">
|
||||||
|
<h1>Title</h1>
|
||||||
|
<p>This is a <strong>bold</strong> paragraph with <a href="#">link</a></p>
|
||||||
|
<ul>
|
||||||
|
<li>Item 1</li>
|
||||||
|
<li>Item 2</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
expect(isHTMLString(htmlContent)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for markdown content', () => {
|
||||||
|
const markdownContent = `
|
||||||
|
***
|
||||||
|
### Data Sharing Policies
|
||||||
|
If there is any question or concern regarding the data sharing policies,
|
||||||
|
please contact the support team <test@test.com>.
|
||||||
|
***
|
||||||
|
`;
|
||||||
|
|
||||||
|
expect(isHTMLString(markdownContent)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for plain text', () => {
|
||||||
|
const plainText = 'This is just plain text without any formatting';
|
||||||
|
|
||||||
|
expect(isHTMLString(plainText)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for empty string', () => {
|
||||||
|
expect(isHTMLString('')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false when content has both HTML and markdown', () => {
|
||||||
|
const mixedContent = `
|
||||||
|
<div>
|
||||||
|
# Markdown Header
|
||||||
|
* List item
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
expect(isHTMLString(mixedContent)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -122,12 +122,40 @@ export const formatValueBasedOnContent = (value: string) =>
|
|||||||
value === '<p></p>' ? '' : value;
|
value === '<p></p>' ? '' : value;
|
||||||
|
|
||||||
export const isHTMLString = (content: string) => {
|
export const isHTMLString = (content: string) => {
|
||||||
|
// Quick check for common HTML tags
|
||||||
|
const commonHtmlTags =
|
||||||
|
/<(p|div|span|a|ul|ol|li|h[1-6]|br|strong|em|code|pre)[>\s]/i;
|
||||||
|
|
||||||
|
// If content doesn't have any HTML-like structure, return false early
|
||||||
|
if (!commonHtmlTags.test(content)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const parser = new DOMParser();
|
const parser = new DOMParser();
|
||||||
const parsedDocument = parser.parseFromString(content, 'text/html');
|
const parsedDocument = parser.parseFromString(content, 'text/html');
|
||||||
|
|
||||||
// since text can be also counted as child node so we will check if length is greater than 1
|
// Check if there are any actual HTML elements (not just text nodes)
|
||||||
return parsedDocument.body.childNodes.length > 1;
|
const hasHtmlElements = Array.from(parsedDocument.body.childNodes).some(
|
||||||
|
(node) => node.nodeType === Node.ELEMENT_NODE
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the content has markdown-specific patterns
|
||||||
|
const markdownPatterns = [
|
||||||
|
/^#{1,6}\s/, // Headers
|
||||||
|
/^\s*[-*+]\s/, // Lists
|
||||||
|
/^\s*\d+\.\s/, // Numbered lists
|
||||||
|
/^\s*>{1,}\s/, // Blockquotes
|
||||||
|
/^---|\*\*\*|___/, // Horizontal rules
|
||||||
|
/`{1,3}[^`]+`{1,3}/, // Code blocks
|
||||||
|
];
|
||||||
|
|
||||||
|
const hasMarkdownSyntax = markdownPatterns.some((pattern) =>
|
||||||
|
pattern.test(content)
|
||||||
|
);
|
||||||
|
|
||||||
|
// If it has markdown syntax but also parsed as HTML, prefer markdown interpretation
|
||||||
|
return hasHtmlElements && !hasMarkdownSyntax;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user