Skip to content

Refactor compressor.js#356

Open
aandrew-me wants to merge 1 commit intomainfrom
compressor_refactor
Open

Refactor compressor.js#356
aandrew-me wants to merge 1 commit intomainfrom
compressor_refactor

Conversation

@aandrew-me
Copy link
Owner

@aandrew-me aandrew-me commented Nov 18, 2025

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced hardware detection for improved GPU support across multiple vendors.
    • Improved menu interactions with smooth animations.
  • Refactor

    • Reorganized initialization flow for better app startup and configuration handling.
    • Centralized theme management with persistent storage.
    • Streamlined compression workflow with unified error and success feedback.
    • Enhanced progress tracking and UI updates during video compression.

@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Walkthrough

Significant refactor of src/compressor.js introducing centralized initialization flow, global constants (VAAPI_DEVICE, FFMPEG_PATH), UI/menu handling, theme management, hardware detection, and modularized helper functions while restructuring event wiring and compression workflows.

Changes

Cohort / File(s) Summary
Initialization and Core Refactor
src/compressor.js
Global constants introduced (VAAPI_DEVICE, FFMPEG_PATH); initialization flow added with setupTheme() and detectHardware() on load; UI/menu handling extracted into toggleMenu/closeMenu helpers with menuIsOpen state tracking and fade animations; translations listener and window navigation retained but reorganized via navigateTo/navigateToWin helpers
Hardware Detection and Theme
src/compressor.js
detectHardware() refactored to centralize GPU detection with showOptions() helper; Nvidia/AMD/Intel branches updated with platform checks; setupTheme() centralized to read localStorage and apply theme consistently; themeToggle listener updated
Compression and Error Handling
src/compressor.js
startCompression(), compressVideo(), and support helpers preserved but restructured; handleCompressionSuccess and handleCompressionError unified handlers introduced; updateProgress() generalized for success/error states; progress item creation and status rendering retained
FFmpeg Command Building
src/compressor.js
buildFFmpegCommand updated to use shared vQuality variable and VAAPI/FFmpeg path references; encoder branches updated; getAmfQuality(speed) helper introduced to map speeds to FF/HW presets; generateOutputPath(file, settings) introduced for output path computation

Sequence Diagram(s)

sequenceDiagram
    participant App as App Load
    participant Init as init()
    participant Theme as setupTheme()
    participant HW as detectHardware()
    participant Menu as Menu Handlers
    participant Compress as Compression Flow

    App->>Init: Window load
    Init->>Theme: setupTheme()
    Note over Theme: Read localStorage,<br/>apply theme
    Init->>HW: detectHardware()
    Note over HW: GPU detection,<br/>platform checks,<br/>showOptions()
    
    rect rgb(220, 240, 255)
    Note over Menu: Event Wiring
    Menu->>Menu: toggleMenu()
    Menu->>Menu: closeMenu()
    Menu->>Menu: navigateTo()/navigateToWin()
    end
    
    rect rgb(240, 220, 255)
    Note over Compress: Compression Workflow
    Compress->>Compress: startCompression()
    Compress->>Compress: buildFFmpegCommand()
    alt Success
        Compress->>Compress: handleCompressionSuccess()
    else Error
        Compress->>Compress: handleCompressionError()
    end
    Compress->>Compress: updateProgress()
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

  • Hardware detection logic: Multiple platform-specific branches (Nvidia/AMD/Intel) with feature flag display logic requires careful validation
  • FFmpeg command builder: Updates to encoder branches and vQuality variable handling need verification across all codec paths
  • Initialization flow and event wiring: New control flow for setupTheme(), detectHardware(), and reorganized event listeners needs tracing through entry points
  • Error handling refactor: New centralized handleCompressionSuccess/handleCompressionError handlers and restructured compression flow require comprehensive testing scenario review
  • State management: menuIsOpen state tracking and fade animations warrant UI behavior validation

Possibly related PRs

  • #353: Updates ffmpeg path resolution and centralized FFMPEG path constants/helpers in src/compressor.js, aligning with this PR's FFMPEG_PATH refactor

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.35% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Refactor compressor.js' is generic and vague, using the term 'Refactor' without specifying what aspects were refactored or the main improvements introduced. Consider a more specific title that highlights key changes, such as 'Refactor compressor.js: Add initialization flow, hardware detection, and error handling' to better convey the scope of modifications.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch compressor_refactor

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/compressor.js (3)

100-123: Cancellation vs error handling can double‑report cancelled jobs

The refactored startCompression() loop is clean, but the interplay with cancellation is a bit off:

  • cancelCompression() marks isCancelled = true and immediately calls updateProgress("error", "Cancelled", currentItemId).
  • When ffmpeg exits due to the injected "q", compressVideo will likely reject, and the catch in startCompression() then calls handleCompressionError(itemId, error), which overwrites the previous “Cancelled” state and appends an error element.

This means a user‑initiated cancel is surfaced as an error with “click for details” instead of remaining a clean “Cancelled” state.

Consider skipping handleCompressionError when isCancelled is true, e.g.:

-    } catch (error) {
-      handleCompressionError(itemId, error);
-    }
+    } catch (error) {
+      if (!isCancelled) {
+        handleCompressionError(itemId, error);
+      }
+    }

(And possibly reset isCancelled in the cancel path once all processes have exited.)


134-183: Guard progress calculation against zero/unknown duration

Nice touch adding the if (!timeStr) return 0; guard in timeToSeconds. However, in compressVideo you still compute:

const totalSeconds = timeToSeconds(video_info.duration);
...
const progress = Math.round((currentSeconds / totalSeconds) * 100);

If time= is logged before Duration: (or Duration has not yet been parsed), video_info.duration is empty, totalSeconds becomes 0, and you end up dividing by zero, yielding Infinity and possibly writing value=Infinity to the <progress> element.

Recommend checking totalSeconds > 0 before computing progress:

