diff --git a/extensions/react-widget/src/components/SearchBar.tsx b/extensions/react-widget/src/components/SearchBar.tsx
index e88bdafd1..42262e08c 100644
--- a/extensions/react-widget/src/components/SearchBar.tsx
+++ b/extensions/react-widget/src/components/SearchBar.tsx
@@ -1,12 +1,11 @@
import React from 'react'
-import styled, { keyframes, createGlobalStyle, ThemeProvider } from 'styled-components';
+import styled, { ThemeProvider } from 'styled-components';
import { WidgetCore } from './DocsGPTWidget';
import { SearchBarProps } from '@/types';
import { getSearchResults } from '../requests/searchAPI'
import { Result } from '@/types';
import MarkdownIt from 'markdown-it';
-import DOMPurify from 'dompurify';
-import { getOS } from '../utils/helper'
+import { getOS, preprocessSearchResultsToHTML } from '../utils/helper'
const themes = {
dark: {
bg: '#000',
@@ -116,7 +115,7 @@ const ResultWrapper = styled.div`
const Markdown = styled.div`
line-height:20px;
font-size: 12px;
-word-break: break-all;
+white-space: pre-wrap;
pre {
padding: 8px;
width: 90%;
@@ -147,17 +146,18 @@ word-break: break-all;
code:not(pre code) {
border-radius: 6px;
- padding: 4px 4px;
- font-size: 12px;
- display: inline-block;
+ padding: 2px 2px;
+ margin: 2px;
+ font-size: 10px;
+ display: inline;
background-color: #646464;
color: #fff ;
}
-
+ img{
+ max-width: 50%;
+ }
code {
- white-space: pre-wrap ;
- overflow-wrap: break-word;
- word-break: break-all;
+ overflow-x: auto;
}
a{
color: #007ee6;
@@ -291,6 +291,8 @@ export const SearchBar = ({
}, 500);
return () => {
+ console.log(results);
+
abortController.abort();
clearTimeout(debounceTimeout.current ?? undefined);
};
@@ -341,22 +343,27 @@ export const SearchBar = ({
(results.length > 0 ?
results.map((res, key) => {
const containsSource = res.source !== 'local';
- return (
- {
- if (!containsSource) return;
- window.open(res.source, '_blank', 'noopener, noreferrer')
- }}
- className={containsSource ? "contains-source" : ""}>
- {res.title}
-
-
-
-
- )
+ const filteredResults = preprocessSearchResultsToHTML(res.text,input)
+ if (filteredResults)
+ return (
+ {
+ if (!containsSource) return;
+ window.open(res.source, '_blank', 'noopener, noreferrer')
+ }}
+ className={containsSource ? "contains-source" : ""}>
+ {res.title}
+
+
+
+
+ )
+ else {
+ setResults((prevItems) => prevItems.filter((_, index) => index !== key));
+ }
})
:
No results
diff --git a/extensions/react-widget/src/utils/helper.ts b/extensions/react-widget/src/utils/helper.ts
index 39c720e21..d9aa19c34 100644
--- a/extensions/react-widget/src/utils/helper.ts
+++ b/extensions/react-widget/src/utils/helper.ts
@@ -1,27 +1,87 @@
+import MarkdownIt from "markdown-it";
+import DOMPurify from "dompurify";
export const getOS = () => {
- const platform = window.navigator.platform;
- const userAgent = window.navigator.userAgent || window.navigator.vendor;
-
- if (/Mac/i.test(platform)) {
- return 'mac';
+ const platform = window.navigator.platform;
+ const userAgent = window.navigator.userAgent || window.navigator.vendor;
+
+ if (/Mac/i.test(platform)) {
+ return 'mac';
+ }
+
+ if (/Win/i.test(platform)) {
+ return 'win';
+ }
+
+ if (/Linux/i.test(platform) && !/Android/i.test(userAgent)) {
+ return 'linux';
+ }
+
+ if (/Android/i.test(userAgent)) {
+ return 'android';
+ }
+
+ if (/iPhone|iPad|iPod/i.test(userAgent)) {
+ return 'ios';
+ }
+
+ return 'other';
+};
+
+export const preprocessSearchResultsToHTML = (text: string, keyword: string) => {
+ const md = new MarkdownIt();
+ const htmlString = md.render(text);
+
+ // Container for processed HTML
+ const filteredResults = document.createElement("div");
+ filteredResults.innerHTML = htmlString;
+
+ if (!processNode(filteredResults, keyword.trim())) return null;
+
+ return filteredResults.innerHTML.trim() ? filteredResults.outerHTML : null;
+};
+
+
+
+// Recursive function to process nodes
+const processNode = (node: Node, keyword: string): boolean => {
+
+ const keywordRegex = new RegExp(`(${keyword})`, "gi");
+ if (node.nodeType === Node.TEXT_NODE) {
+ const textContent = node.textContent || "";
+
+ if (textContent.toLowerCase().includes(keyword.toLowerCase())) {
+ const highlightedHTML = textContent.replace(
+ keywordRegex,
+ `$1`
+ );
+ const tempContainer = document.createElement("div");
+ tempContainer.innerHTML = highlightedHTML;
+
+ // Replace the text node with highlighted content
+ while (tempContainer.firstChild) {
+ node.parentNode?.insertBefore(tempContainer.firstChild, node);
+ }
+ node.parentNode?.removeChild(node);
+
+ return true;
}
-
- if (/Win/i.test(platform)) {
- return 'win';
- }
-
- if (/Linux/i.test(platform) && !/Android/i.test(userAgent)) {
- return 'linux';
- }
-
- if (/Android/i.test(userAgent)) {
- return 'android';
- }
-
- if (/iPhone|iPad|iPod/i.test(userAgent)) {
- return 'ios';
- }
-
- return 'other';
- };
-
\ No newline at end of file
+
+ return false;
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
+
+ const children = Array.from(node.childNodes);
+ let hasKeyword = false;
+
+ children.forEach((child) => {
+ if (!processNode(child, keyword)) {
+ node.removeChild(child);
+ } else {
+ hasKeyword = true;
+ }
+ });
+
+ return hasKeyword;
+ }
+
+ return false;
+};
\ No newline at end of file
diff --git a/extensions/react-widget/tsconfig.json b/extensions/react-widget/tsconfig.json
index e73dd80f2..88e86216c 100644
--- a/extensions/react-widget/tsconfig.json
+++ b/extensions/react-widget/tsconfig.json
@@ -21,7 +21,7 @@
/* Linting */
"strict": true,
"noUnusedLocals": false,
- "noUnusedParameters": true,
+ "noUnusedParameters": false,
"noFallthroughCasesInSwitch": true,
/* The "typeRoots" configuration specifies the locations where
TypeScript looks for type definitions (.d.ts files) to