Skip to content

Port over linkifyJS to shared-components.#32731

Merged
Half-Shot merged 52 commits intodevelopfrom
hs/partial-linkify-move
Mar 12, 2026
Merged

Port over linkifyJS to shared-components.#32731
Half-Shot merged 52 commits intodevelopfrom
hs/partial-linkify-move

Conversation

@Half-Shot
Copy link
Copy Markdown
Member

@Half-Shot Half-Shot commented Mar 5, 2026

Partially completes #32689
Split out from #32525
Playwright test coverage is weak so added #32737

This change moves the global instance of "linkifyjs" to shared-components, along with it's string/html/react variants. The rationale for doing so is we want there to be a single canonical instance of this library to reduce any flakiness or cross contamination. I also had a brief look but I couldn't see a better library that would allow us to do this with less yuck.

Background

The URL Previews MVVM PR (#32525) requires URL previews to be linkified, but unfortunately the Linkify component is absolutely encrusted with lots of app-specific functionality and would take some time to unpack. This PR takes as much common logic as it can and moves it to shared-compoents.

Implementation

shared-components contains and wraps everything linkifyjs, including resolving our custom Room Alias and User ID types and defining any protocols we want to support. Both the linkifyString|linkifyHTML functions and component exist at this level.

element-web contains the logic to map these types into actions, so resolving permalinks and dispatching actions depending on the link found. This now lives entirely within Linkify.tsx. The ElementLinkedText component exposes <LinkedText/> but with the enhancements added on top.

Remaining work

<LinkedText> is not a drop-in replacement yet as it doesn't do any of the advanced replacement work that <ElementLinkedText> does. This could easily come as an update where we might expose a view model or some other way of directing the app, but there would be even more code to port. For the time being I'm satisfied the presents an improvement to the status quo and it can be finished off at a later date.

Comment on lines +131 to +150
// Register plugins
linkifyjs.registerPlugin(LinkifyMatrixOpaqueIdType.RoomAlias, ({ scanner, parser }) => {
const token = scanner.tokens.POUND as "#";
matrixOpaqueIdLinkifyParser({
scanner,
parser,
token,
name: LinkifyMatrixOpaqueIdType.RoomAlias,
});
});

linkifyjs.registerPlugin(LinkifyMatrixOpaqueIdType.UserId, ({ scanner, parser }) => {
const token = scanner.tokens.AT as "@";
matrixOpaqueIdLinkifyParser({
scanner,
parser,
token,
name: LinkifyMatrixOpaqueIdType.UserId,
});
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we avoid to automatically add plugin when the file is loaded?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This matches prior behaviour with Element Web, and because linkifyjs can only exist as a single global instance we need to load these plugins prior to usage. What i've done instead is ensure we load the plugins once, and put a comment explaining why.

In the future, I'd like to burn linkifyjs away with fire and find a better solution.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@Half-Shot Half-Shot enabled auto-merge March 12, 2026 15:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants