Accept semantic work-package identifiers in text macros#23224
Closed
akabiru wants to merge 1 commit into
Closed
Conversation
Broaden the bare `#` branch of the text-macro regex to accept both the numeric (`\d+`) and semantic (`[A-Z][A-Z0-9_]*-\d+`) identifier shapes, reusing `WorkPackage::SemanticIdentifier::ID_ROUTE_CONSTRAINT` as the single source of truth. The link handler interpolates the typed identifier verbatim into the href, label, and `data-id`; the route layer resolves either shape transparently via `find_by_display_id`, so no DB lookup is needed at render time and the behaviour is mode-agnostic. `#PROJ-1` renders as `<a href="/work_packages/PROJ-1">#PROJ-1</a>` and `##PROJ-1` / `###PROJ-1` render as `<opce-macro-wp-quickinfo>` elements with `data-id="PROJ-1"`. Numeric `#1234` rendering is unchanged. The leading-zero canonical-form guard (`#123` stays literal) is preserved on the numeric branch. Two collateral safety guards: - `HashSeparator#applicable?` rejects semantic-shape inputs digit-by- digit so `version#PROJ-1` (and every other prefixed-resource form) short-circuits before issuing a guaranteed-miss `find_by(id: 0)` against the versions / documents / messages / meetings / projects / users / groups / queries tables. - The PDF export's `WorkPackagesLinkHandler` gates `applicable?` on digit-only identifiers. PDF rendering walks a separate Markly pipeline that does not yet resolve semantic ids; without this guard, `#PROJ-1` in an exported body would collapse to `<mention data-id="0">`. Semantic-id PDF support is a follow-up (community WP #74366 / #74766). Refs https://community.openproject.org/wp/74948
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket
https://community.openproject.org/wp/74948
What are you trying to accomplish?
Backend support for project-based semantic identifiers in the work-package text-macro pipeline. Authors typing
#PROJ-1,##PROJ-1, or###PROJ-1in a comment, work-package description, or meeting body get a plain link, an inline quickinfo card, or a detailed quickinfo card — the same shapes that already work for numeric#1234,##1234, and###1234. Numeric references render unchanged.Replaces #23203, which over-engineered the rendering path on the assumption that classic instances would 404 on
/work_packages/PROJ-1— they don't. The route constraint andWorkPackage.find_by_display_idaccept both shapes regardless of thework_packages_identifiersetting, so the text macro can interpolate the typed identifier verbatim into the href and let the route do the resolution.Slice S4 from the parent #22976 slicing plan (replaces the originally-planned twelve-commit version with a single broadened regex plus two collateral guards).
Screenshots
Plain
#PROJ-1link in a work-package comment##PROJ-1inline quickinfo card###PROJ-1detailed quickinfo cardWhat approach did you choose and why?
The bare
#branch ofResourceLinksMatcher.regexpwidens to accept either\d+or[A-Z][A-Z0-9_]*-\d+, reusingWorkPackage::SemanticIdentifier::ID_ROUTE_CONSTRAINTso routing, formatting, and the macro regex share one source of truth. The link handler readsmatcher.identifieras a string and interpolates it into the href, label, anddata-iddirectly — noto_icoercion, no DB lookup, no mode gate. The route layer resolves either shape transparently.#0123still falls through to literal text via the canonical-form check on the numeric branch.Quickinfo widgets (
##PROJ-1/###PROJ-1) emit<opce-macro-wp-quickinfo data-id="PROJ-1">with the user-facing identifier; the frontend macro component already handles both shapes when it calls back to APIv3. Hover-card URLs follow the same path so the URL the user sees matches the URL the link points at.Two collateral guards ship alongside the matcher widening:
HashSeparator#applicable?rejects semantic-shape inputs digit-by-digit. Before this change,version#PROJ-1would reach the version handler with"PROJ-1".to_i == 0and issue a guaranteed-missVersion.find_by(id: 0). The same shape would have hit every other prefixed-resource table (documents, messages, meetings, projects, users, groups, queries). The new gate short-circuits all of them before any database round-trip.The PDF export's
WorkPackagesLinkHandlergatesapplicable?on digit-only identifiers. PDF rendering walks a separate Markly pipeline that does not yet resolve semantic identifiers. Without this guard,#PROJ-1in an exported body would collapse to<mention data-id="0">— broken-looking output that's hard to attribute. Semantic-id support on the PDF side lands separately via #23138 (community WP #74366 / #74766).Out of scope: the CKEditor / autocomplete / mention-envelope surface (slice S5, paired with CKEditor build PR #113), and a per-render preload that batches lookups across many references in one body. The minimal path here renders without any work-package SELECTs — a regression guard in the spec asserts zero
FROM "work_packages"queries for the rendering pipeline.Merge checklist
spec/lib/open_project/text_formatting/matchers/link_handlers/work_packages_spec.rb,spec/lib/open_project/text_formatting/markdown/in_tool_links_spec.rb,spec/models/exports/pdf/common/macro_spec.rbgreen#PROJ-1,##PROJ-1,###PROJ-1in semantic mode and in classic mode (route resolves both); PDF export of a body containing#PROJ-1renders as literal text, not a broken mention