The visualizer's PCM cache decoded the entire episode into RAM (22050 Hz mono s16 ~160 MB/hr of audio) and held it until stop() — a 3-hour episode pinned ~500 MB and long-form content hit 2.5 GB. The 4x decode also pulled the whole remote file even when only minutes were listened to. - audio-pcm-cache: sliding window around the playback position — the decode head caps at maxAheadSec (600s) ahead of the cursor, segments older than keepBehindSec (300s) are pruned, and the tail refills as playback advances. Steady state ~40 MB regardless of episode length; a backward seek past the window restarts a segment there (the existing seek-hole mechanism, no new failure mode). - feed: cap the full-parse episode cache at 1000 episodes/feed so archive-heavy subscriptions can't pin their entire history in RAM; the visible list stays bounded by the user's cache preference and fetch-more keeps working within the ceiling. - tests: pin the new head-cap and prune contracts (8/8 in audio-pcm-cache.test.ts; full suite 193 pass). Also includes the in-flight cleanup/refactor pass (cover-art resolve helper, page and comment tightening, ESLint config removal).
27 lines
689 B
TypeScript
27 lines
689 B
TypeScript
/**
|
|
* JSONC parser utility for handling JSON with comments
|
|
*
|
|
* JSONC (JSON with Comments) is a superset of JSON that allows single-line
|
|
* and multi-line comments, which is useful for configuration files.
|
|
*/
|
|
|
|
function stripComments(jsonString: string): string {
|
|
const comments = [
|
|
{ pattern: /\/\/.*$/gm, replacement: "" },
|
|
{ pattern: /\/\*[\s\S]*?\*\//g, replacement: "" },
|
|
];
|
|
|
|
let result = jsonString;
|
|
|
|
for (const { pattern, replacement } of comments) {
|
|
result = result.replace(pattern, replacement);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function parseJSONC(jsonString: string): unknown {
|
|
const stripped = stripComments(jsonString);
|
|
return JSON.parse(stripped);
|
|
}
|