feat: add the ability to generate "collapsed" version of mods#233
feat: add the ability to generate "collapsed" version of mods#233SlayerOrnstein merged 7 commits intoWFCD:mainfrom
Conversation
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a new exported generateCollapsed renderer and accompanying collapsed/expanded workflow; introduces pixel-manipulation helpers (shadePixel, tintPixel, shadeImage), font updates, drawing adjustments, README/example updates, and test changes. A "collpased" typo appears in example/test output paths. Changes
Sequence DiagramsequenceDiagram
participant User
participant Generator
participant ImageOps
participant Canvas
User->>Generator: call generateCollapsed(mod props)
Generator->>ImageOps: loadImage(imageName)
ImageOps-->>Generator: Image
Generator->>ImageOps: shadeImage(Image)
ImageOps->>ImageOps: apply shadePixel per-pixel
ImageOps-->>Generator: shaded Image
Generator->>Canvas: create canvas & drawHeader (tint via tintPixel)
Generator->>Canvas: drawBottomImage / layout elements
Generator->>Canvas: export PNG buffer
Canvas-->>Generator: PNG buffer
Generator-->>User: return Buffer
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 (1)
tests/generator.spec.ts (1)
30-45:⚠️ Potential issue | 🟠 MajorFix the extra loop iteration and tighten collapsed-output assertions.
Line 30 should use
< mods.lengthto avoid the out-of-range iteration; also assertmodMinand fix the_collpasedtypo at Line 44.✅ Proposed patch
- for (let i = 0; i <= mods.length; i += 1) { + for (let i = 0; i < mods.length; i += 1) { await Promise.all( formats.map(async (format) => { @@ - const modFull = await generate({ mod, rank: mod.fusionLimit, output: { format } }); - const modMin = await generateCollapsed({ mod, rank: mod.fusionLimit, output: { format } }); + const modFull = await generate({ mod, rank: mod.fusionLimit, output: { format } }); + const modMin = await generateCollapsed({ mod, rank: mod.fusionLimit, output: { format } }); assert.ok(modFull); + assert.ok(modMin); @@ - if (modMin) await writeFile(join(imagePath, `${mod.name.replaceAll(' ', '_')}_collpased.${format}`), modMin); + if (modMin) await writeFile(join(imagePath, `${mod.name.replaceAll(' ', '_')}_collapsed.${format}`), modMin); }) ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/generator.spec.ts` around lines 30 - 45, The for-loop iterates one too many times and the collapsed output assertions/filename are incorrect: change the loop condition to use i < mods.length (instead of <=) to avoid out-of-range access when calling find.findItem(mods[i]), add an assertion assert.ok(modMin) after generating modMin (from generateCollapsed) to tighten the test, and fix the output filename typo from "_collpased" to "_collapsed" when calling writeFile; reference the generate, generateCollapsed, modFull, modMin, mods, find.findItem, and writeFile usages to locate the changes.
🧹 Nitpick comments (2)
src/utils.ts (2)
208-214: Add fail-fast validation inhexToRGB.This helper is exported; validating input format prevents silent
NaNchannel values when callers pass malformed hex.♻️ Proposed patch
export const hexToRGB = (hex: string): RGB => { + if (!/^#[0-9a-fA-F]{6}$/.test(hex)) { + throw new Error(`Invalid hex color: ${hex}`); + } const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); return { r, g, b }; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/utils.ts` around lines 208 - 214, The exported helper hexToRGB currently parses slices without validating input, which can produce NaN for malformed hex strings; update hexToRGB to validate the input first (e.g. test against a regex like /^#([0-9A-Fa-f]{6})$/), throw a clear Error when the format is invalid, and only then parse the r,g,b channels with parseInt and return the RGB object so callers fail fast on bad input.
217-237: Clamp percentage/channel outputs in pixel helpers for safer reuse.
shadePixel/tintPixelcurrently rely on caller discipline; clamping avoids out-of-range values when these utilities are reused.♻️ Proposed patch
export const shadePixel = (pixel: RGB, percentage: number): RGB => { - const redShade = Math.round(Math.max(0, pixel.r - pixel.r * percentage)); - const greenShade = Math.round(Math.max(0, pixel.g - pixel.g * percentage)); - const blueShade = Math.round(Math.max(0, pixel.b - pixel.b * percentage)); + const p = Math.min(1, Math.max(0, percentage)); + const redShade = Math.round(Math.min(255, Math.max(0, pixel.r - pixel.r * p))); + const greenShade = Math.round(Math.min(255, Math.max(0, pixel.g - pixel.g * p))); + const blueShade = Math.round(Math.min(255, Math.max(0, pixel.b - pixel.b * p))); return { r: redShade, g: greenShade, b: blueShade }; }; @@ export const tintPixel = (pixel: RGB, tint: RGB, percentage: number = 0.8): RGB => { const maxColors = 255; + const p = Math.min(1, Math.max(0, percentage)); @@ - const tintedRed = Math.min(maxColors, pixel.r * originalWeight + tint.r * brightness * percentage); - const tintedGreen = Math.min(maxColors, pixel.g * originalWeight + tint.g * brightness * percentage); - const tintedBlue = Math.min(maxColors, pixel.b * originalWeight + tint.b * brightness * percentage); + const tintedRed = Math.round(Math.min(maxColors, Math.max(0, pixel.r * originalWeight + tint.r * brightness * p))); + const tintedGreen = Math.round(Math.min(maxColors, Math.max(0, pixel.g * originalWeight + tint.g * brightness * p))); + const tintedBlue = Math.round(Math.min(maxColors, Math.max(0, pixel.b * originalWeight + tint.b * brightness * p)));🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/utils.ts` around lines 217 - 237, Clamp inputs and outputs in shadePixel and tintPixel: validate/normalize the percentage parameter to the 0..1 range (e.g., percentage = Math.max(0, Math.min(1, percentage)) within each function), ensure computed channel values are integers and clamped to 0..255 before returning (use Math.round and Math.max/Math.min on each of red/green/blue results), and apply the same clamping for tintPixel's computed tintedRed/tintedGreen/tintedBlue so both helpers always return valid RGB values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@README.md`:
- Around line 43-48: The README example has a typo and path reuse: replace the
misspelled variable "collpased" with the correct "collapsed" (result of
generateCollapsed) and write the two outputs to distinct files so the expanded
and collapsed images aren't overwritten; update the writeFileSync calls that use
the variables from generate(...) and generateCollapsed(...) accordingly (look
for generate, generateCollapsed, expanded, collapsed, and writeFileSync).
- Around line 7-25: Fix the README typos and heading level: change the "###
Collapsed" heading to "## Collapsed", correct all occurrences of "collpased" to
"collapsed" (including alt text and any image path tokens like
"Augur_Message_collpased.png" if those filenames are meant to be "collapsed"),
and change the misspelled "Auger Message" to "Augur Message" in the Expanded
image captions; update the image paths/captions consistently so alt text,
visible text, and file names match (refer to the strings "### Collapsed",
"collpased", "Augur_Message_collpased.png", and "Auger Message"/"Augur Message"
to locate edits).
In `@src/generator.ts`:
- Around line 25-49: generateCollapsed currently performs canvas/text operations
without registering custom fonts, causing fallback metrics; call registerFonts()
at the start of the generateCollapsed function (before createCanvas or any
drawing/text calls) so that text rendering (e.g., context.font and
context.fillText) uses the intended fonts; ensure the call mirrors how generate
uses registerFonts() to guarantee correct metrics and appearance.
---
Outside diff comments:
In `@tests/generator.spec.ts`:
- Around line 30-45: The for-loop iterates one too many times and the collapsed
output assertions/filename are incorrect: change the loop condition to use i <
mods.length (instead of <=) to avoid out-of-range access when calling
find.findItem(mods[i]), add an assertion assert.ok(modMin) after generating
modMin (from generateCollapsed) to tighten the test, and fix the output filename
typo from "_collpased" to "_collapsed" when calling writeFile; reference the
generate, generateCollapsed, modFull, modMin, mods, find.findItem, and writeFile
usages to locate the changes.
---
Nitpick comments:
In `@src/utils.ts`:
- Around line 208-214: The exported helper hexToRGB currently parses slices
without validating input, which can produce NaN for malformed hex strings;
update hexToRGB to validate the input first (e.g. test against a regex like
/^#([0-9A-Fa-f]{6})$/), throw a clear Error when the format is invalid, and only
then parse the r,g,b channels with parseInt and return the RGB object so callers
fail fast on bad input.
- Around line 217-237: Clamp inputs and outputs in shadePixel and tintPixel:
validate/normalize the percentage parameter to the 0..1 range (e.g., percentage
= Math.max(0, Math.min(1, percentage)) within each function), ensure computed
channel values are integers and clamped to 0..255 before returning (use
Math.round and Math.max/Math.min on each of red/green/blue results), and apply
the same clamping for tintPixel's computed tintedRed/tintedGreen/tintedBlue so
both helpers always return valid RGB values.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (14)
assets/readme/Afterburn.pngis excluded by!**/*.pngassets/readme/Afterburn_collpased.pngis excluded by!**/*.pngassets/readme/Archgun_Riven_Mod.pngis excluded by!**/*.pngassets/readme/Archon_Intensify.pngis excluded by!**/*.pngassets/readme/Augur_Message.pngis excluded by!**/*.pngassets/readme/Augur_Message_collpased.pngis excluded by!**/*.pngassets/readme/Augur_Message_empty.pngis excluded by!**/*.pngassets/readme/Augur_Message_filled.pngis excluded by!**/*.pngassets/readme/Primed_Flow.pngis excluded by!**/*.pngassets/readme/Primed_Flow_collpased.pngis excluded by!**/*.pngassets/readme/Steel_Charge.pngis excluded by!**/*.pngassets/readme/Steel_Charge_collpased.pngis excluded by!**/*.pngassets/readme/Streamline.pngis excluded by!**/*.pngassets/readme/Vitality.pngis excluded by!**/*.png
📒 Files selected for processing (6)
README.mdsrc/drawers.tssrc/generator.tssrc/styling.tssrc/utils.tstests/generator.spec.ts
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (2)
README.md (2)
47-47:⚠️ Potential issue | 🟡 MinorFix variable typo in the collapsed output write.
Line 47 writes
collpased, which is undefined.Suggested patch
-writeFileSync('directory/collapsed.png', collpased); +writeFileSync('directory/collapsed.png', collapsed);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` at line 47, The README has a typo in the writeFileSync call: it uses the undefined variable name "collpased"; change the variable passed to writeFileSync('directory/collapsed.png', collpased) to the correct variable "collapsed" so the call becomes writeFileSync('directory/collapsed.png', collapsed), ensuring the correct image/buffer variable used by the surrounding code (search for usages/definition of "collapsed" in the same example to confirm the correct identifier).
7-7:⚠️ Potential issue | 🟡 MinorStandardize
collapsedspelling across docs and asset references.Line 7 and Lines 15-18 still use
collpased. This leaves inconsistent docs wording and likely broken references if assets are named withcollapsed.Suggested patch
-Assembles [Mod Assets](https://wiki.warframe.com/w/Mod/Assets) into full/collpased mod images using warframe-items +Assembles [Mod Assets](https://wiki.warframe.com/w/Mod/Assets) into full/collapsed mod images using warframe-items @@ - - - - + + + +Also applies to: 15-18
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@README.md` at line 7, Replace the misspelled token "collpased" with the correct "collapsed" wherever it appears (e.g., in the README description and the asset reference lines), ensuring link text, headings, and any asset name references use "collapsed" consistently; search for the exact string "collpased" and update all occurrences to "collapsed" so documentation and asset references match.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@README.md`:
- Around line 43-44: Update calls to generate and generateCollapsed to use the
new async object-based API: pass a GenerateModProps object (e.g., { mod, rank: 3
}) instead of positional args, and await both functions since they return
Promises; change any places that directly log the return value (like line 46) to
await the result before using it. Locate usages by the function names generate
and generateCollapsed and ensure the argument shape matches GenerateModProps and
that the calls are awaited.
In `@src/generator.ts`:
- Around line 52-57: In generateCollapsed the top image is always drawn at x=0
which left-aligns oversized tops and mispositions the mod-set header; compute a
topX = (canvas.width - top.width) / 2 and use context.drawImage(top, topX, 0,
...) so the top is centered (negative topX is fine when top.width >
canvas.width), then update the header draw call to use that topX (e.g.
context.drawImage(await drawHeader(...), topX + top.width * 0.35, 0, ...) so
header alignment follows the centered top; adjust any width/height scaling
arguments accordingly.
---
Duplicate comments:
In `@README.md`:
- Line 47: The README has a typo in the writeFileSync call: it uses the
undefined variable name "collpased"; change the variable passed to
writeFileSync('directory/collapsed.png', collpased) to the correct variable
"collapsed" so the call becomes writeFileSync('directory/collapsed.png',
collapsed), ensuring the correct image/buffer variable used by the surrounding
code (search for usages/definition of "collapsed" in the same example to confirm
the correct identifier).
- Line 7: Replace the misspelled token "collpased" with the correct "collapsed"
wherever it appears (e.g., in the README description and the asset reference
lines), ensuring link text, headings, and any asset name references use
"collapsed" consistently; search for the exact string "collpased" and update all
occurrences to "collapsed" so documentation and asset references match.
What did you fix?
Adds the ability to generate smaller "collapsed" versions
Reproduction steps
Evidence/screenshot/link to line
Considerations
Summary by CodeRabbit
New Features
Documentation
Style
Bug Fixes
Tests