Skip to content

Commit

Permalink
feat: 优化规则编辑
Browse files Browse the repository at this point in the history
  • Loading branch information
aooiuu committed Sep 14, 2024
1 parent abca764 commit c4aea8d
Show file tree
Hide file tree
Showing 38 changed files with 282 additions and 171 deletions.
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
*.d.ts
/docs
/docs/.vitepress/cache
/docs/.vitepress/dist
/dist
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

// 使用 eslint 格式化代码
"eslint.enable": true,
"eslint.validate": ["javascript", "html", "vue", "typescript"],

"[vue]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
Expand Down
12 changes: 12 additions & 0 deletions alias.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { resolve } from 'path';

function r(p: string) {
return resolve(__dirname, p);
}

export const alias: Record<string, string> = {
'@any-reader/core': r('./packages/core/src'),
'@any-reader/shared': r('./packages/shared/src'),
'@any-reader/rule-utils': r('./packages/rule-utils/src'),
'@any-reader/epub': r('./packages/epub/src')
};
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ corepack enable
# 安装依赖
pnpm i

# 编译 解析库、工具库、前端模板
pnpm run build
# 运行网页版
pnpm run web:dev
```

### 源码目录结构
Expand Down
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"docs:preview": "vitepress preview"
},
"devDependencies": {
"@any-reader/core": "workspace:^",
"mermaid": "^11.2.0",
"vitepress": "^1.3.4",
"vitepress-plugin-mermaid": "^2.0.16"
Expand Down
5 changes: 5 additions & 0 deletions docs/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineConfig } from 'vite';
import { alias } from '../alias';

export default defineConfig({
optimizeDeps: {
Expand All @@ -8,5 +9,9 @@ export default defineConfig({
hmr: {
overlay: false
}
},

resolve: {
alias
}
});
5 changes: 4 additions & 1 deletion packages/core/__test__/analyzer.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { describe, expect, it } from 'vitest';
import { createAnalyzerManager } from '../src';
import { JSEngine } from '../src/analyzer/JSEngine';

const analyzerManager = createAnalyzerManager();
const analyzerManager = createAnalyzerManager({
JSEngine
});

describe('analyzer', () => {
it('CSS', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/build.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineBuildConfig } from 'unbuild';

export default defineBuildConfig({
entries: ['src/index'],
entries: ['src/index', 'src/browser/index'],
clean: true,
declaration: true,
rollup: {
Expand Down
6 changes: 5 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
".": {
"require": "./dist/index.cjs",
"import": "./dist/index.mjs"
},
"./browser": {
"require": "./dist/browser/index.cjs",
"import": "./dist/browser/index.mjs"
}
},
"main": "./dist/index.cjs",
Expand All @@ -27,6 +31,7 @@
"stub": "unbuild --stub"
},
"dependencies": {
"@any-reader/rule-utils": "workspace:^",
"@xmldom/xmldom": "^0.9.2",
"axios": "^1.7.7",
"chardet": "^2.0.0",
Expand All @@ -41,7 +46,6 @@
"xpath.js": "^1.1.0"
},
"devDependencies": {
"@any-reader/rule-utils": "workspace:^",
"@types/content-type": "^1.1.8",
"@types/crypto-js": "^4.2.2",
"@types/xmldom": "^0.1.34",
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/analyzer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@ import { AnalyzerFilter } from './analyzer/AnalyzerFilter';
import { AnalyzerHtml } from './analyzer/AnalyzerHtml';
import { AnalyzerJS } from './analyzer/AnalyzerJS';
import { AnalyzerJSONPath } from './analyzer/AnalyzerJSONPath';
import { AnalyzerManager, Analyzers } from './analyzer/AnalyzerManager';
import { AnalyzerRegExp } from './analyzer/AnalyzerRegExp';
import { AnalyzerReplace } from './analyzer/AnalyzerReplace';
import { AnalyzerXPath } from './analyzer/AnalyzerXPath';
import { AnalyzerWeb } from './analyzer/AnalyzerWeb';
import { ILogger, LogLevel, NoLogger } from './logger';
import { AnalyzerManager, AnalyzerManagerOption } from './analyzer/AnalyzerManager';
import { LogLevel, NoLogger } from './logger';
import { JSEngine } from './analyzer/JSEngine';

export { analyzerUrl } from './analyzer/analyzerUrl';
export { AnalyzerHtml, AnalyzerJS, AnalyzerJSONPath, AnalyzerRegExp, AnalyzerReplace, AnalyzerXPath, AnalyzerFilter, AnalyzerWeb };

export function createAnalyzerManager(params: { analyzers?: Analyzers[]; logger?: ILogger; logLevel?: LogLevel } = {}): AnalyzerManager {
export function createAnalyzerManager(params: Partial<AnalyzerManagerOption> = {}): AnalyzerManager {
return new AnalyzerManager({
logger: params.logger || new NoLogger(),
logLevel: params.logLevel || LogLevel.Off,
JSEngine: params.JSEngine || JSEngine,
analyzers: params.analyzers || [
{
pattern: /^@css:/i,
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/analyzer/Analyzer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { JSEngine } from '../sandbox/JSEngine';

export abstract class IAnalyzer {
abstract parse(content: string): void;
abstract getString(rule: string): Promise<string>;
Expand All @@ -6,6 +8,12 @@ export abstract class IAnalyzer {
}

export class Analyzer implements IAnalyzer {
JSEngine: typeof JSEngine;

constructor(options: { JSEngine: typeof JSEngine }) {
this.JSEngine = options.JSEngine;
}

parse(_: string): void {
throw new Error('Method not implemented.');
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerFilter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import puppeteer from 'puppeteer';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerFilter implements Analyzer {
export class AnalyzerFilter extends Analyzer {
private _content!: string;
private _url!: string;

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerHtml.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { load } from 'cheerio';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

function htmlDecode(str: string) {
return str
Expand All @@ -21,7 +21,7 @@ function getHtmlString(html: string) {
return htmlDecode(html.replaceAll(/<\/?(?:div|p|br|hr|h\d|article|b|dd|dl)[^>]*>/g, '\n').replace(/<!--[\w\W\r\n]*?-->/gim, ''));
}

export class AnalyzerHtml implements Analyzer {
export class AnalyzerHtml extends Analyzer {
_content!: string;

parse(content: string | string[]) {
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/analyzer/AnalyzerJS.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { JSEngine } from './JSEngine';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerJS implements Analyzer {
export class AnalyzerJS extends Analyzer {
_content!: any;

parse(content: any) {
Expand All @@ -14,11 +13,11 @@ export class AnalyzerJS implements Analyzer {
}

async getStringList(rule: string): Promise<string[]> {
return this.getElements(rule);
return this.getElements(rule) as Promise<string[]>;
}

async getElements(rule: string) {
return await JSEngine.evaluate(rule, {
return await this.JSEngine.evaluate(rule, {
result: this._content
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerJSONPath.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JSONPath } from 'jsonpath-plus';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerJSONPath implements Analyzer {
export class AnalyzerJSONPath extends Analyzer {
_content!: any;

parse(content: string | any) {
Expand Down
45 changes: 38 additions & 7 deletions packages/core/src/analyzer/AnalyzerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AnalyzerException } from '../exception/AnalyzerException';
import { ILogger, LogLevel } from '../logger';
import type { Analyzer } from './Analyzer';
import { AnalyzerJS } from './AnalyzerJS';
import type { JSEngine } from '../sandbox/JSEngine';

const RULE_TYPE_PATTERN = /@js:|@hetu:|@web:|@webview:|@css:|@json:|@http:|@xpath:|@match:|@regex:|@regexp:|@filter:|@replace:|@encode:|@decode:|^/gi;

Expand All @@ -26,15 +27,24 @@ export interface Analyzers {
Analyzer: typeof Analyzer;
}

export interface AnalyzerManagerOption {
analyzers: Analyzers[];
logger: ILogger;
logLevel: LogLevel;
JSEngine: typeof JSEngine;
}

export class AnalyzerManager {
public analyzers: Analyzers[];
public logger: ILogger;
public logLevel: LogLevel;
public JSEngine: typeof JSEngine;

constructor(params: { analyzers: Analyzers[]; logger: ILogger; logLevel: LogLevel }) {
constructor(params: AnalyzerManagerOption) {
this.analyzers = params.analyzers || [];
this.logger = params.logger || console;
this.logLevel = params.logLevel || LogLevel.Off;
this.JSEngine = params.JSEngine;
}

getAnalyzer(rule: string) {
Expand All @@ -57,9 +67,25 @@ export class AnalyzerManager {
r = r.replace(analyzer.replace || analyzer.pattern, '');
const position = r.indexOf('##');
if (position > -1) {
ruleList.push(new SingleRule(new analyzer.Analyzer(), r.substring(0, position), r.substring(position + 2)));
ruleList.push(
new SingleRule(
new analyzer.Analyzer({
JSEngine: this.JSEngine
}),
r.substring(0, position),
r.substring(position + 2)
)
);
} else {
ruleList.push(new SingleRule(new analyzer.Analyzer(), r, ''));
ruleList.push(
new SingleRule(
new analyzer.Analyzer({
JSEngine: this.JSEngine
}),
r,
''
)
);
}
}
return ruleList.reverse();
Expand Down Expand Up @@ -96,7 +122,7 @@ export class AnalyzerManager {
}
}

async getElements(rule: string, body: string): Promise<any[]> {
public async getElements(rule: string, body: string): Promise<any[]> {
let temp: string | string[] = body;

for (const r of this.splitRuleReversed(rule)) {
Expand Down Expand Up @@ -141,7 +167,7 @@ export class AnalyzerManager {
}
}

async getString(rule: string, body: string): Promise<string> {
public async getString(rule: string, body: string): Promise<string> {
if (!rule) return '';
const expressionPattern = /\{\{(.*?)\}\}/g;

Expand Down Expand Up @@ -180,7 +206,7 @@ export class AnalyzerManager {
}
}

async getStringList(rule: string, body: string): Promise<string[]> {
public async getStringList(rule: string, body: string): Promise<string[]> {
if (!rule) return [];
const expressionPattern = /\{\{(.*?)\}\}/g;

Expand Down Expand Up @@ -209,7 +235,12 @@ export class AnalyzerManager {
return Array.isArray(temp) ? temp : [temp];
}

async getUrl(rule: string, host: string, body: string): Promise<string> {
public async parseJsUrl(url: string) {
if (url.startsWith('@js:')) return await this.JSEngine.evaluate(url.substring(4));
return url;
}

public async getUrl(rule: string, host = '', body = ''): Promise<string> {
let url = await this.getString(rule, body);
if (typeof url !== 'string') return url;

Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerRegExp.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerRegExp implements Analyzer {
export class AnalyzerRegExp extends Analyzer {
_content!: string;

parse(content: string) {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerReplace.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerReplace implements Analyzer {
export class AnalyzerReplace extends Analyzer {
private _content!: string;

replaceSmart(replace: string) {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/src/analyzer/AnalyzerWeb.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import type { Rule } from '@any-reader/rule-utils';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';
import { analyzerUrl } from './analyzerUrl';
import { JSEngine } from './JSEngine';

export class AnalyzerWeb implements Analyzer {
export class AnalyzerWeb extends Analyzer {
_content!: string;

parse(content: string) {
this._content = content;
}

async getString(rule: string): Promise<string> {
return (await analyzerUrl(rule, '', '', JSEngine.environment.rule as Rule)).body;
return (await analyzerUrl(rule, '', '', this.JSEngine.environment.rule as Rule)).body;
}

getStringList(_: string): Promise<string[]> {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/analyzer/AnalyzerXPath.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import xpath from 'xpath.js';
import { DOMParser, MIME_TYPE } from '@xmldom/xmldom';
import type { Analyzer } from './Analyzer';
import { Analyzer } from './Analyzer';

export class AnalyzerXPath implements Analyzer {
export class AnalyzerXPath extends Analyzer {
_content!: string;

parse(content: string | string[]) {
Expand Down
7 changes: 5 additions & 2 deletions packages/core/src/analyzer/JSEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import type { Rule } from '@any-reader/rule-utils';
import { AnalyzerXPath } from '../analyzer/AnalyzerXPath';
import { JsVmException } from '../exception/JsVmException';
import { __http__ } from './request';
import { JSEngine as BaseJSEngine } from '../sandbox/JSEngine';

export class JSEngine {
export class JSEngine extends BaseJSEngine {
static environment: any = {};
static VMCtx: any;

Expand All @@ -33,7 +34,9 @@ export class JSEngine {
},
http,
xpath: async (html: string, xpath: string): Promise<string[]> => {
const analyzer = new AnalyzerXPath();
const analyzer = new AnalyzerXPath({
JSEngine: null as unknown as typeof JSEngine
});
analyzer.parse(html);
return await analyzer.getStringList(xpath);
}
Expand Down
Loading

0 comments on commit c4aea8d

Please sign in to comment.