Skip to content

Development: Replace graphemer and markdown-it-highlightjs with platform code#12915

Merged
FelixTJDietrich merged 9 commits into
developfrom
chore/replace-graphemer-and-highlightjs
Jun 19, 2026
Merged

Development: Replace graphemer and markdown-it-highlightjs with platform code#12915
FelixTJDietrich merged 9 commits into
developfrom
chore/replace-graphemer-and-highlightjs

Conversation

@krusche

@krusche krusche commented Jun 14, 2026

Copy link
Copy Markdown
Member

Summary

Removes two small client dependencies by replacing them with platform/native equivalents, with no behavior change:

  • graphemer -> native Intl.Segmenter
  • markdown-it-highlightjs -> a tiny local markdown-it plugin over the already-present highlight.js engine

Motivation and Context

Part of an incremental client dependency cleanup. Both libraries wrap functionality that the platform (or an already-installed engine) provides directly.

Description

graphemer (1 site). The Monaco editor registers a custom backspace action that deletes one grapheme cluster at a time (so emoji and combined characters delete as a unit and collaborative edits stay minimal). The single Graphemer().splitGraphemes(...) call is replaced by Intl.Segmenter with granularity: 'grapheme', which is supported in all target browsers and the Node test runtime.

markdown-it-highlightjs (1 site). The plugin was used with default options (auto, code, ignoreIllegals). It is replaced by a small local markdown-it plugin (markdownItHighlightjs in markdown.conversion.util.ts) that:

  • sets md.options.highlight to delegate to highlight.js (auto-detect when no language, explicit language otherwise, escaped-HTML fallback on error), and
  • wraps the fence / code_block renderers to add the hljs CSS class.

This reproduces the exact markup the plugin produced. The vs.css / monokai.css highlight.js themes target the .hljs class, so highlighting is unchanged in both themes. highlight.js remains a direct dependency.

Steps for Testing

Verified locally:

  1. pnpm run compile (full tsc) passes.
  2. ESLint passes on both changed files.
  3. markdown.conversion.util.spec.ts: 81 tests pass, including "should convert fenced code blocks".
  4. monaco-editor.component.spec.ts: 52 tests pass, including "delete a combined emoji entirely on backspace" and "delete combined emojis one cluster at a time".

To test manually: render markdown containing fenced code blocks (with and without a language) and confirm syntax highlighting in light and dark mode; in the Monaco editor, type an emoji / combined character and press Backspace to confirm the whole cluster is removed.

Client

  • I strictly followed the client coding guidelines.
  • No visual change; syntax-highlighting markup and grapheme deletion behavior are preserved.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Updated editor Backspace behavior to delete Unicode grapheme clusters using native text segmentation.
    • Updated Markdown code-block rendering to use an in-app highlight.js integration with auto-detection and safe handling for unknown languages, preserving existing styling.
  • Chores
    • Removed grapheme-splitting and Markdown highlight dependencies and updated build configuration accordingly.
  • Documentation
    • Updated the Markdown tools reference to reflect the new code-block syntax highlighting approach.

…orm/native code

graphemer: the single use in the Monaco editor's custom backspace action
(grapheme-cluster aware delete) now uses the native Intl.Segmenter, which
is supported across all target browsers and the Node test runtime.

markdown-it-highlightjs: inline a tiny local markdown-it plugin that sets
the highlight hook to delegate to highlight.js and wraps the fence /
code_block renderers to keep the `hljs` CSS class. This reproduces the
exact markup the plugin emitted (the vs.css / monokai.css themes target
`.hljs`), so syntax highlighting is unchanged in light and dark mode. The
highlight.js engine stays a direct dependency.

Verified: tsc compile, ESLint, markdown conversion spec (81 tests, incl.
fenced code blocks) and the Monaco editor spec (52 tests, incl. the
combined-emoji backspace cluster deletion) all pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 14, 2026 10:47
@github-project-automation github-project-automation Bot moved this to Work In Progress in Artemis Development Jun 14, 2026
@github-actions github-actions Bot added the client Pull requests that update TypeScript code. (Added Automatically!) label Jun 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR reduces client dependencies by replacing two small third-party utilities with platform/native equivalents while aiming to preserve existing behavior in markdown code highlighting and Monaco backspace grapheme deletion.

Changes:

  • Replace graphemer usage in the Monaco custom backspace action with Intl.Segmenter-based grapheme segmentation.
  • Replace markdown-it-highlightjs with a local markdown-it plugin that delegates highlighting to the existing highlight.js dependency and preserves the hljs CSS class.
  • Remove the two dependencies from package.json and update pnpm-lock.yaml accordingly.

Reviewed changes

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

