Skip to content

Conversation

@j9t
Copy link
Owner

@j9t j9t commented Nov 28, 2025

Picks up kangax/html-minifier#1152 to offer the respective support in HMN.

Summary by CodeRabbit

  • New Features

    • Automatic minification of JSON inside script tags (JSON-LD, import maps, manifests, geo+json, speculation rules, etc.); malformed JSON is left unchanged by default or can be configured to raise errors.
  • Tests

    • Extensive coverage for JSON script minification, type-attribute variations, error handling, presets, and interactions with other minification options.
  • Documentation

    • Updated preset wording and added changelog entry for version 4.6.0.
  • Chores

    • Version bumped to 4.6.0.

✏️ Tip: You can customize this high-level summary in your review settings.

j9t added 3 commits November 28, 2025 21:08
Introduce automatic minification for JSON-based script types like `application/json` and `application/ld+json`. Add tests to ensure coverage for valid and malformed JSON, improving overall functionality and reliability.

(This commit message was AI-generated.)

Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Document the addition of automatic minification for JSON script tags, covering various MIME types and improvements in handling malformed JSON. This update ensures the changelog reflects the latest enhancements in functionality.

(This commit message was AI-generated.)

Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Walkthrough

Adds automatic minification of JSON content in script tags for several MIME types, introduces internal JSON helpers in the HTML minifier, bumps package to 4.6.0, adds tests and a changelog entry, and updates README wording for a preset.

Changes

Cohort / File(s) Summary
Version & Changelog
CHANGELOG.md, package.json, README.md
Bumped package version to 4.6.0, added changelog entry for v4.6.0, and updated README wording for the "comprehensive" preset.
Core implementation
src/htmlminifier.js
Added jsonScriptTypes set, minifyJson() utility, and hasJsonScriptType() detector; updated script processing to auto-minify JSON script contents (supports several MIME types) with configurable error behavior; integrated detection into minifyHTML() while preserving existing script handling.
Tests
tests/html.spec.js
Added tests covering JSON script minification across MIME types, case/whitespace/parameter variations, malformed-JSON handling and continueOnMinifyError behavior, interactions with other minifiers/options, and preset-related expectations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Review minifyJson() behavior for parsing, re-stringifying, and error handling (continueOnMinifyError default).
  • Verify jsonScriptTypes matching (case/parameter normalization) and hasJsonScriptType() logic.
  • Inspect integration points in processScript() and minifyHTML() to ensure existing script flows remain unchanged.
  • Check new tests in tests/html.spec.js for coverage of edge cases and option interactions.

Suggested reviewers

  • jonasgeiler

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Improve support for JSON minification' directly summarizes the main change: adding automatic JSON minification for script tags with JSON-related MIME types.
✨ 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 feature/json-script-minification

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.40.0)
tests/html.spec.js

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 (1)
src/htmlminifier.js (1)

465-479: Critical: Same type attribute normalization issue in processScript.

Line 469 has the same critical issue as hasJsonScriptType - it compares currentAttrs[i].value directly without normalization. This will fail to match type attributes with different casing, whitespace, or parameters.

