## Documentation for LNReader plugins - [PluginBase](#pluginbase) - [NovelItem](#novelitem) - [SourceNovel](#sourcenovel) - [ChapterItem](#chapteritem) - [Filters](#filters) - [Using Cheerio](#using-cheerio) - [Custom fetching functions](#custom-fetching-functions) Most of the Plugin/Novel type definitions accessed using the `Plugin` namespace imported via ```ts import { Plugin } from "@typings/plugin"; ``` ### PluginBase PluginBase is a base class for all plugins. ```ts class ExamplePlugin implements Plugin.PluginBase {} ``` | Field | Required | Description | | -------------------------------------------------------------- | -------- | ----------------------------------------------------- | | [id](#pluginbaseid) | yes | Plugin ID | | [name](#pluginbasename) | yes | Plugin Name | | [icon](#pluginbasename) | yes | Plugin Icon | | [site](#pluginbasesite) | yes | Plugin site link | | [version](#pluginbaseversion) | yes | Plugin version | | [imageRequestInit](#pluginbaseimagerequestinit) | no | Plugin Image Request Init | | [filters](#pluginbasefilters) | no | [Filter definition](#filter-definition-object) object | | [popularNovels(page, options)](#pluginbasepopularnovels) | yes | Novel list getter | | [parseNovelAndChapters(url)](#pluginbaseparsenovelandchapters) | yes | Novel info and chapter list getter | | [parseChapter(url)](#pluginbaseparsechapter) | yes | Chapter text getter | | [searchNovels(searchTerm, page)](#pluginbasesearchnovels) | yes | Novel searching getter | #### PluginBase::id Unique ID of your plugin ```ts class ExamplePlugin implements Plugin.PluginBase { ... id = "templateID"; ... } ``` #### PluginBase::name The name of your plugin that is shown in-app ```ts class ExamplePlugin implements Plugin.PluginBase { ... name = "template Plugin"; ... } ``` #### PluginBase::icon The path to your plugin's icon inside of `icon` folder ```ts class ExamplePlugin implements Plugin.PluginBase { ... icon = "src/eng/templateplugin/icon.png"; ... } ``` > [!WARNING] > Icons should be 96x96px #### PluginBase::site The url to the plugin's site ###### Example ```ts class ExamplePlugin implements Plugin.PluginBase { ... site = "https://example.com"; ... } ``` #### PluginBase::version Version of your plugin formatted according to [semver2.0 spec](https://semver.org/) i.e. `..` Where - `patch` increments on small fixes that fix the plugin (like site changed a selector, filter had a typo etc.) - `minor` increments on fixes that improve the plugin (like adding/removing filters, adding search options etc.) - `major` increments on fixes that fix the major issues with the plugin (like changing site link) ###### Example ```ts class ExamplePlugin implements Plugin.PluginBase { ... version = "1.0.0"; ... } ``` #### PluginBase::imageRequestInit The init for request to obtain images Used if images failed to load due to site's protection ###### Example ```ts class ExamplePlugin implements Plugin.PluginBase { ... imageRequestInit: Plugin.ImageRequestInit = { headers: { Referer: 'https://example.com', }, }; ... } ``` #### PluginBase::filters A [Filter definition]() object that holds filters used in [popularNovels](#pluginbasepopularnovels) function ###### Example ```ts class ExamplePlugin implements Plugin.PluginBase { ... filters = { order: { label:"Order", options: [ { label: "Popular", value: "" }, { label: "Newest", value: "newest" } ], type: FilterTypes.Picker, value: "" }, status: { label: "Status", options: [ { label: "All", value: "" }, { label: "Ongoing", value: "ongoing" }, { label: "Hiatus", value: "hiatus" }, { label: "Completed", value: "completed" }, ], type: FilterTypes.Picker, value: "", } } ... } ``` #### PluginBase::popularNovels Function that is used to get the (filtered) list of novels from the front page of the site ```ts async popularNovels( page: number, options: Plugin.PopularNovelsOptions ): Promise ``` See [Using cheerio](#using-cheerio) for more information on how to parse HTML documents ###### Parameters - `page` current page to fetch - `options` [PopularNovelsOptions](#pluginbasepopularnovelsoptions) ###### Returns `NovelItem[]` An array of filtered main-page [NovelItems](#novelitem) ###### Example: ```ts class ExamplePlugin implements Plugin.PluginBase { ... async popularNovels( page: number, options: Plugin.PopularNovelsOptions ): Promise { const novels: Plugin.NovelItem[] = []; if(options.filters.example.value === "test"){ novels.push({ name: "Novel1", url: "https://example.com/novel1", cover:defaultCover }) } return novels; } } ``` ##### PluginBase::PopularNovelsOptions This type is used for getting the options of the [popularNovels](#pluginbasepopularnovels) function - `showLatestNovels: boolean` flag set when opened with `Latest` button - `filters: FilterValues` object containing all selected filter values. [More about Filters](#filters) #### PluginBase::parseNovelAndChapters Function that is used to get the information about particular novel and the list of it's chapters ```ts async parseNovelAndChapters(novelUrl: string): Promise ``` See [Using cheerio](#using-cheerio) for more information on how to parse HTML documents ###### Parameters - `novelUrl` value from [NovelItem::url](#novelitemurl) ###### Returns `SourceNovel` Novel information and chapter list as [SourceNovel](#sourcenovel) object > [!CAUTION] > [SourceNovel::url]() should be the same value as [NovelItem::url]() provided as parameter! ###### Example: ```ts class ExamplePlugin implements Plugin.PluginBase { ... async parseNovelAndChapters(novelUrl: string): Promise { const novel: Plugin.SourceNovel = { url: novelUrl, name: "test", artist: "none", author: "none", cover: defaultCover, genres: "Isekai, Neverland", status: NovelStatus.Completed, summary: "" }; let chapters: Plugin.ChapterItem[] = []; const chapter: Plugin.ChapterItem = { name: "", url: "", releaseTime: "", chapterNumber: 0, }; chapters.push(chapter); novel.chapters = chapters; return novel; } ... } ``` #### PluginBase::parseChapter Function that is used to get the information about particular novel and the list of it's chapters ```ts async parseChapter(chapterUrl: string): Promise ``` See [Using cheerio](#using-cheerio) for more information on how to parse HTML documents ###### Parameters - `chapterUrl` value from [ChapterItem::url](#chapteritemurl) ###### Returns `string` HTML content of the chapter ###### Example: ```ts class ExamplePlugin implements Plugin.PluginBase { ... async parseChapter(chapterUrl: string): Promise{ return "

