|
@@ -26,44 +26,51 @@ function escapeRegExp(string: string): string {
|
|
|
}
|
|
|
|
|
|
export const replaceTokens = (content, sourceIds, char, user) => {
|
|
|
- const charToken = /{{char}}/gi;
|
|
|
- const userToken = /{{user}}/gi;
|
|
|
- const videoIdToken = /{{VIDEO_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the video ID
|
|
|
- const htmlIdToken = /{{HTML_FILE_ID_([a-f0-9-]+)}}/gi; // Regex to capture the HTML ID
|
|
|
-
|
|
|
- // Replace {{char}} if char is provided
|
|
|
- if (char !== undefined && char !== null) {
|
|
|
- content = content.replace(charToken, char);
|
|
|
- }
|
|
|
+ const tokens = [
|
|
|
+ { regex: /{{char}}/gi, replacement: char },
|
|
|
+ { regex: /{{user}}/gi, replacement: user },
|
|
|
+ {
|
|
|
+ regex: /{{VIDEO_FILE_ID_([a-f0-9-]+)}}/gi,
|
|
|
+ replacement: (_, fileId) =>
|
|
|
+ `<video src="${WEBUI_BASE_URL}/api/v1/files/${fileId}/content" controls></video>`
|
|
|
+ },
|
|
|
+ {
|
|
|
+ regex: /{{HTML_FILE_ID_([a-f0-9-]+)}}/gi,
|
|
|
+ replacement: (_, fileId) =>
|
|
|
+ `<iframe src="${WEBUI_BASE_URL}/api/v1/files/${fileId}/content/html" width="100%" frameborder="0" onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"></iframe>`
|
|
|
+ }
|
|
|
+ ];
|
|
|
+
|
|
|
+ // Replace tokens outside code blocks only
|
|
|
+ const processOutsideCodeBlocks = (text, replacementFn) => {
|
|
|
+ return text
|
|
|
+ .split(/(```[\s\S]*?```|`[\s\S]*?`)/)
|
|
|
+ .map((segment) => {
|
|
|
+ return segment.startsWith('```') || segment.startsWith('`')
|
|
|
+ ? segment
|
|
|
+ : replacementFn(segment);
|
|
|
+ })
|
|
|
+ .join('');
|
|
|
+ };
|
|
|
|
|
|
- // Replace {{user}} if user is provided
|
|
|
- if (user !== undefined && user !== null) {
|
|
|
- content = content.replace(userToken, user);
|
|
|
- }
|
|
|
+ // Apply replacements
|
|
|
+ content = processOutsideCodeBlocks(content, (segment) => {
|
|
|
+ tokens.forEach(({ regex, replacement }) => {
|
|
|
+ if (replacement !== undefined && replacement !== null) {
|
|
|
+ segment = segment.replace(regex, replacement);
|
|
|
+ }
|
|
|
+ });
|
|
|
|
|
|
- // Replace video ID tags with corresponding <video> elements
|
|
|
- content = content.replace(videoIdToken, (match, fileId) => {
|
|
|
- const videoUrl = `${WEBUI_BASE_URL}/api/v1/files/${fileId}/content`;
|
|
|
- return `<video src="${videoUrl}" controls></video>`;
|
|
|
- });
|
|
|
+ if (Array.isArray(sourceIds)) {
|
|
|
+ sourceIds.forEach((sourceId, idx) => {
|
|
|
+ const regex = new RegExp(`\\[${idx}\\]`, 'g');
|
|
|
+ segment = segment.replace(regex, `<source_id data="${idx}" title="${sourceId}" />`);
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- // Replace HTML ID tags with corresponding HTML content
|
|
|
- content = content.replace(htmlIdToken, (match, fileId) => {
|
|
|
- const htmlUrl = `${WEBUI_BASE_URL}/api/v1/files/${fileId}/content/html`;
|
|
|
- return `<iframe src="${htmlUrl}" width="100%" frameborder="0" onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"></iframe>`;
|
|
|
+ return segment;
|
|
|
});
|
|
|
|
|
|
- // Remove sourceIds from the content and replace them with <source_id>...</source_id>
|
|
|
- if (Array.isArray(sourceIds)) {
|
|
|
- sourceIds.forEach((sourceId, idx) => {
|
|
|
- // Create a token based on the exact `[sourceId]` string
|
|
|
- const sourceToken = `\\[${idx}\\]`; // Escape special characters for RegExp
|
|
|
- const sourceRegex = new RegExp(sourceToken, 'g'); // Match all occurrences of [sourceId]
|
|
|
-
|
|
|
- content = content.replace(sourceRegex, `<source_id data="${idx}" title="${sourceId}" />`);
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
return content;
|
|
|
};
|
|
|
|