Apply this diff to fix the issue:

 async function processScript(text, options, currentAttrs) {
   for (let i = 0, len = currentAttrs.length; i < len; i++) {
     if (currentAttrs[i].name.toLowerCase() === 'type') {
+      const normalizedType = trimWhitespace((currentAttrs[i].value || '').split(/;/, 2)[0]).toLowerCase();
       // Minify JSON script types automatically
-      if (jsonScriptTypes.includes(currentAttrs[i].value)) {
+      if (jsonScriptTypes.includes(normalizedType)) {
         return minifyJson(text, options);
       }
       // Process custom script types if specified
       if (options.processScripts && options.processScripts.includes(currentAttrs[i].value)) {
         return await minifyHTML(text, options);
       }
     }
   }
   return text;
 }

Note: The processScripts comparison at line 473 also has this issue, but that appears to be a pre-existing bug not introduced by this PR.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f3b9d50 and 1c3c2de.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • package.json (1 hunks)
  • src/htmlminifier.js (2 hunks)
  • tests/html.spec.js (1 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.
📚 Learning: 2025-09-04T19:01:27.237Z
Learnt from: j9t
Repo: j9t/html-minifier-next PR: 51
File: README.md:176-178
Timestamp: 2025-09-04T19:01:27.237Z
Learning: In html-minifier-next, the minifyJS option callback uses parameters (text, inline) while the minifyCSS option callback uses parameters (text, type). The README documentation correctly reflects these different parameter names for each option.

Applied to files:

  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • src/htmlminifier.js
🧬 Code graph analysis (1)
tests/html.spec.js (1)
src/htmlminifier.js (2)
  • minify (1517-1523)
  • minify (1517-1523)
🔇 Additional comments (4)
package.json (1)

87-87: Version bump aligned with new feature release

Version 4.6.0 here matches the new changelog entry and added JSON script minification behavior; nothing else needed.

src/htmlminifier.js (3)

434-441: LGTM - Comprehensive list of JSON MIME types.

The array covers the most common JSON-related script types including JSON-LD, import maps, and speculation rules.


443-453: Verify error handling consistency with other minification functions.

The function always returns the original text on error without checking options.continueOnMinifyError. In contrast, minifyJS (lines 849-858) and minifyCSS (lines 796-829) respect this flag and throw when it's set to false.

Should this function also respect the continueOnMinifyError option for consistency? Here's a suggested fix:

 function minifyJson(text, options) {
   try {
     return JSON.stringify(JSON.parse(text));
   }
   catch (err) {
+    if (!options.continueOnMinifyError) {
+      throw err;
+    }
     if (options.log) {
       options.log(err);
     }
     return text;
   }
 }

1355-1357: Good integration approach for automatic JSON minification.

The condition correctly triggers script processing for both custom processScripts types and JSON script types automatically. This allows JSON minification to work without requiring users to configure the processScripts option.

However, this depends on the fixes needed in hasJsonScriptType (line 455-463) to handle type attribute normalization correctly.

@coderabbitai
Copy link

coderabbitai bot commented Nov 29, 2025

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #131

coderabbitai bot added a commit that referenced this pull request Nov 29, 2025
Docstrings generation was requested by @j9t.

* #130 (comment)

The following files were modified:

* `src/htmlminifier.js`
j9t added 4 commits November 29, 2025 11:15
Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Add tests for various JSON script MIME types, malformed content, and error-handling scenarios to ensure robust minification. Includes validations for presets and automatic behavior checks.

(This commit message was AI-generated.)

Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 1c3c2de and fe6c8e2.

📒 Files selected for processing (4)
  • CHANGELOG.md (1 hunks)
  • README.md (1 hunks)
  • src/htmlminifier.js (2 hunks)
  • tests/html.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.
Learnt from: j9t
Repo: j9t/html-minifier-next PR: 51
File: README.md:176-178
Timestamp: 2025-09-04T19:01:27.237Z
Learning: In html-minifier-next, the minifyJS option callback uses parameters (text, inline) while the minifyCSS option callback uses parameters (text, type). The README documentation correctly reflects these different parameter names for each option.
📚 Learning: 2025-09-04T19:01:27.237Z
Learnt from: j9t
Repo: j9t/html-minifier-next PR: 51
File: README.md:176-178
Timestamp: 2025-09-04T19:01:27.237Z
Learning: In html-minifier-next, the minifyJS option callback uses parameters (text, inline) while the minifyCSS option callback uses parameters (text, type). The README documentation correctly reflects these different parameter names for each option.

Applied to files:

  • README.md
  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • src/htmlminifier.js
🧬 Code graph analysis (1)
tests/html.spec.js (2)
src/htmlminifier.js (5)
  • minify (1523-1529)
  • minify (1523-1529)
  • result (802-808)
  • result (856-856)
  • result (1526-1526)
src/presets.js (1)
  • getPreset (54-58)
🔇 Additional comments (5)
README.md (1)

109-111: Preset wording now correctly reflects comprehensive behavior

Updating “all conservative options” to “relevant conservative options” matches the current preset composition (after removing conservativeCollapse from comprehensive) and avoids overselling its option set.

tests/html.spec.js (2)

1288-1295: Good regression coverage for JSON script type preservation

These assertions nicely lock in the contract that removeScriptTypeAttributes must not strip JSON/structured‑data types (application/ld+json, importmap), preventing them from ever becoming executable JS by accident.


1777-3315: JSON script tests comprehensively exercise types, failures, and presets

The new JSON-script block covers:

  • All documented MIME types (application/json, application/ld+json, application/manifest+json, application/vnd.geo+json, importmap, speculationrules), including malformed cases that must be preserved when continueOnMinifyError is true.
  • Type‑matching edge cases (case‑insensitive values, surrounding whitespace, charset parameters) while preserving the original/normalized type text as intended.
  • Error‑mode semantics via continueOnMinifyError (best‑effort vs throwing SyntaxError), aligned with other minifiers.
  • Preset and “no options” flows, asserting that JSON minification is automatic under presets and even with {} options.

This suite is thorough and matches the behavior documented in the changelog; I don’t see gaps that would block merging.

src/htmlminifier.js (2)

456-467: hasJsonScriptType now normalizes type correctly

hasJsonScriptType now trims, strips parameters, and lowercases the type attribute before comparing against jsonScriptTypes, mirroring the logic in isScriptTypeAttribute. This addresses the earlier concern about case/whitespace/charset variants like type="Application/JSON" or type="application/json; charset=utf-8" not being detected.


1361-1365: Chars handler: JSON scripts now always go through processScript—confirm precedence over processScripts

The new condition

if (specialContentTags.has(currentTag) && (options.processScripts || hasJsonScriptType(currentAttrs))) {
  text = await processScript(text, options, currentAttrs);
}

nicely ensures JSON script types get minified even when options.processScripts is unset.

Two behavioral nuances to be aware of:

  1. For JSON-like types that are also listed in processScripts, processScript will now always take the JSON path (returning from minifyJson) before it ever considers treating them as HTML, effectively making the JSON behavior take precedence.
  2. Non-JSON processScripts types continue to work as before, but with the matching change noted around Line 471 this may not align with how processScripts is matched in createSortFns.

If this precedence for JSON over processScripts is intentional (and you don’t expect users to treat application/json etc. as HTML templates), then this looks good. Otherwise, you might want to invert the order in processScript so that explicit processScripts config wins over auto JSON handling.

j9t added 3 commits November 29, 2025 11:37
Refactor `jsonScriptTypes` to use `Set` for improved performance and simplify related checks. Adjust processing logic for better readability and accuracy when handling `type` attributes.

(This commit message was AI-generated.)

Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Add test cases to validate `processScripts` matching semantics and JSON script type detection. Covers case-sensitive matching, normalized comparison, and parameter handling for robust script minification behavior.

(This commit message was AI-generated.)

Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
Signed-off-by: Jens Oliver Meiert <jens@meiert.com>
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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between fe6c8e2 and 6f378b2.

📒 Files selected for processing (3)
  • CHANGELOG.md (1 hunks)
  • src/htmlminifier.js (2 hunks)
  • tests/html.spec.js (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.
Learnt from: j9t
Repo: j9t/html-minifier-next PR: 51
File: README.md:176-178
Timestamp: 2025-09-04T19:01:27.237Z
Learning: In html-minifier-next, the minifyJS option callback uses parameters (text, inline) while the minifyCSS option callback uses parameters (text, type). The README documentation correctly reflects these different parameter names for each option.
📚 Learning: 2025-09-04T19:01:27.237Z
Learnt from: j9t
Repo: j9t/html-minifier-next PR: 51
File: README.md:176-178
Timestamp: 2025-09-04T19:01:27.237Z
Learning: In html-minifier-next, the minifyJS option callback uses parameters (text, inline) while the minifyCSS option callback uses parameters (text, type). The README documentation correctly reflects these different parameter names for each option.

Applied to files:

  • CHANGELOG.md
  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads, non-git environments) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • tests/html.spec.js
  • src/htmlminifier.js
📚 Learning: 2025-09-10T13:18:01.568Z
Learnt from: jonasgeiler
Repo: j9t/html-minifier-next PR: 58
File: package.json:84-84
Timestamp: 2025-09-10T13:18:01.568Z
Learning: In html-minifier-next project (JavaScript/Node.js), the maintainer jonasgeiler prefers not to add git worktree checks to the prepare script in package.json. They consider the failure scenario (ZIP downloads) acceptable since those users aren't following standard git workflows and can remove the script if needed.

Applied to files:

  • src/htmlminifier.js
🧬 Code graph analysis (1)
src/htmlminifier.js (1)
src/htmlparser.js (1)
  • i (85-85)
🔇 Additional comments (3)
CHANGELOG.md (1)

7-19: JSON script minification entry accurately reflects behavior and coverage

The 4.6.0 notes line up with the implementation: supported script types match jsonScriptTypes, and the error-handling description correctly mirrors continueOnMinifyError semantics used in minifyJson (best-effort by default, strict when disabled). Looks good.

src/htmlminifier.js (2)

434-467: JSON helpers and type detection are consistent and robust

Using a Set for jsonScriptTypes and routing JSON through minifyJson gives a clear, self-contained path with error handling that matches the existing CSS/JS/URL contracts (respecting continueOnMinifyError and log). hasJsonScriptType now correctly normalizes the type attribute (trim, strip parameters, lowercase), so valid variants like different casing or charset parameters are detected reliably.


471-482: processScript + chars integration preserves processScripts semantics and adds safe JSON auto-minification

The updated processScript uses the normalized type only for JSON detection while matching options.processScripts against the raw type value, keeping behavior in sync with createSortFns.scan and avoiding surprises for existing configs. The chars handler now calls processScript for script/style when either processScripts is configured or a JSON script type is present, so JSON blocks are minified even without processScripts, while executable scripts still flow exclusively through minifyJS and styles through minifyCSS. This wiring looks correct and non-breaking.

Also applies to: 1362-1364

@j9t j9t merged commit d0c1947 into main Nov 29, 2025
8 checks passed
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.

2 participants