feat(domain): naming template engine (Jinja safe subset, MP variables, path layout)
- naming/engine: lexer/parser/AST/render for {{ }} / if-elif-else / whitelisted filters
(default pad pad2 upper lower trim replace truncate date join); rejects for/set/attribute/
subscript/call/~/% with line:col errors and 'did you mean' hints
- naming/variables: variable table aligned with MoviePilot names plus ours (cut, airDate,
issue, slotName, libraryRoot ...); buildNamingVars from parsed release + entity + units
- naming/layout: split by literal '/', segment roles (category/root/season/sub/file),
value escaping, reserved names, 255-byte segments, validateNamingTemplate
- naming/defaults: MP default movie/tv + our variety template, v1 syntax upgrade,
entity > root > global override resolution, builtin preview samples
- path/binding: resolveTargetDirectory keeps bound dirs, only unbound segments render;
renderMediaFileName = last segment of the full template; DEFAULT_TEMPLATES = MP v2
- differential: 34 cases vs MP (21 identical, 13 documented deviations)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
e8745115f4
commit
f7c75ad781
22 files changed
+2674
-281
No files matched your search
@@ -206,8 +206,8 @@ describe.skipIf(!hasPg)("E7 常规剧集纵切", () => {
|
||||
expect(existsSync(join(e.lib.root, f.target_path!))).toBe(true);
|
||||
}
|
||||
expect(files.map((f) => f.target_path!)).toEqual([
|
||||
expect.stringMatching(/S01E01\.mkv$/),
|
||||
expect.stringMatching(/S01E02\.mkv$/),
|
||||
expect.stringMatching(/S01E01 - 第 1 集\.mkv$/),
|
||||
expect.stringMatching(/S01E02 - 第 2 集\.mkv$/),
|
||||
]);
|
||||
// 路径绑定固定:没有因为第二集新建任何绑定
|
||||
const bindings1 = await e.db
|
||||
|
||||
@@ -242,7 +242,7 @@ describe.skipIf(skip)("files W5-A2", () => {
|
||||
const tv = groups.find((g: { mediaEntityId: string }) => g.mediaEntityId === series);
|
||||
const mv = groups.find((g: { mediaEntityId: string }) => g.mediaEntityId === film);
|
||||
const tvTargets = tv.files.map((f: { target: string | null }) => f.target);
|
||||
expect(tvTargets.some((t: string | null) => t?.endsWith("Season 2/剧 - S02E03-E04.mkv"))).toBe(true);
|
||||
expect(tvTargets.some((t: string | null) => t?.endsWith("Season 2/剧 - S02E03-E04 - 第 3-4 集.mkv"))).toBe(true);
|
||||
// 非连续集号不应用(只按季覆写,文件名无集号 → 计划排除),其余覆写不进 warnings
|
||||
expect(tv.warnings).toEqual([expect.stringMatching(/weird-b\.mkv: 集号 5,7 不连续/)]);
|
||||
expect(mv.warnings).toEqual([expect.stringMatching(/电影不适用季\/集覆写/)]);
|
||||
|
||||
Reference in new issue
Block a user