Skip to content

Commit c89dd6d

Browse files
authored
Shield matrix to links (#786)
<!-- Please read https://github.com/SableClient/Sable/blob/dev/CONTRIBUTING.md before submitting your pull request --> ### Description <!-- Please include a summary of the change. Please also include relevant motivation and context. List any dependencies that are required for this change. --> Matrix.to links sent directly without intentional \[markdown](overrides) will no longer be formatted as \<a> tags. Should solve issues with OOYE and Cinny displaying full urls instead of directly linking. #### Type of change - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update ### Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings ### AI disclosure: - [ ] Partially AI assisted (clarify which code was AI assisted and briefly explain what it does). - [ ] Fully AI generated (explain what all the generated code does in moderate detail). <!-- Write any explanation required here, but do not generate the explanation using AI!! You must prove you understand what the code in this PR does. -->
2 parents 1853974 + 3e399d3 commit c89dd6d

2 files changed

Lines changed: 48 additions & 2 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
default: patch
3+
---
4+
5+
Matrix.to links sent without explicit markdown formatting are sent as raw links instead of html links.

src/app/plugins/markdown/markdownToHtml.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,39 @@ const decodeHtmlEntities = (text: string): string => {
5050
return result;
5151
};
5252

53+
const MATRIX_TO_PLACEHOLDER_PREFIX = 'MATRIXTORAWLINKTOKEN';
54+
55+
const escapeHtml = (text: string): string =>
56+
text
57+
.replace(/&/g, '&amp;')
58+
.replace(/</g, '&lt;')
59+
.replace(/>/g, '&gt;')
60+
.replace(/"/g, '&quot;')
61+
.replace(/'/g, '&#39;');
62+
63+
const shieldBareMatrixToLinks = (
64+
input: string
65+
): { shielded: string; placeholders: Map<string, string> } => {
66+
const placeholders = new Map<string, string>();
67+
let index = 0;
68+
69+
const shielded = input.replace(/(?<!\]\()https?:\/\/matrix\.to\/[^\s<)]+/gi, (url) => {
70+
const key = `${MATRIX_TO_PLACEHOLDER_PREFIX}${index++}X`;
71+
placeholders.set(key, url);
72+
return key;
73+
});
74+
75+
return { shielded, placeholders };
76+
};
77+
78+
const unshieldBareMatrixToLinks = (html: string, placeholders: Map<string, string>): string => {
79+
let result = html;
80+
for (const [key, url] of placeholders.entries()) {
81+
result = result.split(key).join(escapeHtml(url));
82+
}
83+
return result;
84+
};
85+
5386
/**
5487
* Converts markdown string to sanitized Matrix-compatible HTML.
5588
* Uses marked for parsing and DOMPurify for sanitization per Matrix spec.
@@ -67,7 +100,10 @@ export function markdownToHtml(markdown: string): string {
67100

68101
const preprocessed = preprocessEmoticon(blockquotePrefixed);
69102

70-
const mathInput = shieldDollarRunsForMarked(maskDollarSignsInsideMarkdownCode(preprocessed));
103+
const { shielded: matrixToShielded, placeholders: matrixToPlaceholders } =
104+
shieldBareMatrixToLinks(preprocessed);
105+
106+
const mathInput = shieldDollarRunsForMarked(maskDollarSignsInsideMarkdownCode(matrixToShielded));
71107

72108
// Parse markdown to HTML using marked with our Matrix extensions
73109
const html = processor.parse(mathInput) as string;
@@ -164,5 +200,10 @@ export function markdownToHtml(markdown: string): string {
164200
}
165201
);
166202

167-
return restoredMxEmoticonHeight.replace(/<li>(<p><\/p>)?<\/li>/gi, '<li><br></li>');
203+
const unshieldedMatrixTo = unshieldBareMatrixToLinks(
204+
restoredMxEmoticonHeight,
205+
matrixToPlaceholders
206+
);
207+
208+
return unshieldedMatrixTo.replace(/<li>(<p><\/p>)?<\/li>/gi, '<li><br></li>');
168209
}

0 commit comments

Comments
 (0)