feat(m3u): support #KODIPROP lines placed before #EXTINF (#1234)

* 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>
This commit is contained in:
4grayandClaude Fable 5 authored and GitHub committed 2026-07-25 11:43:58 +02:00
1 parent f852bc7459
commit 0ee73f2d0f
5 files changed
+70 -140

No files matched your search

+19 -130
View File
@@ -123,8 +123,8 @@ importers:
specifier: 1.6.13
version: 1.6.13
iptv-playlist-parser:
specifier: github:4gray/iptv-playlist-parser#v0.15.2-iptvnator.1
version: https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/33f5e9c09539524d758901c02a6f29302833c0a4
specifier: github:4gray/iptv-playlist-parser#v0.15.2-iptvnator.2
version: https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/d547b6be8a44431c85fbcbcdefb41f28c0dadf6d
marked:
specifier: 18.0.5
version: 18.0.5
@@ -398,7 +398,7 @@ importers:
version: 30.2.0
jest-preset-angular:
specifier: ~15.0.0
version: 15.0.3(c17320d959ee89222a5c83bff087787c)
version: 15.0.3(75c2f4d3e02d43367177c3c83cdeef78)
jest-util:
specifier: ^30.0.2
version: 30.2.0
@@ -431,7 +431,7 @@ importers:
version: 3.4.19(tsx@4.21.0)(yaml@2.8.2)
ts-jest:
specifier: ^29.4.5
version: 29.4.6(@babel/core@7.29.7)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.7))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3)
version: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3)
ts-node:
specifier: 10.9.2
version: 10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)
@@ -7578,9 +7578,9 @@ packages:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'}
iptv-playlist-parser@https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/33f5e9c09539524d758901c02a6f29302833c0a4:
resolution: {tarball: https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/33f5e9c09539524d758901c02a6f29302833c0a4}
version: 0.15.2-iptvnator.1
iptv-playlist-parser@https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/d547b6be8a44431c85fbcbcdefb41f28c0dadf6d:
resolution: {tarball: https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/d547b6be8a44431c85fbcbcdefb41f28c0dadf6d}
version: 0.15.2-iptvnator.2
engines: {node: '>=18'}
iron-webcrypto@1.2.1:
@@ -10508,7 +10508,6 @@ packages:
shaka-player@5.2.1:
resolution: {integrity: sha512-Sj8Kg94Ws8hUxzjHnC570o1jQcZwB7OxIwi25vLI3mOVmL8xpso3HyIqM7hjbgAhsOgdFojpJYwtcvR/t0a9vA==}
engines: {node: '>=18'}
shallow-clone@3.0.1:
resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==}
@@ -12877,12 +12876,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12893,12 +12886,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12909,12 +12896,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12925,12 +12906,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-decorators@7.27.1(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12951,12 +12926,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12967,12 +12936,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -12983,12 +12946,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13009,12 +12966,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13025,12 +12976,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13041,12 +12986,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13057,12 +12996,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13073,12 +13006,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13089,12 +13016,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13105,12 +13026,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -13121,12 +13036,6 @@ snapshots:
'@babel/core': 7.29.0
'@babel/helper-plugin-utils': 7.27.1
'@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.7)':
dependencies:
'@babel/core': 7.29.7
'@babel/helper-plugin-utils': 7.27.1
optional: true
'@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.5)':
dependencies:
'@babel/core': 7.28.5
@@ -17719,13 +17628,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
babel-jest@30.2.0(@babel/core@7.29.7):
babel-jest@30.2.0(@babel/core@7.29.0):
dependencies:
'@babel/core': 7.29.7
'@babel/core': 7.29.0
'@jest/transform': 30.2.0
'@types/babel__core': 7.20.5
babel-plugin-istanbul: 7.0.1
babel-preset-jest: 30.2.0(@babel/core@7.29.7)
babel-preset-jest: 30.2.0(@babel/core@7.29.0)
chalk: 4.1.2
graceful-fs: 4.2.11
slash: 3.0.0
@@ -17838,37 +17747,17 @@ snapshots:
'@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.0)
'@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.0)
babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7):
dependencies:
'@babel/core': 7.29.7
'@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.29.7)
'@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.29.7)
'@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.29.7)
'@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.29.7)
'@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.29.7)
'@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.29.7)
'@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.29.7)
'@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.29.7)
'@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.29.7)
'@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.29.7)
optional: true
babel-preset-jest@30.2.0(@babel/core@7.28.5):
dependencies:
'@babel/core': 7.28.5
babel-plugin-jest-hoist: 30.2.0
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.28.5)
babel-preset-jest@30.2.0(@babel/core@7.29.7):
babel-preset-jest@30.2.0(@babel/core@7.29.0):
dependencies:
'@babel/core': 7.29.7
'@babel/core': 7.29.0
babel-plugin-jest-hoist: 30.2.0
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7)
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.0)
optional: true
bail@2.0.2: {}
@@ -20652,7 +20541,7 @@ snapshots:
ipaddr.js@2.3.0: {}
iptv-playlist-parser@https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/33f5e9c09539524d758901c02a6f29302833c0a4: {}
iptv-playlist-parser@https://codeload.github.com/4gray/iptv-playlist-parser/tar.gz/d547b6be8a44431c85fbcbcdefb41f28c0dadf6d: {}
iron-webcrypto@1.2.1: {}
@@ -21095,7 +20984,7 @@ snapshots:
optionalDependencies:
jest-resolve: 30.2.0
jest-preset-angular@15.0.3(c17320d959ee89222a5c83bff087787c):
jest-preset-angular@15.0.3(75c2f4d3e02d43367177c3c83cdeef78):
dependencies:
'@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3)
'@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.15.1)
@@ -21108,7 +20997,7 @@ snapshots:
jest-util: 30.2.0
jsdom: 26.1.0
pretty-format: 30.2.0
ts-jest: 29.4.6(@babel/core@7.29.7)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.7))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3)
ts-jest: 29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3)
typescript: 5.9.3
optionalDependencies:
esbuild: 0.28.1
@@ -24994,7 +24883,7 @@ snapshots:
ts-interface-checker@0.1.13: {}
ts-jest@29.4.6(@babel/core@7.29.7)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.7))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3):
ts-jest@29.4.6(@babel/core@7.29.0)(@jest/transform@30.2.0)(@jest/types@30.2.0)(babel-jest@30.2.0(@babel/core@7.29.0))(esbuild@0.28.1)(jest-util@30.2.0)(jest@30.2.0(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)))(typescript@5.9.3):
dependencies:
bs-logger: 0.2.6
fast-json-stable-stringify: 2.1.0
@@ -25008,10 +24897,10 @@ snapshots:
typescript: 5.9.3
yargs-parser: 21.1.1
optionalDependencies:
'@babel/core': 7.29.7
'@babel/core': 7.29.0
'@jest/transform': 30.2.0
'@jest/types': 30.2.0
babel-jest: 30.2.0(@babel/core@7.29.7)
babel-jest: 30.2.0(@babel/core@7.29.0)
esbuild: 0.28.1
jest-util: 30.2.0