* add prettier

* lint-staged

* prettier

* upgrade husky
This commit is contained in:
nyagami
2024-03-23 22:00:29 +07:00
committed by GitHub
parent c22979b10f
commit 5f9a067ab9
113 changed files with 79244 additions and 50841 deletions
+68 -70
View File
@@ -1,100 +1,98 @@
import fs from "fs";
import { languages } from "@libs/languages";
import path from "path";
import { PluginList } from "@typings/types";
import { Plugin } from "@typings/plugin";
import { Filters } from "@libs/filterInputs";
const root = path.dirname(require?.main?.filename || "");
import fs from 'fs';
import { languages } from '@libs/languages';
import path from 'path';
import { PluginList } from '@typings/types';
import { Plugin } from '@typings/plugin';
import { Filters } from '@libs/filterInputs';
const root = path.dirname(require?.main?.filename || '');
export const fetchHeaders: Record<string, string> = {};
export const all_plugins = (): PluginList => {
const res: PluginList = {};
for (let languageEnglish in languages) {
//language with English name
const languageNative =
languages[languageEnglish as keyof typeof languages];
const langPath = path.join(
root,
"plugins",
languageEnglish.toLowerCase()
);
if (!fs.existsSync(langPath)) continue;
const plugins = fs.readdirSync(langPath);
res[languageEnglish] = [];
plugins.forEach((plugin) => {
if (plugin.startsWith(".")) return;
const requirePath = `@plugins/${languageEnglish.toLowerCase()}/${
plugin.split(".")[0]
}`;
const instance = require(requirePath).default;
const { id, name, version, icon } = instance;
const info: Plugin.PluginItem = {
id,
name: name + (plugin.match(/(\[.+\])/)?.[1] || ''),
lang: languageNative,
version,
requirePath,
icon,
}; // lang: language with native name
res[languageEnglish].push(info);
});
}
return res;
const res: PluginList = {};
for (let languageEnglish in languages) {
//language with English name
const languageNative = languages[languageEnglish as keyof typeof languages];
const langPath = path.join(root, 'plugins', languageEnglish.toLowerCase());
if (!fs.existsSync(langPath)) continue;
const plugins = fs.readdirSync(langPath);
res[languageEnglish] = [];
plugins.forEach(plugin => {
if (plugin.startsWith('.')) return;
const requirePath = `@plugins/${languageEnglish.toLowerCase()}/${
plugin.split('.')[0]
}`;
const instance = require(requirePath).default;
const { id, name, version, icon } = instance;
const info: Plugin.PluginItem = {
id,
name: name + (plugin.match(/(\[.+\])/)?.[1] || ''),
lang: languageNative,
version,
requirePath,
icon,
}; // lang: language with native name
res[languageEnglish].push(info);
});
}
return res;
};
const getPlugin = async (
requirePath: string
requirePath: string,
): Promise<Plugin.PluginBase | Plugin.PagePlugin | null> => {
const plugin = await require(requirePath).default;
return plugin;
const plugin = await require(requirePath).default;
return plugin;
};
export const getFilter = async (pluginRequirePath: string) =>
(await getPlugin(pluginRequirePath))?.filters;
(await getPlugin(pluginRequirePath))?.filters;
export const popularNovels = async (
pluginRequirePath: string,
page: number,
options: Plugin.PopularNovelsOptions<Filters>
pluginRequirePath: string,
page: number,
options: Plugin.PopularNovelsOptions<Filters>,
) => (await getPlugin(pluginRequirePath))?.popularNovels(page, options);
export const searchNovels = async (
pluginRequirePath: string,
page: number,
searchTerm: string
pluginRequirePath: string,
page: number,
searchTerm: string,
) => (await getPlugin(pluginRequirePath))?.searchNovels(searchTerm, page);
export const parseNovel = async (
pluginRequirePath: string,
novelPath: string
pluginRequirePath: string,
novelPath: string,
) => (await getPlugin(pluginRequirePath))?.parseNovel(novelPath);
export const hasParsePage = async (
pluginRequirePath: string,
) => (await getPlugin(pluginRequirePath) as Plugin.PagePlugin | null)?.parsePage;
export const hasParsePage = async (pluginRequirePath: string) =>
((await getPlugin(pluginRequirePath)) as Plugin.PagePlugin | null)?.parsePage;
export const parsePage = async(
pluginRequirePath: string,
novelPath: string,
page: string
) => (await getPlugin(pluginRequirePath) as Plugin.PagePlugin | null)?.parsePage(novelPath, page);
export const parsePage = async (
pluginRequirePath: string,
novelPath: string,
page: string,
) =>
((await getPlugin(pluginRequirePath)) as Plugin.PagePlugin | null)?.parsePage(
novelPath,
page,
);
export const parseChapter = async (
pluginRequirePath: string,
chapterPath: string
pluginRequirePath: string,
chapterPath: string,
) => (await getPlugin(pluginRequirePath))?.parseChapter(chapterPath);
export const fetchImage = async (pluginRequirePath: string, url: string) =>
(await getPlugin(pluginRequirePath))?.fetchImage(url);
(await getPlugin(pluginRequirePath))?.fetchImage(url);
export const resolveUrl = async (
pluginRequirePath: string,
path: string,
isNovel?: boolean,
pluginRequirePath: string,
path: string,
isNovel?: boolean,
) => {
const plugin = await getPlugin(pluginRequirePath);
if (!plugin) return path;
if (plugin.resolveUrl) return plugin.resolveUrl(path, isNovel);
return plugin.site + path;
};
const plugin = await getPlugin(pluginRequirePath);
if (!plugin) return path;
if (plugin.resolveUrl) return plugin.resolveUrl(path, isNovel);
return plugin.site + path;
};
+91 -91
View File
@@ -1,91 +1,91 @@
/** @ts-check */
class AccordionContent extends HTMLElement {
constructor() {
super();
this.gridElement = document.createElement("div");
}
get content() {
return this.gridElement;
}
connectedCallback() {
// create a div that'll animate the collapsing
this.gridElement.append(...Array.from(this.childNodes));
this.gridElement.classList.add("accordion-animation-content");
this.innerHTML = "";
this.append(this.gridElement);
}
}
class AccordionHeader extends HTMLElement {
constructor() {
super();
console.log("contructor?");
this.btn = document.createElement("button");
}
get html() {
return this.btn.innerHTML;
}
set html(val) {
this.btn.innerHTML = val;
}
get text() {
return this.btn.innerText;
}
set text(val) {
this.btn.innerText = val;
}
get parentBox() {
return this.parentElement;
}
connectedCallback() {
const childNodes = Array.from(this.childNodes);
this.innerHTML = "";
this.btn.append(...childNodes);
this.append(this.btn);
this.btn.addEventListener("click", this._btnClicked.bind(this));
}
_btnClicked() {
this.parentBox?.toggle();
}
}
class AccordionBox extends HTMLElement {
constructor() {
super();
}
get collapsed() {
return this.hasAttribute("collapsed");
}
set collapsed(val) {
if (val) {
this.setAttribute("collapsed", "");
} else {
this.removeAttribute("collapsed");
}
}
toggle() {
this.collapsed = !this.collapsed;
}
}
class Accordion extends HTMLElement {
constructor() {
super();
}
}
window.customElements.define("main-accordion", Accordion);
window.customElements.define("accordion-box", AccordionBox);
window.customElements.define("accordion-header", AccordionHeader);
window.customElements.define("accordion-content", AccordionContent);
// Export types for use in index.js
const module = {};
module.exports = {
AccordionBox,
Accordion,
AccordionContent,
AccordionHeader,
};
/** @ts-check */
class AccordionContent extends HTMLElement {
constructor() {
super();
this.gridElement = document.createElement('div');
}
get content() {
return this.gridElement;
}
connectedCallback() {
// create a div that'll animate the collapsing
this.gridElement.append(...Array.from(this.childNodes));
this.gridElement.classList.add('accordion-animation-content');
this.innerHTML = '';
this.append(this.gridElement);
}
}
class AccordionHeader extends HTMLElement {
constructor() {
super();
console.log('contructor?');
this.btn = document.createElement('button');
}
get html() {
return this.btn.innerHTML;
}
set html(val) {
this.btn.innerHTML = val;
}
get text() {
return this.btn.innerText;
}
set text(val) {
this.btn.innerText = val;
}
get parentBox() {
return this.parentElement;
}
connectedCallback() {
const childNodes = Array.from(this.childNodes);
this.innerHTML = '';
this.btn.append(...childNodes);
this.append(this.btn);
this.btn.addEventListener('click', this._btnClicked.bind(this));
}
_btnClicked() {
this.parentBox?.toggle();
}
}
class AccordionBox extends HTMLElement {
constructor() {
super();
}
get collapsed() {
return this.hasAttribute('collapsed');
}
set collapsed(val) {
if (val) {
this.setAttribute('collapsed', '');
} else {
this.removeAttribute('collapsed');
}
}
toggle() {
this.collapsed = !this.collapsed;
}
}
class Accordion extends HTMLElement {
constructor() {
super();
}
}
window.customElements.define('main-accordion', Accordion);
window.customElements.define('accordion-box', AccordionBox);
window.customElements.define('accordion-header', AccordionHeader);
window.customElements.define('accordion-content', AccordionContent);
// Export types for use in index.js
const module = {};
module.exports = {
AccordionBox,
Accordion,
AccordionContent,
AccordionHeader,
};
+5034 -9
View File
File diff suppressed because one or more lines are too long
+57 -59
View File
@@ -1,59 +1,57 @@
// This is an un-browserified version of the script! If you make any changes to this file you need to run
// npx browserify html-sanitize-nonbrowser.js -o html-sanitize.js
// for your changes to be visible inside of the browser!
const sanitizeHtml = require("sanitize-html");
/** @typedef {{removeExtraParagraphSpacing?: boolean}} Options */
const loadingGif =
"https://raw.githubusercontent.com/LNReader/lnreader/plugins/android/app/src/main/assets/images/loading.gif";
/**
*
* @param {string} html
* @param {Options?} options
*/
window.sanitizeChapterText = (html, options) => {
if (html) {
html = html.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
}
let text = sanitizeHtml(html, {
allowedTags: sanitizeHtml.defaults.allowedTags.concat([
"img",
"i",
"em",
"b",
"a",
"div",
]),
allowedAttributes: {
img: ["src"],
a: ["href"],
},
allowedSchemes: ["data", "http", "https", "file"],
});
if (text) {
if (options?.removeExtraParagraphSpacing) {
text = text
.replace(/<\s*br[^>]*>/gi, "\n")
.replace(/\n{2,}/g, "\n\n");
}
const imgHandlerRegex = /<img([^>]*src="[^"]+"[^>]*)>/g;
const ttsHandlerRegex =
/(< *\w+ *>[^<.?!]+< *\/\w+ *>|< *a *href *= *"[^"]+" *>\s*(<img[^>]+>|[^<]+|(< *\w+ *>[^]+< *\/\w+ *>)*)\s*< *\/a *>|< *img[^>]+>|[^<>.?!]+[.?!])/g;
// first -> match whole tags which dont have attribute and [.?!] inside
// second -> match a tags and its childs
// third -> match img tags
// match sentence split by [.?!]
text = text
.replace(
imgHandlerRegex,
`<img alt="Plugin can't fetch this img" onload="reader.refresh()" onerror="this.setAttribute('error-src', this.src);reader.post({type:'error-img',data:this.src});this.src='${loadingGif}';this.onerror=undefined" $1>`
)
.replace(ttsHandlerRegex, "<t-t-s>$1</t-t-s>");
} else {
text = "HTML is empty";
}
return text;
};
// This is an un-browserified version of the script! If you make any changes to this file you need to run
// npx browserify html-sanitize-nonbrowser.js -o html-sanitize.js
// for your changes to be visible inside of the browser!
const sanitizeHtml = require('sanitize-html');
/** @typedef {{removeExtraParagraphSpacing?: boolean}} Options */
const loadingGif =
'https://raw.githubusercontent.com/LNReader/lnreader/plugins/android/app/src/main/assets/images/loading.gif';
/**
*
* @param {string} html
* @param {Options?} options
*/
window.sanitizeChapterText = (html, options) => {
if (html) {
html = html.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
}
let text = sanitizeHtml(html, {
allowedTags: sanitizeHtml.defaults.allowedTags.concat([
'img',
'i',
'em',
'b',
'a',
'div',
]),
allowedAttributes: {
img: ['src'],
a: ['href'],
},
allowedSchemes: ['data', 'http', 'https', 'file'],
});
if (text) {
if (options?.removeExtraParagraphSpacing) {
text = text.replace(/<\s*br[^>]*>/gi, '\n').replace(/\n{2,}/g, '\n\n');
}
const imgHandlerRegex = /<img([^>]*src="[^"]+"[^>]*)>/g;
const ttsHandlerRegex =
/(< *\w+ *>[^<.?!]+< *\/\w+ *>|< *a *href *= *"[^"]+" *>\s*(<img[^>]+>|[^<]+|(< *\w+ *>[^]+< *\/\w+ *>)*)\s*< *\/a *>|< *img[^>]+>|[^<>.?!]+[.?!])/g;
// first -> match whole tags which dont have attribute and [.?!] inside
// second -> match a tags and its childs
// third -> match img tags
// match sentence split by [.?!]
text = text
.replace(
imgHandlerRegex,
`<img alt="Plugin can't fetch this img" onload="reader.refresh()" onerror="this.setAttribute('error-src', this.src);reader.post({type:'error-img',data:this.src});this.src='${loadingGif}';this.onerror=undefined" $1>`,
)
.replace(ttsHandlerRegex, '<t-t-s>$1</t-t-s>');
} else {
text = 'HTML is empty';
}
return text;
};
File diff suppressed because one or more lines are too long
+1618 -1661
View File
File diff suppressed because it is too large Load Diff
+5594 -1
View File
File diff suppressed because one or more lines are too long
+8765 -11
View File
File diff suppressed because one or more lines are too long
+24179 -18759
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -1,5 +1,5 @@
interface Window {
themes: Record<string, ThemeType>;
sanitizeChapterText(html: string, options?: Options);
encodeHTML5(html: string, options?: Options);
}
interface Window {
themes: Record<string, ThemeType>;
sanitizeChapterText(html: string, options?: Options);
encodeHTML5(html: string, options?: Options);
}
+14 -14
View File
@@ -1,14 +1,14 @@
// @ts-check
/** @typedef {{backgroundColor:string, textColor:string}[]} Theme */
/** @type {Theme} */
window.themes = [
{ backgroundColor: "#f5f5fa", textColor: "#111111" },
{ backgroundColor: "#F7DFC6", textColor: "#593100" },
{ backgroundColor: "#dce5e2", textColor: "#000000" },
{ backgroundColor: "#292832", textColor: "#CCCCCC" },
{
backgroundColor: "#000000",
textColor: "#FFFFFFB3",
},
];
// @ts-check
/** @typedef {{backgroundColor:string, textColor:string}[]} Theme */
/** @type {Theme} */
window.themes = [
{ backgroundColor: '#f5f5fa', textColor: '#111111' },
{ backgroundColor: '#F7DFC6', textColor: '#593100' },
{ backgroundColor: '#dce5e2', textColor: '#000000' },
{ backgroundColor: '#292832', textColor: '#CCCCCC' },
{
backgroundColor: '#000000',
textColor: '#FFFFFFB3',
},
];