ani-client 1.5.1 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,13 @@
1
- # ani-client
1
+ # ani-client
2
2
 
3
+ ![ani-client logo](docs/public/assets/logo.png)
3
4
  [![CI](https://github.com/gonzyui/ani-client/actions/workflows/ci.yml/badge.svg)](https://github.com/gonzyui/ani-client/actions/workflows/ci.yml)
4
5
  [![npm](https://img.shields.io/npm/v/ani-client)](https://www.npmjs.com/package/ani-client)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
7
 
7
8
  > A simple, typed client to fetch anime, manga, character, staff and user data from [AniList](https://anilist.co).
8
9
 
9
- ✨ **Showcase**: [Check here](https://docs-aniclient.gonzyuidev.xyz/showcase) to see which projects use this package!
10
+ ✨ **Showcase**: [Check here](https://ani-client.js.org/showcase) to see which projects use this package!
10
11
 
11
12
  - **Zero dependencies** — uses the native `fetch` API
12
13
  - **Universal** — Node.js ≥ 20, Bun, Deno and modern browsers
@@ -17,7 +18,7 @@
17
18
 
18
19
  The full API reference, usage guide, and configuration examples are available on our official documentation website!
19
20
 
20
- **[👉 View the full documentation here](https://docs-aniclient.gonzyuidev.xyz/)**
21
+ **[👉 View the full documentation here](https://ani-client.js.org)**
21
22
 
22
23
  ## Install
23
24
 
@@ -55,6 +56,43 @@ const results = await client.searchMedia({
55
56
  console.log(results.results.map((m) => m.title.english));
56
57
  ```
57
58
 
59
+ ### Fetch user favorites
60
+
61
+ ```ts
62
+ const favs = await client.getUserFavorites("AniList");
63
+
64
+ favs.anime.forEach((a) => console.log(a.title.romaji));
65
+ favs.characters.forEach((c) => console.log(c.name.full));
66
+ ```
67
+
68
+ ### Monitor rate limits
69
+
70
+ ```ts
71
+ const client = new AniListClient({
72
+ rateLimit: {
73
+ retryStrategy: (attempt) => (attempt + 1) * 1000, // linear backoff
74
+ },
75
+ });
76
+
77
+ await client.getMedia(1);
78
+
79
+ const info = client.rateLimitInfo;
80
+ console.log(`${info?.remaining}/${info?.limit} requests remaining`);
81
+
82
+ const meta = client.lastRequestMeta;
83
+ console.log(`${meta?.durationMs}ms, cache: ${meta?.fromCache}`);
84
+ ```
85
+
86
+ ### Cancel requests
87
+
88
+ ```ts
89
+ const controller = new AbortController();
90
+ const client = new AniListClient({ signal: controller.signal });
91
+
92
+ setTimeout(() => controller.abort(), 5_000);
93
+ await client.getMedia(1); // aborted after 5s
94
+ ```
95
+
58
96
  ## Contributing
59
97
 
60
98
  See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and how to submit changes.
package/dist/index.d.mts CHANGED
@@ -67,6 +67,16 @@ interface RateLimitOptions {
67
67
  timeoutMs?: number;
68
68
  /** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
69
69
  retryOnNetworkError?: boolean;
70
+ /**
71
+ * Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
72
+ * and should return the delay in ms before retrying.
73
+ * When omitted, the default exponential backoff with jitter is used.
74
+ *
75
+ * @example
76
+ * // Linear backoff: 1s, 2s, 3s, ...
77
+ * retryStrategy: (attempt) => (attempt + 1) * 1000
78
+ */
79
+ retryStrategy?: (attempt: number, baseDelayMs: number) => number;
70
80
  }
71
81
  /** Event hooks for logging, debugging, and monitoring. */
72
82
  interface AniListHooks {
@@ -79,7 +89,27 @@ interface AniListHooks {
79
89
  /** Called when a request is retried (429 or network error). */
80
90
  onRetry?: (attempt: number, reason: string, delayMs: number) => void;
81
91
  /** Called when a request completes. */
82
- onResponse?: (query: string, durationMs: number, fromCache: boolean) => void;
92
+ onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
93
+ /** Called when a request fails with an error. */
94
+ onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
95
+ }
96
+ /** Rate limit information parsed from AniList API response headers. */
97
+ interface RateLimitInfo {
98
+ /** Maximum number of requests allowed per window. */
99
+ limit: number;
100
+ /** Remaining requests in the current window. */
101
+ remaining: number;
102
+ /** UNIX timestamp (seconds) when the rate limit window resets. */
103
+ reset: number;
104
+ }
105
+ /** Metadata about the last request, useful for debugging and monitoring. */
106
+ interface ResponseMeta {
107
+ /** Duration of the request in milliseconds. */
108
+ durationMs: number;
109
+ /** Whether the response was served from cache. */
110
+ fromCache: boolean;
111
+ /** Rate limit information from the API response headers (not present for cached responses). */
112
+ rateLimitInfo?: RateLimitInfo;
83
113
  }
84
114
  interface AniListClientOptions {
85
115
  /** Optional AniList OAuth token for authenticated requests */
@@ -94,6 +124,8 @@ interface AniListClientOptions {
94
124
  rateLimit?: RateLimitOptions;
95
125
  /** Event hooks for logging, debugging, and monitoring */
96
126
  hooks?: AniListHooks;
127
+ /** Optional AbortSignal to cancel all requests made by this client */
128
+ signal?: AbortSignal;
97
129
  }
98
130
 
99
131
  declare enum StaffSort {
@@ -409,6 +441,58 @@ interface SearchUserOptions {
409
441
  page?: number;
410
442
  perPage?: number;
411
443
  }
444
+ interface FavoriteMediaNode {
445
+ id: number;
446
+ title: {
447
+ romaji: string | null;
448
+ english: string | null;
449
+ native: string | null;
450
+ userPreferred: string | null;
451
+ };
452
+ coverImage: {
453
+ large: string | null;
454
+ medium: string | null;
455
+ };
456
+ type: string | null;
457
+ format: string | null;
458
+ siteUrl: string | null;
459
+ }
460
+ interface FavoriteCharacterNode {
461
+ id: number;
462
+ name: {
463
+ full: string | null;
464
+ native: string | null;
465
+ };
466
+ image: {
467
+ large: string | null;
468
+ medium: string | null;
469
+ };
470
+ siteUrl: string | null;
471
+ }
472
+ interface FavoriteStaffNode {
473
+ id: number;
474
+ name: {
475
+ full: string | null;
476
+ native: string | null;
477
+ };
478
+ image: {
479
+ large: string | null;
480
+ medium: string | null;
481
+ };
482
+ siteUrl: string | null;
483
+ }
484
+ interface FavoriteStudioNode {
485
+ id: number;
486
+ name: string;
487
+ siteUrl: string | null;
488
+ }
489
+ interface UserFavorites {
490
+ anime: FavoriteMediaNode[];
491
+ manga: FavoriteMediaNode[];
492
+ characters: FavoriteCharacterNode[];
493
+ staff: FavoriteStaffNode[];
494
+ studios: FavoriteStudioNode[];
495
+ }
412
496
 
413
497
  declare enum MediaType {
414
498
  ANIME = "ANIME",
@@ -877,8 +961,21 @@ declare class AniListClient {
877
961
  private readonly cacheAdapter;
878
962
  private readonly rateLimiter;
879
963
  private readonly hooks;
964
+ private readonly signal?;
880
965
  private readonly inFlight;
966
+ private _rateLimitInfo?;
967
+ private _lastRequestMeta?;
881
968
  constructor(options?: AniListClientOptions);
969
+ /**
970
+ * The current rate limit information from the last API response.
971
+ * Updated after every non-cached request.
972
+ */
973
+ get rateLimitInfo(): RateLimitInfo | undefined;
974
+ /**
975
+ * Metadata about the last request (duration, cache status, rate limit info).
976
+ * Useful for debugging and monitoring.
977
+ */
978
+ get lastRequestMeta(): ResponseMeta | undefined;
882
979
  /** @internal */
883
980
  request<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
884
981
  /** @internal */
@@ -937,6 +1034,19 @@ declare class AniListClient {
937
1034
  searchUsers(options?: SearchUserOptions): Promise<PagedResult<User>>;
938
1035
  /** Get a user's anime or manga list. */
939
1036
  getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>>;
1037
+ /**
1038
+ * Fetch a user's favorite anime, manga, characters, staff, and studios.
1039
+ *
1040
+ * @param idOrName - AniList user ID (number) or username (string)
1041
+ * @returns The user's favorites grouped by category
1042
+ *
1043
+ * @example
1044
+ * ```typescript
1045
+ * const favs = await client.getUserFavorites("AniList");
1046
+ * favs.anime.forEach(a => console.log(a.title.romaji));
1047
+ * ```
1048
+ */
1049
+ getUserFavorites(idOrName: number | string): Promise<UserFavorites>;
940
1050
  /** Fetch a studio by its AniList ID. */
941
1051
  getStudio(id: number): Promise<Studio>;
942
1052
  /** Search for studios by name. */
@@ -969,7 +1079,7 @@ declare class AniListClient {
969
1079
  /** Clear the entire response cache. */
970
1080
  clearCache(): Promise<void>;
971
1081
  /** Number of entries currently in the cache. */
972
- get cacheSize(): number | Promise<number>;
1082
+ cacheSize(): Promise<number>;
973
1083
  /** Remove cache entries whose key matches the given pattern. */
974
1084
  invalidateCache(pattern: string | RegExp): Promise<number>;
975
1085
  /** Clean up resources held by the client. */
@@ -1106,10 +1216,13 @@ declare class RateLimiter {
1106
1216
  private readonly enabled;
1107
1217
  private readonly timeoutMs;
1108
1218
  private readonly retryOnNetworkError;
1219
+ private readonly retryStrategy?;
1109
1220
  /** @internal — sliding window: circular buffer of timestamps */
1110
1221
  private readonly timestamps;
1111
1222
  private head;
1112
1223
  private count;
1224
+ /** @internal — active sleep timers for cleanup */
1225
+ private readonly activeTimers;
1113
1226
  constructor(options?: RateLimitOptions);
1114
1227
  /**
1115
1228
  * Wait until it's safe to make a request (respects rate limit window).
@@ -1123,20 +1236,28 @@ declare class RateLimiter {
1123
1236
  onRetry?: (attempt: number, reason: string, delayMs: number) => void;
1124
1237
  onRateLimit?: (retryAfterMs: number) => void;
1125
1238
  }): Promise<Response>;
1126
- /** @internal — Exponential backoff with jitter, capped at 30s */
1239
+ /** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */
1127
1240
  private exponentialDelay;
1128
1241
  /** @internal */
1129
1242
  private fetchWithTimeout;
1130
1243
  private sleep;
1244
+ /** Cancel all pending sleep timers and reset internal state. */
1245
+ dispose(): void;
1131
1246
  }
1132
1247
 
1133
1248
  /**
1134
1249
  * Parses AniList specific markdown into standard HTML.
1135
- * Includes formatting for spoilers, images, videos (youtube/webm), and standard markdown elements.
1250
+ * Includes formatting for spoilers, images, videos (youtube/webm), headings,
1251
+ * lists, code blocks, and standard markdown elements.
1252
+ *
1253
+ * @security This function escapes HTML entities to prevent XSS attacks.
1254
+ * However, the output is still raw HTML — consumers should always use a
1255
+ * Content Security Policy and consider additional sanitization when rendering
1256
+ * user-generated content in a browser.
1136
1257
  *
1137
1258
  * @param text The AniList markdown text to parse
1138
1259
  * @returns The parsed HTML string
1139
1260
  */
1140
1261
  declare function parseAniListMarkdown(text: string): string;
1141
1262
 
1142
- export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
1263
+ export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,16 @@ interface RateLimitOptions {
67
67
  timeoutMs?: number;
68
68
  /** Retry on network errors like ECONNRESET / ETIMEDOUT (default: true) */
69
69
  retryOnNetworkError?: boolean;
70
+ /**
71
+ * Custom retry delay strategy. Receives the attempt number (0-based) and the base delay,
72
+ * and should return the delay in ms before retrying.
73
+ * When omitted, the default exponential backoff with jitter is used.
74
+ *
75
+ * @example
76
+ * // Linear backoff: 1s, 2s, 3s, ...
77
+ * retryStrategy: (attempt) => (attempt + 1) * 1000
78
+ */
79
+ retryStrategy?: (attempt: number, baseDelayMs: number) => number;
70
80
  }
71
81
  /** Event hooks for logging, debugging, and monitoring. */
72
82
  interface AniListHooks {
@@ -79,7 +89,27 @@ interface AniListHooks {
79
89
  /** Called when a request is retried (429 or network error). */
80
90
  onRetry?: (attempt: number, reason: string, delayMs: number) => void;
81
91
  /** Called when a request completes. */
82
- onResponse?: (query: string, durationMs: number, fromCache: boolean) => void;
92
+ onResponse?: (query: string, durationMs: number, fromCache: boolean, rateLimitInfo?: RateLimitInfo) => void;
93
+ /** Called when a request fails with an error. */
94
+ onError?: (error: Error, query: string, variables: Record<string, unknown>) => void;
95
+ }
96
+ /** Rate limit information parsed from AniList API response headers. */
97
+ interface RateLimitInfo {
98
+ /** Maximum number of requests allowed per window. */
99
+ limit: number;
100
+ /** Remaining requests in the current window. */
101
+ remaining: number;
102
+ /** UNIX timestamp (seconds) when the rate limit window resets. */
103
+ reset: number;
104
+ }
105
+ /** Metadata about the last request, useful for debugging and monitoring. */
106
+ interface ResponseMeta {
107
+ /** Duration of the request in milliseconds. */
108
+ durationMs: number;
109
+ /** Whether the response was served from cache. */
110
+ fromCache: boolean;
111
+ /** Rate limit information from the API response headers (not present for cached responses). */
112
+ rateLimitInfo?: RateLimitInfo;
83
113
  }
84
114
  interface AniListClientOptions {
85
115
  /** Optional AniList OAuth token for authenticated requests */
@@ -94,6 +124,8 @@ interface AniListClientOptions {
94
124
  rateLimit?: RateLimitOptions;
95
125
  /** Event hooks for logging, debugging, and monitoring */
96
126
  hooks?: AniListHooks;
127
+ /** Optional AbortSignal to cancel all requests made by this client */
128
+ signal?: AbortSignal;
97
129
  }
98
130
 
99
131
  declare enum StaffSort {
@@ -409,6 +441,58 @@ interface SearchUserOptions {
409
441
  page?: number;
410
442
  perPage?: number;
411
443
  }
444
+ interface FavoriteMediaNode {
445
+ id: number;
446
+ title: {
447
+ romaji: string | null;
448
+ english: string | null;
449
+ native: string | null;
450
+ userPreferred: string | null;
451
+ };
452
+ coverImage: {
453
+ large: string | null;
454
+ medium: string | null;
455
+ };
456
+ type: string | null;
457
+ format: string | null;
458
+ siteUrl: string | null;
459
+ }
460
+ interface FavoriteCharacterNode {
461
+ id: number;
462
+ name: {
463
+ full: string | null;
464
+ native: string | null;
465
+ };
466
+ image: {
467
+ large: string | null;
468
+ medium: string | null;
469
+ };
470
+ siteUrl: string | null;
471
+ }
472
+ interface FavoriteStaffNode {
473
+ id: number;
474
+ name: {
475
+ full: string | null;
476
+ native: string | null;
477
+ };
478
+ image: {
479
+ large: string | null;
480
+ medium: string | null;
481
+ };
482
+ siteUrl: string | null;
483
+ }
484
+ interface FavoriteStudioNode {
485
+ id: number;
486
+ name: string;
487
+ siteUrl: string | null;
488
+ }
489
+ interface UserFavorites {
490
+ anime: FavoriteMediaNode[];
491
+ manga: FavoriteMediaNode[];
492
+ characters: FavoriteCharacterNode[];
493
+ staff: FavoriteStaffNode[];
494
+ studios: FavoriteStudioNode[];
495
+ }
412
496
 
413
497
  declare enum MediaType {
414
498
  ANIME = "ANIME",
@@ -877,8 +961,21 @@ declare class AniListClient {
877
961
  private readonly cacheAdapter;
878
962
  private readonly rateLimiter;
879
963
  private readonly hooks;
964
+ private readonly signal?;
880
965
  private readonly inFlight;
966
+ private _rateLimitInfo?;
967
+ private _lastRequestMeta?;
881
968
  constructor(options?: AniListClientOptions);
969
+ /**
970
+ * The current rate limit information from the last API response.
971
+ * Updated after every non-cached request.
972
+ */
973
+ get rateLimitInfo(): RateLimitInfo | undefined;
974
+ /**
975
+ * Metadata about the last request (duration, cache status, rate limit info).
976
+ * Useful for debugging and monitoring.
977
+ */
978
+ get lastRequestMeta(): ResponseMeta | undefined;
882
979
  /** @internal */
883
980
  request<T>(query: string, variables?: Record<string, unknown>): Promise<T>;
884
981
  /** @internal */
@@ -937,6 +1034,19 @@ declare class AniListClient {
937
1034
  searchUsers(options?: SearchUserOptions): Promise<PagedResult<User>>;
938
1035
  /** Get a user's anime or manga list. */
939
1036
  getUserMediaList(options: GetUserMediaListOptions): Promise<PagedResult<MediaListEntry>>;
1037
+ /**
1038
+ * Fetch a user's favorite anime, manga, characters, staff, and studios.
1039
+ *
1040
+ * @param idOrName - AniList user ID (number) or username (string)
1041
+ * @returns The user's favorites grouped by category
1042
+ *
1043
+ * @example
1044
+ * ```typescript
1045
+ * const favs = await client.getUserFavorites("AniList");
1046
+ * favs.anime.forEach(a => console.log(a.title.romaji));
1047
+ * ```
1048
+ */
1049
+ getUserFavorites(idOrName: number | string): Promise<UserFavorites>;
940
1050
  /** Fetch a studio by its AniList ID. */
941
1051
  getStudio(id: number): Promise<Studio>;
942
1052
  /** Search for studios by name. */
@@ -969,7 +1079,7 @@ declare class AniListClient {
969
1079
  /** Clear the entire response cache. */
970
1080
  clearCache(): Promise<void>;
971
1081
  /** Number of entries currently in the cache. */
972
- get cacheSize(): number | Promise<number>;
1082
+ cacheSize(): Promise<number>;
973
1083
  /** Remove cache entries whose key matches the given pattern. */
974
1084
  invalidateCache(pattern: string | RegExp): Promise<number>;
975
1085
  /** Clean up resources held by the client. */
@@ -1106,10 +1216,13 @@ declare class RateLimiter {
1106
1216
  private readonly enabled;
1107
1217
  private readonly timeoutMs;
1108
1218
  private readonly retryOnNetworkError;
1219
+ private readonly retryStrategy?;
1109
1220
  /** @internal — sliding window: circular buffer of timestamps */
1110
1221
  private readonly timestamps;
1111
1222
  private head;
1112
1223
  private count;
1224
+ /** @internal — active sleep timers for cleanup */
1225
+ private readonly activeTimers;
1113
1226
  constructor(options?: RateLimitOptions);
1114
1227
  /**
1115
1228
  * Wait until it's safe to make a request (respects rate limit window).
@@ -1123,20 +1236,28 @@ declare class RateLimiter {
1123
1236
  onRetry?: (attempt: number, reason: string, delayMs: number) => void;
1124
1237
  onRateLimit?: (retryAfterMs: number) => void;
1125
1238
  }): Promise<Response>;
1126
- /** @internal — Exponential backoff with jitter, capped at 30s */
1239
+ /** @internal — Exponential backoff with jitter, capped at 30s (or custom strategy) */
1127
1240
  private exponentialDelay;
1128
1241
  /** @internal */
1129
1242
  private fetchWithTimeout;
1130
1243
  private sleep;
1244
+ /** Cancel all pending sleep timers and reset internal state. */
1245
+ dispose(): void;
1131
1246
  }
1132
1247
 
1133
1248
  /**
1134
1249
  * Parses AniList specific markdown into standard HTML.
1135
- * Includes formatting for spoilers, images, videos (youtube/webm), and standard markdown elements.
1250
+ * Includes formatting for spoilers, images, videos (youtube/webm), headings,
1251
+ * lists, code blocks, and standard markdown elements.
1252
+ *
1253
+ * @security This function escapes HTML entities to prevent XSS attacks.
1254
+ * However, the output is still raw HTML — consumers should always use a
1255
+ * Content Security Policy and consider additional sanitization when rendering
1256
+ * user-generated content in a browser.
1136
1257
  *
1137
1258
  * @param text The AniList markdown text to parse
1138
1259
  * @returns The parsed HTML string
1139
1260
  */
1140
1261
  declare function parseAniListMarkdown(text: string): string;
1141
1262
 
1142
- export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };
1263
+ export { type AiringSchedule, AiringSort, AniListClient, type AniListClientOptions, AniListError, type AniListHooks, type CacheAdapter, type CacheOptions, type Character, type CharacterImage, type CharacterIncludeOptions, type CharacterMediaEdge, type CharacterName, CharacterRole, CharacterSort, type DayOfWeek, type ExternalLink, type FavoriteCharacterNode, type FavoriteMediaNode, type FavoriteStaffNode, type FavoriteStudioNode, type FuzzyDate, type GetAiringOptions, type GetPlanningOptions, type GetRecentChaptersOptions, type GetRecommendationsOptions, type GetSeasonOptions, type GetUserMediaListOptions, type Media, type MediaCharacterConnection, type MediaCharacterEdge, type MediaConnection, type MediaCoverImage, type MediaEdge, MediaFormat, type MediaIncludeOptions, type MediaListEntry, MediaListSort, MediaListStatus, type MediaRecommendationNode, MediaRelationType, MediaSeason, MediaSort, MediaSource, type MediaStaffConnection, type MediaStaffEdge, type MediaStats, MediaStatus, type MediaTag, type MediaTitle, type MediaTrailer, MediaType, MemoryCache, type NextAiringEpisode, type PageInfo, type PagedResult, type RateLimitInfo, type RateLimitOptions, RateLimiter, type Recommendation, RecommendationSort, RedisCache, type RedisCacheOptions, type RedisLikeClient, type ResponseMeta, type ScoreDistribution, type SearchCharacterOptions, type SearchMediaOptions, type SearchStaffOptions, type SearchStudioOptions, type SearchThreadOptions, type SearchUserOptions, type Staff, type StaffImage, type StaffIncludeOptions, type StaffMediaNode, type StaffName, StaffSort, type StatusDistribution, type StreamingEpisode, type Studio, type StudioConnection, type Thread, type ThreadCategory, type ThreadMediaCategory, ThreadSort, type User, type UserAvatar, type UserFavorites, UserSort, type UserStatistics, type VoiceActor, type WeeklySchedule, parseAniListMarkdown };