mirror of
https://github.com/jellyfin/jellyfin.org.git
synced 2026-09-03 03:10:04 +03:00
Use generated data for plugin list
This commit is contained in:
@@ -39,263 +39,10 @@ All plugins hosted on the repository can be built from source and manually added
|
||||
|
||||
## List
|
||||
|
||||
### Official Plugins
|
||||
import { Plugins } from '../../../../src/data/plugins';
|
||||
import PluginList from '../../../../src/components/plugins/PluginList';
|
||||
|
||||
#### Metadata Plugins
|
||||
|
||||
Manage your Anime in Jellyfin with several different metadata providers and options for organizing your collection.
|
||||
|
||||
##### Anilist
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anilist)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anilist)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anilist)
|
||||
|
||||
Provides metadata support from [Anilist](https://anilist.co/).
|
||||
|
||||
**Link:**
|
||||
|
||||
- [Github](https://github.com/jellyfin/jellyfin-plugin-anilist)
|
||||
|
||||
##### Anidb
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anidb)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anidb)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anidb)
|
||||
|
||||
Provides metadata support from [Anidb](https://anidb.net/).
|
||||
|
||||
**Link:**
|
||||
|
||||
- [Github](https://github.com/jellyfin/jellyfin-plugin-anidb)
|
||||
|
||||
##### Anisearch
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anisearch)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anisearch)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-anisearch)
|
||||
|
||||
Provides metadata support from [Anisearch](https://www.anisearch.com/).
|
||||
|
||||
**Link:**
|
||||
|
||||
- [Github](https://github.com/jellyfin/jellyfin-plugin-anisearch)
|
||||
|
||||
##### Bookshelf
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-bookshelf)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-bookshelf)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-bookshelf)
|
||||
|
||||
Supports several different metadata providers and options for organizing your collection.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-bookshelf)
|
||||
|
||||
##### Kitsu
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kitsu)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kitsu)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kitsu)
|
||||
|
||||
Provides metadata support from [Kitsu](https://kitsu.io/).
|
||||
|
||||
- [Github](https://github.com/jellyfin/jellyfin-plugin-kitsu)
|
||||
|
||||
#### Fanart
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-fanart)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-fanart)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-fanart)
|
||||
|
||||
Scrape poster images for movies, shows, and artists in your library from [fanart.tv](https://fanart.tv).
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-fanart)
|
||||
|
||||
#### Kodi Sync Queue
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kodisyncqueue)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kodisyncqueue)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-kodisyncqueue)
|
||||
|
||||
Helps keep Jellyfin for Kodi in sync with the library without needing to run periodic full scans.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-kodisyncqueue)
|
||||
|
||||
#### LDAP
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-ldapauth)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-ldapauth)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-ldapauth)
|
||||
|
||||
Authenticate your Jellyfin users against an LDAP database, and optionally create users who do not yet exist automatically. Allows the administrator to customize most aspects of the LDAP authentication process, including customizable search attributes, username attribute, and a search filter for administrative users (set on user creation). The user, via the "Manual Login" process, can enter any valid attribute value, which will be mapped back to the specified username attribute automatically as well.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-ldapauth)
|
||||
|
||||
#### NextPVR
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-nextpvr)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-nextpvr)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-nextpvr)
|
||||
|
||||
Provides access to Live TV, Program Guide, and Recordings from [NextPVR](https://www.nextpvr.com/).
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-nextpvr)
|
||||
|
||||
#### [Open Subtitles](/docs/general/server/plugins/open-subtitles)
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-opensubtitles)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-opensubtitles)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-opensubtitles)
|
||||
|
||||
Download subtitles from the internet to use with your media files from [Open Subtitles](https://www.opensubtitles.org/). You can configure the languages it downloads on a per-library basis.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-opensubtitles)
|
||||
|
||||
#### Playback Reporting
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-playbackreporting)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-playbackreporting)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-playbackreporting)
|
||||
|
||||
Collect and show user playback statistics, such as total time watched, media watched, time of day watched, and time of week watched. Can keep information for as long as you want or can cull older information automatically. Also allows you to manually query the data collected so you can generate your own reports.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-playbackreporting)
|
||||
|
||||
#### Reports
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-reports)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-reports)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-reports)
|
||||
|
||||
Generate reports of your media library.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-reports)
|
||||
|
||||
#### TMDb Box Sets
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tmdbboxsets)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tmdbboxsets)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tmdbboxsets)
|
||||
|
||||
Automatically create movie box sets based on TMDb collections. Configurable minimum number of films to be considered a boxset. Boxsets are created as collections and includes a scheduled task to ensure that new media is automatically put into boxsets.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-tmdbboxsets)
|
||||
|
||||
#### Trakt
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-trakt)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-trakt)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-trakt)
|
||||
|
||||
Record your watched media with [Trakt](https://trakt.tv).
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-trakt)
|
||||
|
||||
#### TVHeadend
|
||||
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tvheadend)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tvheadend)
|
||||
[](https://github.com/jellyfin/jellyfin-plugin-tvheadend)
|
||||
|
||||
Manage TVHeadEnd from Jellyfin. Click [here](/docs/general/server/plugins/tvheadend) for plugin support.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jellyfin/jellyfin-plugin-tvheadend)
|
||||
|
||||
### 3rd-Party Plugins
|
||||
|
||||
#### Ani-Sync
|
||||
|
||||
Ani-Sync lets you synchronize/scrobble your Jellyfin Anime watch progress to popular services like MyAnimeList, AniList, Kitsu.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/vosmiic/jellyfin-ani-sync)
|
||||
|
||||
#### Intros
|
||||
|
||||
Download flashy intros from prerolls.video for your movies.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/dkanada/jellyfin-plugin-intros)
|
||||
|
||||
#### Kinopoisk metadata plugin
|
||||
|
||||
Fetches metadata from [https://kinopoisk.ru](https://kinopoisk.ru). This site is popular in the Russian-speaking community and contains almost no English-language information. Can provide movies and series rating, description, actors and staff, trailers and so on.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/LinFor/jellyfin-plugin-kinopoisk)
|
||||
|
||||
#### Last.FM
|
||||
|
||||
Enables audio scrobbling to Last.FM as well as a metadata fetcher source.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/jesseward/jellyfin-plugin-lastfm)
|
||||
|
||||
#### Merge Versions
|
||||
|
||||
Automatically group every repeated movie.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/danieladov/jellyfin-plugin-mergeversions)
|
||||
|
||||
#### Shokofin
|
||||
|
||||
A plugin to integrate your Shoko database with the Jellyfin media server.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/ShokoAnime/Shokofin)
|
||||
|
||||
#### Skin Manager
|
||||
|
||||
Download and manage the most popular skins.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/danieladov/jellyfin-plugin-skin-manager)
|
||||
|
||||
#### Themerr
|
||||
|
||||
Plugin for Jellyfin that adds theme songs to movies using ThemerrDB.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/LizardByte/themerr-jellyfin)
|
||||
|
||||
#### YouTube Metadata
|
||||
|
||||
Downloads metadata of YouTube videos with a YouTube API key.
|
||||
|
||||
**Links:**
|
||||
|
||||
- [GitHub](https://github.com/ankenyr/jellyfin-youtube-metadata-plugin)
|
||||
<PluginList plugins={Plugins} />
|
||||
|
||||
## Repositories
|
||||
|
||||
|
||||
Generated
+409
-2
@@ -52,6 +52,7 @@
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"prettier": "3.1.1",
|
||||
"tsx": "4.6.2",
|
||||
"typescript": "5.3.3",
|
||||
"typescript-plugin-css-modules": "5.0.2"
|
||||
},
|
||||
@@ -3270,6 +3271,358 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
|
||||
"integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz",
|
||||
"integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz",
|
||||
"integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz",
|
||||
"integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz",
|
||||
"integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz",
|
||||
"integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz",
|
||||
"integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz",
|
||||
"integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz",
|
||||
"integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz",
|
||||
"integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz",
|
||||
"integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz",
|
||||
"integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz",
|
||||
"integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz",
|
||||
"integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz",
|
||||
"integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@eslint-community/eslint-utils": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
|
||||
@@ -7517,6 +7870,43 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
|
||||
"integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/android-arm": "0.18.20",
|
||||
"@esbuild/android-arm64": "0.18.20",
|
||||
"@esbuild/android-x64": "0.18.20",
|
||||
"@esbuild/darwin-arm64": "0.18.20",
|
||||
"@esbuild/darwin-x64": "0.18.20",
|
||||
"@esbuild/freebsd-arm64": "0.18.20",
|
||||
"@esbuild/freebsd-x64": "0.18.20",
|
||||
"@esbuild/linux-arm": "0.18.20",
|
||||
"@esbuild/linux-arm64": "0.18.20",
|
||||
"@esbuild/linux-ia32": "0.18.20",
|
||||
"@esbuild/linux-loong64": "0.18.20",
|
||||
"@esbuild/linux-mips64el": "0.18.20",
|
||||
"@esbuild/linux-ppc64": "0.18.20",
|
||||
"@esbuild/linux-riscv64": "0.18.20",
|
||||
"@esbuild/linux-s390x": "0.18.20",
|
||||
"@esbuild/linux-x64": "0.18.20",
|
||||
"@esbuild/netbsd-x64": "0.18.20",
|
||||
"@esbuild/openbsd-x64": "0.18.20",
|
||||
"@esbuild/sunos-x64": "0.18.20",
|
||||
"@esbuild/win32-arm64": "0.18.20",
|
||||
"@esbuild/win32-ia32": "0.18.20",
|
||||
"@esbuild/win32-x64": "0.18.20"
|
||||
}
|
||||
},
|
||||
"node_modules/escalade": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
@@ -8997,7 +9387,6 @@
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz",
|
||||
"integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
@@ -15801,7 +16190,6 @@
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
@@ -17203,6 +17591,25 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.6.2.tgz",
|
||||
"integrity": "sha512-QPpBdJo+ZDtqZgAnq86iY/PD2KYCUPSUGIunHdGwyII99GKH+f3z3FZ8XNFLSGQIA4I365ui8wnQpl8OKLqcsg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.18.20",
|
||||
"get-tsconfig": "^4.7.2"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
||||
+3
-1
@@ -18,7 +18,8 @@
|
||||
"lint": "eslint --ext .ts,.js,.json,.jsx,.tsx .",
|
||||
"test:blog-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-blog-urls.json",
|
||||
"test:docs-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-docs-urls.json",
|
||||
"test:web-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-web-urls.json"
|
||||
"test:web-urls": "node ./scripts/check-urls.mjs ./scripts/data/jellyfin-web-urls.json",
|
||||
"update-plugins": "tsx ./scripts/update-plugins.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.0.1",
|
||||
@@ -77,6 +78,7 @@
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"prettier": "3.1.1",
|
||||
"tsx": "4.6.2",
|
||||
"typescript": "5.3.3",
|
||||
"typescript-plugin-css-modules": "5.0.2"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { AllPluginRepositories, PluginRepository } from '../src/data/pluginRepositories';
|
||||
import { Plugin } from '../src/data/plugins';
|
||||
import { writeFile } from 'node:fs/promises';
|
||||
|
||||
const OUTPUT_PATH = new URL('../src/data/plugins.generated.json', import.meta.url);
|
||||
|
||||
async function getPluginManifest(repository: PluginRepository) {
|
||||
try {
|
||||
const response = await fetch(repository.url);
|
||||
const json = await response.json();
|
||||
return json;
|
||||
} catch (cause) {
|
||||
console.warn(`Failed to retrieve plugin repository ${repository.name} at ${repository.url}`, { cause });
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function getPlugins(repositories: Array<PluginRepository>) {
|
||||
const plugins: { repository: string; plugin: Plugin }[] = [];
|
||||
|
||||
for (const repository of repositories) {
|
||||
const manifest = await getPluginManifest(repository);
|
||||
for (const plugin of manifest) {
|
||||
plugins.push({ repository: repository.id, plugin });
|
||||
}
|
||||
}
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
async function updatePlugins(repositories = AllPluginRepositories) {
|
||||
console.log(`Downloading data for ${repositories.length} repositories`);
|
||||
const plugins = await getPlugins(AllPluginRepositories);
|
||||
console.log(`Writing ${plugins.length} plugins to ${OUTPUT_PATH}`);
|
||||
await writeFile(OUTPUT_PATH, JSON.stringify(plugins, null, '\t'));
|
||||
}
|
||||
|
||||
updatePlugins();
|
||||
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
|
||||
import DetailsCard from '../common/DetailsCard';
|
||||
import { Plugin, PluginWithRepository } from '../../data/plugins';
|
||||
import { RepositoryById } from '../../data/pluginRepositories';
|
||||
|
||||
function PluginDetails({ plugin }: { plugin: Plugin | PluginWithRepository }) {
|
||||
const repository = 'repository' in plugin ? RepositoryById(plugin.repository) : null;
|
||||
// TODO: Add filtering?
|
||||
if (repository.unstable) return;
|
||||
|
||||
const targetAbi = plugin.versions.find((version) => version.targetAbi)?.targetAbi ?? null;
|
||||
const latestVersion = plugin.versions.find((version) => version.sourceUrl && version.version) ?? null;
|
||||
|
||||
return (
|
||||
<DetailsCard
|
||||
id={plugin.guid}
|
||||
title={plugin.name}
|
||||
badges={
|
||||
<>
|
||||
{repository.official ? (
|
||||
<span className='badge badge--primary margin-right--sm'>Official</span>
|
||||
) : (
|
||||
<span className='badge badge--secondary margin-right--sm'>Third Party</span>
|
||||
)}
|
||||
{repository.unstable && <span className='badge badge--warning margin-right--sm'>Unstable</span>}
|
||||
|
||||
<span className='badge badge--secondary margin-right--sm'>{plugin.category}</span>
|
||||
{targetAbi && <span className='badge badge--secondary margin-right--sm'>{targetAbi}</span>}
|
||||
</>
|
||||
}
|
||||
description={plugin.description}
|
||||
primaryButtons={[
|
||||
latestVersion && (
|
||||
<a key='download' href={latestVersion.sourceUrl} className='button button--primary'>
|
||||
Download {latestVersion.version}
|
||||
</a>
|
||||
)
|
||||
]}
|
||||
// description={<pre>{JSON.stringify(plugin, null, '\t')}</pre>}
|
||||
// footerDetails={<img src={plugin.imageUrl} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default PluginDetails;
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
|
||||
import { Plugin } from '../../data/plugins';
|
||||
import PluginDetails from './PluginDetails';
|
||||
|
||||
const PluginList = ({ plugins }: { plugins: Array<Plugin> }) => (
|
||||
<>
|
||||
{plugins.map((plugin) => (
|
||||
<PluginDetails key={plugin.guid} plugin={plugin} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
export default PluginList;
|
||||
@@ -2,43 +2,34 @@ import React from 'react';
|
||||
|
||||
import DetailsCard from '../common/DetailsCard';
|
||||
import { PluginRepository } from '../../data/pluginRepositories';
|
||||
import { PluginsForRepository } from '../../data/plugins';
|
||||
|
||||
const PluginRepositoryDetails = ({ repository }: { repository: PluginRepository }) => (
|
||||
<DetailsCard
|
||||
id={repository.id}
|
||||
title={repository.name}
|
||||
badges={
|
||||
<>
|
||||
{repository.official ? (
|
||||
<span className='badge badge--primary margin-right--sm'>Official</span>
|
||||
) : (
|
||||
<span className='badge badge--secondary margin-right--sm'>Third Party</span>
|
||||
)}
|
||||
{repository.unstable && <span className='badge badge--warning margin-right--sm'>Unstable</span>}
|
||||
</>
|
||||
}
|
||||
description={
|
||||
<>
|
||||
<span>Repository URL</span>
|
||||
<pre>{repository.url}</pre>
|
||||
function PluginRepositoryDetails({ repository }: { repository: PluginRepository }) {
|
||||
const plugins = PluginsForRepository(repository.id);
|
||||
|
||||
{Object.entries(repository.includes).length > 0 && (
|
||||
<>
|
||||
<h4>Includes</h4>
|
||||
<ul>
|
||||
{Object.entries(repository.includes).map(([name, url]) => (
|
||||
<li key={url}>
|
||||
<a href={url} target='_blank' rel='noreferrer'>
|
||||
{name}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<DetailsCard
|
||||
id={repository.id}
|
||||
title={repository.name}
|
||||
badges={
|
||||
<>
|
||||
{repository.official ? (
|
||||
<span className='badge badge--primary margin-right--sm'>Official</span>
|
||||
) : (
|
||||
<span className='badge badge--secondary margin-right--sm'>Third Party</span>
|
||||
)}
|
||||
{repository.unstable && <span className='badge badge--warning margin-right--sm'>Unstable</span>}
|
||||
</>
|
||||
}
|
||||
description={
|
||||
<>
|
||||
<span>Repository URL</span>
|
||||
<pre>{repository.url}</pre>
|
||||
Included plugins: {plugins.map((plugin) => plugin.name).join(', ')}.
|
||||
</>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default PluginRepositoryDetails;
|
||||
|
||||
@@ -99,3 +99,10 @@ export const ThirdPartyRepositories: Array<PluginRepository> = [
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
export const AllPluginRepositories: Array<PluginRepository> = [
|
||||
...OfficialPluginRepositories,
|
||||
...ThirdPartyRepositories
|
||||
];
|
||||
|
||||
export const RepositoryById = (id: string) => AllPluginRepositories.find((repository) => repository.id === id) ?? null;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,39 @@
|
||||
import GeneratedPlugins from './plugins.generated.json';
|
||||
|
||||
export type PluginManifest = Array<Plugin>;
|
||||
|
||||
export type Plugin = {
|
||||
guid: string;
|
||||
name: string;
|
||||
description: string;
|
||||
overview: string;
|
||||
category: string;
|
||||
owner: string;
|
||||
imageUrl?: string;
|
||||
versions: Array<PluginVersion>;
|
||||
};
|
||||
|
||||
export type PluginWithRepository = Plugin & { repository: string };
|
||||
|
||||
export type PluginVersion = {
|
||||
changelog?: string;
|
||||
targetAbi?: string;
|
||||
sourceUrl?: string;
|
||||
checksum?: string;
|
||||
timestamp?: string;
|
||||
version?: string;
|
||||
};
|
||||
|
||||
type GeneratedPlugin = {
|
||||
repository: string;
|
||||
plugin: Plugin;
|
||||
};
|
||||
|
||||
export const Plugins: Array<PluginWithRepository> = (GeneratedPlugins as GeneratedPlugin[]).map(
|
||||
({ repository, plugin }) => ({ ...plugin, repository })
|
||||
);
|
||||
|
||||
export const PluginsForRepository = (repository: string) =>
|
||||
(GeneratedPlugins as GeneratedPlugin[])
|
||||
.filter((plugin) => plugin.repository === repository)
|
||||
.map(({ plugin }) => plugin);
|
||||
Reference in New Issue
Block a user