diff --git a/searching-front/app/core/components/WebsiteCard/WebsiteCard.tsx b/searching-front/app/core/components/WebsiteCard/WebsiteCard.tsx
index 0552bff..9c818c1 100644
--- a/searching-front/app/core/components/WebsiteCard/WebsiteCard.tsx
+++ b/searching-front/app/core/components/WebsiteCard/WebsiteCard.tsx
@@ -1,18 +1,33 @@
import { cleanUrlForUi } from "app/core/helpers/common"
+import { useEffect, useState } from "react"
import s from "./styles.module.css"
interface Props {
url: string
title: string
description: string
+ faviconUrl?: string
}
const WebsiteCard = (props: Props) => {
+ const faviconUrl = props.faviconUrl;
+ const [faviconLoaded, setFaviconLoaded] = useState(false)
+ useEffect(() => {
+ if (faviconUrl) {
+ const faviconNode = document.createElement("img")
+ faviconNode.src = faviconUrl;
+ faviconNode.onload = () => {
+ setFaviconLoaded(true)
+ }
+ }
+ }, [faviconUrl])
const urlObj = new URL(props.url)
urlObj.searchParams.set("from", "Searching.ton")
- const url = urlObj.toString();
+ const url = urlObj.toString()
+
return (
+ {faviconLoaded &&
}
{props.title}
diff --git a/searching-front/app/core/components/WebsiteCard/styles.module.css b/searching-front/app/core/components/WebsiteCard/styles.module.css
index 75e3790..1467026 100644
--- a/searching-front/app/core/components/WebsiteCard/styles.module.css
+++ b/searching-front/app/core/components/WebsiteCard/styles.module.css
@@ -4,6 +4,7 @@
border-radius: 12px;
display: flex;
flex-direction: column;
+ position: relative;
}
.root:not(:last-of-type) {
@@ -34,3 +35,18 @@
.description {
font-size: 13px;
}
+
+.favicon {
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ position: absolute;
+ left: -24px;
+ top: 16px;
+}
+
+@media only screen and (max-width: 700px) {
+ .favicon {
+ left: -16px;
+ }
+}
diff --git a/searching-front/app/core/layouts/Layout/styles.module.css b/searching-front/app/core/layouts/Layout/styles.module.css
index 5d449ee..6093b93 100644
--- a/searching-front/app/core/layouts/Layout/styles.module.css
+++ b/searching-front/app/core/layouts/Layout/styles.module.css
@@ -8,7 +8,7 @@
margin-top: 20px;
display: flex;
flex-direction: column;
-
+ padding: 0 20px;
flex: 1;
/* margin: auto; */
}
diff --git a/searching-front/app/search-requests/queries/getSearchResult.ts b/searching-front/app/search-requests/queries/getSearchResult.ts
index bc72b86..e98726e 100644
--- a/searching-front/app/search-requests/queries/getSearchResult.ts
+++ b/searching-front/app/search-requests/queries/getSearchResult.ts
@@ -22,6 +22,7 @@ const processResult = ({ bodyText, ...res }: Object, search: string) => {
return {
...res,
description: res.description || bodyToDescription(bodyText, search),
+ faviconUrl: res.faviconUrl,
}
}
diff --git a/searching-front/services/modules/elastic/index.ts b/searching-front/services/modules/elastic/index.ts
index a2bda1d..9d1d8df 100644
--- a/searching-front/services/modules/elastic/index.ts
+++ b/searching-front/services/modules/elastic/index.ts
@@ -11,6 +11,7 @@ export interface ElasticIndexParams {
h1?: string
bodyText: string
description?: string
+ faviconUrl?: string
}
export interface ElasticSearchParams {
text: string
@@ -102,6 +103,7 @@ class Elastic {
public index = async (params: ElasticIndexParams) => {
const indexName = getIndexNameByText(params.title + params.bodyText)
+ console.log('index',params)
await this.client.index({
index: indexName,
id: params.url,
@@ -111,6 +113,7 @@ class Elastic {
h1: params.h1,
bodyText: params.bodyText,
description: params.description,
+ faviconUrl: params.faviconUrl,
},
})
}
diff --git a/searching-front/services/modules/parser/index.ts b/searching-front/services/modules/parser/index.ts
index 076ebea..2df9b0c 100644
--- a/searching-front/services/modules/parser/index.ts
+++ b/searching-front/services/modules/parser/index.ts
@@ -23,9 +23,29 @@ const isInvalidLink = (link: string) => {
return link.match(/\./) && !(link.match(/\.html/) || link.match(/\.htm/))
}
+const getFaviconUrl = (dom:JSDOM, domain:string) => {
+ try{
+ const node = dom.window.document.querySelector("[rel=icon][type*=image]") as HTMLLinkElement;;
+ const href = node?.href;
+ let url;
+ if(href){
+ try {
+ url = new URL(href);
+ } catch(e){
+ url = new URL(domain+href);
+ url.pathname = url.pathname.replace('//','/');
+ }
+ return url.toString();
+ }
+ } catch(e){
+ return undefined
+ }
+
+}
+
class Parser {
constructor() {}
- parseUrl = async (url: string) => {
+ parseUrl = async (url: string, domain:string) => {
try {
const { data, headers } = await axios.get(url,{
@@ -66,6 +86,7 @@ class Parser {
.querySelector("meta[name='description']")
?.getAttribute("content") || "",
url,
+ faviconUrl: getFaviconUrl(dom, domain)
},
subPages,
}
diff --git a/searching-front/services/parser.ts b/searching-front/services/parser.ts
index 1d1b724..85a18ab 100644
--- a/searching-front/services/parser.ts
+++ b/searching-front/services/parser.ts
@@ -15,8 +15,7 @@ const indexWebsite = async (domain: string, path: string, subpages: SubPages = {
const subpagesLength = Object.keys(subpages).length;
if (!subpages[path]) {
const url = domain + path;
- const parseInfo = await Parser.parseUrl(url)
- console.log(parseInfo)
+ const parseInfo = await Parser.parseUrl(url,domain);
subpages[path] = true
let pages = {}
if (parseInfo !== SHOULD_NOT_PARSE && subpagesLength < 50) {