refactor(plugins): searx rewrite to jsx

and fix pageno problem
This commit is contained in:
Artemy 2024-05-13 17:59:31 +03:00
parent 3cee45b591
commit c2e6475624
7 changed files with 87 additions and 42 deletions

View File

@ -0,0 +1,41 @@
import { JSX } from '@txtdot/sdk';
export function PageFooter({
page,
previous,
next,
}: {
page: number;
previous: string | false;
next: string | false;
}) {
return (
<>
{page !== 1 ? (
<>
<a href={previous}>Previous </a> |
</>
) : (
<></>
)}
<a href={next}> Next</a>
</>
);
}
export function ResultItem({
url,
title,
content,
}: {
url: string;
title: string;
content: string;
}) {
return (
<>
<a href={url}>{title}</a>
<p>{content}</p>
</>
);
}

View File

@ -1,13 +0,0 @@
import { Engine } from '@txtdot/sdk';
import { JSX } from '@txtdot/sdk';
const Habr = new Engine('Habr', 'Habr parser', ['*']);
Habr.route('*path', async (input, ro) => {
return {
content: <div>Test</div>,
};
});
export default Habr;

View File

@ -1,6 +1,5 @@
import StackOverflow from './stackoverflow'; import StackOverflow from './stackoverflow';
import Readability from './readability'; import Readability from './readability';
import SearX from './searx'; import SearX from './searx';
import Habr from './habr';
export { StackOverflow, Readability, SearX, Habr }; export { StackOverflow, Readability, SearX };

View File

@ -1,6 +1,7 @@
import { Engine } from '@txtdot/sdk'; import { Engine, JSX } from '@txtdot/sdk';
import { HandlerInput, Route } from '@txtdot/sdk'; import { HandlerInput, Route } from '@txtdot/sdk';
import { parseHTML } from 'linkedom'; import { parseHTML } from 'linkedom';
import { PageFooter, ResultItem } from '../components/searchers';
const SearX = new Engine('SearX', "Engine for searching with 'SearXNG'", [ const SearX = new Engine('SearX', "Engine for searching with 'SearXNG'", [
'searx.*', 'searx.*',
@ -14,13 +15,19 @@ async function search(
const search = ro.q.search; const search = ro.q.search;
const page = parseInt(ro.q.pageno || '1'); const page = parseInt(ro.q.pageno || '1');
const page_footer = `${ let previous: string | false;
page !== 1 let next: string | false;
? `<a href="${ro.reverse({ search, pageno: page - 1 })}">Previous </a>|`
: '' if (ro.q.pageno) {
}<a href="${ro.reverse({ search, pageno: page + 1 })}"> Next</a>`; previous = ro.reverse({ search, pageno: page - 1 });
next = ro.reverse({ search, pageno: page + 1 });
} else {
previous = false;
next = `/search?q=${search}&pageno=${page + 1}`;
}
const articles = Array.from(document.querySelectorAll('.result')); const articles = Array.from(document.querySelectorAll('.result'));
const articles_parsed = articles.map((a) => { const articles_parsed = articles.map((a) => {
const parsed = { const parsed = {
url: url:
@ -35,21 +42,24 @@ async function search(
}; };
return { return {
html: `<a href="${parsed.url}">${parsed.title}</a><p>${parsed.content}</p><hr>`, html: <ResultItem {...parsed} />,
text: `${parsed.title} (${parsed.url})\n${parsed.content}\n---\n\n`, text: `${parsed.title} (${parsed.url})\n${parsed.content}\n---\n\n`,
}; };
}); });
const content = `${articles_parsed const content = (
.map((a) => a.html) <>
.join('')}${page_footer}`; {articles_parsed.map((a) => a.html).join('')}
<PageFooter page={page} previous={previous} next={next} />
</>
);
const textContent = articles_parsed.map((a) => a.text).join(''); const textContent = articles_parsed.map((a) => a.text).join('');
return { return {
content: content, content: content,
textContent, textContent,
title: `${search} - Searx - Page ${page}`, title: `${search} - Searx - Page ${page}`,
lang: document.documentElement.lang,
}; };
} }

View File

@ -8,17 +8,25 @@ export namespace JSX {
} }
export function createElement( export function createElement(
name: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any
props: { [id: string]: string }, name: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
props: { [id: string]: any },
...content: string[] ...content: string[]
) { ) {
props = props || {}; if (typeof name === 'string') {
const propsstr = Object.keys(props) props = props || {};
.map((key) => { const propsstr = Object.keys(props)
const value = props[key]; .map((key) => {
if (key === 'className') return `class=${value}`; const value = props[key];
else return `${key}=${value}`; if (key === 'className') return `class=${value}`;
}) else return `${key}=${value}`;
.join(' '); })
return `<${name} ${propsstr}>${content.join('')}</${name}>`; .join(' ');
return `<${name} ${propsstr}>${content.join('')}</${name}>`;
} else if (typeof name === 'function') {
return name(props, ...content);
} else {
return content.join('');
}
} }

View File

@ -28,8 +28,8 @@ export class HandlerInput {
export interface HandlerOutput { export interface HandlerOutput {
content: string; content: string;
textContent: string; textContent: string;
title?: string; title: string;
lang?: string; lang: string;
} }
export interface EngineOutput { export interface EngineOutput {

View File

@ -73,14 +73,14 @@ export class Distributor {
); );
const purify = DOMPurify(dom); const purify = DOMPurify(dom);
const content = purify.sanitize(output.content); const content = purify.sanitize(dom.document.toString());
return { return {
content, content,
textContent: textContent:
output.textContent || dom.document.documentElement.textContent || '', output.textContent || dom.document.documentElement.textContent || '',
title: output.title, title: output.title || dom.document.title,
lang: output.lang, lang: output.lang || dom.document.documentElement.lang,
}; };
} }