69 lines
1.8 KiB
TypeScript
69 lines
1.8 KiB
TypeScript
import React from 'react';
|
|
|
|
interface ListingComponentProps {
|
|
text?: string;
|
|
}
|
|
|
|
const ListingComponent: React.FC<ListingComponentProps> = ({ text }) => {
|
|
if (!text) {
|
|
return null;
|
|
}
|
|
|
|
const lines = text.split('\n');
|
|
const elements: React.ReactNode[] = [];
|
|
let currentParagraph: string[] = [];
|
|
let currentList: React.ReactNode[] = [];
|
|
|
|
const flushParagraph = () => {
|
|
if (currentParagraph.length > 0) {
|
|
elements.push(<p key={elements.length}>{currentParagraph.join('\n')}</p>);
|
|
currentParagraph = [];
|
|
}
|
|
};
|
|
|
|
const flushList = () => {
|
|
if (currentList.length > 0) {
|
|
elements.push(<ul key={elements.length}>{currentList}</ul>);
|
|
currentList = [];
|
|
}
|
|
};
|
|
|
|
let currentListItemContent: string[] = [];
|
|
|
|
const flushListItem = () => {
|
|
if(currentListItemContent.length > 0) {
|
|
currentList.push(<li key={currentList.length}>{currentListItemContent.join('\n')}</li>);
|
|
currentListItemContent = [];
|
|
}
|
|
}
|
|
|
|
for (const line of lines) {
|
|
const trimmedLine = line.trim();
|
|
|
|
if (trimmedLine.startsWith('- ') || trimmedLine.startsWith('* ')) {
|
|
flushParagraph(); // End any ongoing paragraph
|
|
flushListItem(); // End previous list item
|
|
currentListItemContent.push(trimmedLine.substring(2));
|
|
} else if (trimmedLine === '') {
|
|
flushListItem();
|
|
flushList(); // An empty line ends the list
|
|
} else {
|
|
if (currentList.length > 0 || currentListItemContent.length > 0) {
|
|
// This line belongs to the current list item
|
|
currentListItemContent.push(line);
|
|
} else {
|
|
// This is a paragraph line
|
|
flushList();
|
|
currentParagraph.push(line);
|
|
}
|
|
}
|
|
}
|
|
|
|
flushListItem();
|
|
flushList();
|
|
flushParagraph();
|
|
|
|
return <>{elements}</>;
|
|
};
|
|
|
|
export default ListingComponent; |