about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/css/match.nim3
-rw-r--r--src/css/selectorparser.nim2
-rw-r--r--src/html/dom.nim13
-rw-r--r--src/server/buffer.nim7
4 files changed, 24 insertions, 1 deletions
diff --git a/src/css/match.nim b/src/css/match.nim
index 41df6ded..e1b3b832 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -147,6 +147,9 @@ func matches(element: Element; pseudo: PseudoData;
   of pcFocus:
     depends.add(element, dtFocus)
     return element.document.focus == element
+  of pcTarget:
+    depends.add(element, dtTarget)
+    return element.document.target == element
   of pcNot:
     return not element.matches(pseudo.fsels, depends)
   of pcIs, pcWhere:
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index 4330bd18..90da97c9 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -38,6 +38,7 @@ type
     pcLang = "lang"
     pcLink = "link"
     pcVisited = "visited"
+    pcTarget = "target"
     pcFirstNode = "-cha-first-node"
     pcLastNode = "-cha-last-node"
 
@@ -371,6 +372,7 @@ proc parsePseudoSelector(state: var SelectorParser): Selector =
       of "focus": add_pseudo_class pcFocus
       of "link": add_pseudo_class pcLink
       of "visited": add_pseudo_class pcVisited
+      of "target": add_pseudo_class pcTarget
       of "-cha-first-node": add_pseudo_class pcFirstNode
       of "-cha-last-node": add_pseudo_class pcLastNode
       else: fail
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 3af310ee..e7ca7565 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -68,7 +68,7 @@ type
 
 type
   DependencyType* = enum
-    dtHover, dtChecked, dtFocus
+    dtHover, dtChecked, dtFocus, dtTarget
 
   Location = ref object
     window: Window
@@ -200,6 +200,7 @@ type
 
     parserCannotChangeModeFlag*: bool
     internalFocus: Element
+    internalTarget: Element
     contentType* {.jsget.}: string
     renderBlockingElements: seq[Element]
 
@@ -2686,6 +2687,16 @@ proc setFocus*(document: Document; element: Element) =
   if element != nil:
     element.invalidDeps.incl(dtFocus)
 
+func target*(document: Document): Element =
+  return document.internalTarget
+
+proc setTarget*(document: Document; element: Element) =
+  if document.target != nil:
+    document.target.invalidDeps.incl(dtTarget)
+  document.internalTarget = element
+  if element != nil:
+    element.invalidDeps.incl(dtTarget)
+
 func hover*(element: Element): bool =
   return element.internalHover
 
diff --git a/src/server/buffer.nim b/src/server/buffer.nim
index bbae50f2..501a5d94 100644
--- a/src/server/buffer.nim
+++ b/src/server/buffer.nim
@@ -715,6 +715,8 @@ proc gotoAnchor*(buffer: Buffer; anchor: string; autofocus: bool):
   if buffer.document == nil:
     return GotoAnchorResult(found: false)
   var anchor = buffer.document.findAnchor(anchor)
+  if anchor != nil:
+    buffer.document.setTarget(anchor)
   var focus: ReadLineResult = nil
   # Do not use buffer.config.autofocus when we just want to check if the
   # anchor can be found.
@@ -1032,6 +1034,11 @@ proc clone*(buffer: Buffer; newurl: URL): int {.proxy.} =
     for it in connecting:
       # connecting: just reconnect
       buffer.loader.reconnect(it)
+    # Set target now, because it's convenient.
+    # (It is also possible that newurl has no hash, and then gotoAnchor
+    # isn't called at all.)
+    let target = buffer.document.findAnchor(newurl.hash)
+    buffer.document.setTarget(target)
     return 0
   else: # parent
     discard close(pipefd[1]) # close write