Skip to content

feat: migrate deprecated classes and custom properties#4338

Merged
Blackbaud-ErikaMcVey merged 10 commits intomainfrom
deprecated-class-schematic
Mar 26, 2026
Merged

feat: migrate deprecated classes and custom properties#4338
Blackbaud-ErikaMcVey merged 10 commits intomainfrom
deprecated-class-schematic

Conversation

@Blackbaud-ErikaMcVey
Copy link
Copy Markdown
Contributor

@Blackbaud-ErikaMcVey Blackbaud-ErikaMcVey commented Mar 25, 2026

Summary by CodeRabbit

  • New Features

    • Added a migration that automatically replaces deprecated CSS variables and class names across HTML, JS/TS, and CSS/SCSS files.
    • Registered the migration in package migration configuration so it can be run as part of updates.
  • Tests

    • Added comprehensive end-to-end tests validating replacements, boundary/edge cases, mixed updates, ignored file types, and fallback source-root behavior.
  • Chores

    • Bumped design-tokens dependency and enabled JSON module imports in TypeScript config.

@Blackbaud-ErikaMcVey Blackbaud-ErikaMcVey added the risk level (author): 2 This change has a slight chance of introducing a bug label Mar 25, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new Angular migration schematic and tests that scan workspace source files to replace deprecated CSS classes and custom properties using mappings derived from imported design-token/style JSON; includes type definitions, migrations manifest entry, JSON import support, and dependency bumps.

Changes

Cohort / File(s) Summary
Migrations manifest & packages
libs/components/packages/migrations.json, libs/components/packages/package.json, libs/components/theme/package.json, package.json
Added replace-deprecated-css-vars-and-classes schematic entry; bumped @blackbaud/skyux-design-tokens to 5.5.0.
Compiler config
libs/components/packages/tsconfig.json
Enabled resolveJsonModule to allow importing JSON token/style files.
Migration implementation
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts
New schematic rule that imports styles/tokens JSON, builds class and custom-property replacement maps, visits projects' source roots, performs boundary-aware replacements in .html/.ts/.js/.css/.scss files, writes updates, and exports traversal helpers and build rule.
Type definitions for mappings
libs/components/packages/src/schematics/.../types/public-api-style-group.ts, .../public-api-style.ts, .../public-api-styles.ts, .../public-api-token-group.ts, .../public-api-token.ts, .../public-api-tokens.ts
Added interfaces modeling styles, tokens, groups, and fields for deprecated/obsolete class names and custom properties used to generate replacement maps.
Tests
libs/components/packages/src/schematics/.../replace-deprecated-css-vars-and-classes.spec.ts
Comprehensive Jest/SchematicTestRunner tests covering class and custom-property replacements across file types, edge cases, mixed replacements, sourceRoot fallback, ignored extensions, and unit tests for traversal helpers.

Sequence Diagram

sequenceDiagram
    participant CLI as User/CLI
    participant Schematic as Migration Schematic
    participant Styles as Styles JSON
    participant Tokens as Tokens JSON
    participant Workspace as Workspace Config
    participant Files as Source Files

    CLI->>Schematic: run migration
    Schematic->>Styles: import styles JSON
    Styles-->>Schematic: provide style groups & deprecated classes
    Schematic->>Tokens: import tokens JSON
    Tokens-->>Schematic: provide token groups & deprecated properties
    Schematic->>Schematic: build replacement maps
    Schematic->>Workspace: read projects and sourceRoot
    Workspace-->>Schematic: return project roots
    Schematic->>Files: iterate supported files & read contents
    Files-->>Schematic: return file content
    Schematic->>Schematic: apply boundary-aware replacements
    alt file changed
        Schematic->>Files: write updated content
        Files-->>Schematic: confirm write
        Schematic->>CLI: log "Updated <filePath>"
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • Blackbaud-SteveBrush
  • Blackbaud-SandhyaRajasabeson

