* feat(m3u): support #KODIPROP lines placed before #EXTINF
Bumps the iptv-playlist-parser fork pin to v0.15.2-iptvnator.2: Kodi
property lines apply to the next list entry, so #KODIPROP lines placed
above the #EXTINF are now preserved in item.raw (previously the parser
dropped them and ClearKey config in that layout was lost). The DASH +
ClearKey feature (#1225) extracts license config from item.raw, so both
KODIPROP layouts now work on every import path.
Covered by a parser contract case and an extended web-backend /parse
regression (before-EXTINF + between-EXTINF-and-URL + plain channel).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: reflect before-#EXTINF KODIPROP support in the M3U architecture doc
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: list the KODIPROP delta in the parser-fork inventory
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(m3u): parse playlists with URLs longer than 2084 characters
Pluto TV style playlists (issue #1189) embed a session JWT in every
stream URL (~2200 chars). validator.isURL inside iptv-playlist-parser
rejected anything over its IE-era 2084-char default, and the parser's
stalled item index then collapsed the whole playlist into a single
channel.
Sync the 4gray/iptv-playlist-parser fork with upstream v0.15.2, which
removes URL validation entirely and adds an explicit branch so '#'
comments and unknown directives are never treated as URLs. Two fork
deltas are preserved on top: the radio attribute (radio player
detection) and pipe stripping (item.url is cut at the first '|' while
|User-Agent=/|Referer= params still land in item.http). The now-dead
validator/is-valid-path dependencies are dropped from the fork.
- pin iptv-playlist-parser to the fork commit SHA
- add a parser contract spec guarding long URLs, comment handling,
radio, pipe stripping, and header EPG attrs
- document the parser fork contract in the M3U architecture doc
Fixes#1189
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(m3u): bump parser to optimized fork build
Pulls the fork's optimized parse() rewrite (2.5-3x faster: 100k
channels ~780ms -> ~285ms, 10k ~79ms -> ~25ms) and the README
documenting fork deltas. Output is differential-verified byte-identical
to the previous build; all parser-contract, unit, and import E2E suites
rerun green against the new pin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(m3u): bump parser for input robustness and library hygiene
Pulls the fork's real-world input tolerance: UTF-8 BOM, blank lines and
whitespace before the header, and case-insensitive #EXTM3U no longer
reject the playlist (all VLC-accepted forms); Node Buffers are decoded
as UTF-8 and other non-string input throws a clear TypeError. Also
brings truthful types (url?: string), fork metadata, an enforced 100%
coverage gate, and the fork CHANGELOG.
Extends the contract spec with a BOM regression test.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* chore(m3u): pin parser to the tagged fork release v0.15.2-iptvnator.1
Same commit as before (33f5e9c) — the readable tag replaces the raw
SHA in package.json while pnpm-lock still records the immutable
codeload tarball by commit. Fork release:
https://github.com/4gray/iptv-playlist-parser/releases/tag/v0.15.2-iptvnator.1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(types): make ParsedPlaylistItem.url optional to match runtime
The parser fork's d.ts now truthfully declares url?: string (a trailing
#EXTINF without a stream URL yields url === undefined at runtime, and
always has). The local ParsedPlaylistItem mirrored the old type lie and
made the production typecheck reject the parser's Playlist type.
createChannel and createPlaylistObject already tolerate the absent url.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>