No chapter here

"; } ... } ``` #### PluginBase::searchNovels Function that is used to find Novels in the source ```ts async searchNovels(searchTerm: string, pageNo: number): Promise ``` See [Using cheerio](#using-cheerio) for more information on how to parse HTML documents ###### Parameters - `searchTerm` the search term - `page` search page number ###### Returns `NovelItem[]` An array of found [NovelItems](#novelitem) ###### Example ```ts class ExamplePlugin implements Plugin.PluginBase { ... async searchNovels( searchTerm: string, pageNo: number ): Promise { let novels: Plugin.NovelItem[] = []; return novels; } ... } ``` --- ### NovelItem It is an object representing information how to store/access the novel | Field | type | Required | Description | | -------------------------------- | -------- | -------- | ------------------------------------------ | |

url

| `string` | yes | The url to the site | |

name

| `string` | yes | The name of the novel shown in the library | |

cover

| `string` | no | URL to novel's cover | #### Default cover You can use the default `Cover not available` cover by importing ```ts import { defaultCover } from "@libs/defaultCover"; ``` --- ### SourceNovel | Field | Type | Required | Desciption | | ----- | ------ | -------- | ---------- | | url | string | yes | | | name | string | no | string | |cover|`string`|no|| |genres|`string`|no|| |summary|`string`|no|| |author|`string`|no|| |artist|`string`|no|| |status|[NovelStatus] or `string`|no|| chapters?: ChapterItem[]; --- ### ChapterItem --- ### Filters `Filters` and `FilterTypes` are not in the `Plugin` namespace and are from `@libs/filterInputs` file: ```ts import { FilterTypes, Filters } from "@libs/filterInputs"; ``` There are 2 main objects when using filters: - [Filter definition](#filter-definition-object) object - [FilterValues](#filterValue) object #### Filter definition object This is the user-defined object that defines strictly what filters are available in the "filter" menu in app. Every property of this object is a different filter. The key of the object is the name that will be used to reference this filter's value in the [FilterValues](#filtervalues-object) object ```ts filters = { order: {} } satisfies Filters; // accessible in popularNovels as options.filters.order ``` > [!CAUTION] > Do not forget to add `satisfies Filters` after the Filter definition object! ##### FilterProperties | Name | Type | Required | Desciption | | ------- | ---------------------------- | ------------- | ------------------------------------------------------------------ | | label | `string` | yes | in-app label | | type | `FilterTypes` | yes | type of the filter | | value | [check types](#filter-types) | yes | Default value for this filter and the starting filter state in-app | | options | [check types](#filter-types) | in some types | The options available in the given type | ###### Example ```ts filters = { genre: { type: FilterTypes.CheckboxGroup, label: "Genres", value: [], options: [ { label: "Isekai", value: "isekai" }, { label: "Romance", value: "romans" }, ], }, } satisfies Filters; ``` ##### Filter types Types of filters supported | FilterType | Description | `value` | `options` | | ------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------- | ----------------------------------------------- | | `Picker` | A spinner for choosing one of the choices provided in `options` | `string` the picked value | [Picker](#picker-options) options | | `TextInput` | A filter allowing a free text input | `string` written value | N/A | | `Switch` | A boolean switch | `boolean` state of the switch | N/A | | `CheckboxGroup` | A grouping of checkboxes | `string[]` array containing selected values | [CheckboxGroup](#checkboxgroup-options) options | | `ExcludableCheckboxGroup` | A filter allowing to pick one of the choices provided in `options` | [ExcludableCheckboxGroupValues](#excludablecheckboxgroupvalue-object) object | [CheckboxGroup](#checkboxgroup-options) options | ###### Picker options ```ts options: [ { label: "default", // in-app label value: "", // in-code value }, { label: "Value ABC", value: "abc", }, ]; ``` ###### CheckboxGroup options ```ts options: [ { label: "Value ABC", // in-app label value: "abc", // in-code value }, { label: "Value DEF", value: "def", }, ]; ``` #### FilterValues object It is an object used inisde of `popularNovels` that contains selected values for all filters defined in the [Filter definition](#filter-definition-object) object. The keys of the filter values correspond to Filter definition keys ```ts // Filter definition object filters = { abc: {} } satisfies Filters; // then options.filters; // FilterValues options.filters.abc; // FilterValue for abc filter ``` ##### FilterValue Properties of FilterValue: - `type: FilterType` type of the filter - `value` value dependent on [FilterTypes](#filter-types) ```ts options.filters.abc.value; // value of the filter options.filters.abc.type; // type of the filter ``` ###### ExcludableCheckboxGroupValue object ```ts { included: string[], // options with selected selected excluded: string[] // options with excluded selected } ``` ### Using Cheerio ### Custom fetching functions