Poem

🐰 I hop through tokens and tidy each class,

Old vars farewell, new names come to pass,
I nibble through files with careful delight,
Rewriting old footprints deep into night,
A small rabbit's patchwork—neat, swift, and light.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately summarizes the main change: introducing a migration schematic for deprecated CSS classes and custom properties across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch deprecated-class-schematic

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

@nx-cloud
Copy link
Copy Markdown

nx-cloud bot commented Mar 25, 2026

View your CI Pipeline Execution ↗ for commit 806911b

Command Status Duration Result
nx build code-examples-playground --baseHref=ht... ✅ Succeeded 1m 50s View ↗
nx build playground --baseHref=https://blackbau... ✅ Succeeded 1m 35s View ↗
nx build integration --baseHref=https://blackba... ✅ Succeeded 34s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-26 20:50:52 UTC

Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts`:
- Around line 102-115: applyCustomPropertyReplacements currently does a raw
global string replace which causes substring matches (e.g., --sky-old-var
matching --sky-old-var-extended); update the matching logic in
applyCustomPropertyReplacements to use a boundary-aware RegExp similar to the
class replacement path (use lookarounds or explicit token boundaries around the
custom property name) so only exact custom property names are replaced, and add
a regression test that covers a suffixed property (e.g., --sky-old-var and
--sky-old-var-extended) to ensure only the exact name is changed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 685de262-bfca-4c33-8b5c-1d041d13cb57

📥 Commits

Reviewing files that changed from the base of the PR and between 2d4676b and bcf08aa.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • libs/components/packages/migrations.json
  • libs/components/packages/package.json
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts
  • libs/components/packages/tsconfig.json

@blackbaud-sky-build-user
Copy link
Copy Markdown
Collaborator

blackbaud-sky-build-user commented Mar 25, 2026

Storybook preview

Component Storybooks:

  • (no component storybooks affected in this pr)

Apps:

Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts (1)

85-122: Extract the shared boundary-aware replacement loop.

applyClassReplacements() and applyCustomPropertyReplacements() now have identical logic. Pulling that loop into one helper would keep future matcher changes from drifting between the two paths.

♻️ Suggested simplification
+function applyBoundaryAwareReplacements(
+  content: string,
+  replacements: Record<string, string>,
+): string {
+  let updated = content;
+
+  for (const [oldValue, newValue] of Object.entries(replacements)) {
+    const pattern = new RegExp(
+      `(?<![\\w-])${escapeRegExp(oldValue)}(?![\\w-])`,
+      'g',
+    );
+    updated = updated.replace(pattern, newValue);
+  }
+
+  return updated;
+}
+
 function applyClassReplacements(
   content: string,
   replacements: Record<string, string>,
 ): string {
-  let updated = content;
-
-  for (const [oldClass, newClass] of Object.entries(replacements)) {
-    const pattern = new RegExp(
-      `(?<![\\w-])${escapeRegExp(oldClass)}(?![\\w-])`,
-      'g',
-    );
-    updated = updated.replace(pattern, newClass);
-  }
-
-  return updated;
+  return applyBoundaryAwareReplacements(content, replacements);
 }
@@
 function applyCustomPropertyReplacements(
   content: string,
   replacements: Record<string, string>,
 ): string {
-  let updated = content;
-
-  for (const [oldProp, newProp] of Object.entries(replacements)) {
-    const pattern = new RegExp(
-      `(?<![\\w-])${escapeRegExp(oldProp)}(?![\\w-])`,
-      'g',
-    );
-    updated = updated.replace(pattern, newProp);
-  }
-
-  return updated;
+  return applyBoundaryAwareReplacements(content, replacements);
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts`
around lines 85 - 122, Both applyClassReplacements and
applyCustomPropertyReplacements contain the same boundary-aware loop; extract
that loop into a single helper (e.g., applyBoundaryAwareReplacements or
replaceWithBoundaryAwarePattern) that accepts content and replacements and
returns the updated string, and then have applyClassReplacements and
applyCustomPropertyReplacements call that helper with their respective
replacements; preserve the existing regex construction using escapeRegExp and
the lookaround (`(?<![\\w-])... (?![\\w-])`) and keep behavior identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts`:
- Around line 85-122: Both applyClassReplacements and
applyCustomPropertyReplacements contain the same boundary-aware loop; extract
that loop into a single helper (e.g., applyBoundaryAwareReplacements or
replaceWithBoundaryAwarePattern) that accepts content and replacements and
returns the updated string, and then have applyClassReplacements and
applyCustomPropertyReplacements call that helper with their respective
replacements; preserve the existing regex construction using escapeRegExp and
the lookaround (`(?<![\\w-])... (?![\\w-])`) and keep behavior identical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91ebe3eb-ff4e-4cb1-8c6e-941f76390e0b

📥 Commits

Reviewing files that changed from the base of the PR and between bcf08aa and 586d03e.

📒 Files selected for processing (2)
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts

@Blackbaud-SteveBrush Blackbaud-SteveBrush self-assigned this Mar 25, 2026
Copy link
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (1)
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts (1)

2-3: Consider pinning the replacement tables for this migration.

Because this rule lives under update-14, deriving its maps from the current design-token bundles makes the rewrite set drift with that package. If public-api-styles.json / public-api-tokens.json are not guaranteed to retain every historical alias across future releases, freezing the generated maps locally would make this migration deterministic for later upgrade paths.

Also applies to: 63-72

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts`
around lines 2 - 3, The migration currently imports live replacement maps via
stylesJson and tokensJson from
'@blackbaud/skyux-design-tokens/bundles/public-api-styles.json' and
public-api-tokens.json which makes the rule non-deterministic; replace those
dynamic imports by embedding pinned, versioned replacement tables as local
constants (e.g., a JSON snapshot assigned to a const like pinnedStylesMap and
pinnedTokensMap) inside replace-deprecated-css-vars-and-classes.ts so the
migration uses fixed maps for update-14; update any references to
stylesJson/tokensJson to use the pinned constants and add a brief comment noting
the source/version used for the snapshot.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts`:
- Around line 407-408: The assertions in the overlap test are checking the wrong
token names: update the two expectations that reference '.sky-old-color' and
'--sky-old-color' to assert the actual pre-migration names used in the fixture
('.sky-color' and '--sky-color') so the `updated` output is validated against
the real old tokens; locate the two expect(updated).not.toContain(...) lines in
replace-deprecated-css-vars-and-classes.spec.ts and change the string literals
accordingly.

---

Nitpick comments:
In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts`:
- Around line 2-3: The migration currently imports live replacement maps via
stylesJson and tokensJson from
'@blackbaud/skyux-design-tokens/bundles/public-api-styles.json' and
public-api-tokens.json which makes the rule non-deterministic; replace those
dynamic imports by embedding pinned, versioned replacement tables as local
constants (e.g., a JSON snapshot assigned to a const like pinnedStylesMap and
pinnedTokensMap) inside replace-deprecated-css-vars-and-classes.ts so the
migration uses fixed maps for update-14; update any references to
stylesJson/tokensJson to use the pinned constants and add a brief comment noting
the source/version used for the snapshot.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 69862e2d-2271-4eba-ada2-d5b215e12e79

