mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-17 23:05:20 +00:00
71 lines
1.5 KiB
TypeScript
71 lines
1.5 KiB
TypeScript
|
|
// Helper function to find matching closing tag
|
||
|
|
function findMatchingClosingTag(src, openTag, closeTag) {
|
||
|
|
let depth = 1;
|
||
|
|
let index = openTag.length;
|
||
|
|
while (depth > 0 && index < src.length) {
|
||
|
|
if (src.startsWith(openTag, index)) {
|
||
|
|
depth++;
|
||
|
|
} else if (src.startsWith(closeTag, index)) {
|
||
|
|
depth--;
|
||
|
|
}
|
||
|
|
if (depth > 0) {
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return depth === 0 ? index + closeTag.length : -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
function detailsTokenizer(src) {
|
||
|
|
const detailsRegex = /^<details>\n/;
|
||
|
|
const summaryRegex = /^<summary>(.*?)<\/summary>\n/;
|
||
|
|
|
||
|
|
if (detailsRegex.test(src)) {
|
||
|
|
const endIndex = findMatchingClosingTag(src, '<details>', '</details>');
|
||
|
|
if (endIndex === -1) return;
|
||
|
|
|
||
|
|
const fullMatch = src.slice(0, endIndex);
|
||
|
|
let content = fullMatch.slice(10, -10).trim(); // Remove <details> and </details>
|
||
|
|
|
||
|
|
let summary = '';
|
||
|
|
const summaryMatch = summaryRegex.exec(content);
|
||
|
|
if (summaryMatch) {
|
||
|
|
summary = summaryMatch[1].trim();
|
||
|
|
content = content.slice(summaryMatch[0].length).trim();
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
type: 'details',
|
||
|
|
raw: fullMatch,
|
||
|
|
summary: summary,
|
||
|
|
text: content
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function detailsStart(src) {
|
||
|
|
return src.match(/^<details>/) ? 0 : -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
function detailsRenderer(token) {
|
||
|
|
return `<details>
|
||
|
|
${token.summary ? `<summary>${token.summary}</summary>` : ''}
|
||
|
|
${token.text}
|
||
|
|
</details>`;
|
||
|
|
}
|
||
|
|
|
||
|
|
function detailsExtension() {
|
||
|
|
return {
|
||
|
|
name: 'details',
|
||
|
|
level: 'block',
|
||
|
|
start: detailsStart,
|
||
|
|
tokenizer: detailsTokenizer,
|
||
|
|
renderer: detailsRenderer
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export default function (options = {}) {
|
||
|
|
return {
|
||
|
|
extensions: [detailsExtension(options)]
|
||
|
|
};
|
||
|
|
}
|