Skip to content

Commit

Permalink
Recognize Markdown link title syntax (#11791)
Browse files Browse the repository at this point in the history
Recognize Markdown link title syntax. We don't use the title content because we display the 'Ctrl-Click to follow link...' message, but this PR hides the title when displaying the link in rendered view.
  • Loading branch information
kazcw authored Dec 6, 2024
1 parent 1347ee0 commit 7b4d46e
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,34 +88,42 @@ defineExpose({
font-size: 20px;
line-height: 1.75;
}

.heading2 {
font-weight: 700;
font-size: 16px;
line-height: 1.75;
}

.heading3,
.heading4,
.heading5,
.heading6 {
font-size: 14px;
line-height: 2;
}

.processingInstruction {
opacity: 20%;
}

.emphasis:not(.processingInstruction) {
font-style: italic;
}

.strong:not(.processingInstruction) {
font-weight: bold;
}

.strikethrough:not(.processingInstruction) {
text-decoration: line-through;
}

.monospace {
/*noinspection CssNoGenericFontName*/
font-family: var(--font-mono);
}

.url {
color: royalblue;
}
Expand All @@ -127,22 +135,24 @@ defineExpose({
:global(.cm-image-markup) {
display: none;
}

.processingInstruction {
display: none;
}
.url {

.link:not(a *) {
display: none;
}
a .url {
display: inline;
}

a {
cursor: pointer;
color: blue;

&:hover {
text-decoration: underline;
}
}

&:has(.list.processingInstruction) {
display: list-item;
list-style-type: disc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ function decorations<T>(
}),
})
const vueHost = {
register: () => ({ unregister: () => {} }),
register: () => ({
unregister: () => {},
}),
}
view.dispatch({ effects: setVueHost.of(vueHost) })
const decorationSets = view.state.facet(EditorView.decorations)
Expand All @@ -39,6 +41,7 @@ function links(source: string) {
return {
text: source.substring(from, to),
href: deco.spec.attributes.href,
title: deco.spec.attributes.title,
}
}
})
Expand Down Expand Up @@ -67,6 +70,16 @@ test.each([
},
],
},
{
markdown: '[Link text](https://www.example.com/index.html "title text")',
expectedLinks: [
{
text: 'Link text',
href: 'https://www.example.com/index.html',
title: '"title text"',
},
],
},
{
markdown: '[Link text](<https://www.example.com/index.html>)',
expectedLinks: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function markdownLinkEditPopup(): Extension {
return linkEditPopup((el) => (el instanceof HTMLElement ? el.dataset.href : undefined))
}

function parseAutolink(nodeRef: SyntaxNodeRef, doc: Text) {
function parseAutolink(nodeRef: SyntaxNodeRef, doc: Text): LinkLikeInfo | undefined {
const cursor = nodeRef.node.cursor()
if (!cursor.firstChild()) return // <
const linkFrom = cursor.from
Expand Down Expand Up @@ -73,7 +73,7 @@ function decorateLink(
: nodeRef.name === 'Autolink' ? parseAutolink(nodeRef, doc)
: undefined
if (!parsed) return
const { linkFrom, linkTo, textFrom, textTo, url } = parsed
const { linkFrom, linkTo, textFrom, textTo, url, title } = parsed
if (textFrom === textTo) return
emitDecoration(
linkFrom,
Expand All @@ -83,12 +83,13 @@ function decorateLink(
attributes: { 'data-href': url },
}),
)
const attributes = makeAttributes(url)
emitDecoration(
textFrom,
textTo,
Decoration.mark({
tagName: 'a',
attributes: makeAttributes(url),
attributes: title ? { title, ...attributes } : attributes,
}),
)
}
Expand Down Expand Up @@ -188,8 +189,17 @@ class ImageWidget extends WidgetType {

// === Common ===

interface LinkLikeInfo {
linkFrom: number
linkTo: number
textFrom: number
textTo: number
url: string
title?: string | undefined
}

/** Parse a link or image */
function parseLinkLike(nodeRef: SyntaxNodeRef, doc: Text) {
function parseLinkLike(nodeRef: SyntaxNodeRef, doc: Text): LinkLikeInfo | undefined {
const cursor = nodeRef.node.cursor()
if (!cursor.firstChild()) return
const linkFrom = cursor.from // [ or ![
Expand All @@ -201,6 +211,11 @@ function parseLinkLike(nodeRef: SyntaxNodeRef, doc: Text) {
} while (!isNodeType(cursor, 'URL'))
const url = doc.sliceString(cursor.from, cursor.to)
cursor.nextSibling()
let title: string | undefined = undefined
if (isNodeType(cursor, 'LinkTitle')) {
title = doc.sliceString(cursor.from, cursor.to)
cursor.nextSibling()
}
let linkTo: number
do {
linkTo = cursor.to
Expand All @@ -212,5 +227,6 @@ function parseLinkLike(nodeRef: SyntaxNodeRef, doc: Text) {
textFrom,
textTo,
url,
title,
}
}

0 comments on commit 7b4d46e

Please sign in to comment.