docs.md

May 18, 2026 ยท View on GitHub

Documentation for LNReader plugins

Most of the Plugin/Novel type definitions accessed using the Plugin namespace imported via

import { Plugin } from '@/types/plugin';

PluginBase

PluginBase is a base class for all plugins.

class ExamplePlugin implements Plugin.PluginBase {}
FieldRequiredDescription
idyesPlugin ID
nameyesPlugin Name
iconyesPlugin Icon
siteyesPlugin site link
versionyesPlugin version
imageRequestInitnoPlugin Image Request Init
filtersnoFilter definition object
pluginSettingsnoPlugin settings object
popularNovels(page, options)yesNovel list getter
parseNovel(path)yesNovel info and chapter list getter
parseChapter(path)yesChapter text getter
searchNovels(searchTerm, page)yesNovel searching getter

PluginBase::id

Unique ID of your plugin

class ExamplePlugin implements Plugin.PluginBase {
    ...
    id = "templateID";
    ...
}

PluginBase::name

The name of your plugin that is shown in-app

class ExamplePlugin implements Plugin.PluginBase {
    ...
    name = "template Plugin";
    ...
}

PluginBase::icon

The path to your plugin's icon inside of public/static folder

class ExamplePlugin implements Plugin.PluginBase {
    ...
    icon = "src/en/templateplugin/icon.png";
    ...
}

Warning

Icons should be 96x96px

PluginBase::site

The url to the plugin's site

Example
class ExamplePlugin implements Plugin.PluginBase {
    ...
    site = "https://example.com";
    ...
}

PluginBase::version

Version of your plugin formatted according to semver2.0 spec i.e. <major>.<minor>.<patch>

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
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
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 function

Example
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

async popularNovels(
        page: number,
        options: Plugin.PopularNovelsOptions<typeof this.filters>
    ): Promise<Plugin.NovelItem[]>

See Using cheerio for more information on how to parse HTML documents

Parameters
Returns

NovelItem[] An array of filtered main-page NovelItems

Example:
class ExamplePlugin implements Plugin.PluginBase {
    ...
    async popularNovels(
        page: number,
        options: Plugin.PopularNovelsOptions<typeof this.filters>
    ): Promise<Plugin.NovelItem[]> {
        const novels: Plugin.NovelItem[] = [];
        if(options.filters.example.value === "test"){
            novels.push({
                name: "Novel1",
                path: "/novel1",
                cover:defaultCover
            })
        }
        return novels;
    }
}
PluginBase::PopularNovelsOptions

This type is used for getting the options of the popularNovels function

  • showLatestNovels: boolean flag set when opened with Latest button

  • filters: FilterValues<typeof filters> object containing all selected filter values. More about Filters

PluginBase::parseNovel

Function that is used to get the information about particular novel and the list of it's chapters

async parseNovel(novelPath: string): Promise<Plugin.SourceNovel>

See Using cheerio for more information on how to parse HTML documents

Parameters
Returns

SourceNovel Novel information and chapter list as SourceNovel object

[!CAUTION] > SourceNovel::path should be the same value as NovelItem::path provided as parameter!

Example:
class ExamplePlugin implements Plugin.PluginBase {
    ...
    async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
        const novel: Plugin.SourceNovel = {
            path: novelPath,
            name: "test",
            artist: "none",
            author: "none",
            cover: defaultCover,
            genres: "Isekai, Neverland",
            status: NovelStatus.Completed,
            summary: ""
        };
        let chapters: Plugin.ChapterItem[] = [];
        const chapter: Plugin.ChapterItem = {
            name: "",
            path: "",
            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

async parseChapter(chapterPath: string): Promise<string>

See Using cheerio for more information on how to parse HTML documents

Parameters
Returns

string HTML content of the chapter

Example:
class ExamplePlugin implements Plugin.PluginBase {
    ...
    async parseChapter(chapterPath: string): Promise<string>{
        return "<h1>No chapter here</h1>";
    }
    ...
}

PluginBase::searchNovels

Function that is used to find Novels in the source

async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]>

See 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

Example
class ExamplePlugin implements Plugin.PluginBase {
    ...
    async searchNovels(
        searchTerm: string,
        pageNo: number
    ): Promise<Plugin.NovelItem[]> {
        let novels: Plugin.NovelItem[] = [];
        return novels;
    }
    ...
}

NovelItem

It is an object representing information how to store/access the novel

FieldtypeRequiredDescription

path

stringyesThe relative path to the novel

name

stringyesThe name of the novel shown in the library

cover

stringnoURL to novel's cover

Default cover

You can use the default Cover not available cover by importing

import { defaultCover } from '@libs/defaultCover';

SourceNovel

FieldTypeRequiredDesciption
pathstringyes
namestringnostring
coverstringno
genresstringno
summarystringno
authorstringno
artiststringno
status[NovelStatus] or stringno
    chapters?: ChapterItem[];

ChapterItem

FieldTypeRequiredDescription
namestringyes
pathstringyes
releaseTimestringnorelease time in YYYY-MM-DD
chapterNumbernumberno
pagestringnofor multi-page chapter lists

Filters

Filters and FilterTypes are not in the Plugin namespace and are from @libs/filterInputs file:

import { FilterTypes, Filters } from '@libs/filterInputs';

There are 2 main objects when using filters:

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 object

filters = {
    order: {<FilterProperties>}
} satisfies Filters;
// accessible in popularNovels as
options.filters.order

Caution

Do not forget to add satisfies Filters after the Filter definition object!

FilterProperties
NameTypeRequiredDesciption
labelstringyesin-app label
typeFilterTypesyestype of the filter
valuecheck typesyesDefault value for this filter and the starting filter state in-app
optionscheck typesin some typesThe options available in the given type
Example
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

FilterTypeDescriptionvalueoptions
PickerA spinner for choosing one of the choices provided in optionsstring the picked valuePicker options
TextInputA filter allowing a free text inputstring written valueN/A
SwitchA boolean switchboolean state of the switchN/A
CheckboxGroupA grouping of checkboxesstring[] array containing selected valuesCheckboxGroup options
ExcludableCheckboxGroupA filter allowing to pick one of the choices provided in optionsExcludableCheckboxGroupValues objectCheckboxGroup options
Picker options
options: [
  {
    label: 'default', // in-app label
    value: '', // in-code value
  },
  {
    label: 'Value ABC',
    value: 'abc',
  },
];
CheckboxGroup options
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 object. The keys of the filter values correspond to Filter definition keys

// 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
options.filters.abc.value; // value of the filter
options.filters.abc.type; // type of the filter
ExcludableCheckboxGroupValue object
{
    included: string[], // options with selected selected
    excluded: string[]  // options with excluded selected
}

PluginSettings

Plugin settings allow plugins to define user-configurable options that are displayed in the app's settings UI. These settings are persistent and can be accessed within the plugin code.

PluginBase::pluginSettings

A user-defined object that defines configurable settings for the plugin. Each property of this object is a different setting that will be displayed in the app's settings UI.

pluginSettings = {
    settingKey: {
        value: '',
        label: 'Setting Label',
        type: 'Text', // optional, defaults to 'Text'
    },
};
Setting Properties
NameTypeRequiredDescription
valuestringyesDefault value for this setting
labelstringyesDisplay label shown in the app's settings UI
typestringnoType of the setting UI component (see below)
Setting Types

Currently, two setting types are supported:

TypeDescriptionUI ComponentDefault Value Type
SwitchA boolean toggle switchSwitchItemboolean
TextA text input field (default if type is omitted)TextInputstring

Note

If type is not specified, the setting defaults to Text type and will be rendered as a TextInput.

Accessing Settings Values

Settings values are stored and can be accessed using the storage utility:

import { storage } from '@libs/storage';

// Get a setting value
const settingValue = storage.get('settingKey');

// Set a setting value
storage.set('settingKey', 'newValue');
Examples
Example 1: Switch Setting
class ExamplePlugin implements Plugin.PluginBase {
    ...
    hideLocked = storage.get('hideLocked');
    
    pluginSettings = {
        hideLocked: {
            value: '',
            label: 'Hide locked chapters',
            type: 'Switch',
        },
    };
    
    async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
        // Use the setting value
        if (this.hideLocked) {
            // Filter out locked chapters
        }
        ...
    }
    ...
}
Example 2: Text Settings
class ExamplePlugin implements Plugin.PluginBase {
    ...
    site = storage.get('url');
    email = storage.get('email');
    password = storage.get('password');
    
    pluginSettings = {
        url: {
            value: '',
            label: 'URL',
            // type: 'Text' is optional
        },
        email: {
            value: '',
            label: 'Email',
            type: 'Text',
        },
        password: {
            value: '',
            label: 'Password',
            // type defaults to 'Text' if omitted
        },
    };
    
    async makeRequest(url: string): Promise<string> {
        return await fetchApi(url, {
            headers: {
                'Authorization': `Basic ${this.btoa(this.email + ':' + this.password)}`,
            },
            Referer: this.site,
        }).then(res => res.text());
    }
    ...
}

Using Cheerio

Custom fetching functions