Skip to content

Add GitLab Flavored Markdown (GLFM) flavour - #214

Draft
Aboobacker MK (tachyons) wants to merge 1 commit into
JetBrains:masterfrom
tachyons:glfm-flavour
Draft

Aboobacker MK (tachyons) wants to merge 1 commit into
JetBrains:masterfrom
tachyons:glfm-flavour

Conversation

@tachyons

Copy link
Copy Markdown

Summary

This PR introduces a new GLFMFlavourDescriptor implementing GitLab Flavored Markdown on top of the existing GFMFlavourDescriptor.

Features

Feature Syntax Rendered as
Inline diff addition {+ added +} / {+added+} <span class="idiff addition">
Inline diff deletion [- removed -] / [-removed-] <span class="idiff deletion">
Emoji shortcodes :smile:, :+1: <span class="gl-emoji"> with Unicode emoji (customizable map)
User mention @user link with gfm-project_member
Issue reference #123, group/project#123 link with gfm-issue
Merge request !123 link with gfm-merge_request
Snippet / Epic $123 / &123 gfm-snippet / gfm-epic links
Label ~bug, ~"multi word" link with gfm-label
Milestone %v1.0 link with gfm-milestone
Alerts > [!note] (also tip/important/caution/warning) <div class="gl-alert gl-alert-note">
Multiline blockquote >>> … >>> single <blockquote>

Design notes

  • Zero changes to existing files — everything lives in a new flavours/glfm package (commonMain) plus one test file.
  • Reuses the GFM lexer as-is; GitLab-specific inline syntax is handled by new SequentialParser implementations (InlineDiffParser, EmojiParser, GitLabReferenceParser) that work with the token shapes the GFM lexer produces.
  • Multiline blockquotes use a MarkerBlockProvider + MarkerBlock pair; the fence artifacts are flattened at HTML generation time.
  • Alerts are detected at HTML generation time on top of regular blockquotes (the [!note] marker parses as a SHORT_REFERENCE_LINK, which the alert provider recognizes and strips).
  • Parser correctness details: inline diffs cannot span lines, numeric references require a word boundary (#123abc is not a reference), arr[-1] is not a deletion, ~~strikethrough~~ is not a label, emails are not mentions, and emoji names cannot contain whitespace.

Configuration

val flavour = GLFMFlavourDescriptor(
    gitlabBaseUrl = "https://gitlab.com",
    gitlabProject = "group/project",
    emojiMap = customEmojiMap, // optional
)

Testing

  • 100+ new unit tests in GLFMFeaturesTest covering every feature, inherited GFM behaviour (math, strikethrough, tables, task lists) and edge-case interactions.
  • Full jvmTest suite passes (1617 tests, 0 failures); JS target compiles.

Notes for reviewers

  • Cross-project references mid-sentence (see group/project#1) are not detected because the GFM lexer emits the whole phrase as one TEXT token which sequential parsers cannot split; standalone occurrences work.
  • Draft status: opening early for direction feedback — happy to adjust API shape (e.g. reference URL building could be pluggable instead of gitlabBaseUrl/gitlabProject string params).

Introduces GLFMFlavourDescriptor, extending GFMFlavourDescriptor with
GitLab-specific markdown features:

- Inline diffs: {+ addition +} / [- deletion -] (with and without spaces,
  restricted to a single line)
- Emoji shortcodes: :name: with a customizable emoji map
- GitLab references: @user, #issue, !merge_request, $snippet, &epic,
  ~label (incl. quoted ~"multi word"), %milestone, and cross-project
  group/project#id, rendered as links with gfm-* classes
- Alerts: > [!note|tip|important|caution|warning] blockquotes rendered
  as styled gl-alert containers
- Multiline blockquotes: >>> ... >>> fences

All features are implemented in commonMain on top of the existing GFM
lexer and parser infrastructure (sequential parsers, marker blocks and
HTML generating providers), with no changes to existing files.

Covered by 100+ unit tests in GLFMFeaturesTest, including edge cases
like emoji false positives (times, spaced colons), array indexing not
being a deletion, emails not being mentions, and word-boundary rules
for numeric references.
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.

1 participant