Skip to content

Use formatted_id and displayId in WP MentionFilter rendering#23150

Merged
akabiru merged 3 commits into
implementation/74315-use-formatted-id-and-displayid-for-wp-text-macrosfrom
implementation/mention-filter-wp-displayid-parity
May 12, 2026
Merged

Use formatted_id and displayId in WP MentionFilter rendering#23150
akabiru merged 3 commits into
implementation/74315-use-formatted-id-and-displayid-for-wp-text-macrosfrom
implementation/mention-filter-wp-displayid-parity

Conversation

@akabiru
Copy link
Copy Markdown
Member

@akabiru akabiru commented May 9, 2026

Ticket

Follow-up to #22976. Paired with opf/commonmark-ckeditor-build#113, which carries the matching frontend changes.

Contract

data-id = work-package id. data-display-id = user-facing identifier (PROJ-7 in semantic mode, the numeric id in classic). Same convention on <mention> envelopes and <opce-macro-wp-quickinfo>. Matches data-type="user"/"group" mentions, which already used numeric data-id.

Storage rule

One invariant across both modes:

  • Autocomplete pick → <mention> envelope.
  • Source-typed shorthand → bare markdown.

Backend render matrix

Stored markdown Rendered HTML
<mention data-type="work_package" data-text="#X" data-id="<id>" data-display-id="<displayId>"> <a class="issue work_package" href="/work_packages/<displayId>"><displayId></a>
<mention …data-text="##X"> / <mention …data-text="###X"> <opce-macro-wp-quickinfo data-id="<id>" data-display-id="<displayId>" data-detailed="false"> / "true"
bare #X / ##X / ###X markdown (any mode) same <a> / <opce-macro-wp-quickinfo> shapes
<mention …data-id="42"> legacy (no data-display-id) resolves via find_by(id:); renders the WP's current display_id label

Changes

  • MentionFilter#work_package_mention and LinkHandlers::WorkPackages#render_work_package_macro emit both data-id (work-package id) and data-display-id (display_id) on <opce-macro-wp-quickinfo>.
  • render_for_semantic fetches the preloaded work package so the rendered macro can carry the id. The preload is already populated in semantic mode — no extra query.
  • MentionFilter reads data-id as the id and resolves via find_by(id:). Non-numeric data-id (parser-emitted source-typed mentions) falls back to literal text.
  • WorkPackageQuickinfoMacroComponent reads dataset.displayId ?? dataset.id so legacy stored markdown keeps working.
  • Vendor bundle rebuilt to pick up the matched upstream changes.

Notes

  • Side observation (out of scope): PatternMatcherFilter.process_text_nodes walks every text node, including text inside <a> ancestors, so the label this filter emits gets re-matched and produces a sibling anchor. Invisible in classic mode (identical href/hover-card-url, empty rendering) but doubles the DOM per mention. Semantic mode no longer triggers it after this change — formatted_id (PROJ-N) doesn't match WP_REF_RE. A proper fix needs cross-matcher impact analysis and warrants its own ticket.

Merge checklist

  • Added/updated tests
  • Added/updated documentation in Lookbook (patterns, previews, etc)
  • Tested major browsers (Chrome, Firefox, Edge, ...)

@akabiru akabiru self-assigned this May 9, 2026
@akabiru akabiru force-pushed the implementation/mention-filter-wp-displayid-parity branch from 66961d9 to b5badf2 Compare May 11, 2026 07:27
@akabiru akabiru changed the base branch from dev to implementation/74315-use-formatted-id-and-displayid-for-wp-text-macros May 11, 2026 07:27
@akabiru akabiru marked this pull request as ready for review May 11, 2026 07:52
@akabiru akabiru requested review from a team, oliverguenther and ulferts May 11, 2026 07:52
@akabiru akabiru marked this pull request as draft May 11, 2026 12:23
@akabiru akabiru removed request for a team, oliverguenther and ulferts May 11, 2026 12:24
@akabiru akabiru force-pushed the implementation/mention-filter-wp-displayid-parity branch 6 times, most recently from 3f75980 to ecdc7d7 Compare May 12, 2026 06:07
akabiru added 2 commits May 12, 2026 09:39
`MentionFilter#work_package_mention` and
`LinkHandlers::WorkPackages#render_work_package_macro` render
`<opce-macro-wp-quickinfo data-id="<wp.id>" data-display-id="<wp.display_id>" data-detailed="…">`.
`data-id` is the work-package id (stable across renames);
`data-display-id` is the user-facing identifier (semantic in
semantic mode, numeric string in classic). The convention matches
the wire form on `<mention>` envelopes and the
`data-type="user"`/`"group"` mention convention, where `data-id`
has always been the record id.

The link-handler fetches the work package on the semantic-mode
quickinfo branch too — the preload is already populated in semantic
mode, so this is a `RequestStore` hit, not a SELECT.
`MentionFilter` reads `data-id` and resolves via `find_by(id:)`.
Non-numeric `data-id` (parser-emitted source-typed mentions) falls
back to literal text.

`WorkPackageQuickinfoMacroComponent` reads
`dataset.displayId ?? dataset.id` so stored markdown produced before
the attribute split keeps loading: legacy
`<opce-macro-wp-quickinfo data-id="DISPLAY">` resolves via the
fallback; new shape resolves via the preferred attribute.

Backend specs lock the new shape end-to-end: the link handler test
fixture, the in-tool-links pipeline test, and the MentionFilter
spec all assert distinct `data-id` (id) and `data-display-id`
(display_id) values where they diverge, and identical values where
they don't.
The `## / ###` autocomplete assertions pin both `data-id` (the
record id, `mentioned_work_package.id` in either mode) and
`data-display-id` (what the user typed — `wp_display_id` resolving
to the numeric id in classic and the identifier in semantic) on the
widget DOM that appears in the editor right after a pick. The
classic / semantic asymmetry now lives in the assertion itself
rather than in a per-context CSS selector.
@akabiru akabiru force-pushed the implementation/mention-filter-wp-displayid-parity branch from 0ec9220 to 1fbe9d2 Compare May 12, 2026 06:40
Picks up the matched upstream work in
opf/commonmark-ckeditor-build#113:

- Parser recognises semantic identifiers (`#PROJ-N` / `##PROJ-N` /
  `###PROJ-N`) and guards stored mention envelopes against
  re-promotion on reload.
- Mention feed and caster pass record id (`dataId`) and displayed
  identifier (`dataDisplayId`) through to the wire as `data-id` and
  `data-display-id`. The sidecar emission is gated to work-package
  mentions; user/group mentions stay single-attribute.
- `##` / `###` autocomplete picks render as quickinfo widgets in
  both classic and semantic modes. Autocomplete persists as a
  `<mention>` envelope (id survives a rename or alias drop);
  source-typed shorthand persists as bare markdown.
- Constantises the quickinfo model element name alongside the view
  tag for typo safety.
@akabiru akabiru force-pushed the implementation/mention-filter-wp-displayid-parity branch from b71b078 to 5df1456 Compare May 12, 2026 07:37
@akabiru akabiru marked this pull request as ready for review May 12, 2026 07:44
@akabiru akabiru merged commit 9001986 into implementation/74315-use-formatted-id-and-displayid-for-wp-text-macros May 12, 2026
13 checks passed
@akabiru akabiru deleted the implementation/mention-filter-wp-displayid-parity branch May 12, 2026 07:44
@github-actions github-actions Bot locked and limited conversation to collaborators May 12, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant