about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-12-28 20:21:58 +0100
committerbptato <nincsnevem662@gmail.com>2023-12-28 20:21:58 +0100
commit1d6af9e4583f29206480598c9aa774665dc9696f (patch)
treee9511e0eb62398f1ff110e9aca3f58bb81c5e311
parenta24e6467ea2a3bb1260efbfbcb11a98d73b2bcc8 (diff)
downloadchawan-1d6af9e4583f29206480598c9aa774665dc9696f.tar.gz
tests 18 .. 20
* Implement template stuff in minidom
* Foreign content fixes
* Fix </tbody> in "in row" switching to "in body" instead of
  "in table body"
-rw-r--r--chame/htmlparser.nim9
-rw-r--r--chame/minidom.nim32
-rw-r--r--chame/utils/twtstr.nim9
-rw-r--r--tests/shared/tree_common.nim25
-rw-r--r--tests/tree.nim9
5 files changed, 61 insertions, 23 deletions
diff --git a/chame/htmlparser.nim b/chame/htmlparser.nim
index 330961ee..f3a0d9d4 100644
--- a/chame/htmlparser.nim
+++ b/chame/htmlparser.nim
@@ -1075,7 +1075,9 @@ func isHTMLIntegrationPoint[Handle, Atom](parser: HTML5Parser[Handle, Atom],
     if localName == parser.atomMap[ATOM_ANNOTATION_XML]:
       let i = token.findAttr(parser.atomMap[ATOM_ENCODING])
       if i != -1:
-        return token.attrs[i].value in ["text/html", "application/xhtml+xml"]
+        let value = token.attrs[i].value
+        return value.equalsIgnoreCase("text/html") or
+          value.equalsIgnoreCase("application/xhtml+xml")
   elif namespace == Namespace.SVG:
     let elements = [
       parser.atomMap[ATOM_FOREIGNOBJECT],
@@ -2484,7 +2486,7 @@ proc processInHTMLContent[Handle, Atom](parser: var HTML5Parser[Handle, Atom],
         else:
           clear_the_stack_back_to_a_table_row_context
           pop_current_node
-          parser.insertionMode = IN_BODY
+          parser.insertionMode = IN_TABLE_BODY
           reprocess token
       )
       ("</body>", "</caption>", "</col>", "</colgroup>", "</html>", "</td>",
@@ -2808,6 +2810,7 @@ proc processInForeignContent(parser: var HTML5Parser, token: Token) =
       parser.insertCharacter(token.s)
       parser.framesetOk = false
     )
+    TokenType.COMMENT => (block: parser.insertComment(token))
     TokenType.DOCTYPE => (block: parse_error UNEXPECTED_DOCTYPE)
     ("<b>", "<big>", "<blockquote>", "<body>", "<br>", "<center>", "<code>",
      "<dd>", "<div>", "<dl>", "<dt>", "<em>", "<embed>", "<h1>", "<h2>",
@@ -2884,7 +2887,7 @@ proc constructTree[Handle, Atom](parser: var HTML5Parser[Handle, Atom]) =
       if ismmlip and token.t in CharacterToken or
           ismmlip and token.t == START_TAG and token.tagname notin mmlnoatoms or
           namespace == Namespace.MATHML and localName == annotationXml and
-            token.tagtype == TAG_SVG or
+            token.t == START_TAG and token.tagtype == TAG_SVG or
           ishtmlip and token.t == START_TAG or
           ishtmlip and token.t in CharacterToken:
         parser.processInHTMLContent(token, parser.insertionMode)
diff --git a/chame/minidom.nim b/chame/minidom.nim
index 1261c6c6..02860d50 100644
--- a/chame/minidom.nim
+++ b/chame/minidom.nim
@@ -123,6 +123,11 @@ type
     attrs*: seq[Attribute]
     document*: Document
 
+  DocumentFragment* = ref object of Node
+
+  HTMLTemplateElement* = ref object of Element
+    content*: DocumentFragment
+
 type
   MiniDOMBuilder* = ref object of DOMBuilder[Node, MAtom]
     document*: Document
@@ -188,9 +193,13 @@ proc getDocument(builder: DOMBuilder[Node, MAtom]): Node =
 proc getAtomFactory(builder: DOMBuilder[Node, MAtom]): AtomFactory[MAtom] =
   return MiniDOMBuilder(builder).factory
 
-proc getParentNode(builder: DOMBuilder[Node, MAtom], handle: Node): Option[Node] =
+proc getParentNode(builder: DOMBuilder[Node, MAtom], handle: Node):
+    Option[Node] =
   return option(handle.parentNode)
 
+proc getTemplateContent(builder: DOMBuilder[Node, MAtom], handle: Node): Node =
+  return HTMLTemplateElement(handle).content
+
 proc getLocalName(builder: DOMBuilder[Node, MAtom], handle: Node): MAtom =
   return Element(handle).localName
 
@@ -200,14 +209,17 @@ proc getNamespace(builder: DOMBuilder[Node, MAtom], handle: Node): Namespace =
 proc createElement(builder: DOMBuilder[Node, MAtom], localName: MAtom,
     namespace: Namespace, attrs: seq[Attribute]): Node =
   let builder = cast[MiniDOMBuilder](builder)
-  let element = Element(
-    nodeType: ELEMENT_NODE,
-    localName: localName,
-    namespace: namespace,
-    document: builder.document,
-    attrs: attrs
-  )
-  assert element.document != nil and element.document.factory != nil
+  let element = if localName.toTagType() == TAG_TEMPLATE:
+    HTMLTemplateElement(
+      content: DocumentFragment()
+    )
+  else:
+    Element()
+  element.nodeType = ELEMENT_NODE
+  element.localName = localName
+  element.namespace = namespace
+  element.document = builder.document
+  element.attrs = attrs
   for attr in element.attrs.mitems:
     attr.value = attr.value.toValidUTF8()
   return element
@@ -359,6 +371,7 @@ proc initMiniDOMBuilder*(builder: MiniDOMBuilder) =
   builder.getDocument = getDocument
   builder.getAtomFactory = getAtomFactory
   builder.getParentNode = getParentNode
+  builder.getTemplateContent = getTemplateContent
   builder.getLocalName = getLocalName
   builder.getNamespace = getNamespace
   builder.createElement = createElement
@@ -419,7 +432,6 @@ proc parseHTMLFragment*(inputStream: Stream, element: Element,
     namespace: HTML,
     document: document
   )
-  assert root.document != nil and root.document.factory != nil
   let rootToken = Token[MAtom](t: START_TAG, tagname: htmlAtom)
   document.childList = @[Node(root)]
   var opts = opts
diff --git a/chame/utils/twtstr.nim b/chame/utils/twtstr.nim
index d2af5dfe..970a3cdf 100644
--- a/chame/utils/twtstr.nim
+++ b/chame/utils/twtstr.nim
@@ -34,6 +34,15 @@ func until*(s: string, c: set[char]): string =
 
 func until*(s: string, c: char): string = s.until({c})
 
+func after*(s: string, c: set[char]): string =
+  var i = 0
+  while i < s.len:
+    if s[i] in c:
+      return s.substr(i + 1)
+    inc i
+
+func after*(s: string, c: char): string = s.after({c})
+
 func isSurrogate*(u: uint32): bool = u in 0xD800u32..0xDFFFu32
 func isNonCharacter*(u: uint32): bool =
   u in 0xFDD0u32..0xFDEFu32 or
diff --git a/tests/shared/tree_common.nim b/tests/shared/tree_common.nim
index e1f1ad28..a5033750 100644
--- a/tests/shared/tree_common.nim
+++ b/tests/shared/tree_common.nim
@@ -7,6 +7,7 @@ import std/unittest
 import test1
 import chame/htmlparser
 import chame/minidom
+import chame/utils/twtstr
 
 type
   TCError = object
@@ -189,17 +190,22 @@ proc parseTestDocument(ctx: var TCTestParser): Document =
       elif nameStr.startsWith("math "):
         nameStr = nameStr.substr("math ".len)
         namespace = Namespace.MATHML
-      let element = Element(
-        nodeType: ELEMENT_NODE,
-        namespace: namespace,
-        localName: ctx.factory.strToAtom(nameStr),
-        document: result
-      )
+      let element = if nameStr == "template":
+        HTMLTemplateElement()
+      else:
+        Element()
+      element.nodeType = ELEMENT_NODE
+      element.localName = ctx.factory.strToAtom(nameStr)
+      element.namespace = namespace
+      element.document = result
       top.childList.add(element)
       stack.add(element)
       indent += 2
     elif str == "content":
-      assert false, "todo"
+      let fragment = DocumentFragment()
+      HTMLTemplateElement(top).content = fragment
+      stack.add(fragment)
+      indent += 2
     elif str[0] == '"':
       let text = Text(nodeType: TEXT_NODE)
       top.childList.add(text)
@@ -210,8 +216,7 @@ proc parseTestDocument(ctx: var TCTestParser): Document =
         text.data = str.substr(1, str.high - 1)
     else:
       assert '=' in str
-      let ss = str.split('=')
-      var name = ss[0]
+      var name = str.until('=')
       var prefix = NO_PREFIX
       var ns = NO_NAMESPACE
       if name.startsWith("xml "):
@@ -227,7 +232,7 @@ proc parseTestDocument(ctx: var TCTestParser): Document =
         prefix = PREFIX_XLINK
         name = name.substr("xlink ".len)
       let na = ctx.factory.strToAtom(name)
-      let value = ss[1][1..^2]
+      let value = str.after('=')[1..^2]
       Element(top).attrs.add((prefix, ns, na, value))
   while indent > 1:
     pop_node
diff --git a/tests/tree.nim b/tests/tree.nim
index ea269367..17c53d34 100644
--- a/tests/tree.nim
+++ b/tests/tree.nim
@@ -94,3 +94,12 @@ test "tests16.dat":
 
 test "tests17.dat":
   runTests("tests17.dat")
+
+test "tests18.dat":
+  runTests("tests18.dat")
+
+test "tests19.dat":
+  runTests("tests19.dat")
+
+test "tests20.dat":
+  runTests("tests20.dat")