Skip to content

Commit

Permalink
Add support for reference links
Browse files Browse the repository at this point in the history
  • Loading branch information
CalebJohn committed Apr 8, 2024
1 parent bf2d645 commit a0eabe6
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 7 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ Go to [Tips](https://github.com/CalebJohn/joplin-rich-markdown/blob/main/TIPS.md


# Known Issues
- [Reference Links](https://spec.commonmark.org/0.29/#reference-link) are not supported yet.
- file:// links only work with markdown link syntax (\[\]\(\) \<\>)
- When hovering over an image on the bottom line, the image will be cut off
- This can be fixed by scrolling the editor down enough to display the image
Expand Down
10 changes: 10 additions & 0 deletions src/clickHandlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ it also contains other links like <joplinapp.org> this
but it doesn't forget plain old https://joplinapp.org links
and all the rest!
(In this [page](https://joplinapp.org) you can see a test)
it also has [reference links] which are neat!
[reference links]: https://joplinapp.org
`

test("getMatchAt works for markdown links", () => {
Expand Down Expand Up @@ -48,3 +51,10 @@ test("getMatchAt works on the boundary of a match (but not over)", () => {
match = ClickHandlers.getMatchAt(test_text, Overlay.link_regex, 71);
expect(match).toBeNull();
});

test("reference link regexes are working okay", () => {
let match = ClickHandlers.getMatchAt(test_text, Overlay.link_reference_regex, 290);
expect(match).not.toBeNull();
match = ClickHandlers.getMatchAt(test_text, Overlay.link_label_regex, 290);
expect(match).not.toBeNull();
});
38 changes: 32 additions & 6 deletions src/clickHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ function normalizeCoord(coord: any) {
return coord;
}

// Only internal links are supported for now
export function isLink(event: MouseEvent) {
if (!event.target) return false;
const target = event.target as HTMLElement;

return target.matches('.cm-rm-link *, .cm-rm-link');
return target.matches('.cm-rm-link *, .cm-rm-link') || target.matches('.cm-rm-link-label');
}

export function isCheckbox(event: MouseEvent) {
Expand Down Expand Up @@ -112,11 +111,38 @@ function getLinkAt(cm: any, coord: any) {

const match = getMatchAt(lineText, Overlay.link_regex, ch);

if (!match) return;

let url = '';
for (let i = 1; i <= 4; i++) {
url = url || match[i];
if (match) {
for (let i = 1; i <= 4; i++) {
url = url || match[i];
}
}
else { // This might be a reference link, check for that
const reference_match = getMatchAt(lineText, Overlay.link_reference_regex, ch)

if (!reference_match) return;

const reference = reference_match[1] || reference_match[2];

const link_definition_regex = new RegExp(`\\[${reference}\\]:\\s([^\\n]+)`, 'g');

for (let i = 0; i < cm.lineCount(); i++) {
// a link reference definition can only be preceded by up to 3
// spaces, so we will be sure to find a match (if it exists) that
// contains character 4
const definition_match = getMatchAt(cm.getLine(i), link_definition_regex, 4);

if (definition_match) {
url = definition_match[1];
break;
};
}

// No match found, just exit
if (url === '') {
alert(`No link defintion for [${reference}]. Press Esc to dismiss.`);
return;
}
}

// Special case, if this matches a link inside of an image, we will need to strip
Expand Down
3 changes: 3 additions & 0 deletions src/overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export const checkbox_inner_regex = /(?<=\[)[Xx ](?=\])/g;
// This regex will match html tags tht somehow include a . in them
// I've decided that this is an acceptable level of functionality
export const link_regex = /(?<![\\])\[[^\]]*\]\(([^\(\)]+)\)|<([^>\s]+\.[^>\s]+)>|((?:[a-zA-Z0-9\+\.\-])+:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|(?:[a-zA-Z0-9\+\.\-])+:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,}[^\)])(?<!\))|joplin:\/\/x-callback-url\/.*/g;
export const link_reference_regex = /(?<![\\])\[([^\]]*)\](?!\()|\]\[([^\]]*)\]\s/g;
export const link_label_regex = /((?<![\\])\[[^\]]*\])/g;
export const image_regex = /!\[[^\]]*\]\([^\(]+\)/g;
// Modified from https://stackoverflow.com/a/18665138/12245502
export const html_image_regex = /<img([^>]+?)\/?>/g;
Expand Down Expand Up @@ -84,6 +86,7 @@ export const overlays = [
regexOverlay('rm-checkbox', checkbox_regex, []),
regexOverlay('rm-checkbox-check', checkbox_inner_regex, ['extraCSS']),
regexOverlay('rm-link', link_regex, []),
regexOverlay('rm-link-label', link_label_regex, []),
regexOverlay('rm-image', image_regex, []),
regexOverlay('rm-image', html_image_regex, []),
regexOverlay('rm-list-token', list_token_regex, []),
Expand Down

0 comments on commit a0eabe6

Please sign in to comment.