Merge pull request #157 from TxtDot/dev
Add jsx support to engines plugins, fix text output
This commit is contained in:
commit
a9abfd0889
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 TxtDot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Artemy
|
||||
Copyright (c) 2024 TxtDot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@txtdot/plugins",
|
||||
"version": "1.1.1",
|
||||
"version": "2.0.0",
|
||||
"description": "Official txtdot plugins",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
@ -19,9 +19,12 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mozilla/readability": "^0.5.0",
|
||||
"@txtdot/sdk": "workspace:*"
|
||||
"@txtdot/sdk": "workspace:*",
|
||||
"html-to-text": "^9.0.5",
|
||||
"linkedom": "^0.18.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/html-to-text": "^9.0.4",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
|
35
packages/plugins/src/components/searchers.tsx
Normal file
35
packages/plugins/src/components/searchers.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { JSX } from '@txtdot/sdk';
|
||||
|
||||
export function PageFooter({
|
||||
page,
|
||||
previous,
|
||||
next,
|
||||
}: {
|
||||
page: number;
|
||||
previous: string | null;
|
||||
next: string | null;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
{page !== 1 ? <a href={previous}>Previous </a> : <></>}| {page} |
|
||||
<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>
|
||||
</>
|
||||
);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Readability as OReadability } from '@mozilla/readability';
|
||||
import { EngineParseError } from '@txtdot/sdk/dist/types/errors';
|
||||
|
||||
import { Engine } from '@txtdot/sdk';
|
||||
import { Engine, EngineParseError } from '@txtdot/sdk';
|
||||
import { parseHTML } from 'linkedom';
|
||||
|
||||
const Readability = new Engine(
|
||||
'Readability',
|
||||
@ -10,7 +10,7 @@ const Readability = new Engine(
|
||||
);
|
||||
|
||||
Readability.route('*path', async (input, ro) => {
|
||||
const reader = new OReadability(input.parseDom().window.document);
|
||||
const reader = new OReadability(input.document);
|
||||
const parsed = reader.parse();
|
||||
|
||||
if (!parsed) {
|
||||
@ -19,7 +19,6 @@ Readability.route('*path', async (input, ro) => {
|
||||
|
||||
return {
|
||||
content: parsed.content,
|
||||
textContent: parsed.textContent,
|
||||
title: parsed.title,
|
||||
lang: parsed.lang,
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { Engine } from '@txtdot/sdk';
|
||||
import { HandlerInput, Route } from '@txtdot/sdk/dist/types/handler';
|
||||
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.*',
|
||||
@ -9,17 +11,23 @@ async function search(
|
||||
input: HandlerInput,
|
||||
ro: Route<{ search: string; pageno?: string }>
|
||||
) {
|
||||
const document = input.parseDom().window.document;
|
||||
const document = input.document;
|
||||
const search = ro.q.search;
|
||||
const page = parseInt(ro.q.pageno || '1');
|
||||
|
||||
const page_footer = `${
|
||||
page !== 1
|
||||
? `<a href="${ro.reverse({ search, pageno: page - 1 })}">Previous </a>|`
|
||||
: ''
|
||||
}<a href="${ro.reverse({ search, pageno: page + 1 })}"> Next</a>`;
|
||||
let previous: string | null;
|
||||
let next: string | null;
|
||||
|
||||
if (ro.q.pageno) {
|
||||
previous = ro.reverse({ search, pageno: page - 1 }) || null;
|
||||
next = ro.reverse({ search, pageno: page + 1 }) || null;
|
||||
} else {
|
||||
previous = null;
|
||||
next = `/search?q=${search}&pageno=${page + 1}`;
|
||||
}
|
||||
|
||||
const articles = Array.from(document.querySelectorAll('.result'));
|
||||
|
||||
const articles_parsed = articles.map((a) => {
|
||||
const parsed = {
|
||||
url:
|
||||
@ -33,22 +41,18 @@ async function search(
|
||||
.textContent || '',
|
||||
};
|
||||
|
||||
return {
|
||||
html: `<a href="${parsed.url}">${parsed.title}</a><p>${parsed.content}</p><hr>`,
|
||||
text: `${parsed.title} (${parsed.url})\n${parsed.content}\n---\n\n`,
|
||||
};
|
||||
return <ResultItem {...parsed} />;
|
||||
});
|
||||
|
||||
const content = `${articles_parsed
|
||||
.map((a) => a.html)
|
||||
.join('')}${page_footer}`;
|
||||
const textContent = articles_parsed.map((a) => a.text).join('');
|
||||
|
||||
const content = (
|
||||
<>
|
||||
{articles_parsed}
|
||||
<PageFooter page={page} previous={previous} next={next} />
|
||||
</>
|
||||
);
|
||||
return {
|
||||
content,
|
||||
textContent,
|
||||
title: `${search} - Searx - Page ${page}`,
|
||||
lang: document.documentElement.lang,
|
||||
content: content,
|
||||
title: `"${(document.getElementById('q') as HTMLInputElement).value}" - Searx - Page ${page}`,
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { HandlerInput, Route } from '@txtdot/sdk/dist/types/handler';
|
||||
import { HandlerInput, Route } from '@txtdot/sdk';
|
||||
import { JSX } from '@txtdot/sdk';
|
||||
|
||||
async function questions(
|
||||
input: HandlerInput,
|
||||
ro: Route<{ id: string; slug: string }>
|
||||
) {
|
||||
const document = input.parseDom().window.document;
|
||||
const document = input.document;
|
||||
|
||||
const questionEl = document.getElementById('question');
|
||||
const question = postParser(questionEl);
|
||||
@ -15,12 +16,15 @@ async function questions(
|
||||
const answers = allAnswers.map((a) => postParser(a));
|
||||
|
||||
return {
|
||||
content: `${question}<hr>${answers.length} answers <hr>${answers.join(
|
||||
'<hr>'
|
||||
)}`,
|
||||
textContent: `${ro.q.id}/${ro.q.slug}\nText output not supported`, // TODO
|
||||
content: (
|
||||
<>
|
||||
{question}
|
||||
<hr />
|
||||
{answers.length} answers <hr />
|
||||
{answers.join(<hr />)}
|
||||
</>
|
||||
),
|
||||
title,
|
||||
lang: document.documentElement.lang,
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,12 +41,27 @@ function postParser(el: Element | null): string {
|
||||
(el.querySelector('.user-details a') as HTMLAnchorElement)?.href || '';
|
||||
const userTitle = el.querySelector('.user-action-time')?.textContent || '';
|
||||
|
||||
return `<h4>${userTitle}${
|
||||
userUrl ? ` by <a href="${userUrl}">${userName}</a>` : ''
|
||||
}</h4>`;
|
||||
return (
|
||||
<h4>
|
||||
{userTitle}
|
||||
{userUrl ? (
|
||||
<>
|
||||
by <a href={userUrl}>{userName}</a>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</h4>
|
||||
);
|
||||
});
|
||||
|
||||
return `<h3>${voteCount} votes</h3>${body}${footer.join('')}`;
|
||||
return (
|
||||
<>
|
||||
<h3>{voteCount} votes</h3>
|
||||
{body}
|
||||
{footer}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default questions;
|
@ -1,10 +1,11 @@
|
||||
import { HandlerInput, Route } from '@txtdot/sdk/dist/types/handler';
|
||||
import { HandlerInput, Route } from '@txtdot/sdk';
|
||||
import { JSX } from '@txtdot/sdk';
|
||||
|
||||
async function users(
|
||||
input: HandlerInput,
|
||||
ro: Route<{ id: string; slug: string }>
|
||||
) {
|
||||
const document = input.parseDom().window.document;
|
||||
const document = input.document;
|
||||
|
||||
const userInfo =
|
||||
document.querySelector('.md\\:ai-start > div:nth-child(2)')?.textContent ||
|
||||
@ -21,15 +22,27 @@ async function users(
|
||||
const type =
|
||||
el.querySelector('.iconAnswer, .iconQuestion')?.textContent || '';
|
||||
|
||||
return `<strong>${type} (${votes}) </strong><a href="${url}">${title}</a>`;
|
||||
return (
|
||||
<>
|
||||
<strong>
|
||||
{type} ({votes}){' '}
|
||||
</strong>
|
||||
<a href={url}>{title}</a>
|
||||
</>
|
||||
);
|
||||
})
|
||||
.join('<br/>');
|
||||
.join(<br />);
|
||||
|
||||
return {
|
||||
content: `${userInfo}<hr><h3>Top Posts</h3>${topPosts}`,
|
||||
textContent: `${ro.q.id}/${ro.q.slug}\n`, // TODO
|
||||
content: (
|
||||
<>
|
||||
{userInfo}
|
||||
<hr />
|
||||
<h3>Top Posts</h3>
|
||||
{topPosts}
|
||||
</>
|
||||
),
|
||||
title: document.querySelector('title')?.textContent || '',
|
||||
lang: document.documentElement.lang,
|
||||
};
|
||||
}
|
||||
|
@ -7,3 +7,12 @@ export const engineList = [
|
||||
engines.SearX,
|
||||
engines.Readability,
|
||||
];
|
||||
|
||||
import { compile } from 'html-to-text';
|
||||
|
||||
export const html2text = compile({
|
||||
longWordSplit: {
|
||||
forceWrapOnLimit: true,
|
||||
},
|
||||
selectors: [{ selector: 'img', format: 'skip' }],
|
||||
});
|
||||
|
@ -3,9 +3,9 @@
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
"incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
|
||||
// "composite": true /* Enable constraints that allow a TypeScript project to be used with project references. */,
|
||||
"tsBuildInfoFile": "./.tsbuildinfo" /* Specify the path to .tsbuildinfo incremental compilation file. */,
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
@ -13,13 +13,13 @@
|
||||
/* Language and Environment */
|
||||
"target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
"jsx": "react" /* Specify what JSX code is generated. */,
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
"reactNamespace": "JSX" /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */,
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Artemy
|
||||
Copyright (c) 2024 TxtDot
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@txtdot/sdk",
|
||||
"version": "1.1.1",
|
||||
"version": "2.0.0",
|
||||
"description": "SDK for creating plugins for TxtDot",
|
||||
"main": "dist/lib.js",
|
||||
"types": "dist/lib.d.ts",
|
||||
@ -18,7 +18,7 @@
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"linkedom": "^0.16.11",
|
||||
"linkedom": "^0.18.0",
|
||||
"route-parser": "^0.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -2,9 +2,9 @@ import Route from 'route-parser';
|
||||
|
||||
import {
|
||||
HandlerInput,
|
||||
IHandlerOutput,
|
||||
EngineFunction,
|
||||
RouteValues,
|
||||
EngineOutput,
|
||||
} from './types/handler';
|
||||
|
||||
import { NoHandlerFoundError } from './types/errors';
|
||||
@ -33,7 +33,7 @@ export class Engine {
|
||||
this.routes.push({ route: new Route<TParams>(path), handler });
|
||||
}
|
||||
|
||||
async handle(input: HandlerInput): Promise<IHandlerOutput> {
|
||||
async handle(input: HandlerInput): Promise<EngineOutput> {
|
||||
const url = new URL(input.getUrl());
|
||||
const path = url.pathname + url.search + url.hash;
|
||||
for (const route of this.routes) {
|
||||
|
35
packages/sdk/src/jsx.ts
Normal file
35
packages/sdk/src/jsx.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
export namespace JSX {
|
||||
export type Element = string;
|
||||
export interface IntrinsicElements {
|
||||
[elemName: string]: any;
|
||||
}
|
||||
}
|
||||
|
||||
export function createElement(
|
||||
name: any,
|
||||
props: { [id: string]: any },
|
||||
...inner: (string | string[])[]
|
||||
) {
|
||||
const content = inner.flat().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 inner.length === 0
|
||||
? `<${name} ${propsstr}/>`
|
||||
: `<${name} ${propsstr}>${content}</${name}>`;
|
||||
} else if (typeof name === 'function') {
|
||||
return name(props, content);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
}
|
@ -1,3 +1,38 @@
|
||||
import { Engine } from './engine';
|
||||
|
||||
export { Engine };
|
||||
import {
|
||||
EngineParseError,
|
||||
NoHandlerFoundError,
|
||||
TxtDotError,
|
||||
} from './types/errors';
|
||||
|
||||
import {
|
||||
EngineFunction,
|
||||
EngineMatch,
|
||||
Engines,
|
||||
RouteValues,
|
||||
EnginesMatch,
|
||||
HandlerInput,
|
||||
HandlerOutput,
|
||||
Route,
|
||||
handlerSchema,
|
||||
} from './types/handler';
|
||||
|
||||
import * as JSX from './jsx';
|
||||
|
||||
export {
|
||||
Engine,
|
||||
EngineParseError,
|
||||
NoHandlerFoundError,
|
||||
TxtDotError,
|
||||
EngineFunction,
|
||||
EngineMatch,
|
||||
Engines,
|
||||
RouteValues,
|
||||
EnginesMatch,
|
||||
HandlerInput,
|
||||
HandlerOutput,
|
||||
Route,
|
||||
handlerSchema,
|
||||
JSX,
|
||||
};
|
||||
|
@ -4,7 +4,7 @@ import { Engine } from '../engine';
|
||||
export class HandlerInput {
|
||||
private data: string;
|
||||
private url: string;
|
||||
private dom?: Window;
|
||||
private window?: Window;
|
||||
|
||||
constructor(data: string, url: string) {
|
||||
this.data = data;
|
||||
@ -15,19 +15,26 @@ export class HandlerInput {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
parseDom(): Window {
|
||||
if (this.dom) {
|
||||
return this.dom;
|
||||
get document(): Document {
|
||||
if (this.window) {
|
||||
return this.window.document;
|
||||
}
|
||||
|
||||
this.dom = parseHTML(this.data);
|
||||
return this.dom;
|
||||
this.window = parseHTML(this.data);
|
||||
return this.window.document;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IHandlerOutput {
|
||||
export interface HandlerOutput {
|
||||
content: string;
|
||||
textContent: string;
|
||||
title: string;
|
||||
lang: string;
|
||||
}
|
||||
|
||||
export interface EngineOutput {
|
||||
content: string;
|
||||
textContent?: string;
|
||||
title?: string;
|
||||
lang?: string;
|
||||
}
|
||||
@ -66,7 +73,7 @@ export interface RouteValues {
|
||||
export type EngineFunction<TParams extends RouteValues> = (
|
||||
input: HandlerInput,
|
||||
ro: Route<TParams>
|
||||
) => Promise<IHandlerOutput>;
|
||||
) => Promise<EngineOutput>;
|
||||
|
||||
export type EnginesMatch<TParams extends RouteValues> = EngineMatch<TParams>[];
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
"incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
|
||||
// "composite": true /* Enable constraints that allow a TypeScript project to be used with project references. */,
|
||||
"tsBuildInfoFile": "./.tsbuildinfo" /* Specify the path to .tsbuildinfo incremental compilation file. */,
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@txtdot/server",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"private": true,
|
||||
"description": "txtdot is an HTTP proxy that parses only text, links and pictures from pages reducing internet bandwidth usage, removing ads and heavy scripts",
|
||||
"main": "dist/app.js",
|
||||
@ -18,6 +18,7 @@
|
||||
"dev": "tsc-watch --onSuccess \"node ./dist/src/app.js\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/one-line-logger": "^1.3.0",
|
||||
"@fastify/static": "^7.0.3",
|
||||
"@fastify/swagger": "^8.14.0",
|
||||
"@fastify/swagger-ui": "^3.0.0",
|
||||
@ -32,7 +33,7 @@
|
||||
"iconv-lite": "^0.6.3",
|
||||
"ip-range-check": "^0.2.0",
|
||||
"json-schema-to-ts": "^3.0.1",
|
||||
"linkedom": "^0.16.11",
|
||||
"linkedom": "^0.18.0",
|
||||
"micromatch": "^4.0.5",
|
||||
"sharp": "^0.33.3"
|
||||
},
|
||||
|
@ -23,7 +23,11 @@ import config from './config';
|
||||
class App {
|
||||
async init() {
|
||||
const fastify = Fastify({
|
||||
logger: true,
|
||||
logger: {
|
||||
transport: {
|
||||
target: '@fastify/one-line-logger',
|
||||
},
|
||||
},
|
||||
trustProxy: config.env.reverse_proxy,
|
||||
connectionTimeout: config.env.timeout,
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { IAppConfig } from '../types/appConfig';
|
||||
import { engineList } from '@txtdot/plugins';
|
||||
import { IAppConfig } from '../types/pluginConfig';
|
||||
import { engineList, html2text } from '@txtdot/plugins';
|
||||
|
||||
/**
|
||||
* Configuration of plugins
|
||||
@ -7,6 +7,7 @@ import { engineList } from '@txtdot/plugins';
|
||||
*/
|
||||
const plugin_config: IAppConfig = {
|
||||
engines: [...engineList],
|
||||
html2text,
|
||||
};
|
||||
|
||||
export default plugin_config;
|
||||
|
@ -5,11 +5,12 @@ import { Readable } from 'stream';
|
||||
import { NotHtmlMimetypeError } from './errors/main';
|
||||
import { decodeStream, parseEncodingName } from './utils/http';
|
||||
import replaceHref from './utils/replace-href';
|
||||
import { parseHTML } from 'linkedom';
|
||||
|
||||
import { Engine } from '@txtdot/sdk';
|
||||
import { HandlerInput, IHandlerOutput } from '@txtdot/sdk/dist/types/handler';
|
||||
import { HandlerInput, HandlerOutput } from '@txtdot/sdk';
|
||||
import config from './config';
|
||||
import { parseHTML } from 'linkedom';
|
||||
import { html2text } from './utils/html2text';
|
||||
|
||||
interface IEngineId {
|
||||
[key: string]: number;
|
||||
@ -32,7 +33,7 @@ export class Distributor {
|
||||
requestUrl: URL, // proxy URL
|
||||
engineName?: string,
|
||||
redirectPath: string = 'get'
|
||||
): Promise<IHandlerOutput> {
|
||||
): Promise<HandlerOutput> {
|
||||
const urlObj = new URL(remoteUrl);
|
||||
|
||||
const webder_url = config.env.third_party.webder_url;
|
||||
@ -52,6 +53,7 @@ export class Distributor {
|
||||
}
|
||||
|
||||
const engine = this.getFallbackEngine(urlObj.hostname, engineName);
|
||||
|
||||
const output = await engine.handle(
|
||||
new HandlerInput(
|
||||
await decodeStream(data, parseEncodingName(mime)),
|
||||
@ -59,15 +61,35 @@ export class Distributor {
|
||||
)
|
||||
);
|
||||
|
||||
const dom = parseHTML(output.content);
|
||||
|
||||
// Get text content before link replacement, because in text format we need original links
|
||||
const stdTextContent = dom.document.documentElement.textContent;
|
||||
|
||||
// post-process
|
||||
// TODO: generate dom in handler and not parse here twice
|
||||
const dom = parseHTML(output.content);
|
||||
replaceHref(dom, requestUrl, new URL(remoteUrl), engineName, redirectPath);
|
||||
replaceHref(
|
||||
dom.document,
|
||||
requestUrl,
|
||||
new URL(remoteUrl),
|
||||
engineName,
|
||||
redirectPath
|
||||
);
|
||||
|
||||
const purify = DOMPurify(dom.window);
|
||||
output.content = purify.sanitize(dom.document.toString());
|
||||
const purify = DOMPurify(dom);
|
||||
const content = purify.sanitize(dom.document.toString());
|
||||
const title = output.title || dom.document.title;
|
||||
const lang = output.lang || dom.document.documentElement.lang;
|
||||
const textContent =
|
||||
html2text(stdTextContent, output, title) ||
|
||||
'Text output cannot be generated.';
|
||||
|
||||
return output;
|
||||
return {
|
||||
content,
|
||||
textContent,
|
||||
title,
|
||||
lang,
|
||||
};
|
||||
}
|
||||
|
||||
getFallbackEngine(host: string, specified?: string): Engine {
|
||||
|
@ -2,7 +2,7 @@ import { FastifyReply, FastifyRequest } from 'fastify';
|
||||
import { NotHtmlMimetypeError } from './main';
|
||||
import { getFastifyError } from './validation';
|
||||
|
||||
import { TxtDotError } from '@txtdot/sdk/dist/types/errors';
|
||||
import { TxtDotError } from '@txtdot/sdk';
|
||||
|
||||
import { IGetSchema } from '../types/requests/browser';
|
||||
import config from '../config';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import config from '../config';
|
||||
import { TxtDotError } from '@txtdot/sdk/dist/types/errors';
|
||||
import { TxtDotError } from '@txtdot/sdk';
|
||||
|
||||
export class LocalResourceError extends TxtDotError {
|
||||
constructor() {
|
||||
|
@ -1,5 +0,0 @@
|
||||
import { Engine } from '@txtdot/sdk';
|
||||
|
||||
export interface IAppConfig {
|
||||
engines: Engine[];
|
||||
}
|
14
packages/server/src/types/pluginConfig.ts
Normal file
14
packages/server/src/types/pluginConfig.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Engine } from '@txtdot/sdk';
|
||||
|
||||
type Html2TextConverter = (html: string) => string;
|
||||
|
||||
export interface IAppConfig {
|
||||
/**
|
||||
* List of engines, ordered
|
||||
*/
|
||||
engines: Engine[];
|
||||
/**
|
||||
* HTML to text converter, if engine doesn't support text
|
||||
*/
|
||||
html2text?: Html2TextConverter;
|
||||
}
|
@ -2,7 +2,7 @@ import { FastifySchema, FastifyRequest } from 'fastify';
|
||||
import { IApiError, errorResponseSchema } from '../../errors/api';
|
||||
import { engineList } from '../../plugin_manager';
|
||||
import { FromSchema } from 'json-schema-to-ts';
|
||||
import { handlerSchema } from '@txtdot/sdk/dist/types/handler';
|
||||
import { handlerSchema } from '@txtdot/sdk';
|
||||
|
||||
export interface IApiResponse<T> {
|
||||
data?: T;
|
||||
|
18
packages/server/src/utils/html2text.ts
Normal file
18
packages/server/src/utils/html2text.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { EngineOutput } from '@txtdot/sdk/dist/types/handler';
|
||||
import config from '../config';
|
||||
|
||||
function setTitle(body: string | null, title: string) {
|
||||
if (!body) return null;
|
||||
return `${title.toUpperCase()}\n${'='.repeat(title.length)}\n\n${body}`;
|
||||
}
|
||||
|
||||
export function html2text(
|
||||
stdTextContent: string | null,
|
||||
output: EngineOutput,
|
||||
title: string
|
||||
) {
|
||||
if (output.textContent) return output.textContent;
|
||||
else if (config.plugin.html2text)
|
||||
return setTitle(config.plugin.html2text(output.content), title);
|
||||
else return setTitle(stdTextContent, title);
|
||||
}
|
@ -2,13 +2,12 @@ import config from '../config';
|
||||
import { generateParserUrl, generateProxyUrl } from './generate';
|
||||
|
||||
export default function replaceHref(
|
||||
dom: Window,
|
||||
doc: Document,
|
||||
requestUrl: URL,
|
||||
remoteUrl: URL,
|
||||
engine?: string,
|
||||
redirectPath: string = 'get'
|
||||
) {
|
||||
const doc: Document = dom.window.document;
|
||||
const parserUrl = (href: string) =>
|
||||
generateParserUrl(requestUrl, remoteUrl, href, engine, redirectPath);
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
"incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
|
||||
// "composite": true /* Enable constraints that allow a TypeScript project to be used with project references. */,
|
||||
"tsBuildInfoFile": "./.tsbuildinfo" /* Specify the path to .tsbuildinfo incremental compilation file. */,
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
174
pnpm-lock.yaml
generated
174
pnpm-lock.yaml
generated
@ -41,7 +41,16 @@ importers:
|
||||
'@txtdot/sdk':
|
||||
specifier: workspace:*
|
||||
version: link:../sdk
|
||||
html-to-text:
|
||||
specifier: ^9.0.5
|
||||
version: 9.0.5
|
||||
linkedom:
|
||||
specifier: ^0.18.0
|
||||
version: 0.18.0
|
||||
devDependencies:
|
||||
'@types/html-to-text':
|
||||
specifier: ^9.0.4
|
||||
version: 9.0.4
|
||||
typescript:
|
||||
specifier: ^5.4.5
|
||||
version: 5.4.5
|
||||
@ -49,8 +58,8 @@ importers:
|
||||
packages/sdk:
|
||||
dependencies:
|
||||
linkedom:
|
||||
specifier: ^0.16.11
|
||||
version: 0.16.11
|
||||
specifier: ^0.18.0
|
||||
version: 0.18.0
|
||||
route-parser:
|
||||
specifier: ^0.0.5
|
||||
version: 0.0.5
|
||||
@ -64,6 +73,9 @@ importers:
|
||||
|
||||
packages/server:
|
||||
dependencies:
|
||||
'@fastify/one-line-logger':
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
'@fastify/static':
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.4
|
||||
@ -107,8 +119,8 @@ importers:
|
||||
specifier: ^3.0.1
|
||||
version: 3.1.0
|
||||
linkedom:
|
||||
specifier: ^0.16.11
|
||||
version: 0.16.11
|
||||
specifier: ^0.18.0
|
||||
version: 0.18.0
|
||||
micromatch:
|
||||
specifier: ^4.0.5
|
||||
version: 4.0.5
|
||||
@ -190,6 +202,9 @@ packages:
|
||||
'@fastify/merge-json-schemas@0.1.1':
|
||||
resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==}
|
||||
|
||||
'@fastify/one-line-logger@1.3.0':
|
||||
resolution: {integrity: sha512-91Rqm1UPCcF6eL/g0LkjNrIZBBK/7/lmUbKdIcqZAor5ZN8VV/CiHkEwK9SGl2IUN9CS1BFhSZBwTU6ovzH7Yw==}
|
||||
|
||||
'@fastify/send@2.1.0':
|
||||
resolution: {integrity: sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==}
|
||||
|
||||
@ -534,6 +549,9 @@ packages:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@selderee/plugin-htmlparser2@0.11.0':
|
||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||
|
||||
'@sigstore/bundle@1.1.0':
|
||||
resolution: {integrity: sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==}
|
||||
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
|
||||
@ -606,6 +624,9 @@ packages:
|
||||
'@types/ejs@3.1.5':
|
||||
resolution: {integrity: sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==}
|
||||
|
||||
'@types/html-to-text@9.0.4':
|
||||
resolution: {integrity: sha512-pUY3cKH/Nm2yYrEmDlPR1mR7yszjGx4DrwPjQ702C4/D5CwHuZTgZdIdwPkRbcuhs7BAh2L5rg3CL5cbRiGTCQ==}
|
||||
|
||||
'@types/jsdom@21.1.6':
|
||||
resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==}
|
||||
|
||||
@ -1031,6 +1052,9 @@ packages:
|
||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||
engines: {node: '>=12.5.0'}
|
||||
|
||||
colorette@2.0.20:
|
||||
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
||||
|
||||
columnify@1.6.0:
|
||||
resolution: {integrity: sha512-lomjuFZKfM6MSAnV9aCZC9sc0qGbmZdfygNv+nCpqVkSKdCxCklLtd16O0EILGkImHw9ZpHkAnHaB+8Zxq5W6Q==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
@ -1132,6 +1156,9 @@ packages:
|
||||
dateformat@3.0.3:
|
||||
resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==}
|
||||
|
||||
dateformat@4.6.3:
|
||||
resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==}
|
||||
|
||||
debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -1155,6 +1182,10 @@ packages:
|
||||
deep-is@0.1.4:
|
||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
|
||||
deepmerge@4.3.1:
|
||||
resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
defaults@1.0.4:
|
||||
resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==}
|
||||
|
||||
@ -1355,6 +1386,9 @@ packages:
|
||||
fast-content-type-parse@1.1.0:
|
||||
resolution: {integrity: sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==}
|
||||
|
||||
fast-copy@3.0.2:
|
||||
resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==}
|
||||
|
||||
fast-decode-uri-component@1.0.1:
|
||||
resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==}
|
||||
|
||||
@ -1381,6 +1415,9 @@ packages:
|
||||
resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
fast-safe-stringify@2.1.1:
|
||||
resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==}
|
||||
|
||||
fast-uri@2.3.0:
|
||||
resolution: {integrity: sha512-eel5UKGn369gGEWOqBShmFJWfq/xSJvsgDzgLYC845GneayWvXBf0lJCBn5qTABfewy1ZDPoaR5OZCP+kssfuw==}
|
||||
|
||||
@ -1591,6 +1628,9 @@ packages:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
help-me@5.0.0:
|
||||
resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==}
|
||||
|
||||
hosted-git-info@2.8.9:
|
||||
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
|
||||
|
||||
@ -1613,6 +1653,13 @@ packages:
|
||||
html-escaper@3.0.3:
|
||||
resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==}
|
||||
|
||||
html-to-text@9.0.5:
|
||||
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
htmlparser2@8.0.2:
|
||||
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==}
|
||||
|
||||
htmlparser2@9.1.0:
|
||||
resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
|
||||
|
||||
@ -1832,6 +1879,10 @@ packages:
|
||||
resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==}
|
||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||
|
||||
joycon@3.1.1:
|
||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
|
||||
@ -1904,6 +1955,9 @@ packages:
|
||||
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
leac@0.6.0:
|
||||
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
|
||||
|
||||
lerna@8.1.2:
|
||||
resolution: {integrity: sha512-RCyBAn3XsqqvHbz3TxLfD7ylqzCi1A2UJnFEZmhURgx589vM3qYWQa/uOMeEEf565q6cAdtmulITciX1wgkAtw==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@ -1931,8 +1985,8 @@ packages:
|
||||
resolution: {integrity: sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
linkedom@0.16.11:
|
||||
resolution: {integrity: sha512-WgaTVbj7itjyXTsCvgerpneERXShcnNJF5VIV+/4SLtyRLN+HppPre/WDHRofAr2IpEuujSNgJbCBd5lMl6lRw==}
|
||||
linkedom@0.18.0:
|
||||
resolution: {integrity: sha512-Xtu+w437ENHrgggnSHssua47vYXX/a/MzNdo+AR3UuWoOAxGZNwDSvjRPnPbVRFoygT990HS+7BDVBE1MK6FLQ==}
|
||||
|
||||
load-json-file@4.0.0:
|
||||
resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==}
|
||||
@ -2130,6 +2184,9 @@ packages:
|
||||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
multimatch@5.0.0:
|
||||
resolution: {integrity: sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==}
|
||||
engines: {node: '>=10'}
|
||||
@ -2396,6 +2453,9 @@ packages:
|
||||
parse5@7.1.2:
|
||||
resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
|
||||
|
||||
parseley@0.12.1:
|
||||
resolution: {integrity: sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==}
|
||||
|
||||
path-exists@3.0.0:
|
||||
resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
|
||||
engines: {node: '>=4'}
|
||||
@ -2430,6 +2490,9 @@ packages:
|
||||
pause-stream@0.0.11:
|
||||
resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==}
|
||||
|
||||
peberminta@0.9.0:
|
||||
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
|
||||
|
||||
picocolors@1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
|
||||
@ -2456,6 +2519,10 @@ packages:
|
||||
pino-abstract-transport@1.2.0:
|
||||
resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==}
|
||||
|
||||
pino-pretty@10.3.1:
|
||||
resolution: {integrity: sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==}
|
||||
hasBin: true
|
||||
|
||||
pino-std-serializers@6.2.2:
|
||||
resolution: {integrity: sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==}
|
||||
|
||||
@ -2529,6 +2596,9 @@ packages:
|
||||
engines: {node: '>= 0.10'}
|
||||
hasBin: true
|
||||
|
||||
pump@3.0.0:
|
||||
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
|
||||
|
||||
punycode@2.3.1:
|
||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||
engines: {node: '>=6'}
|
||||
@ -2700,6 +2770,9 @@ packages:
|
||||
secure-json-parse@2.7.0:
|
||||
resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
|
||||
|
||||
selderee@0.11.0:
|
||||
resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==}
|
||||
|
||||
semver@5.7.2:
|
||||
resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
|
||||
hasBin: true
|
||||
@ -3233,6 +3306,10 @@ snapshots:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
|
||||
'@fastify/one-line-logger@1.3.0':
|
||||
dependencies:
|
||||
pino-pretty: 10.3.1
|
||||
|
||||
'@fastify/send@2.1.0':
|
||||
dependencies:
|
||||
'@lukeed/ms': 2.0.2
|
||||
@ -3659,6 +3736,11 @@ snapshots:
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@selderee/plugin-htmlparser2@0.11.0':
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
selderee: 0.11.0
|
||||
|
||||
'@sigstore/bundle@1.1.0':
|
||||
dependencies:
|
||||
'@sigstore/protobuf-specs': 0.2.1
|
||||
@ -3738,6 +3820,8 @@ snapshots:
|
||||
|
||||
'@types/ejs@3.1.5': {}
|
||||
|
||||
'@types/html-to-text@9.0.4': {}
|
||||
|
||||
'@types/jsdom@21.1.6':
|
||||
dependencies:
|
||||
'@types/node': 20.12.11
|
||||
@ -4198,6 +4282,8 @@ snapshots:
|
||||
color-convert: 2.0.1
|
||||
color-string: 1.9.1
|
||||
|
||||
colorette@2.0.20: {}
|
||||
|
||||
columnify@1.6.0:
|
||||
dependencies:
|
||||
strip-ansi: 6.0.1
|
||||
@ -4326,6 +4412,8 @@ snapshots:
|
||||
|
||||
dateformat@3.0.3: {}
|
||||
|
||||
dateformat@4.6.3: {}
|
||||
|
||||
debug@4.3.4:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
@ -4341,6 +4429,8 @@ snapshots:
|
||||
|
||||
deep-is@0.1.4: {}
|
||||
|
||||
deepmerge@4.3.1: {}
|
||||
|
||||
defaults@1.0.4:
|
||||
dependencies:
|
||||
clone: 1.0.4
|
||||
@ -4552,6 +4642,8 @@ snapshots:
|
||||
|
||||
fast-content-type-parse@1.1.0: {}
|
||||
|
||||
fast-copy@3.0.2: {}
|
||||
|
||||
fast-decode-uri-component@1.0.1: {}
|
||||
|
||||
fast-deep-equal@3.1.3: {}
|
||||
@ -4584,6 +4676,8 @@ snapshots:
|
||||
|
||||
fast-redact@3.5.0: {}
|
||||
|
||||
fast-safe-stringify@2.1.1: {}
|
||||
|
||||
fast-uri@2.3.0: {}
|
||||
|
||||
fastify-plugin@4.5.1: {}
|
||||
@ -4830,6 +4924,8 @@ snapshots:
|
||||
dependencies:
|
||||
function-bind: 1.1.2
|
||||
|
||||
help-me@5.0.0: {}
|
||||
|
||||
hosted-git-info@2.8.9: {}
|
||||
|
||||
hosted-git-info@3.0.8:
|
||||
@ -4850,6 +4946,21 @@ snapshots:
|
||||
|
||||
html-escaper@3.0.3: {}
|
||||
|
||||
html-to-text@9.0.5:
|
||||
dependencies:
|
||||
'@selderee/plugin-htmlparser2': 0.11.0
|
||||
deepmerge: 4.3.1
|
||||
dom-serializer: 2.0.0
|
||||
htmlparser2: 8.0.2
|
||||
selderee: 0.11.0
|
||||
|
||||
htmlparser2@8.0.2:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 5.0.3
|
||||
domutils: 3.1.0
|
||||
entities: 4.5.0
|
||||
|
||||
htmlparser2@9.1.0:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
@ -4900,7 +5011,7 @@ snapshots:
|
||||
|
||||
humanize-ms@1.2.1:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
ms: 2.1.3
|
||||
|
||||
iconv-lite@0.4.24:
|
||||
dependencies:
|
||||
@ -5069,13 +5180,15 @@ snapshots:
|
||||
|
||||
jest-diff@29.7.0:
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
chalk: 4.1.0
|
||||
diff-sequences: 29.6.3
|
||||
jest-get-type: 29.6.3
|
||||
pretty-format: 29.7.0
|
||||
|
||||
jest-get-type@29.6.3: {}
|
||||
|
||||
joycon@3.1.1: {}
|
||||
|
||||
js-tokens@4.0.0: {}
|
||||
|
||||
js-yaml@3.14.1:
|
||||
@ -5140,6 +5253,8 @@ snapshots:
|
||||
|
||||
kind-of@6.0.3: {}
|
||||
|
||||
leac@0.6.0: {}
|
||||
|
||||
lerna@8.1.2(encoding@0.1.13):
|
||||
dependencies:
|
||||
'@lerna/create': 8.1.2(encoding@0.1.13)(typescript@5.4.5)
|
||||
@ -5259,7 +5374,7 @@ snapshots:
|
||||
|
||||
lines-and-columns@2.0.4: {}
|
||||
|
||||
linkedom@0.16.11:
|
||||
linkedom@0.18.0:
|
||||
dependencies:
|
||||
css-select: 5.1.0
|
||||
cssom: 0.5.0
|
||||
@ -5486,13 +5601,15 @@ snapshots:
|
||||
|
||||
ms@2.1.2: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
multimatch@5.0.0:
|
||||
dependencies:
|
||||
'@types/minimatch': 3.0.5
|
||||
array-differ: 3.0.0
|
||||
array-union: 2.1.0
|
||||
arrify: 2.0.1
|
||||
minimatch: 3.1.2
|
||||
minimatch: 3.0.5
|
||||
|
||||
mute-stream@0.0.8: {}
|
||||
|
||||
@ -5669,7 +5786,7 @@ snapshots:
|
||||
'@yarnpkg/parsers': 3.0.0-rc.46
|
||||
'@zkochan/js-yaml': 0.0.6
|
||||
axios: 1.6.8
|
||||
chalk: 4.1.2
|
||||
chalk: 4.1.0
|
||||
cli-cursor: 3.1.0
|
||||
cli-spinners: 2.6.1
|
||||
cliui: 8.0.1
|
||||
@ -5742,7 +5859,7 @@ snapshots:
|
||||
ora@5.3.0:
|
||||
dependencies:
|
||||
bl: 4.1.0
|
||||
chalk: 4.1.2
|
||||
chalk: 4.1.0
|
||||
cli-cursor: 3.1.0
|
||||
cli-spinners: 2.6.1
|
||||
is-interactive: 1.0.0
|
||||
@ -5869,6 +5986,11 @@ snapshots:
|
||||
dependencies:
|
||||
entities: 4.5.0
|
||||
|
||||
parseley@0.12.1:
|
||||
dependencies:
|
||||
leac: 0.6.0
|
||||
peberminta: 0.9.0
|
||||
|
||||
path-exists@3.0.0: {}
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
@ -5894,6 +6016,8 @@ snapshots:
|
||||
dependencies:
|
||||
through: 2.3.8
|
||||
|
||||
peberminta@0.9.0: {}
|
||||
|
||||
picocolors@1.0.0: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
@ -5911,6 +6035,23 @@ snapshots:
|
||||
readable-stream: 4.5.2
|
||||
split2: 4.2.0
|
||||
|
||||
pino-pretty@10.3.1:
|
||||
dependencies:
|
||||
colorette: 2.0.20
|
||||
dateformat: 4.6.3
|
||||
fast-copy: 3.0.2
|
||||
fast-safe-stringify: 2.1.1
|
||||
help-me: 5.0.0
|
||||
joycon: 3.1.1
|
||||
minimist: 1.2.8
|
||||
on-exit-leak-free: 2.1.2
|
||||
pino-abstract-transport: 1.2.0
|
||||
pump: 3.0.0
|
||||
readable-stream: 4.5.2
|
||||
secure-json-parse: 2.7.0
|
||||
sonic-boom: 3.8.1
|
||||
strip-json-comments: 3.1.1
|
||||
|
||||
pino-std-serializers@6.2.2: {}
|
||||
|
||||
pino@9.0.0:
|
||||
@ -5975,6 +6116,11 @@ snapshots:
|
||||
dependencies:
|
||||
event-stream: 3.3.4
|
||||
|
||||
pump@3.0.0:
|
||||
dependencies:
|
||||
end-of-stream: 1.4.4
|
||||
once: 1.4.0
|
||||
|
||||
punycode@2.3.1: {}
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
@ -6147,6 +6293,10 @@ snapshots:
|
||||
|
||||
secure-json-parse@2.7.0: {}
|
||||
|
||||
selderee@0.11.0:
|
||||
dependencies:
|
||||
parseley: 0.12.1
|
||||
|
||||
semver@5.7.2: {}
|
||||
|
||||
semver@7.6.2: {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user