about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-07-17 13:03:50 +0200
committerbptato <nincsnevem662@gmail.com>2022-07-17 13:03:50 +0200
commit7cdb8c1b679431b1be52c9fbb19b67445a0bb588 (patch)
tree6baedc5ddd3a68ffd9825f76cb853a9940292b6e
parent2496c52449169f0caaba086ca3098b11708e5ba2 (diff)
downloadchawan-7cdb8c1b679431b1be52c9fbb19b67445a0bb588.tar.gz
Fix forms
-rw-r--r--src/css/cascade.nim56
-rw-r--r--src/css/selectorparser.nim4
-rw-r--r--src/html/dom.nim39
-rw-r--r--src/html/htmlparser.nim2
-rw-r--r--src/html/htmltokenizer.nim4
-rw-r--r--src/io/buffer.nim1
-rw-r--r--src/layout/engine.nim8
7 files changed, 45 insertions, 69 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index cc7295ea..16e5664a 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -88,27 +88,6 @@ proc applyImportant(ares: var ApplyResult, decls: seq[CSSDeclaration]) =
     if decl.important:
       ares.important.add(decl)
 
-proc checkRendered(element: Element, prev: CSSComputedValues, ppseudo: array[PSEUDO_BEFORE..PSEUDO_AFTER, CSSComputedValues]) =
-  if element.rendered:
-    for p in PSEUDO_BEFORE..PSEUDO_AFTER:
-      if ppseudo[p] != element.pseudo[p] and ppseudo[p] == nil:
-        if element.parentElement != nil:
-          element.parentElement.rendered = false
-        element.rendered = false
-        return
-    for t in CSSPropertyType:
-      if not element.css[t].equals(prev[t]):
-        if element.parentElement != nil:
-          element.parentElement.rendered = false
-        element.rendered = false
-        return
-    for p in PSEUDO_BEFORE..PSEUDO_AFTER:
-      if ppseudo[p] != nil:
-        for t in CSSPropertyType:
-          if not element.pseudo[p][t].equals(ppseudo[p][t]):
-            element.rendered = false
-            return
-
 # Always returns a new styled node, with the passed declarations applied.
 proc applyDeclarations(elem: Element, parent: CSSComputedValues, ua, user: DeclarationList, author: seq[DeclarationList]): StyledNode =
   let pseudo = PSEUDO_NONE
@@ -122,7 +101,7 @@ proc applyDeclarations(elem: Element, parent: CSSComputedValues, ua, user: Decla
   for rule in author:
     ares.applyImportant(rule[pseudo])
 
-  let style = Element(elem).attr("style")
+  let style = elem.attr("style")
   if style.len > 0:
     let inline_rules = newStringStream(style).parseListOfDeclarations2()
     ares.applyNormal(inline_rules)
@@ -167,15 +146,6 @@ func applyMediaQuery(ss: CSSStylesheet): CSSStylesheet =
     if mq.query.applies():
       result.add(mq.children.applyMediaQuery())
 
-proc resetRules(elem: Element) =
-  elem.css = if elem.parentElement != nil:
-    elem.parentElement.css.inheritProperties()
-  else:
-    rootProperties()
-
-  for pseudo in PSEUDO_BEFORE..PSEUDO_AFTER:
-    elem.pseudo[pseudo] = nil
-
 func calcRules(elem: Element, ua, user: CSSStylesheet, author: seq[CSSStylesheet]): tuple[uadecls, userdecls: DeclarationList, authordecls: seq[DeclarationList]] =
   result.uadecls = calcRules(elem, ua)
   result.userdecls = calcRules(elem, user)
@@ -221,9 +191,7 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
       if cachedChild.t == STYLED_ELEMENT:
         styledChild = StyledNode(t: STYLED_ELEMENT, pseudo: cachedChild.pseudo, computed: cachedChild.computed, node: cachedChild.node)
         if cachedChild.pseudo != PSEUDO_NONE:
-          let content = cachedChild.computed{"content"}
-          if content.len > 0:
-            styledChild.children.add(StyledNode(t: STYLED_TEXT, text: content))
+          styledChild.children = cachedChild.children #TODO does this actually refresh pseudo elems when needed?
       else:
         # Text
         styledChild = StyledNode(t: STYLED_TEXT, text: cachedChild.text, node: cachedChild.node)
@@ -235,12 +203,20 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
     else:
       if pseudo != PSEUDO_NONE:
         let (ua, user, authordecls) = Element(styledParent.node).calcRules(ua, user, author)
-        let styledPseudo = pseudo.applyDeclarations(styledParent.computed, ua, user, authordecls)
-        if styledPseudo != nil:
-          styledParent.children.add(styledPseudo)
-          let content = styledPseudo.computed{"content"}
+        case pseudo
+        of PSEUDO_BEFORE, PSEUDO_AFTER:
+          let styledPseudo = pseudo.applyDeclarations(styledParent.computed, ua, user, authordecls)
+          if styledPseudo != nil:
+            styledParent.children.add(styledPseudo)
+            let content = styledPseudo.computed{"content"}
+            if content.len > 0:
+              styledPseudo.children.add(StyledNode(t: STYLED_TEXT, text: content))
+        of PSEUDO_INPUT_TEXT:
+          let content = HTMLInputElement(styledParent.node).inputString()
           if content.len > 0:
-            styledPseudo.children.add(StyledNode(t: STYLED_TEXT, text: content))
+            styledChild = StyledNode(t: STYLED_TEXT, text: content)
+            styledParent.children.add(styledChild)
+        of PSEUDO_NONE: discard
       else:
         assert child != nil
         if styledParent != nil:
@@ -295,6 +271,8 @@ proc applyRules(document: Document, ua, user: CSSStylesheet, cachedTree: StyledN
       for i in countdown(elem.childNodes.high, 0):
         stack_append styledChild, elem.childNodes[i]
 
+      if elem.tagType == TAG_INPUT:
+        stack_append styledChild, PSEUDO_INPUT_TEXT
       stack_append styledChild, PSEUDO_BEFORE
 
 proc applyStylesheets*(document: Document, uass, userss: CSSStylesheet, previousStyled: StyledNode): StyledNode =
diff --git a/src/css/selectorparser.nim b/src/css/selectorparser.nim
index d44d7168..d6302c24 100644
--- a/src/css/selectorparser.nim
+++ b/src/css/selectorparser.nim
@@ -15,7 +15,9 @@ type
     QUERY_NEXT_SIBLING_COMBINATOR, QUERY_SUBSEQ_SIBLING_COMBINATOR
 
   PseudoElem* = enum
-    PSEUDO_NONE, PSEUDO_BEFORE, PSEUDO_AFTER
+    PSEUDO_NONE, PSEUDO_BEFORE, PSEUDO_AFTER,
+    # internal
+    PSEUDO_INPUT_TEXT
 
   PseudoClass* = enum
     PSEUDO_FIRST_CHILD, PSEUDO_LAST_CHILD, PSEUDO_ONLY_CHILD, PSEUDO_HOVER,
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 6dbfcc0f..5312dc8b 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -3,7 +3,6 @@ import options
 import streams
 import strutils
 
-import css/values
 import css/sheet
 import html/tags
 import types/url
@@ -40,7 +39,7 @@ type
     previousSibling*: Node
     parentNode*: Node
     parentElement*: Element
-    rootNode: Node
+    root: Node
     document*: Document
 
   Attr* = ref object of Node
@@ -84,8 +83,6 @@ type
     id*: string
     classList*: seq[string]
     attributes*: Table[string, string]
-    css*: CSSComputedValues
-    pseudo*: array[PSEUDO_BEFORE..PSEUDO_AFTER, CSSComputedValues]
     hover*: bool
     cssapplied*: bool
     rendered*: bool
@@ -279,8 +276,12 @@ func hasPreviousSibling(node: Node, nodeType: NodeType): bool =
     node = node.previousSibling
   return false
 
+func rootNode*(node: Node): Node =
+  if node.root == nil: return node
+  return node.root
+
 func inSameTree*(a, b: Node): bool =
-  a.rootNode == b.rootNode and (a.rootNode != nil or b.rootNode != nil)
+  a.rootNode == b.rootNode
 
 func children*(node: Node): seq[Element] =
   for child in node.children:
@@ -398,8 +399,7 @@ func inputString*(input: HTMLInputElement): string =
     if input.checked: "*"
     else: " "
   of INPUT_SEARCH, INPUT_TEXT:
-    if input.size > 0: input.value.padToWidth(input.size)
-    else: input.value
+    input.value.padToWidth(input.size)
   of INPUT_PASSWORD:
     '*'.repeat(input.value.len).padToWidth(input.size)
   of INPUT_RESET:
@@ -411,8 +411,7 @@ func inputString*(input: HTMLInputElement): string =
   of INPUT_FILE:
     if input.file.isnone: "".padToWidth(input.size)
     else: input.file.get.path.serialize_unicode().padToWidth(input.size)
-  else:
-    input.value
+  else: input.value
   return text
 
 func isButton*(element: Element): bool =
@@ -504,20 +503,19 @@ func newText*(document: Document, data: string = ""): Text =
   result.nodeType = TEXT_NODE
   result.document = document
   result.data = data
-  result.rootNode = result #TODO apparently we shouldn't be doing this
 
 func newComment*(document: Document, data: string = ""): Comment =
   new(result)
   result.nodeType = COMMENT_NODE
   result.document = document
   result.data = data
-  result.rootNode = result #TODO apparently we shouldn't be doing this
 
 # note: we do not implement custom elements
 func newHTMLElement*(document: Document, tagType: TagType, namespace = Namespace.HTML, prefix = none[string]()): HTMLElement =
   case tagType
   of TAG_INPUT:
     result = new(HTMLInputElement)
+    HTMLInputElement(result).size = 20
   of TAG_A:
     result = new(HTMLAnchorElement)
   of TAG_SELECT:
@@ -558,10 +556,8 @@ func newHTMLElement*(document: Document, tagType: TagType, namespace = Namespace
 
   result.nodeType = ELEMENT_NODE
   result.tagType = tagType
-  result.css = rootProperties()
   result.namespace = namespace
   result.namespacePrefix = prefix
-  result.rootNode = result #TODO apparently we shouldn't be doing this
   result.document = document
 
 func newHTMLElement*(document: Document, localName: string, namespace = Namespace.HTML, prefix = none[string](), tagType = tagType(localName)): Element =
@@ -572,7 +568,6 @@ func newHTMLElement*(document: Document, localName: string, namespace = Namespac
 func newDocument*(): Document =
   new(result)
   result.nodeType = DOCUMENT_NODE
-  result.rootNode = result #TODO apparently we shouldn't be doing this
   result.document = result
 
 func newDocumentType*(document: Document, name: string, publicId = "", systemId = ""): DocumentType =
@@ -581,7 +576,6 @@ func newDocumentType*(document: Document, name: string, publicId = "", systemId
   result.name = name
   result.publicId = publicId
   result.systemId = systemId
-  result.rootNode = result #TODO apparently we shouldn't be doing this
 
 func newAttr*(parent: Element, key, value: string): Attr =
   new(result)
@@ -590,7 +584,6 @@ func newAttr*(parent: Element, key, value: string): Attr =
   result.ownerElement = parent
   result.name = key
   result.value = value
-  result.rootNode = result #TODO apparently we shouldn't be doing this
 
 func getElementById*(document: Document, id: string): Element =
   if id.len == 0:
@@ -714,6 +707,7 @@ proc remove*(node: Node) =
     oldNextSibling.previousSibling = oldPreviousSibling
   node.parentNode = nil
   node.parentElement = nil
+  node.root = nil
 
   #TODO assigned, shadow root, shadow root again, custom nodes, registered observers
   #TODO not surpress observers => queue tree mutation record
@@ -724,10 +718,7 @@ proc adopt(document: Document, node: Node) =
   #TODO shadow root
 
 proc applyChildInsert(parent, child: Node, index: int) =
-  if parent.rootNode != nil:
-    child.rootNode = parent.rootNode
-  else:
-    child.rootNode = parent
+  child.root = parent.rootNode
   child.parentNode = parent
   if parent.nodeType == ELEMENT_NODE:
     child.parentElement = Element(parent)
@@ -809,13 +800,15 @@ proc appendAttribute*(element: Element, k, v: string) =
     of "type": HTMLInputElement(element).inputType = inputType(v)
     of "size":
       var i = 20
-      var fail = v.len > 0
+      var fail = v.len == 0
       for c in v:
         if not c.isDigit:
           fail = true
           break
       if not fail:
         i = parseInt(v)
+        if i <= 0:
+          i = 20
       HTMLInputElement(element).size = i
     of "checked": HTMLInputElement(element).checked = true
   element.attributes[k] = v
@@ -823,7 +816,9 @@ proc appendAttribute*(element: Element, k, v: string) =
 proc setForm*(element: Element, form: HTMLFormElement) =
   case element.tagType
   of TAG_INPUT:
-    HTMLInputElement(element).form = form
+    let input = HTMLInputElement(element)
+    input.form = form
+    form.inputs.add(input)
   of TAG_BUTTON, TAG_FIELDSET, TAG_OBJECT, TAG_OUTPUT, TAG_SELECT, TAG_TEXTAREA, TAG_IMG:
     discard #TODO
   else: assert false
diff --git a/src/html/htmlparser.nim b/src/html/htmlparser.nim
index dfd10589..cec952f6 100644
--- a/src/html/htmlparser.nim
+++ b/src/html/htmlparser.nim
@@ -201,7 +201,7 @@ func createElement(parser: HTML5Parser, token: Token, namespace: Namespace, inte
   if element.tagType in FormAssociatedElements and parser.form != nil and
       not parser.openElements.hasElement(TAG_TEMPLATE) and
       (element.tagType notin ListedElements or not element.attrb("form")) and
-      element.inSameTree(parser.form):
+      intendedParent.inSameTree(parser.form):
     element.setForm(parser.form)
   return element
 
diff --git a/src/html/htmltokenizer.nim b/src/html/htmltokenizer.nim
index 8738323f..4f81f6a6 100644
--- a/src/html/htmltokenizer.nim
+++ b/src/html/htmltokenizer.nim
@@ -848,7 +848,9 @@ iterator tokenize*(tokenizer: var Tokenizer): Token =
       case c
       of whitespace: switch_state BEFORE_ATTRIBUTE_NAME
       of '&': switch_state_return CHARACTER_REFERENCE
-      of '>': switch_state DATA
+      of '>':
+        switch_state DATA
+        emit_tok
       of null:
         parse_error unexpected_null_character
         append_to_current_attr_value Rune(0xFFFD)
diff --git a/src/io/buffer.nim b/src/io/buffer.nim
index 9fa23fe6..03de9988 100644
--- a/src/io/buffer.nim
+++ b/src/io/buffer.nim
@@ -1003,6 +1003,7 @@ proc click*(buffer: Buffer): Option[ClickAction] =
           input.rendered = false
           buffer.reshape = true
         if input.form != nil:
+          eprint "SEARCH", input.value
           let submitaction = submitForm(input.form, input)
           return submitaction
       of INPUT_TEXT, INPUT_PASSWORD:
diff --git a/src/layout/engine.nim b/src/layout/engine.nim
index 1596add2..a449f6a3 100644
--- a/src/layout/engine.nim
+++ b/src/layout/engine.nim
@@ -640,7 +640,7 @@ proc getListItemBox(computed: CSSComputedValues, listItemCounter: int): ListItem
   result.computed = computed.copyProperties()
   result.marker = getMarkerBox(computed, listItemCounter)
 
-func getInputBox(parent: BoxBuilder, input: HTMLInputElement, viewport: Viewport): InlineBoxBuilder =
+func getInputBox(parent: BoxBuilder, input: HTMLInputElement): InlineBoxBuilder =
   let textbox = parent.getTextBox()
   textbox.node = input
   textbox.text.add(input.inputString())
@@ -702,7 +702,6 @@ proc generateFromElem(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup:
 
 proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgroup: var seq[BoxBuilder], viewport: Viewport) =
   var ibox: InlineBoxBuilder = nil
-
   var listItemCounter = 1 # ordinal value of current list
 
   for child in styledNode.children:
@@ -712,7 +711,7 @@ proc generateInlineBoxes(box: BlockBoxBuilder, styledNode: StyledNode, blockgrou
     of STYLED_TEXT:
       if ibox == nil:
         ibox = getTextBox(styledNode.computed)
-        ibox.node = child.node
+        ibox.node = styledNode.node
       ibox.text.add(child.text)
 
   flush_ibox
@@ -722,7 +721,6 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport): BlockBoxBuild
   let box = getBlockBox(styledNode.computed)
   var blockgroup: seq[BoxBuilder]
   var ibox: InlineBoxBuilder = nil
-
   var listItemCounter = 1 # ordinal value of current list
   
   for child in styledNode.children:
@@ -734,7 +732,7 @@ proc generateBlockBox(styledNode: StyledNode, viewport: Viewport): BlockBoxBuild
       if canGenerateAnonymousInline(blockgroup, box.computed, child.text):
         if ibox == nil:
           ibox = getTextBox(styledNode.computed)
-          ibox.node = child.node
+          ibox.node = styledNode.node
         ibox.text.add(child.text)
 
   flush_ibox