Skip to content

Conversation

@tbouffard
Copy link
Member

@tbouffard tbouffard commented Nov 18, 2025

From typescript-eslint
Prior to ES2015, Array#indexOf and String#indexOf comparisons against -1 were the standard ways to check whether a
value exists in an array or string, respectively.
Alternatives that are easier to read and write now exist: ES2015 added String#includes and ES2016 added Array#includes

Summary by CodeRabbit

  • Refactor

    • Modernized many internal membership and string checks to use contemporary includes-based operations, improving readability, null-safety, and consistency without changing user-visible behavior.
  • Chores

    • ESLint configuration updated to enforce includes-style checks to maintain consistent coding standards across the core codebase.

From typescript-eslint
  Prior to ES2015, Array#indexOf and String#indexOf comparisons against -1 were the standard ways to check whether a
  value exists in an array or string, respectively.
  Alternatives that are easier to read and write now exist: ES2015 added String#includes and ES2016 added Array#includes
  .
@tbouffard tbouffard added the refactor Code refactoring label Nov 18, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Walkthrough

Added ESLint rule enforcing unicorn/prefer-includes and replaced many uses of indexOf(...) with includes(...) (or negated includes) across TypeScript files in packages/core/src and a few GUI files to modernize membership/string checks.

Changes

Cohort / File(s) Summary
ESLint configuration
eslint.config.mjs
Added unicorn/prefer-includes: 'error' to the rules for files: ['packages/core/src/**/*'].
Client & UA/host checks
packages/core/src/Client.ts, packages/core/src/gui/MaxLog.ts, packages/core/src/gui/MaxWindow.ts
Replaced indexOf-based string checks on navigator.userAgent and HTTP/HTTPS checks with includes() and adjusted negations to preserve prior semantics.
Array membership & utilities
packages/core/src/i18n/Translations.ts, packages/core/src/serialization/ObjectCodec.ts, packages/core/src/util/cloneUtils.ts, packages/core/src/util/domUtils.ts, packages/core/src/util/mathUtils.ts, packages/core/src/view/GraphSelectionModel.ts, packages/core/src/view/cell/Cell.ts, packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts, packages/core/src/view/layout/hierarchical/SwimlaneModel.ts, packages/core/src/view/mixins/CellsMixin.ts, packages/core/src/view/mixins/SwimlaneMixin.ts, packages/core/src/view/shape/Shape.ts, packages/core/src/view/style/edge/Manhattan.ts
Replaced array.indexOf(...) >= 0 / indexOf(...) < 0 / indexOf(...) === -1 patterns with includes(...) or negated includes(...); added a module-scoped Set for block elements in domUtils; adjusted hex-string detection in mathUtils. No public API/signature changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Homogeneous, repetitive refactor (indexOf → includes) across many files.
  • Review focus areas:
    • packages/core/src/Client.ts — multiple UA-detection lines where negation inversion must preserve semantics.
    • packages/core/src/util/mathUtils.ts — altered hex detection logic; verify edge-case behavior.
    • packages/core/src/util/domUtils.ts — new Set usage and newline handling.

Possibly related PRs

Suggested labels

javascript

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the rationale for the change but lacks required PR checklist completion and detailed coverage of tests, documentation, and issue linking. Complete the PR checklist by addressing all required items: link to an issue, confirm discussion with maintainers, add test cases, provide screenshots if applicable, verify documentation updates, and confirm Conventional Commits compliance.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main refactoring change: replacing indexOf comparisons with the more modern includes method across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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 refactor/prefer_includes_to_indexOf

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: 0

🧹 Nitpick comments (1)
packages/core/src/Client.ts (1)

77-83: Membership checks correctly migrated to includes, but consider guarding IS_FF

The refactors to use includes/!includes for IS_NS, IS_ANDROID, IS_MT, NO_FO, and IS_LOCAL preserve the original indexOf logic and improve readability. One thing to consider: IS_FF now (and likely previously) dereferences navigator.userAgent without the typeof window !== 'undefined' / null guard used by nearby flags, which can throw in non‑browser/SSR environments; aligning it with the other feature flags would make this safer:

-  static IS_FF = navigator.userAgent.toLowerCase().includes('firefox');
+  static IS_FF =
+    typeof window !== 'undefined' &&
+    navigator.userAgent != null &&
+    navigator.userAgent.toLowerCase().includes('firefox');

Based on learnings

Also applies to: 93-95, 122-122, 129-141, 153-159, 196-199

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ff3d2c and 162f9a0.

