mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-23 12:15:28 -07:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a0aa3ec98
|
||
|
|
b87cc3cfdd
|
||
|
|
8cb3c8c90a
|
||
|
|
03ea903927
|
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: subminer-release
|
||||
description: Prepare, cut, publish, or repair SubMiner stable and prerelease releases. Use for hands-on release work; do not use for general release questions.
|
||||
---
|
||||
|
||||
# SubMiner release
|
||||
|
||||
Carry out the requested release phase using the repository's current release process.
|
||||
|
||||
## Source of truth
|
||||
|
||||
Read `docs/RELEASING.md` completely before changing files or release state. Treat it as canonical. Read `changes/README.md` when the work touches change fragments or generated release notes.
|
||||
|
||||
Do not copy release commands or policy into this skill. If this skill disagrees with the release guide, follow the guide and reconcile the skill before handoff.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Identify whether the request is for a stable release, prerelease, release preparation, publication, or repair.
|
||||
2. Inspect the current branch, worktree status, package version, pending change fragments, relevant tags, and latest CI state before making changes.
|
||||
3. Follow the matching procedure in `docs/RELEASING.md` in order. Review generated changelog and release-note Markdown before it can be committed or published.
|
||||
4. Run every required gate for the requested release phase. Do not treat a cheaper test lane as a substitute for the documented release gate.
|
||||
5. Before a stable tag, confirm the package and tag versions match and no pending `changes/*.md` fragments remain. Preserve fragments for prereleases as documented.
|
||||
6. Report the resulting version, completed checks, local commit and tag state, remote publication state, skipped platform checks, and any remaining manual work.
|
||||
|
||||
## Authorization boundaries
|
||||
|
||||
- A request to prepare a release stops before commit, tag, push, or remote publication unless the user also authorizes those actions.
|
||||
- A clear request to cut or publish a release includes the documented commit, tag, and push steps. Ask before the first remote mutation when the wording is ambiguous.
|
||||
- Do not edit an existing GitHub release, publish to the AUR, change secrets, or alter signing configuration unless the user explicitly requests that operation.
|
||||
- Do not switch branches without consent.
|
||||
|
||||
## Stop conditions
|
||||
|
||||
Stop and report the blocker when required CI or a release gate fails, authentication is missing, versions disagree, required artifacts are absent, or the worktree contains unexpected changes that overlap the release. Do not tag or publish a partially verified release.
|
||||
@@ -49,6 +49,7 @@ tests/*
|
||||
!.agents/skills/
|
||||
.agents/skills/*
|
||||
!.agents/skills/subminer-change-verification/
|
||||
!.agents/skills/subminer-release/
|
||||
!.agents/skills/subminer-scrum-master/
|
||||
.agents/skills/subminer-change-verification/*
|
||||
!.agents/skills/subminer-change-verification/SKILL.md
|
||||
@@ -56,6 +57,8 @@ tests/*
|
||||
.agents/skills/subminer-change-verification/scripts/*
|
||||
!.agents/skills/subminer-change-verification/scripts/classify_subminer_diff.sh
|
||||
!.agents/skills/subminer-change-verification/scripts/verify_subminer_change.sh
|
||||
.agents/skills/subminer-release/*
|
||||
!.agents/skills/subminer-release/SKILL.md
|
||||
.agents/skills/subminer-scrum-master/*
|
||||
!.agents/skills/subminer-scrum-master/SKILL.md
|
||||
favicon.png
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- The macOS window-tracking helper is now built for macOS 12.0+, so the overlay attaches to mpv on older systems (previously the helper required the macOS version of the build machine and crashed on e.g. Ventura, leaving the overlay stuck on "Overlay loading").
|
||||
@@ -1,4 +1,4 @@
|
||||
type: fixed
|
||||
area: overlay
|
||||
|
||||
- Secondary subtitles now parse the selected ASS/SRT/VTT source with the primary subtitle deduplication pipeline, preventing layered animation text from appearing several times in the overlay, mined cards, and statistics. Long ASS lines repeated as dialogue and positioned signs are also collapsed when they differ only in whitespace or terminal punctuation. Dense multi-row sign layouts no longer become one concatenated secondary line. Live mpv text remains the fallback for unreadable tracks and applies full-line duplicate filtering before display.
|
||||
- Secondary subtitles now parse the selected ASS/SRT/VTT source with the primary subtitle deduplication pipeline, preventing layered animation text from appearing several times in the overlay, mined cards, and statistics. Fragmented ASS karaoke keeps spaces authored at event boundaries instead of joining every word together. Long ASS lines repeated as dialogue and positioned signs are also collapsed when they differ only in whitespace or terminal punctuation. Dense multi-row sign layouts no longer become one concatenated secondary line. Live mpv text remains the fallback for unreadable tracks and applies full-line duplicate filtering before display.
|
||||
|
||||
@@ -6,7 +6,7 @@ For internal architecture/workflow guidance, use `docs/README.md` at the repo ro
|
||||
|
||||
- [Bun](https://bun.sh)
|
||||
- A system `lua` interpreter for `bun run test:launcher` / `bun run test:plugin:src`
|
||||
- macOS builds compile a Swift helper via `scripts/build-macos-helper.sh` (skip with `SUBMINER_SKIP_MACOS_HELPER_BUILD=1`)
|
||||
- macOS builds compile a Swift helper via `scripts/prepare-build-assets.mjs` (skip with `SUBMINER_SKIP_MACOS_HELPER_BUILD=1`)
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Read when: finding internal docs or checking verification status
|
||||
| Quality scorecard | `docs/knowledge-base/quality.md` | active | 2026-03-13 | quality grades and gaps |
|
||||
| Workflow index | `docs/workflow/README.md` | active | 2026-08-13 | execution map |
|
||||
| Planning guide | `docs/workflow/planning.md` | active | 2026-05-23 | lightweight vs execution plans |
|
||||
| Agent skills | `docs/workflow/agent-skills.md` | active | 2026-08-13 | repo-local workflow skill ownership |
|
||||
| Agent skills | `docs/workflow/agent-skills.md` | active | 2026-08-23 | repo-local workflow skill ownership |
|
||||
| Verification guide | `docs/workflow/verification.md` | active | 2026-08-13 | maintained verification lanes |
|
||||
| Release guide | `docs/RELEASING.md` | active | 2026-05-23 | release checklist |
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
# Agent Skills
|
||||
|
||||
Status: active
|
||||
Last verified: 2026-08-13
|
||||
Last verified: 2026-08-23
|
||||
Owner: Kyle Yasuda
|
||||
Read when: using, adding, or changing a repo-local agent workflow skill
|
||||
|
||||
@@ -12,6 +12,9 @@ Read when: using, adding, or changing a repo-local agent workflow skill
|
||||
- `.agents/skills/subminer-change-verification/`
|
||||
- Selects the cheapest sufficient repo-native verification lane.
|
||||
- Defers command ownership to `package.json` and `docs/workflow/verification.md`.
|
||||
- `.agents/skills/subminer-release/`
|
||||
- Prepares, cuts, publishes, or repairs stable and prerelease releases.
|
||||
- Defers release procedure and policy to `docs/RELEASING.md`.
|
||||
|
||||
Repo-local workflows stay as standalone skills. Do not add plugin packaging, marketplace metadata, or compatibility shims unless the workflow is intentionally being distributed beyond this repository.
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"name": "subminer",
|
||||
"productName": "SubMiner",
|
||||
"desktopName": "SubMiner.desktop",
|
||||
"version": "0.19.4-beta.3",
|
||||
"version": "0.19.4-beta.4",
|
||||
"description": "All-in-one sentence mining overlay with AnkiConnect and dictionary integration",
|
||||
"packageManager": "bun@1.3.5",
|
||||
"main": "dist/main-entry.js",
|
||||
|
||||
+15
-13
@@ -6,39 +6,41 @@
|
||||
### Added
|
||||
|
||||
- Library Merge & Reassignment
|
||||
- Duplicate library entries for the same show can now be merged: pick entries in "Select" mode and use "Merge Selected" to combine their sessions, mined cards, and watch time onto one card.
|
||||
- Episodes can be moved to a different library entry with a per-episode "→" button, fixing cases where a stray filename split off its own entry; manual assignments now survive later filename parsing, Jellyfin refreshes, and season repair, and other episodes in the same folder pick up the same fix automatically unless they already belong elsewhere.
|
||||
- Exact AniList matches with compatible seasons now merge automatically, and likely (fuzzy) matches surface as a dismissible "Possible duplicate" suggestion instead of merging silently; entries with conflicting seasons are left alone either way.
|
||||
- Duplicate library cards for the same show can be combined: select entries in "Select" mode and use "Merge Selected" to combine their sessions, mined cards, and watch time onto one card.
|
||||
- Episodes can be moved to a different entry with a per-episode "→" button, fixing stray files that split off their own entry; manual assignments now survive later filename parsing, Jellyfin refreshes, and season repair.
|
||||
- Exact AniList matches with compatible seasons merge automatically, while likely (fuzzy) matches surface as a dismissible "Possible duplicate" suggestion instead of merging silently.
|
||||
|
||||
- Duplicate Line Cleanup
|
||||
- The Vocabulary tab's new **Duplicates** button scans a chosen time window for the repeated-line bursts described under Fixed below and collapses each burst to a single line once you confirm it; a matching `subminer stats cleanup --duplicate-lines` command (with `--dry-run` and `--lookback-days <n>`) is available from the terminal.
|
||||
- The Vocabulary tab's new **Duplicates** button scans a chosen time window for the repeated-line bursts described under Fixed below and collapses each burst to a single line once confirmed.
|
||||
- A matching `subminer stats cleanup --duplicate-lines` command (with `--dry-run` and `--lookback-days <n>`) is available from the terminal.
|
||||
- Only the affected subtitle lines and the vocabulary counts they inflated are touched; watch time and lines-seen totals are left as recorded.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Subtitle Duplication from Karaoke & Animated Signs
|
||||
- Typeset ASS karaoke and animated signs no longer flood the overlay, subtitle sidebar, immersion history, mined cards, or stats with repeated glyph fragments or per-frame duplicates; the complete authored line is recovered instead, without merging genuinely repeated dialogue or separately positioned signs. Dialogue spoken while a song's animation is on screen is kept intact instead of being replaced by the lyric, and lyric transitions (including seeking into the middle of a line) resolve to the clean line instead of a stray entrance or exit frame.
|
||||
- The secondary overlay now shares the same deduplication logic as the primary overlay, including collapsing lines that only differ by whitespace or trailing punctuation, so layered animation text and dense multi-row sign layouts no longer appear duplicated or garbled there or in what gets mined.
|
||||
- Sidebar navigation now moves between the clean, sanitized lyric lines instead of the raw generated animation events, and selecting an overlapping lyric keeps the right line selected.
|
||||
- Vocabulary stats no longer count every animation frame of a karaoke opening as a separate line, which previously could push an OP lyric to the top of "Top Repeated Words."
|
||||
- Typeset ASS karaoke and animated signs no longer flood the overlay, subtitle sidebar, immersion history, mined cards, or stats with repeated glyph fragments or per-frame duplicates; the complete authored line is recovered instead, without merging genuinely repeated dialogue or separately positioned signs.
|
||||
- Fragmented karaoke now preserves the spaces the author placed between words instead of joining them together, and lyric transitions (including seeking into the middle of a line) resolve to the clean line instead of a stray entrance or exit frame.
|
||||
- The secondary overlay shares the same deduplication logic as the primary overlay, including collapsing lines that differ only by whitespace or trailing punctuation, and sidebar navigation moves between clean lyric lines while keeping the right line selected.
|
||||
|
||||
- Anki Media Generation
|
||||
- Sentence-audio generation no longer times out on slow network-mounted video files with many subtitle and font streams (bounded probing plus a two-minute extraction budget), and a failed extraction now reports a clear error instead of a raw `ENOENT`.
|
||||
- Sentence-audio generation no longer times out on slow network-mounted video files with many subtitle and font streams, and a failed extraction now reports a clear error instead of a raw `ENOENT`.
|
||||
- Mined audio and animated AVIF clips now capture the subtitle line you actually mined, instead of whatever line happened to be on screen once slow audio extraction finished.
|
||||
|
||||
- Character Dictionary Performance & Notifications
|
||||
- Character dictionary generation, merged rebuilds, and imports no longer freeze the app on large dictionaries, and cached results (including character portraits) are reused across launches instead of regenerating everything every time. Portraits also now display correctly if their cache finishes loading after subtitles have already started showing.
|
||||
- Character dictionary generation, merged rebuilds, and imports no longer freeze the app on large dictionaries, and cached results (including character portraits) are reused across launches instead of regenerating everything every time.
|
||||
- Portraits also now display correctly if their cache finishes loading after subtitles have already started showing.
|
||||
- Desktop progress notifications, including on Linux AppImage installs, now update in place instead of flickering closed and reopening.
|
||||
|
||||
- Overlay Reliability
|
||||
- Overlay modals (settings, stats, etc.) now open promptly on the first shortcut press, including on repeated sessions on Windows, and appear above fullscreen mpv on macOS instead of switching Spaces or opening off-screen.
|
||||
- The macOS window-tracking helper is now built for macOS 12.0+, so the overlay attaches to mpv on older systems like Ventura instead of crashing and getting stuck on "Overlay loading."
|
||||
- The overlay no longer gets stuck on "Overlay loading" indefinitely if mpv's connection stalls; it now retries and shows an actionable error after 30 seconds.
|
||||
- Fixed native Wayland drag-and-drop from file managers like Thunar, so subtitle and video files dropped on the overlay reach mpv.
|
||||
- Fixed system-wide mouse lag on Windows caused by the overlay's click-through handling and repeated mpv window lookups.
|
||||
- Fixed native Wayland drag-and-drop from file managers like Thunar, and fixed system-wide mouse lag on Windows caused by the overlay's click-through handling.
|
||||
|
||||
- Stats Dashboard
|
||||
- Deletes, library merges, video moves, and AniList reassignments no longer freeze the stats dashboard or rebuild lifetime totals from scratch; large deletes that used to take minutes now finish in milliseconds.
|
||||
- Vocabulary totals and charts now count all tracked vocabulary instead of just the first page, new-word history uses corrected daily rollups, calendar labels respect time zones west of UTC, and vocabulary cards refresh automatically after editing the word exclusion list (with a Retry option if a load fails).
|
||||
- Vocabulary totals and charts now count all tracked vocabulary instead of just the first page, and new-word history uses corrected daily rollups.
|
||||
- Calendar labels respect time zones west of UTC, and vocabulary cards refresh automatically after editing the word exclusion list (with a Retry option if a load fails).
|
||||
|
||||
- Linux Launcher Thumbnails
|
||||
- Fixed missing MKV thumbnails in the Linux rofi picker when the system thumbnailer only registers legacy Matroska MIME aliases.
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Build macOS window tracking helper binary
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SWIFT_SOURCE="$SCRIPT_DIR/get-mpv-window-macos.swift"
|
||||
OUTPUT_DIR="$SCRIPT_DIR/../dist/scripts"
|
||||
OUTPUT_BINARY="$OUTPUT_DIR/get-mpv-window-macos"
|
||||
OUTPUT_SOURCE_COPY="$OUTPUT_DIR/get-mpv-window-macos.swift"
|
||||
|
||||
fallback_to_source() {
|
||||
echo "Falling back to source fallback: $OUTPUT_SOURCE_COPY"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
cp "$SWIFT_SOURCE" "$OUTPUT_SOURCE_COPY"
|
||||
}
|
||||
|
||||
build_swift_helper() {
|
||||
echo "Compiling macOS window tracking helper..."
|
||||
if ! command -v swiftc >/dev/null 2>&1; then
|
||||
echo "swiftc not found in PATH; skipping compilation."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! swiftc -O "$SWIFT_SOURCE" -o "$OUTPUT_BINARY"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
chmod +x "$OUTPUT_BINARY"
|
||||
echo "✓ Built $OUTPUT_BINARY"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Optional skip flag for non-macOS CI/dev environments
|
||||
if [[ "${SUBMINER_SKIP_MACOS_HELPER_BUILD:-}" == "1" ]]; then
|
||||
echo "Skipping macOS helper build (SUBMINER_SKIP_MACOS_HELPER_BUILD=1)"
|
||||
fallback_to_source
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Only build on macOS
|
||||
if [[ "$(uname)" != "Darwin" ]]; then
|
||||
echo "Skipping macOS helper build (not on macOS)"
|
||||
fallback_to_source
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create output directory
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
# Compile Swift script to binary, fallback to source if unavailable or compilation fails
|
||||
if ! build_swift_helper; then
|
||||
fallback_to_source
|
||||
fi
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -52,6 +53,16 @@ function fallbackToMacosSource() {
|
||||
process.stdout.write(`Staged macOS helper source fallback: ${macosHelperSourceCopyPath}\n`);
|
||||
}
|
||||
|
||||
// Pin the minimum macOS to the app's own floor (Electron's `minos`). Without an
|
||||
// explicit target, swiftc stamps the build machine's OS version as the binary's
|
||||
// minimum and the helper fails to load on older systems (#213). The arch stays
|
||||
// the host's, matching the single-arch app electron-builder packages here.
|
||||
const MACOS_HELPER_DEPLOYMENT_TARGET = '12.0';
|
||||
|
||||
function macosHelperTarget() {
|
||||
return `${os.arch() === 'x64' ? 'x86_64' : 'arm64'}-apple-macos${MACOS_HELPER_DEPLOYMENT_TARGET}`;
|
||||
}
|
||||
|
||||
function shouldSkipMacosHelperBuild() {
|
||||
return process.env.SUBMINER_SKIP_MACOS_HELPER_BUILD === '1';
|
||||
}
|
||||
@@ -72,9 +83,13 @@ function buildMacosHelper() {
|
||||
ensureDir(scriptsOutputDir);
|
||||
|
||||
try {
|
||||
execFileSync('swiftc', ['-O', macosHelperSourcePath, '-o', macosHelperBinaryPath], {
|
||||
stdio: 'inherit',
|
||||
});
|
||||
execFileSync(
|
||||
'swiftc',
|
||||
['-O', '-target', macosHelperTarget(), macosHelperSourcePath, '-o', macosHelperBinaryPath],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
fs.chmodSync(macosHelperBinaryPath, 0o755);
|
||||
process.stdout.write(`Built macOS helper: ${macosHelperBinaryPath}\n`);
|
||||
} catch (error) {
|
||||
|
||||
@@ -8,7 +8,7 @@ test('macOS helper build creates dist scripts directory before swiftc output', (
|
||||
const buildFunctionIndex = source.indexOf('function buildMacosHelper()');
|
||||
assert.notEqual(buildFunctionIndex, -1);
|
||||
|
||||
const swiftcIndex = source.indexOf("execFileSync('swiftc'", buildFunctionIndex);
|
||||
const swiftcIndex = source.indexOf("'swiftc'", buildFunctionIndex);
|
||||
assert.notEqual(swiftcIndex, -1);
|
||||
|
||||
const ensureDirIndex = source.lastIndexOf('ensureDir(scriptsOutputDir)', swiftcIndex);
|
||||
@@ -18,3 +18,10 @@ test('macOS helper build creates dist scripts directory before swiftc output', (
|
||||
'buildMacosHelper must create dist/scripts before swiftc writes the helper binary',
|
||||
);
|
||||
});
|
||||
|
||||
// Regression guard for #213: an untargeted swiftc stamps the build machine's OS
|
||||
// version as the helper's minimum, so released builds refuse to load on older macOS.
|
||||
test('macOS helper is compiled with an explicit deployment target', () => {
|
||||
assert.match(source, /-target/);
|
||||
assert.match(source, /apple-macos\$\{MACOS_HELPER_DEPLOYMENT_TARGET\}/);
|
||||
});
|
||||
|
||||
@@ -853,6 +853,10 @@ function parseAnnotatedAssEvents(content: string): ParsedAssEvents {
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
// Event text can end in an authored space. Fragmented karaoke commonly uses that
|
||||
// space to retain word boundaries when its separately positioned events are joined
|
||||
// back into a line, so only remove indentation before slicing the event fields.
|
||||
const eventLine = line.trimStart();
|
||||
|
||||
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
||||
inEventsSection = trimmed.toLowerCase() === '[events]';
|
||||
@@ -883,9 +887,9 @@ function parseAnnotatedAssEvents(content: string): ParsedAssEvents {
|
||||
continue;
|
||||
}
|
||||
|
||||
const eventPrefix = trimmed.startsWith(ASS_DIALOGUE_PREFIX)
|
||||
const eventPrefix = eventLine.startsWith(ASS_DIALOGUE_PREFIX)
|
||||
? ASS_DIALOGUE_PREFIX
|
||||
: trimmed.startsWith(ASS_COMMENT_PREFIX)
|
||||
: eventLine.startsWith(ASS_COMMENT_PREFIX)
|
||||
? ASS_COMMENT_PREFIX
|
||||
: null;
|
||||
if (!eventPrefix) {
|
||||
@@ -896,7 +900,7 @@ function parseAnnotatedAssEvents(content: string): ParsedAssEvents {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fields = trimmed.slice(eventPrefix.length).split(',');
|
||||
const fields = eventLine.slice(eventPrefix.length).split(',');
|
||||
if (
|
||||
fieldIndex.start >= fields.length ||
|
||||
fieldIndex.end >= fields.length ||
|
||||
|
||||
@@ -181,6 +181,41 @@ test('ASS fragment karaoke stays separated by style with authored word spacing',
|
||||
assert.equal(findActiveSubtitleText(parseSubtitleCues(ass, 'ending.ass'), 8.5), 'Iwanttogo');
|
||||
});
|
||||
|
||||
test('ASS fragment karaoke preserves word spaces authored at event boundaries', () => {
|
||||
const fragments = [
|
||||
'The ',
|
||||
'shoot',
|
||||
'ing ',
|
||||
'stars ',
|
||||
'arc',
|
||||
'ing ',
|
||||
'across ',
|
||||
'the ',
|
||||
'sky ',
|
||||
'I ',
|
||||
'wish ',
|
||||
'upon,',
|
||||
];
|
||||
const events: string[] = [];
|
||||
for (const layer of [0, 1]) {
|
||||
fragments.forEach((fragment, index) => {
|
||||
events.push(
|
||||
`Dialogue: ${layer},0:00:01.00,0:00:04.00,op_english,,0,0,0,,{\\pos(${100 + index * 40},110)\\t(0,200,\\fscx110)}${fragment}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
const ass = [
|
||||
'[Events]',
|
||||
'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text',
|
||||
...events,
|
||||
].join('\n');
|
||||
|
||||
assert.equal(
|
||||
findActiveSubtitleText(parseSubtitleCues(ass, 'bravern-s01e10.ass'), 2),
|
||||
'The shooting stars arcing across the sky I wish upon,',
|
||||
);
|
||||
});
|
||||
|
||||
test('findActiveSubtitleText keeps a complete reconstructed line over entrance fragments', () => {
|
||||
const current = {
|
||||
startTime: 1,
|
||||
|
||||
Reference in New Issue
Block a user