📥 Commits

Reviewing files that changed from the base of the PR and between 36edeb4 and a55bbc5.

📒 Files selected for processing (2)
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an ng update migration under @skyux/packages to automatically replace deprecated SKY UX CSS class names and custom properties across project source files, driven by the design-tokens “public API” JSON bundles.

Changes:

  • Bump @blackbaud/skyux-design-tokens to 5.5.0 and add it as a dependency of @skyux/packages.
  • Add a new update-14 migration (replace-deprecated-css-vars-and-classes) that scans workspace projects and performs boundary-aware string replacements in .html/.ts/.js/.css/.scss.
  • Enable TypeScript JSON imports for the packages project and add a comprehensive schematic test suite covering success cases and edge cases.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
package.json Bumps design-tokens dependency to support the new migration inputs.
package-lock.json Locks the updated design-tokens version and updated metadata.
libs/components/theme/package.json Keeps theme package aligned with updated design-tokens.
libs/components/packages/package.json Adds design-tokens dependency needed by the migration at runtime.
libs/components/packages/tsconfig.json Enables resolveJsonModule so schematics can import JSON bundles.
libs/components/packages/migrations.json Registers the new update-14 migration entry.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.ts Implements the traversal + replacement logic and workspace file scanning.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts Adds tests for replacement behavior, boundaries, multi-project scanning, and fallback behaviors.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-token.ts Defines the token JSON shape used for traversal.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-token-group.ts Defines token group JSON shape used for traversal.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-tokens.ts Defines root token JSON shape used for traversal.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-style.ts Defines style JSON shape used for traversal.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-style-group.ts Defines style group JSON shape used for traversal.
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/types/public-api-styles.ts Defines root style JSON shape used for traversal.