📒 Files selected for processing (17)
  • eslint.config.mjs (1 hunks)
  • packages/core/src/Client.ts (6 hunks)
  • packages/core/src/gui/MaxLog.ts (1 hunks)
  • packages/core/src/gui/MaxWindow.ts (1 hunks)
  • packages/core/src/i18n/Translations.ts (1 hunks)
  • packages/core/src/serialization/ObjectCodec.ts (1 hunks)
  • packages/core/src/util/cloneUtils.ts (1 hunks)
  • packages/core/src/util/domUtils.ts (1 hunks)
  • packages/core/src/util/mathUtils.ts (5 hunks)
  • packages/core/src/view/GraphSelectionModel.ts (1 hunks)
  • packages/core/src/view/cell/Cell.ts (1 hunks)
  • packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts (2 hunks)
  • packages/core/src/view/layout/hierarchical/SwimlaneModel.ts (2 hunks)
  • packages/core/src/view/mixins/CellsMixin.ts (2 hunks)
  • packages/core/src/view/mixins/SwimlaneMixin.ts (1 hunks)
  • packages/core/src/view/shape/Shape.ts (1 hunks)
  • packages/core/src/view/style/edge/Manhattan.ts (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 857
File: packages/core/src/view/plugins/SelectionHandler.ts:1081-1092
Timestamp: 2025-06-26T13:27:19.012Z
Learning: User tbouffard prefers to keep PRs focused on their main objective and defer implementation improvements or logic fixes to future dedicated PRs. For maxGraph, refactoring PRs like Dictionary→Map migration should not include unrelated logic improvements even when valid issues are identified in the migrated code.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/AbstractGraph.ts:492-495
Timestamp: 2025-04-24T12:34:56.726Z
Learning: PR #776 focuses on refactoring to introduce AbstractGraph as a base class and moving code from Graph to AbstractGraph. Type improvements and other refinements should be addressed in future PRs to keep this one focused on the core architectural change.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 849
File: packages/html/stories/DragSource.stories.js:98-101
Timestamp: 2025-06-13T07:48:10.300Z
Learning: User tbouffard prefers answers in English; avoid switching to other languages in future replies.
📚 Learning: 2024-11-23T16:12:51.380Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 582
File: packages/core/src/util/config.ts:0-0
Timestamp: 2024-11-23T16:12:51.380Z
Learning: The `shallowCopy` function in `cloneUtils.ts` is intentionally designed to perform a shallow copy on objects that contain only primitive properties, and deep copying is not necessary.

Applied to files:

  • packages/core/src/util/cloneUtils.ts
📚 Learning: 2025-02-17T06:01:50.745Z
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 679
File: packages/html/stories/Drop.stories.js:71-94
Timestamp: 2025-02-17T06:01:50.745Z
Learning: maxGraph does not support Internet Explorer, making IE-specific browser compatibility checks unnecessary.

Applied to files:

  • packages/core/src/Client.ts
🧬 Code graph analysis (1)
packages/core/src/view/mixins/CellsMixin.ts (1)
packages/html/stories/Clipboard.stories.js (1)
  • cells (190-190)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (macos-14)
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (windows-2022)
  • GitHub Check: build
🔇 Additional comments (17)
packages/core/src/view/GraphSelectionModel.ts (1)

114-114: LGTM! Clean refactor to includes.

The change from indexOf(cell) >= 0 to includes(cell) improves readability while maintaining identical behavior for the membership check.

packages/core/src/view/mixins/SwimlaneMixin.ts (1)

269-269: LGTM! Correct negation with includes.

The transformation from indexOf(parentCell) < 0 to !includes(parentCell) is correct and improves code clarity.

packages/core/src/view/shape/Shape.ts (1)

848-848: LGTM! Improved readability in rounded corners logic.

The change to !exclude.includes(i - 1) maintains the correct logic while being more idiomatic.

packages/core/src/view/cell/Cell.ts (1)

518-518: LGTM! Clear membership check before insertion.

The refactor to !this.edges.includes(edge) correctly preserves the duplicate-prevention logic.

packages/core/src/util/domUtils.ts (1)

71-71: LGTM! More readable block element check.

The change to blocks.includes(elts[i + 1].nodeName) is correct and improves code clarity.

packages/core/src/util/cloneUtils.ts (1)

46-46: LGTM! Clearer transient field check.

The refactor to !transients.includes(i) maintains the correct cloning logic with improved readability.

packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts (1)

107-107: LGTM! Consistent edge membership checks.

Both changes correctly refactor the duplicate-edge prevention logic to use !includes(internalEdge), improving code consistency and readability.

Also applies to: 241-241

packages/core/src/i18n/Translations.ts (1)

119-119: LGTM! More idiomatic language support check.

The change to languages.includes(lan) is correct and aligns with modern JavaScript best practices.

packages/core/src/view/style/edge/Manhattan.ts (1)

113-116: String/array membership refactor looks behavior‑preserving

Using !pointString.includes('@') for the delimiter and endPointsKeys.includes(currentKey) for endpoint membership keeps the original semantics while improving readability.

Also applies to: 479-489

packages/core/src/view/layout/hierarchical/SwimlaneModel.ts (1)

100-110: includes usage keeps the edge de‑duplication semantics intact

Switching from indexOf(...) < 0 to !array.includes(...) for connectsAsTarget and connectsAsSource checks maintains the original “only push if not already present” behavior and is easier to read.

Also applies to: 253-258

eslint.config.mjs (1)

94-109: ESLint rule addition aligns config with the refactor

Enabling 'unicorn/prefer-includes': 'error' for packages/core/src/**/* is consistent with this PR’s changes and will prevent regressions back to indexOf-based membership checks.

packages/core/src/gui/MaxWindow.ts (1)

388-396: Presto user‑agent guard refactor preserves the workaround

The updated condition !navigator.userAgent || !navigator.userAgent.includes('Presto/2.5') keeps the original “skip overflow styling only on Presto 2.5.x” behavior while making the intent clearer.

packages/core/src/serialization/ObjectCodec.ts (1)

335-337: isExcluded refactor is semantically equivalent

Using this.exclude.includes(attr) instead of an indexOf comparison preserves the exclusion behavior and keeps the code consistent with the rest of the PR.

packages/core/src/gui/MaxLog.ts (1)

333-343: Presto textarea refresh condition correctly migrated to includes

The updated navigator.userAgent && navigator.userAgent.includes('Presto/2.5') check retains the original workaround behavior while following the new includes style.

packages/core/src/util/mathUtils.ts (1)

236-320: getPortConstraints and isNumeric refactors keep existing behavior

The direction checks in getPortConstraints now use directions.includes('north' | 'west' | 'south' | 'east'), which is equivalent to the old indexOf checks, and the isNumeric guard (typeof n !== 'string' || !n.toLowerCase().includes('0x')) preserves the prior “exclude hex-like strings” logic while matching the new includes style.

Also applies to: 673-678

packages/core/src/view/mixins/CellsMixin.ts (2)

2057-2057: LGTM! Clean refactor to modern array membership check.

The change from indexOf(parent) >= 0 to includes(parent) is correct and improves readability while preserving the existing logic.


2066-2066: LGTM! Consistent refactor for array membership check.

The change from indexOf(parent) >= 0 to includes(parent) is correct and maintains consistency with the refactor pattern applied throughout this PR.

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
3.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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: 0

🧹 Nitpick comments (1)
packages/core/src/util/domUtils.ts (1)

150-150: These null check changes appear unrelated to the PR's objective.

The changes from if (parent != null) to if (parent) refactor explicit null checks to truthiness checks. While low-risk given the Element type, this represents a different type of refactoring than the indexOfincludes modernization that is the focus of this PR.

Consider either reverting these changes to keep the PR focused on its stated objective, or documenting why they're included.

Based on learnings (user prefers focused PRs).

Also applies to: 168-168

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 299c24b and 93cf85c.

📒 Files selected for processing (2)
  • packages/core/src/gui/MaxWindow.ts (1 hunks)
  • packages/core/src/util/domUtils.ts (4 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 857
File: packages/core/src/view/plugins/SelectionHandler.ts:1081-1092
Timestamp: 2025-06-26T13:27:19.012Z
Learning: User tbouffard prefers to keep PRs focused on their main objective and defer implementation improvements or logic fixes to future dedicated PRs. For maxGraph, refactoring PRs like Dictionary→Map migration should not include unrelated logic improvements even when valid issues are identified in the migrated code.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 776
File: packages/core/src/view/AbstractGraph.ts:492-495
Timestamp: 2025-04-24T12:34:56.726Z
Learning: PR #776 focuses on refactoring to introduce AbstractGraph as a base class and moving code from Graph to AbstractGraph. Type improvements and other refinements should be addressed in future PRs to keep this one focused on the core architectural change.
Learnt from: tbouffard
Repo: maxGraph/maxGraph PR: 849
File: packages/html/stories/DragSource.stories.js:98-101
Timestamp: 2025-06-13T07:48:10.300Z
Learning: User tbouffard prefers answers in English; avoid switching to other languages in future replies.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build
  • GitHub Check: build (windows-2022)
  • GitHub Check: build (ubuntu-24.04)
  • GitHub Check: build (macos-14)
🔇 Additional comments (3)
packages/core/src/gui/MaxWindow.ts (1)

388-397: LGTM! Clean refactor with optional chaining.

The refactor from indexOf to includes with optional chaining correctly preserves the original behavior while improving readability. The logic properly skips overflow styling when navigator.userAgent is present and contains 'Presto/2.5', and enables it otherwise.

packages/core/src/util/domUtils.ts (2)

20-35: Excellent modernization to use Set for membership checks.

The change from an array to a Set for blocks is a solid improvement. Set provides O(1) lookup time compared to O(n) for array-based indexOf, and it's semantically clearer for membership testing of this static collection.


72-72: LGTM: Correct use of Set.has() for membership check.

This change aligns perfectly with the PR's objective. Using blocks.has() is more readable and efficient than the previous indexOf comparison.

@tbouffard tbouffard merged commit 99ab051 into main Nov 18, 2025
8 of 9 checks passed
@tbouffard tbouffard deleted the refactor/prefer_includes_to_indexOf branch November 18, 2025 11:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant