mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-21 12:49:53 +08:00
* style: add eslint-unicorn * style: fix unicorn/no-useless-spread * style: fix unicorn/no-useless-promise-resolve-reject * style: fix unicorn/no-for-loop * fix: codeql bad HTML filtering regexp * fix: codeql incomplete replace * fix: unicorn/no-abusive-eslint-disable * style: fix unicorn/no-new-array * style: fix unicorn/no-typeof-undefined * style: fix unicorn/no-zero-fractions * style: fix unicorn/no-empty-file * style: fix unicorn/prefer-date-now * revert: auto fix unicorn/prefer-switch on lib/v2/kuaidi100/utils.js * style: fix unicorn/prefer-array-find * style: fix unicorn/prefer-array-flat * style: fix unicorn/prefer-array-flat-map * style: fix unicorn/prefer-at * style: fix unicorn/prefer-string-starts-ends-with * style: fix unicorn/prefer-includes * fix: codeql URL substring sanitization * style: fix unicorn/prefer-optional-catch-binding * style: fix unicorn/catch-error-name * style: fix unicorn/escape-case * style: fix unicorn/prefer-native-coercion-functions * style: fix unicorn/prefer-regexp-test * style: fix unicorn/require-array-join-separator * style: fix unicorn/prefer-math-trunc * style: fix unicorn/prefer-negative-index * style: fix unicorn/prefer-dom-node-dataset * style: fix unicorn/prefer-dom-node-text-content * style: fix unicorn/prefer-query-selector * style: fix unicorn/no-array-for-each * style: fix unicorn/no-negated-condition * style: fix unicorn/prefer-add-event-listener * style: fix unicorn/import-style * style: fix prefer-regex-literals * style: disable unicorn/no-useless-switch-case * style: disable unicorn/text-encoding-identifier-case * style: fix unicorn/prefer-set-has * style: fix unicorn/prefer-spread * revert: auto fix on lib/routes/universities/ynnu/edu/base64.js * style: fix unicorn/no-useless-undefined * style: fix unicorn/no-array-push-push * style: fix unicorn/no-useless-undefined again * style: fix unicorn/no-lonely-if * style: fix unicorn/prefer-reflect-apply * style: fix unicorn/switch-case-braces * style: fix unicorn/prefer-switch * style: fix unicorn/prefer-array-some * fix: deepscan UNUSED_VAR_ASSIGN * style: fix unicorn/prefer-ternary * fix: follow-up of unicorn/prefer-ternary * revert: auto fix of unicorn/prefer-string-slice for substring() * style: disable unicorn/prefer-string-slice fix: auto fix slice over deprecated substr * style: fix unicorn/throw-new-error * style: fix unicorn/filename-case * test: fix dateParser renaming * style: fix unicorn/better-regex * style: fix unicorn/prefer-string-replace-all * fix(deps): add sanitize-html * style: fix no-prototype-builtins * style: fix unicorn/consistent-destructuring * style: fix unicorn/consistent-function-scoping * style: fix unicorn/prefer-regexp-test * style: fix unicorn/prefer-logical-operator-over-ternary * style: fix unicorn/no-array-callback-reference * style: add prefer-object-has-own * style: warn unicorn/no-empty-file * style: fix unicorn/prefer-number-properties * style: fix no-useless-undefined again * style: fix unicorn/numeric-separators-style * style: disable unicorn/no-array-callback-reference false postive with cheerio
103 lines
4.6 KiB
JavaScript
103 lines
4.6 KiB
JavaScript
const dirname = __dirname + '/v2';
|
|
const fs = require('fs');
|
|
const toSource = require('tosource');
|
|
const path = require('path');
|
|
|
|
// Namespaces that do not require radar.js
|
|
const allowNamespace = new Set(['discourse', 'discuz', 'ehentai', 'lemmy', 'mail', 'test']);
|
|
// Check if a radar.js file is exist under each folder of dirname
|
|
for (const dir of fs.readdirSync(dirname)) {
|
|
const dirPath = path.join(dirname, dir);
|
|
if (!fs.existsSync(path.join(dirPath, 'radar.js')) && !allowNamespace.has(dir)) {
|
|
throw new Error(`No radar.js in "${dirPath}".`);
|
|
}
|
|
}
|
|
|
|
const validateRadarRules = (rule, dir) => {
|
|
const allowDomains = new Set(['www.gov.cn']);
|
|
const blockWords = ['/', 'http', 'www'];
|
|
const domain = Object.keys(rule);
|
|
if (!domain.length && !allowNamespace.has(dir)) {
|
|
// typo check e.g., ✘ module.export, ✔ module.exports
|
|
throw new Error(`No Radar rule in "${dir}".`);
|
|
}
|
|
for (const [d, r] of Object.entries(rule)) {
|
|
if (blockWords.some((word) => d.startsWith(word)) && !allowDomains.has(d)) {
|
|
throw new Error(`Domain name "${d}" should not contain any of ${blockWords.join(', ')}.`);
|
|
}
|
|
if (!Object.hasOwn(r, '_name')) {
|
|
throw new Error(`No _name in "${dir}".`);
|
|
}
|
|
// property check
|
|
for (const [host, items] of Object.entries(r)) {
|
|
if (host !== '_name') {
|
|
if (!Array.isArray(items)) {
|
|
throw new TypeError(`Radar rules for domain "${host}" in "${dir}" should be placed in an array.`);
|
|
}
|
|
for (const item of items) {
|
|
if (!Object.hasOwn(item, 'title') || !Object.hasOwn(item, 'docs')) {
|
|
throw new Error(`Radar rules for "${host}" in "${dir}" should have at least "title" and "docs".`);
|
|
}
|
|
if (!item.title || !item.docs) {
|
|
throw new Error(`Radar rules for "${host}" in "${dir}" should not be empty.`);
|
|
}
|
|
if (!item.docs.startsWith('https://docs.rsshub.app/')) {
|
|
throw new Error(`Radar rules for "${host}" in "${dir}" should start with 'https://docs.rsshub.app/'.`);
|
|
}
|
|
if (Array.isArray(item.source)) {
|
|
if (!item.source.length) {
|
|
// check for []
|
|
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
|
}
|
|
if (item.source.some((s) => s.includes('#') || s.includes('='))) {
|
|
// Some will try to match '/some/path?a=1' which is not supported
|
|
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
|
}
|
|
if (item.source.some((s) => !s.length)) {
|
|
// check for ['/some/thing', ''] and ['']
|
|
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
|
}
|
|
}
|
|
if (typeof item.source === 'string') {
|
|
if (!item.source.length) {
|
|
// check for ''
|
|
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" should not be empty.`);
|
|
}
|
|
if (item.source.includes('#') || item.source.includes('=')) {
|
|
throw new Error(`Radar rule of "${item.title}" for subdomain "${host}" in "${dir}" cannot match URL hash or URL search parameters.`);
|
|
}
|
|
}
|
|
for (const key in item) {
|
|
if (key !== 'title' && key !== 'docs' && key !== 'source' && key !== 'target') {
|
|
throw new Error(`Radar rules for "${host}" in "${dir}" should not have property "${key}".`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const radarRules = require('require-all')({
|
|
dirname,
|
|
filter: /radar\.js$/,
|
|
});
|
|
|
|
let rules = {};
|
|
|
|
for (const dir in radarRules) {
|
|
const rule = radarRules[dir]['radar.js']; // Do not merge other file
|
|
|
|
validateRadarRules(rule, dir);
|
|
|
|
rules = { ...rules, ...rule };
|
|
}
|
|
|
|
const oldRules = require('./radar-rules.js'); // Match old rules
|
|
rules = { ...rules, ...oldRules };
|
|
|
|
module.exports = {
|
|
rules,
|
|
toSource: () => `(${toSource(rules)})`,
|
|
};
|