Copy link
Copy Markdown
Contributor

@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.

♻️ Duplicate comments (1)
libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts (1)

36-69: ⚠️ Potential issue | 🟠 Major

Exercise the real schematic in these integration tests.

Line 39 only proves the migration does not throw, and Lines 56-61 bypass the registered schematic entirely by calling buildReplaceRule() with hand-written mappings. This suite would still stay green if migrations.json, the default factory, or the JSON-derived replacement maps broke and the real multi-project migration became a no-op. Seed one known deprecated class/custom property from the imported token/style JSON and run runner.runSchematic(SCHEMATIC_NAME, {}, tree) for the multi-project path too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts`
around lines 36 - 69, The multi-project test currently bypasses the real
schematic by calling buildReplaceRule directly; change the test to seed one
known deprecated token/class from the real imported JSON into the test trees
(same strings used in your design token/style JSON) and invoke the actual
schematic runner via runner.runSchematic(SCHEMATIC_NAME, {}, tree) (or the
string literal used by your collection) instead of calling buildReplaceRule,
then assert the transformed files contain the expected new class/property; keep
createTestLibrary, COLLECTION_PATH and runSchematic/runner references to locate
the test setup and replace the manual call accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts`:
- Around line 36-69: The multi-project test currently bypasses the real
schematic by calling buildReplaceRule directly; change the test to seed one
known deprecated token/class from the real imported JSON into the test trees
(same strings used in your design token/style JSON) and invoke the actual
schematic runner via runner.runSchematic(SCHEMATIC_NAME, {}, tree) (or the
string literal used by your collection) instead of calling buildReplaceRule,
then assert the transformed files contain the expected new class/property; keep
createTestLibrary, COLLECTION_PATH and runSchematic/runner references to locate
the test setup and replace the manual call accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a9b5b374-e3aa-477e-9e87-84731fdc03ea

📥 Commits

Reviewing files that changed from the base of the PR and between a55bbc5 and 86beb50.

📒 Files selected for processing (1)
  • libs/components/packages/src/schematics/migrations/update-14/replace-deprecated-css-vars-and-classes/replace-deprecated-css-vars-and-classes.spec.ts

@Blackbaud-ErikaMcVey Blackbaud-ErikaMcVey enabled auto-merge (squash) March 26, 2026 20:50
@Blackbaud-ErikaMcVey Blackbaud-ErikaMcVey merged commit a72cffa into main Mar 26, 2026
24 checks passed
@Blackbaud-ErikaMcVey Blackbaud-ErikaMcVey deleted the deprecated-class-schematic branch March 26, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk level (author): 2 This change has a slight chance of introducing a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants