4848from ..commands import JumpToCommandLine
4949from ..data import is_editable , load_configuration , looks_urllike
5050from ..editor import Editor
51+ from ..markdown import wikilink_plugin
5152from ..messages import CopyToClipboard , OpenLocation
5253from ..support import is_copy_request_click , view_in_browser
5354from ..types import HikeHistory , HikeLocation
@@ -175,8 +176,10 @@ def __init__(self) -> None:
175176 """Initialise the widget."""
176177 super ().__init__ (
177178 open_links = False ,
178- parser_factory = lambda : MarkdownIt ("gfm-like" ).use (
179- front_matter .front_matter_plugin
179+ parser_factory = lambda : (
180+ MarkdownIt ("gfm-like" )
181+ .use (front_matter .front_matter_plugin )
182+ .use (wikilink_plugin )
180183 ),
181184 )
182185
@@ -249,6 +252,9 @@ class Viewer(Vertical, can_focus=False):
249252 _source : var [str ] = var ("" )
250253 """The source of the Markdown we're viewing."""
251254
255+ _seek_anchor : var [str | None ] = var (None )
256+ """An optional anchor to seek to once the document is loaded."""
257+
252258 def compose (self ) -> ComposeResult :
253259 """Compose the content of the viewer."""
254260 yield ViewerTitle ()
@@ -456,6 +462,9 @@ async def _update_markdown(self, message: Loaded) -> None:
456462 if front_matter_had_focus and not hikedown .front_matter :
457463 self .query_one (MarkdownScroll ).focus ()
458464 self .query_one (FrontMatter ).front_matter = hikedown .front_matter
465+ if self ._seek_anchor :
466+ self .query_one (HikeDown ).goto_anchor (self ._seek_anchor )
467+ self ._seek_anchor = None
459468 if (
460469 message .remember
461470 and self .location
@@ -476,6 +485,18 @@ def reload(self) -> None:
476485 """Reload the current document."""
477486 self ._visit (self .location , remember = False , preserve_position = True )
478487
488+ def goto_anchor_after_load (self , anchor : str | None ) -> Self :
489+ """Go to an anchor after the document is loaded.
490+
491+ Args:
492+ anchor: The anchor to go to.
493+
494+ Returns:
495+ Self.
496+ """
497+ self ._seek_anchor = anchor
498+ return self
499+
479500 def goto (self , history_location : int ) -> None :
480501 """Go to a specific location in history."""
481502 if self .history .current_location != history_location :
@@ -538,25 +559,28 @@ def _handle_link(self, message: Markdown.LinkClicked) -> None:
538559 )
539560 return
540561
562+ # Having eliminated URLs, it's likely something more local. First
563+ # off, on the off-chance that there's an anchor involved still...
564+ file_name , _ , anchor = message .href .partition ("#" )
565+
566+ # Some sort of internal anchor perhaps?
567+ if anchor and not file_name :
568+ message .markdown .goto_anchor (anchor )
569+ return
570+
541571 # A local file that exists?
542- if (local_file := Path (message . href ).expanduser ()).exists ():
543- self .post_message (OpenLocation (local_file .resolve ()))
572+ if (local_file := Path (file_name ).expanduser ()).exists ():
573+ self .post_message (OpenLocation (local_file .resolve (), anchor ))
544574 return
545575
546576 # A local file relative to the current location?
547577 if (
548578 isinstance (self .location , Path )
549- and (local_file := self .location .parent / Path (message . href ))
579+ and (local_file := self .location .parent / Path (file_name ))
550580 .absolute ()
551581 .exists ()
552582 ):
553- self .post_message (OpenLocation (local_file ))
554- return
555-
556- # Some sort of internal anchor perhaps?
557- if message .href .startswith ("#" ) and message .markdown .goto_anchor (
558- message .href [1 :]
559- ):
583+ self .post_message (OpenLocation (local_file , anchor ))
560584 return
561585
562586 self .notify (
0 commit comments