-      const totalSeconds = timeToSeconds(video_info.duration);
+      const totalSeconds = timeToSeconds(video_info.duration);
...
-      if (currentSeconds && !isCancelled) {
+      if (currentSeconds && totalSeconds > 0 && !isCancelled) {
         const progress = Math.round(
           (currentSeconds / totalSeconds) * 100
         );

This makes progress updates robust even when ffmpeg output arrives in an unexpected order.

Also applies to: 498-498


204-339: Fix videotoolbox argument order, wrap AMF const declarations in blocks, and add videoQuality validation

Three issues confirmed in buildFFmpegCommand:

  1. Critical: videotoolbox arguments are mis-ordered
    Current code produces -c:v -vf format=yuv420p h264_videotoolbox -q:v ..., which fails because -c:v lacks its codec argument. Correct order:

    case "videotoolbox": // macOS
  • args.push(
  • "-c:v",
  • "-vf",
  • "format=yuv420p",
  • "h264_videotoolbox",
  • "-q:v",
  • vQuality
  • );
  • args.push(
  • "-c:v",
  • "h264_videotoolbox",
  • "-vf",
  • "format=yuv420p",
  • "-q:v",
  • vQuality
  • );
    
    
  1. Wrap AMF const declarations in case blocks
    Lines 290 and 307 declare const directly in case clauses, violating Biome's noSwitchDeclarations. Wrap each:

    case "hevc_amf": // AMD Windows HEVC
  • {
    const amfHevcQuality = getAmfQuality(settings.speed);
    args.push(...);
    break;

  • }

    case "amf": // AMD Windows H264

  • {
    const amfQuality = getAmfQuality(settings.speed);
    args.push(...);
    break;

  • }

    
    
  1. Validate videoQuality before parseInt
    Line 209 calls parseInt(settings.videoQuality).toString() without validation. If videoQuality is undefined, null, or non-numeric, parseInt returns NaN, passing the string "NaN" to ffmpeg. Add a guard (e.g., parseInt(settings.videoQuality || 0)) or validate upstream.
🧹 Nitpick comments (2)
src/compressor.js (2)

401-429: Menu open/close behavior mirrors existing patterns; consider deduping fade logic

The toggleMenu / closeMenu pair gives a clear open/close contract and incorporates a fade‑out interval. This is consistent with the snippet in src/common.js (and similar to src/playlist_new.js), but it does mean the fade logic is now duplicated across files.

If you expect menu behavior to stay in sync across multiple windows, consider extracting the fade/close behavior into a shared helper (e.g., in common.js) used by all windows instead of re‑implementing it here.


88-92: Theme toggle element exists, but null-checks remain recommended for defensive coding

Verified that compressor.html includes the themeToggle element (lines 27–28: <select id="themeToggle" ...>), and compressor.js is only loaded by that page. Both lines 88–92 and 441–447 call getId("themeToggle") without null-checks:

  • Line 88: getId("themeToggle").addEventListener("change", ...)
  • Line 445: getId("themeToggle").value = storageTheme

While the element presently exists, the getId() function returns null for missing elements, and these accesses would throw. For robustness and maintainability, add null-checks before .addEventListener() and .value assignments.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 59d1f13 and 88d6045.

📒 Files selected for processing (1)
  • src/compressor.js (13 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/compressor.js (3)
translations/i18n-init.js (1)
  • i18n (2-2)
src/playlist_new.js (4)
  • i18n (11-11)
  • count (161-161)
  • opacity (162-162)
  • fade (163-171)
src/common.js (3)
  • count (15-15)
  • opacity (16-16)
  • fade (17-26)
🪛 Biome (2.1.2)
src/compressor.js

[error] 290-290: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 307-307: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Safe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)

🔇 Additional comments (6)
src/compressor.js (6)

28-39: Menu/navigation and compression button wiring look correct

The new event wiring for menu navigation and the compression/cancel buttons is straightforward and consistent: handlers are pure functions, and using helpers like navigateTo/navigateToWin keeps IPC calls centralized. As long as these elements exist on this page, this wiring is solid.

Also applies to: 67-69


70-86: Output folder UX wiring is reasonable

The output-folder-input checkbox toggles visibility of the custom folder button and clears the displayed path when unchecked, and the "directory-path" IPC handler cleanly updates and reveals the chosen path. This matches expected UX and keeps DOM updates localized.

Also applies to: 94-98


185-203: Centralized success/error UI handlers look good

handleCompressionSuccess and handleCompressionError pair nicely with the generalized updateProgress():

  • Status classes are updated once via updateProgress.
  • Clickable “file saved” and “error details” affordances are created in a focused place.
  • currentItemId is reset in both paths.

This is a solid refactor; just ensure the cancellation path is reconciled as noted earlier so errors aren’t shown for expected cancels.

Also applies to: 388-399


364-373: DOM helpers for IDs and selected file display are fine

getId as a tiny wrapper plus updateSelectedFiles() using formatBytes to render name + size into #selected-files is straightforward and readable. No functional concerns here.


431-439: Navigation helpers keep IPC wiring tidy

navigateTo and navigateToWin both close the menu before sending IPC messages, which keeps the UI consistent across page transitions and centralizes the IPC channel names. Looks good.


358-362: AMF quality values verified as correct

The function correctly maps to valid AMD AMF quality parameters. The AMF encoders accept -quality with three values: speed, balanced, and quality, and getAmfQuality returns exactly these values. No issues.

Comment on lines +8 to 12
const VAAPI_DEVICE = "/dev/dri/renderD128";
const FFMPEG_PATH = `"${getFfmpegPath()}"`;

console.log(`FFmpeg Path: ${FFMPEG_PATH}`);
/** @type {File[]} */
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Fix i18n global access and consider handling missing FFmpeg path more defensively

  • The translations-loaded listener uses window.i18n.translatePage(), but other code in this file uses bare i18n (e.g., Line 188, Line 198), and the provided snippet in translations/i18n-init.js shows const i18n = new I18n();. With a const declaration, i18n is not attached to window, so window.i18n may be undefined at runtime, causing a crash when this event fires. Align this to use i18n.translatePage() or explicitly attach i18n to window in the initializer so usage is consistent.
  • FFMPEG_PATH is computed once at module load time and logged, which is fine. However, on platforms where getFfmpegPath() can legitimately return "" (e.g., FreeBSD without ffmpeg in PATH), the app will still attempt to exec an empty command string later. You may want to short‑circuit with a user‑visible error if getFfmpegPath() returns a falsy value instead of proceeding to exec an invalid command.

Also applies to: 19-27


🌐 Web query:

In a standard browser/renderer environment (non-module scripts), does `const i18n = new I18n();` attach `i18n` to `window`, or is it only available as a global binding (i.e., `i18n` vs `window.i18n`)?

💡 Result:

Short answer: const i18n = new I18n(); (in a non-module, top-level script) creates a global lexical binding named i18n but does NOT create a property on window. So i18n works as an identifier, but window.i18n is undefined. [1][2]

Sources:

  • MDN: Global object — "var statements and function declarations ... create properties of the global object. On the other hand, let and const declarations never create properties of the global object." [1]
  • MDN: let (and const) — "let declarations do not create properties on globalThis when declared at the top level of a script." [2]


---

🏁 Script executed:

```shell
#!/bin/bash
# Find i18n declaration and window.i18n usage in src/compressor.js
echo "=== i18n declaration in translations/i18n-init.js ==="
fd -e js -p translations | head -5 | xargs grep -n "const i18n\|let i18n\|var i18n" 2>/dev/null | head -10

echo ""
echo "=== window.i18n usage in src/compressor.js ==="
rg -n "window\.i18n" src/compressor.js

echo ""
echo "=== bare i18n usage in src/compressor.js ==="
rg -n "i18n\." src/compressor.js | head -15

echo ""
echo "=== getFfmpegPath function ==="
rg -n "getFfmpegPath" src/compressor.js -A5 -B2

Length of output: 888



---

🏁 Script executed:

```shell
#!/bin/bash
# Get full getFfmpegPath function implementation
echo "=== Full getFfmpegPath function ==="
rg -n "^function getFfmpegPath" src/compressor.js -A30

Length of output: 749



---

🏁 Script executed:

```shell
#!/bin/bash
# Check where FFMPEG_PATH is used and if there are guards
echo "=== FFMPEG_PATH usage in exec/spawn commands ==="
rg -n "FFMPEG_PATH" src/compressor.js -B2 -A2

echo ""
echo "=== exec/execSync/spawn patterns ==="
rg -n "exec\(|spawn\(" src/compressor.js -A3 -B2 | head -40

Length of output: 855


Fix i18n global access and add FFmpeg path validation

  • Line 25 calls window.i18n.translatePage(), but i18n is declared with const at translations/i18n-init.js:2. Per MDN, const declarations do not create properties on window, so window.i18n is undefined and will crash at runtime when the translations-loaded event fires. Use bare i18n.translatePage() instead, or attach i18n to window explicitly in the initializer.
  • getFfmpegPath() returns an empty string on FreeBSD when ffmpeg is not found (line 538). This results in FFMPEG_PATH becoming "" (line 9), which produces an invalid command string passed to exec() at line 145. Add a guard in getFfmpegPath() to throw or log an error if the path is empty, or validate FFMPEG_PATH before constructing the command at line 338.
🤖 Prompt for AI Agents
In src/compressor.js (referenced lines ~8-12, and also addressing calls at ~25,
145, 338 and getFfmpegPath at ~538), remove reliance on window.i18n (use
i18n.translatePage() directly or ensure i18n is attached to window in
translations initializer) so the translations-loaded handler doesn't crash, and
add validation for FFmpeg path: update getFfmpegPath() to throw or return a
clear error/log when it finds no binary (empty string) and/or validate
FFMPEG_PATH before building the exec command (abort with a logged error or throw
if empty) to prevent constructing an invalid command.

Comment on lines +449 to +484
function detectHardware() {
si.graphics().then((info) => {
console.log({gpuInfo: info});
const gpuDevices = info.controllers;
const platform = os.platform();

gpuDevices.forEach((gpu) => {
const gpuName = gpu.vendor.toLowerCase();
const gpuModel = gpu.model.toLowerCase();
const isNvidia =
gpuName.includes("nvidia") || gpuModel.includes("nvidia");
const isAMD =
gpuName.includes("advanced micro devices") ||
gpuModel.includes("amd");
const isIntel = gpuName.includes("intel");

if (isNvidia) {
showOptions(".nvidia_opt");
} else if (isAMD) {
if (platform === "win32") showOptions(".amf_opt");
else showOptions(".vaapi_opt");
} else if (isIntel) {
if (platform === "win32") showOptions(".qsv_opt");
else if (platform !== "darwin") showOptions(".vaapi_opt");
} else {
if (platform === "darwin") showOptions(".videotoolbox_opt");
}
});
});
}

function showOptions(selector) {
document.querySelectorAll(selector).forEach((opt) => {
opt.style.display = "block";
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

Hardware detection logic may skip Videotoolbox on Intel macOS

The detectHardware() logic is generally sensible—using systeminformation.graphics() and os.platform() to show encoder‑specific options via CSS selectors—but there is a corner case:

  • For Intel macOS, gpu.vendor/gpu.model will likely match isIntel, and platform === "darwin". In the isIntel branch, you only call showOptions(".qsv_opt") for win32 and .vaapi_opt for non‑darwin platforms. The macOS path for Intel is effectively a no‑op.
  • The final else { if (platform === "darwin") showOptions(".videotoolbox_opt"); } is only reached when the GPU is not recognized as Nvidia/AMD/Intel. So Intel macOS machines never reach the Videotoolbox branch.

If Videotoolbox is intended to be available on macOS regardless of GPU vendor, you may want a separate if (platform === "darwin") showOptions(".videotoolbox_opt") that runs independently of the vendor checks (or adjust the Intel branch accordingly).

Also, if multiple controllers are present, you may end up calling showOptions multiple times for the same selector, which is harmless but redundant.


🌐 Web query:

On macOS with Intel GPUs, is `ffmpeg`'s `h264_videotoolbox` usable regardless of GPU vendor, and should the UI always expose Videotoolbox options when `os.platform() === "darwin"`?

💡 Result:

Short answer: No — you can't blindly expose Videotoolbox on all macOS systems just because os.platform() === "darwin". VideoToolbox is the macOS hardware-acceleration API and, when available, FFmpeg's h264_videotoolbox will use whatever macOS-provided encoder exists (Intel QSV on some Intel Macs, AMD VCE on others, or Apple Media Engine on Apple Silicon). But availability and capabilities depend on the mac model, macOS version and how FFmpeg was built — so the UI should probe capability at runtime rather than assume presence by OS alone. [1][2][3]

Recommended implementation:

  • Check that the running ffmpeg build advertises videotoolbox support (e.g. ffmpeg -hwaccels and ffmpeg -encoders / grep videotoolbox) and/or attempt a small probe encode. [4]
  • Only show Videotoolbox options when those runtime checks succeed; optionally hide or disable them with an explanatory tooltip otherwise. [1][2]

Sources:

  • HandBrake docs — VideoToolbox: VideoToolbox is the macOS hardware encoder, underlying vendor chosen by system; support varies by Mac model/OS. [1]
  • Jellyfin docs — VideoToolbox used on macOS; support varies by Mac generation and may fall back to software for unsupported cases. [2]
  • FFmpeg mailing / notes — h264_videotoolbox uses the VideoToolbox API and can be subject to platform/driver/resolution limits. [3]
  • Practical FFmpeg guidance — how to detect hw accel and videocoders in ffmpeg builds. [4]

Let me verify if the codebase has any runtime capability checks or FFmpeg probing logic:

Now let me search the codebase to see if there's any existing FFmpeg capability detection:

Based on the web search verification, I can now provide the final rewritten review comment. The original concern is valid and confirmed by authoritative sources—Videotoolbox availability on macOS cannot be determined by OS check alone and requires runtime FFmpeg capability probing.


Fix hardware detection to probe FFmpeg Videotoolbox support at runtime, not by OS/GPU vendor alone.

The detectHardware() logic relies on os.platform() and GPU vendor checks to conditionally show encoder options, but this approach is architecturally insufficient. VideoToolbox is conditional on FFmpeg being built with the --enable-videotoolbox flag, and availability varies by Mac model, macOS version, and FFmpeg build configuration—not by OS alone.

Current issues:

  • Intel macOS systems never reach the Videotoolbox branch (they only match the isIntel condition, which lacks a macOS path).
  • Even on macOS, blindly showing .videotoolbox_opt for unknown GPU vendors is unreliable.

Recommended fix:
Use runtime checks like ffmpeg.getAvailableFormats() to probe whether the FFmpeg build supports h264_videotoolbox before showing Videotoolbox options. Only display the option when runtime capability detection succeeds.

🤖 Prompt for AI Agents
In src/compressor.js around lines 449-484, the current detectHardware() shows
Videotoolbox based only on OS/GPU vendor which is unreliable; update it to probe
FFmpeg at runtime for Videotoolbox support (e.g., call FFmpeg to list
encoders/formats or use your ffmpeg wrapper to getAvailableEncoders/formats) and
only call showOptions('.videotoolbox_opt') when the probe confirms
h264_videotoolbox (or the specific encoder/format) is available; also ensure the
Intel macOS path considers this runtime check (so Intel on macOS can show
Videotoolbox if FFmpeg supports it) and handle the async probe with proper
promise/async flow and error handling so UI toggles happen after the capability
check completes.

Comment on lines +503 to +519
function generateOutputPath(file, settings) {
console.log({settings});
const output_extension = settings.extension;
const parsed_file = path.parse(file.path);
let outputDir = settings.outputPath || parsed_file.dir;

if (output_extension === "unchanged") {
return path.join(
outputDir,
`${parsed_file.name}${settings.outputSuffix}${parsed_file.ext}`
);
}
return path.join(
outputDir,
`${parsed_file.name}_compressed.${output_extension}`
);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Output path generation: suffix only applied for “unchanged” extension and debug log

generateOutputPath is a nice encapsulation of the previous path logic, but two details to consider:

  • settings.outputSuffix is only honored in the "unchanged" extension branch. If a user selects a different extension, the filename is always ${name}_compressed.${extension}, and any configured suffix is ignored. If the UI intent is “append this suffix regardless of extension choice,” you’ll want to incorporate settings.outputSuffix into both branches.
  • The console.log({settings}); is likely a leftover debug statement; it can get noisy if many files are processed. Consider removing it or gating it behind a debug flag.

Example adjustment:

- if (output_extension === "unchanged") {
-   return path.join(
-     outputDir,
-     `${parsed_file.name}${settings.outputSuffix}${parsed_file.ext}`
-   );
- }
- return path.join(
-   outputDir,
-   `${parsed_file.name}_compressed.${output_extension}`
- );
+ const suffix = settings.outputSuffix || "";
+ if (output_extension === "unchanged") {
+   return path.join(
+     outputDir,
+     `${parsed_file.name}${suffix}${parsed_file.ext}`
+   );
+ }
+ return path.join(
+   outputDir,
+   `${parsed_file.name}${suffix}_compressed.${output_extension}`
+ );
🤖 Prompt for AI Agents
In src/compressor.js around lines 503-519, remove the stray debug console.log
and update filename construction to honor settings.outputSuffix in both
branches: ensure outputSuffix defaults to an empty string if falsy, keep the
unchanged branch building `${name}${outputSuffix}${ext}` and change the other
branch to include the suffix before the `_compressed` token (e.g.
`${name}${outputSuffix}_compressed.${output_extension}`), preserving the
existing outputPath fallback logic; also optionally normalize/trim outputSuffix
to avoid accidental separators.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant