about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-12-14 20:58:55 +0100
committerbptato <nincsnevem662@gmail.com>2024-12-14 20:58:55 +0100
commit0b3e3ed7c789a6b258d7241c95f79c2113814e14 (patch)
tree7506eea4c0eccfe30150f0341d9c947ba2596139 /src
parent7052e566416185e7217e5db4b749947b4af927bf (diff)
downloadchawan-0b3e3ed7c789a6b258d7241c95f79c2113814e14.tar.gz
css: align h[1-6] behavior with w3m
Implemented using proprietary selectors -cha-first-node and
-cha-last-node, modeled after -moz-first-node and -moz-last-node.
I think they are compatible.

That does mean this is more limited than w3m's trimming, e.g. it can't
really deal with nesting or empty tags. I think this is fine, as it's
mainly meant for unstyled documents in the first place (which are
unlikely to have e.g. MAIN tags).
Diffstat (limited to 'src')
-rw-r--r--src/css/match.nim2
-rw-r--r--src/css/selectorparser.nim4
-rw-r--r--src/html/dom.nim23
3 files changed, 29 insertions, 0 deletions
diff --git a/src/css/match.nim b/src/css/match.nim
index 695f2404..05564600 100644
--- a/src/css/match.nim
+++ b/src/css/match.nim
@@ -73,6 +73,8 @@ func pseudoSelectorMatches(element: Element; sel: Selector;
   case sel.pseudo.t
   of pcFirstChild: return element.parentNode.firstElementChild == element
   of pcLastChild: return element.parentNode.lastElementChild == element
+  of pcFirstNode: return element.isFirstVisualNode()
+  of pcLastNode: return element.isLastVisualNode()
   of pcOnlyChild:
     return element.parentNode.firstElementChild == element and
       element.parentNode.lastElementChild == element
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index f75d6570..b4db5a84 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -38,6 +38,8 @@ type
     pcLang = "lang"
     pcLink = "link"
     pcVisited = "visited"
+    pcFirstNode = "-cha-first-node"
+    pcLastNode = "-cha-last-node"
 
   CombinatorType* = enum
     ctNone, ctDescendant, ctChild, ctNextSibling, ctSubsequentSibling
@@ -366,6 +368,8 @@ 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 "-cha-first-node": add_pseudo_class pcFirstNode
+      of "-cha-last-node": add_pseudo_class pcLastNode
       else: fail
     of cttColon:
       if not state.has(): fail
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 03f6d814..ec01acc2 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -2244,6 +2244,29 @@ func lastElementChild*(node: Node): Element {.jsfget.} =
     return child
   return nil
 
+func isFirstVisualNode*(element: Element): bool =
+  let parent = element.parentNode
+  for child in parent.childList:
+    if child == element:
+      return true
+    if child of Element:
+      break
+    if child of Text and not Text(child).data.onlyWhitespace():
+      break
+  return false
+
+func isLastVisualNode*(element: Element): bool =
+  let parent = element.parentNode
+  for i in countdown(parent.childList.high, 0):
+    let child = parent.childList[i]
+    if child == element:
+      return true
+    if child of Element:
+      break
+    if child of Text and not Text(child).data.onlyWhitespace():
+      break
+  return false
+
 func findAncestor*(node: Node; tagTypes: set[TagType]): Element =
   for element in node.ancestors:
     if element.tagType in tagTypes: