Skip to content

refactor: Deepen highlight-parts transformation into one module#7091

Draft
github-actions[bot] wants to merge 1 commit into
masterfrom
refactor/candidate-1-deepen-highlight-parts-transformation-into-one-m
Draft

refactor: Deepen highlight-parts transformation into one module#7091
github-actions[bot] wants to merge 1 commit into
masterfrom
refactor/candidate-1-deepen-highlight-parts-transformation-into-one-m

Conversation

@github-actions

Copy link
Copy Markdown

Summary

Architecture Refactor Implementation: candidate-1

Run: github-28094741786 Branch: refactor/candidate-1-deepen-highlight-parts-transformation-into-one-m

Selected Approach

Chosen: one unified highlight-parts.ts module, with the four original files kept as thin re-export shims.

The "parse / serialize / reverse a highlighted string" concept was split across four
tiny exports (getHighlightedParts, concatHighlightedParts, reverseHighlightedParts,
getHighlightFromSiblings), two of which independently imported TAG_REPLACEMENT from a
fifth file. I moved the implementation of all four functions into a single deep module,
packages/instantsearch.js/src/lib/utils/highlight-parts.ts, so the inverse operations
(getHighlightedPartsconcatHighlightedParts), the reverse operation, the sibling
default rule, and the single TAG_REPLACEMENT coupling now live in one place. The four
original files became one-line re-export shims so every public/barrel name and every deep
import path (instantsearch.js/es/lib/utils/getHighlightedParts, etc.) keeps resolving
unchanged.

As part of the consolidation I fixed the latent sibling-default bug in
getHighlightFromSiblings: parts[i + 1]?.isHighlighted || true /
parts[i - 1]?.isHighlighted || true collapsed every present false neighbor to
true, so the function effectively always returned true for a non-alphanumeric part.
Replacing || true with ?? true preserves the intended "missing sibling defaults to
highlighted" behavior while honoring a present false neighbor.

Why this approach: It is the lowest-risk option that still deepens the module. All
external consumers (react-instantsearch, vue-instantsearch, and the instantsearch.js
helpers/) import these symbols through the lib/utils barrel, which is untouched. The
shims also keep undocumented deep-import subpaths working, so there is zero migration cost
for any consumer. The implementation is now concentrated in one cohesive module — a
tag-format or sibling-rule change touches one file instead of five.

Rejected alternatives:

  • Delete the four files and re-point the barrel at highlight-parts.ts. Slightly
    cleaner (no pass-through files), but it removes the per-file deep-import subpaths from
    the published es/ build and forces churn in the existing test files. Marginal benefit
    for added compat risk, so rejected in favor of shims (which the scout report explicitly
    proposed: "keep the existing named exports as thin re-exports").
  • Make getHighlightFromSiblings fully private (drop its public/barrel export). This
    best matches the "hide the sibling logic" framing, but getHighlightFromSiblings is
    currently exported from the lib/utils barrel, so removing it is a public-surface
    change with no functional payoff. Kept it exported; it is now simply colocated with the
    reverse logic it serves.
  • Move TAG_REPLACEMENT into the new module. escape-highlight.ts legitimately owns
    that constant (it also drives replaceTagsAndEscape/escapeFacets), so moving it would
    widen the diff and couple escaping to highlight-parts. Left it where it is; the new
    module imports it once instead of from two separate files.

Summary

Consolidated the four highlight-parts utilities into a single deep module while preserving
every public export and import path via thin re-export shims, and fixed the
getHighlightFromSiblings || true sibling-default bug (|| true?? true) so a
non-alphanumeric separator correctly adopts the shared state of present non-highlighted
siblings.

Changed Files

Source:

  • packages/instantsearch.js/src/lib/utils/highlight-parts.ts (new) — unified module
    holding getHighlightedParts, concatHighlightedParts, getHighlightFromSiblings, and
    reverseHighlightedParts, with the single TAG_REPLACEMENT import and the corrected
    ?? true sibling default. Functions carry brief JSDoc describing the inverse/reverse
    relationships.
  • packages/instantsearch.js/src/lib/utils/getHighlightedParts.ts — now re-exports
    getHighlightedParts from ./highlight-parts.
  • packages/instantsearch.js/src/lib/utils/concatHighlightedParts.ts — now re-exports
    concatHighlightedParts from ./highlight-parts.
  • packages/instantsearch.js/src/lib/utils/reverseHighlightedParts.ts — now re-exports
    reverseHighlightedParts from ./highlight-parts.
  • packages/instantsearch.js/src/lib/utils/getHighlightFromSiblings.ts — now re-exports
    getHighlightFromSiblings from ./highlight-parts.

Tests:

  • packages/instantsearch.js/src/lib/utils/__tests__/highlight-parts-test.ts (new) —
    round-trip test asserting concat(get(x)) === x across single-match, multi-match,
    fully-highlighted, and no-highlight inputs, exercised at the unified module's surface.
  • packages/instantsearch.js/src/lib/utils/__tests__/getHighlightFromSiblings-test.ts
    added cases pinning the corrected behavior: present false siblings keep false
    (the bug fix), a missing sibling still defaults to highlighted, and disagreeing siblings
    preserve the part's own state.
  • packages/instantsearch.js/src/lib/utils/__tests__/reverseHighlightedParts-test.ts
    updated the multi-match expectation: the - separator between two reversed-highlighted
    siblings is now true (contiguous) instead of the previous buggy false, with a comment
    explaining the change.

Expected Validation

Ran in this workflow:

  • yarn install --frozen-lockfile — dependencies were absent; installed once. Succeeded.
  • yarn lint:changed — reported "No lintable files matched" because it diffs
    merge-base(HEAD, origin/master)..HEAD, and the change is intentionally left
    uncommitted. Attempts to lint the explicit paths (yarn lint:ox <files> /
    lint:staged) required interactive command/git add approval that is unavailable in
    this workflow, so oxlint did not run on the changed files here. The changes are
    stylistically identical to the pre-existing code (moved verbatim plus JSDoc), so lint
    risk is low; PR CI must run oxlint over these files.
  • yarn jest --findRelatedTests <5 changed source files> --ci --runInBand --passWithNoTests
    296 suites / 3785 tests passed (237 skipped). This includes all four util test
    files, the new highlight-parts-test.ts, and the helper reverseHighlight /
    reverseSnippet snapshot tests, confirming the ?? true fix changes no real-world
    rendered output (the degenerate input it affects cannot be produced by
    getHighlightedParts, which never emits consecutive non-highlighted parts).

Not run (left to PR CI), with rationale:

  • yarn type-check — the candidate does not change any shared TypeScript contract,
    generated declaration, public export name, or cross-package API: the lib/utils barrel
    still exports the same four symbols with identical signatures, and HighlightedParts
    is unchanged. The round-trip test's concat(get(x)) is type-correct because
    getHighlightedParts returns { value: string; isHighlighted: boolean }[], which is
    structurally HighlightedParts[]. Per the validation rules, full type-checking is left
    to PR CI.
  • Full CI suites, builds, bundle-size, e2e — not required for this internal,
    behavior-preserving refactor.

Review Notes

  • Behavior change to verify: the getHighlightFromSiblings fix (|| true?? true).
    In real usage this is reached only via the instantsearch.js reverseHighlight /
    reverseSnippet string helpers (the React/Vue/preact reverse components do a naive
    per-part flip and never call this function). The only input shape whose output changes is
    a non-alphanumeric part sitting between two present false siblings — which
    getHighlightedParts never emits — so all existing helper snapshots are unchanged
    (verified green). The one assertion that changed is the synthetic
    reverseHighlightedParts unit test, which previously encoded the buggy output.
  • Compatibility: the four shim files preserve every barrel export and deep-import
    subpath. If a reviewer prefers no pass-through files, the follow-up would be to delete
    the shims and re-point the barrel at highlight-parts.ts — deliberately deferred here to
    keep migration risk at zero.
  • Out of scope (do not include in this PR): moving TAG_REPLACEMENT out of
    escape-highlight.ts, and the @MAJOR TODO about using TAG_PLACEHOLDER instead of
    TAG_REPLACEMENT in getHighlightedParts — both are pre-existing and unrelated to this
    deepening.

Source

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 21 complexity

Metric Results
Complexity 21

View in Codacy

TIP This summary will be updated as you push new changes.

@pkg-pr-new

pkg-pr-new Bot commented Jun 24, 2026

Copy link
Copy Markdown
More templates

algoliasearch-helper

npm i https://pkg.pr.new/algolia/instantsearch/algoliasearch-helper@7091

instantsearch-ui-components

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch-ui-components@7091

instantsearch.css

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch.css@7091

instantsearch.js

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch.js@7091

react-instantsearch

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch@7091

react-instantsearch-core

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-core@7091

react-instantsearch-nextjs

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-nextjs@7091

react-instantsearch-router-nextjs

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-router-nextjs@7091

vue-instantsearch

npm i https://pkg.pr.new/algolia/instantsearch/vue-instantsearch@7091

commit: 066c235

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.

0 participants