Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/plugin-live-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Plugin Live Check

on:
pull_request:
branches: [master]
workflow_dispatch:
inputs:
plugin_path:
description: 'Plugin file(s) to check (space-separated relative paths)'
required: true
type: string

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
live-check:
name: Plugin Live Check
runs-on: ubuntu-latest

permissions:
contents: read
pull-requests: write

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get Changed Plugin Files
id: changed-files
if: github.event_name == 'pull_request'
uses: tj-actions/changed-files@v45
with:
files: |
plugins/**/*.ts
files_ignore: |
plugins/**/*\[*\]*.ts
plugins/multisrc/**

- name: Determine Targets
id: targets
if: github.event_name == 'workflow_dispatch' || steps.changed-files.outputs.any_changed == 'true'
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "files=${{ inputs.plugin_path }}" >> "$GITHUB_OUTPUT"
else
echo "files=${{ steps.changed-files.outputs.all_changed_files }}" >> "$GITHUB_OUTPUT"
fi

- name: Setup Node.js
if: steps.targets.outputs.files != ''
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install Dependencies
if: steps.targets.outputs.files != ''
run: npm ci

# Multisrc-generated files (plugins/**/*[...].ts) are excluded above.
# They're produced from plugins/multisrc/*/template.ts + sources.json,
# not hand-authored, so testing the generator is out of scope here.
- name: Run Live Check
id: live-check
if: steps.targets.outputs.files != ''
run: |
set +e
node scripts/live-check-plugin.js ${{ steps.targets.outputs.files }} > live-check-output.txt 2>&1
echo "exit_code=$?" >> "$GITHUB_OUTPUT"
cat live-check-output.txt

- name: Post PR Comment
if: github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: plugin-live-check
path: live-check-output.txt

- name: Fail On Real Errors
if: steps.targets.outputs.files != '' && steps.live-check.outputs.exit_code != '0'
run: |
echo "Live check reported at least one FAIL — see the job log or PR comment above."
exit 1
10 changes: 6 additions & 4 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@
1. [Requirements](#requirements)
2. [Single plugin guide](#quick-guide)
3. [Multi-src guide](#creating-multi-src-plugins)
4. [Testing your plugin](./testing.md)

### Requirements

- [git](https://git-scm.com/doc/ext) basics
- Typescript or Javascript basics
- Node >=22
- Installing the dependencies with `npm i`
- [git](https://git-scm.com/doc/ext) basics
- Typescript or Javascript basics
- Node >=22
- Installing the dependencies with `npm i`

### Guide

1. Create plugin script in `/plugins` [<span style="font-size: 0.8rem;">(learn more)</span>](#creating-plugin-script)
2. Copy code from [plugin-template.ts](./plugin-template.ts)
3. Start coding [<span style="font-size:0.8rem">(documentation)</span>](./docs.md)
4. Run `npm run check:plugin -- plugins/<lang>/yourPlugin.ts` before opening a PR — see [Testing your plugin](./testing.md)

#### Creating plugin script

Expand Down
44 changes: 44 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Testing your plugin

`tsc`, ESLint, and Prettier all check that your plugin _compiles_. None of them can tell you
whether it actually returns novels, chapters, or search results from the real site — plugins fail
in ways the compiler can't see, because the wiki/site content they scrape has no schema: an empty
chapter list, a chapter body that's actually a "back to top" nav page, search results leaking
pages in the wrong language, and so on.

## `npm run check:plugin`

Bundles your plugin with esbuild the same way the production build does, then runs it against the
live site — calling `popularNovels`, `searchNovels`, `parseNovel`, and `parseChapter` in sequence,
using your plugin's own default filter values (the same values the app would send).

```sh
npm run check:plugin -- plugins/english/yourPlugin.ts
```

You can check multiple plugins in one run:

```sh
npm run check:plugin -- plugins/english/yourPlugin.ts plugins/english/anotherPlugin.ts
```

Each step reports one of three outcomes:

- **PASS** — got a plausible result (non-empty novel list, a chapter body over ~200 characters,
etc).
- **FAIL** — the plugin ran but returned something wrong (empty results, a novel with no chapters,
a suspiciously short chapter body, or a thrown error that isn't network-related). This is what
you're looking for before opening a PR.
- **INCONCLUSIVE** — the site itself was unreachable, timed out, or returned a Cloudflare-style
block during this run. Not a plugin bug; re-run later or check the site manually.

## CI

Any PR that touches a file under `plugins/**/*.ts` (excluding multisrc-generated files) runs this
same check automatically against just the changed plugins, and posts a summary comment. The check
only fails the PR on a genuine `FAIL` — `INCONCLUSIVE` results (a site being briefly down) never
block a merge.

You can also trigger it manually against any plugin path from the Actions tab
(`Plugin Live Check` → `Run workflow`), which is useful for re-checking an existing plugin after
its target site changes layout.
108 changes: 106 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"format": "prettier --write \"./**/*.{js,ts}\"",
"format:check": "prettier --check \"./**/*.{js,ts}\"",
"check:sites": "node scripts/check-plugin-sites.js",
"check:plugin": "node scripts/live-check-plugin.js",
"prepare": "husky"
},
"author": "LNReader",
Expand Down Expand Up @@ -70,6 +71,7 @@
"dayjs": "^1.11.13",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"esbuild": "^0.25.3",
"globals": "^15.6.0",
"htmlparser2": "^9.1.0",
"http-proxy": "^1.18.1",
Expand Down
Loading
Loading