diff --git a/packages/plugins/src/components/searchers.tsx b/packages/plugins/src/components/searchers.tsx new file mode 100644 index 0000000..32213d1 --- /dev/null +++ b/packages/plugins/src/components/searchers.tsx @@ -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 ? ( + <> + Previous | + + ) : ( + <> + )} + Next + + ); +} + +export function ResultItem({ + url, + title, + content, +}: { + url: string; + title: string; + content: string; +}) { + return ( + <> + {title} +

{content}

+ + ); +} diff --git a/packages/plugins/src/engines/habr.tsx b/packages/plugins/src/engines/habr.tsx deleted file mode 100644 index 1d79441..0000000 --- a/packages/plugins/src/engines/habr.tsx +++ /dev/null @@ -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:
Test
, - }; -}); - -export default Habr; diff --git a/packages/plugins/src/engines/index.ts b/packages/plugins/src/engines/index.ts index ab279b6..b5f8527 100644 --- a/packages/plugins/src/engines/index.ts +++ b/packages/plugins/src/engines/index.ts @@ -1,6 +1,5 @@ import StackOverflow from './stackoverflow'; import Readability from './readability'; import SearX from './searx'; -import Habr from './habr'; -export { StackOverflow, Readability, SearX, Habr }; +export { StackOverflow, Readability, SearX }; diff --git a/packages/plugins/src/engines/searx.ts b/packages/plugins/src/engines/searx.tsx similarity index 68% rename from packages/plugins/src/engines/searx.ts rename to packages/plugins/src/engines/searx.tsx index c947a1c..6b195df 100644 --- a/packages/plugins/src/engines/searx.ts +++ b/packages/plugins/src/engines/searx.tsx @@ -1,6 +1,7 @@ -import { Engine } from '@txtdot/sdk'; +import { Engine, JSX } from '@txtdot/sdk'; import { HandlerInput, Route } from '@txtdot/sdk'; import { parseHTML } from 'linkedom'; +import { PageFooter, ResultItem } from '../components/searchers'; const SearX = new Engine('SearX', "Engine for searching with 'SearXNG'", [ 'searx.*', @@ -14,13 +15,19 @@ async function search( const search = ro.q.search; const page = parseInt(ro.q.pageno || '1'); - const page_footer = `${ - page !== 1 - ? `Previous |` - : '' - } Next`; + let previous: string | false; + let next: string | false; + + if (ro.q.pageno) { + 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_parsed = articles.map((a) => { const parsed = { url: @@ -35,21 +42,24 @@ async function search( }; return { - html: `${parsed.title}

${parsed.content}


`, + html: , text: `${parsed.title} (${parsed.url})\n${parsed.content}\n---\n\n`, }; }); - const content = `${articles_parsed - .map((a) => a.html) - .join('')}${page_footer}`; + const content = ( + <> + {articles_parsed.map((a) => a.html).join('')} + + + ); + const textContent = articles_parsed.map((a) => a.text).join(''); return { content: content, textContent, title: `${search} - Searx - Page ${page}`, - lang: document.documentElement.lang, }; } diff --git a/packages/sdk/src/jsx.ts b/packages/sdk/src/jsx.ts index bc85416..20b0285 100644 --- a/packages/sdk/src/jsx.ts +++ b/packages/sdk/src/jsx.ts @@ -8,17 +8,25 @@ export namespace JSX { } export function createElement( - name: string, - props: { [id: string]: string }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + name: any, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + props: { [id: string]: any }, ...content: string[] ) { - props = props || {}; - const propsstr = Object.keys(props) - .map((key) => { - const value = props[key]; - if (key === 'className') return `class=${value}`; - else return `${key}=${value}`; - }) - .join(' '); - return `<${name} ${propsstr}>${content.join('')}`; + if (typeof name === 'string') { + props = props || {}; + const propsstr = Object.keys(props) + .map((key) => { + const value = props[key]; + if (key === 'className') return `class=${value}`; + else return `${key}=${value}`; + }) + .join(' '); + return `<${name} ${propsstr}>${content.join('')}`; + } else if (typeof name === 'function') { + return name(props, ...content); + } else { + return content.join(''); + } } diff --git a/packages/sdk/src/types/handler.ts b/packages/sdk/src/types/handler.ts index cf14a03..30b2eb0 100644 --- a/packages/sdk/src/types/handler.ts +++ b/packages/sdk/src/types/handler.ts @@ -28,8 +28,8 @@ export class HandlerInput { export interface HandlerOutput { content: string; textContent: string; - title?: string; - lang?: string; + title: string; + lang: string; } export interface EngineOutput { diff --git a/packages/server/src/distributor.ts b/packages/server/src/distributor.ts index 3fbd9c1..1709743 100644 --- a/packages/server/src/distributor.ts +++ b/packages/server/src/distributor.ts @@ -73,14 +73,14 @@ export class Distributor { ); const purify = DOMPurify(dom); - const content = purify.sanitize(output.content); + const content = purify.sanitize(dom.document.toString()); return { content, textContent: output.textContent || dom.document.documentElement.textContent || '', - title: output.title, - lang: output.lang, + title: output.title || dom.document.title, + lang: output.lang || dom.document.documentElement.lang, }; }