File Description
src/main/webapp/app/foundation/util/markdown.conversion.util.ts Introduces local highlight.js integration and renderer wrapping to replace markdown-it-highlightjs.
src/main/webapp/app/editor/monaco-editor/monaco-editor.component.ts Switches grapheme splitting for backspace deletion from Graphemer to Intl.Segmenter.
package.json Removes graphemer and markdown-it-highlightjs dependencies.
pnpm-lock.yaml Reflects dependency removals (and associated lockfile metadata updates).
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main/webapp/app/foundation/util/markdown.conversion.util.ts
Comment thread src/main/webapp/app/foundation/util/markdown.conversion.util.ts
Comment thread src/main/webapp/app/editor/monaco-editor/monaco-editor.component.ts Outdated
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f27d0fca-86fa-4cfb-adba-39657fc65ba6

📥 Commits

Reviewing files that changed from the base of the PR and between c185421 and 1f172dd.

📒 Files selected for processing (1)
  • src/main/webapp/app/foundation/util/markdown.conversion.util.ts

Walkthrough

Two npm dependencies are removed by substituting native or inline alternatives. graphemer is replaced with the browser-native Intl.Segmenter API for grapheme-aware backspace in MonacoEditorComponent, and markdown-it-highlightjs is replaced with a locally defined plugin in markdown.conversion.util.ts that uses highlight.js directly. Build configuration and documentation are updated accordingly.

Changes

Dependency Removal and Inline Replacements

Layer / File(s) Summary
Replace graphemer with Intl.Segmenter in Monaco Backspace
package.json, src/main/webapp/app/editor/monaco-editor/monaco-editor.component.ts
Removes graphemer from package.json dependencies and its import. The custom Backspace command now uses Intl.Segmenter with granularity: 'grapheme' to segment text before the cursor and computes the deletion range from the last segment's length.
Replace markdown-it-highlightjs with inline plugin
package.json, src/main/webapp/app/foundation/util/markdown.conversion.util.ts
Removes markdown-it-highlightjs from package.json. Adds a direct hljs import and defines a local markdownItHighlightjs plugin with highlightWithHljs (with try/catch fallback to escaped HTML for unknown languages) and an addHljsClass wrapper that applies the hljs CSS class to rendered <code> elements. Both the cached and non-cached MarkdownIt instances are switched to use the new plugin.
Build configuration and documentation updates
angular.json, documentation/docs/student/tools-reference/markdown-support.mdx
Removes graphemer and markdown-it-highlightjs from the allowedCommonJsDependencies list in angular.json. Updates markdown support documentation to reflect highlight.js as the syntax highlighting solution instead of MarkdownIt HighlightJS.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: removing graphemer and markdown-it-highlightjs dependencies and replacing them with platform-native or existing alternatives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/replace-graphemer-and-highlightjs

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.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

End-to-End Test Results

Phase Status Details
All Tests ❌ Failed
TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
All E2E Tests Report (PR)283 ran277 passed3 skipped3 failed49m 25s
❌ Failed Tests
  • Group chat messages › Write/edit/delete message in group chat › Student should be able to edit a message in group chat (1m 30s)
  • Message interactions › Message forwarding › Forwarded reply renders its preview in the destination conversation (1m 51s)
  • Static code analysis tests › Verifies SCA feedback is displayed correctly after submission (6m 46s)

Flakiness Scores for Failed Tests

Test Flakiness Score Default Branch Failure Rate Combined Failure Rate
e2e/course/CourseGroupChatMessages.spec.ts#Group chat messages › Write/edit/delete message in group chat › Student should be able to edit a message in group chat 0% 0.3% 0.3%
e2e/course/CourseMessageInteractions.spec.ts#Message interactions › Message forwarding › Forwarded reply renders its preview in the destination conversation 0% 50.9% 50.9%
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts#Static code analysis tests › Verifies SCA feedback is displayed correctly after submission 75.90361445783131% 12.0% 12.0%

Test Strategy: Running all tests (configuration or infrastructure changes detected)

Overall: ❌ E2E tests failed

🔗 Workflow Run · 📊 Test Report

@krusche krusche changed the title Development: Replace graphemer and markdown-it-highlightjs with platform code Development: Replace graphemer and markdown-it-highlightjs with platform code Jun 14, 2026
@krusche krusche added this to the 9.5 milestone Jun 14, 2026
@krusche

krusche commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

@Claudia-Anthropica review

@Claudia-Anthropica

Copy link
Copy Markdown
Contributor

@krusche acknowledged, queuing this up for immediate review!

…hemer-and-highlightjs

# Conflicts:
#	pnpm-lock.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 27: Remove the three unrelated dependencies that were accidentally added
to package.json: `@dagrejs/dagre` (line 27), `d3-shape` (line 49), and
`@types/d3-shape` (line 97). These graph and shape libraries are not part of the
PR's stated objective of removing `graphemer` and `markdown-it-highlightjs`, and
should be removed to keep the changes focused and aligned with the PR scope.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72eadb26-9763-4562-9a34-6965ca348203

📥 Commits

Reviewing files that changed from the base of the PR and between ce3c343 and d1605dc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
📒 Files selected for processing (1)
  • package.json

@github-project-automation github-project-automation Bot moved this from Work In Progress to Ready For Review in Artemis Development Jun 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@package.json`:
- Line 27: Remove the three unrelated dependencies that were accidentally added
to package.json: `@dagrejs/dagre` (line 27), `d3-shape` (line 49), and
`@types/d3-shape` (line 97). These graph and shape libraries are not part of the
PR's stated objective of removing `graphemer` and `markdown-it-highlightjs`, and
should be removed to keep the changes focused and aligned with the PR scope.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 72eadb26-9763-4562-9a34-6965ca348203

📥 Commits

Reviewing files that changed from the base of the PR and between ce3c343 and d1605dc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !**/*.yaml
📒 Files selected for processing (1)
  • package.json
🛑 Comments failed to post (1)
package.json (1)

27-27: ⚠️ Potential issue | 🟠 Major | ⚖️ Poor tradeoff

Unrelated dependency additions detected.

The additions of @dagrejs/dagre, d3-shape, and @types/d3-shape are not mentioned in the PR objectives, which focus exclusively on removing graphemer and markdown-it-highlightjs. These graph and shape libraries appear unrelated to the grapheme segmentation or markdown highlighting changes.

Were these dependencies accidentally included from another branch or PR? Consider removing them to keep this PR focused on its stated objective.

Also applies to: 49-49, 97-97

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 27, Remove the three unrelated dependencies that were
accidentally added to package.json: `@dagrejs/dagre` (line 27), `d3-shape` (line
49), and `@types/d3-shape` (line 97). These graph and shape libraries are not
part of the PR's stated objective of removing `graphemer` and
`markdown-it-highlightjs`, and should be removed to keep the changes focused and
aligned with the PR scope.

- highlightWithHljs: check hljs.getLanguage(language) before calling
  hljs.highlight() so unknown languages produce an escaped-HTML fallback
  without throwing an exception (avoids relying on try/catch for common
  cases).
- Intl.Segmenter: hoist the instance to a module-level const
  (GRAPHEME_SEGMENTER) so it is created once rather than on every Backspace
  keystroke.
- addHljsClass: kept unchanged since the string replacement is a verbatim
  port of the former library's approach and guarantees identical output;
  switching to token-attribute manipulation would risk subtle markup
  differences.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
@krusche

krusche commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

@Claudia-Anthropica review

@Claudia-Anthropica

Copy link
Copy Markdown
Contributor

@krusche got it, but I'm tapped out right now (my weekly quota is maxed). Queued — I'll pick it up when capacity resets at 2026-06-17 14:25 UTC (~2d 22h from now).

@krusche krusche temporarily deployed to playwright-e2e-tests June 16, 2026 19:33 — with GitHub Actions Inactive
@krusche krusche temporarily deployed to playwright-e2e-tests June 16, 2026 19:55 — with GitHub Actions Inactive

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@krusche The code replacement itself looks solid and matches the old wrapper behavior. I left one cleanup note for stale dependency references; client build/style/tests are green, and the remaining red CI looks unrelated to this client-only change.

Comment thread package.json
…erences

Remove both packages from the allowedCommonJsDependencies allow-list in
angular.json and update the markdown support docs to reference highlight.js
instead of the removed markdown-it-highlightjs plugin.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 18, 2026
@FelixTJDietrich FelixTJDietrich temporarily deployed to playwright-e2e-tests June 18, 2026 12:17 — with GitHub Actions Inactive

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@krusche The dependency cleanup looks good now. I compared the markdown rendering against the removed plugin for the relevant cases and the targeted markdown/Monaco Vitest files pass locally, so approving.

@helios-aet helios-aet Bot temporarily deployed to artemis-test2.artemis.cit.tum.de June 18, 2026 12:34 Inactive

@FelixTJDietrich FelixTJDietrich left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tested on TS2, works as expected. I applied the review comments to fix a stale reference.

@krusche krusche temporarily deployed to playwright-e2e-tests June 18, 2026 19:43 — with GitHub Actions Inactive
Rephrase the code-highlighting JSDoc to describe current behavior instead of
narrating the migration away from markdown-it-highlightjs, so the docs stay
accurate once the former dependency is forgotten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@FelixTJDietrich FelixTJDietrich dismissed stale reviews from coderabbitai[bot], Claudia-Anthropica, and themself via 1f172dd June 19, 2026 08:10
@FelixTJDietrich FelixTJDietrich merged commit 58a663d into develop Jun 19, 2026
26 of 29 checks passed
@FelixTJDietrich FelixTJDietrich deleted the chore/replace-graphemer-and-highlightjs branch June 19, 2026 08:11
@github-project-automation github-project-automation Bot moved this from Ready For Review to Merged in Artemis Development Jun 19, 2026
@FelixTJDietrich FelixTJDietrich temporarily deployed to playwright-e2e-tests June 19, 2026 08:18 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Pull requests that update TypeScript code. (Added Automatically!) documentation ready for review

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

4 participants