about summary refs log tree commit diff stats
path: root/src/html
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2022-12-26 19:42:19 +0100
committerbptato <nincsnevem662@gmail.com>2022-12-26 19:42:19 +0100
commit774aad55da0fc62f8de8c95dbbb3d2ad41010e3f (patch)
treec80f7a6d783261b5fe741749aa5f8a52abcc7919 /src/html
parent636ddbb788a4a4dcd4dc4bc247159b6bb191ef8a (diff)
downloadchawan-774aad55da0fc62f8de8c95dbbb3d2ad41010e3f.tar.gz
dom: correct constructors, more create functions
Diffstat (limited to 'src/html')
-rw-r--r--src/html/dom.nim128
-rw-r--r--src/html/htmlparser.nim7
2 files changed, 89 insertions, 46 deletions
diff --git a/src/html/dom.nim b/src/html/dom.nim
index ab800406..6c3f93c2 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -145,6 +145,9 @@ type
     value* {.jsget.}: string
     ownerElement* {.jsget.}: Element
 
+  DOMImplementation = ref object
+    document: Document
+
   Document* = ref object of Node
     charset*: Charset
     window*: Window
@@ -153,6 +156,8 @@ type
     mode*: QuirksMode
     currentScript: HTMLScriptElement
     isxml*: bool
+    implementation {.jsget.}: DOMImplementation
+    origin: Origin
 
     scriptsToExecSoon*: seq[HTMLScriptElement]
     scriptsToExecInOrder*: Deque[HTMLScriptElement]
@@ -162,7 +167,7 @@ type
     parser_cannot_change_the_mode_flag*: bool
     is_iframe_srcdoc*: bool
     focus*: Element
-    contentType*: string
+    contentType* {.jsget.}: string
 
     renderBlockingElements: seq[Element]
 
@@ -176,7 +181,7 @@ type
   CDATASection = ref object of CharacterData
 
   ProcessingInstruction = ref object of CharacterData
-    target: string
+    target {.jsget.}: string
 
   DocumentFragment* = ref object of Node
     host*: Element
@@ -1052,38 +1057,49 @@ func target*(element: Element): string {.jsfunc.} =
       return base.attr("target")
   return ""
 
-#TODO we shouldn't have to pass document in DOM (so first arg should be window)
-func newText*(document: Document, data: string = ""): Text {.jsctor.} =
-  new(result)
-  result.nodeType = TEXT_NODE
-  result.document = document
-  result.data = data
+func newText(document: Document, data: string): Text =
+  return Text(
+    nodeType: TEXT_NODE,
+    document: document,
+    data: data
+  )
+
+func newText(window: Window, data: string = ""): Text {.jsgctor.} =
+  return window.document.newText(data)
 
 func newCDATASection(document: Document, data: string): CDATASection =
-  new(result)
-  result.nodeType = CDATA_SECTION_NODE
-  result.document = document
-  result.data = data
+  return CDATASection(
+    nodeType: CDATA_SECTION_NODE,
+    document: document,
+    data: data
+  )
 
 func newProcessingInstruction(document: Document, target, data: string): ProcessingInstruction =
-  new(result)
-  result.nodeType = PROCESSING_INSTRUCTION_NODE
-  result.document = document
-  result.target = target
-  result.data = data
+  return ProcessingInstruction(
+    nodeType: PROCESSING_INSTRUCTION_NODE,
+    document: document,
+    target: target,
+    data: data
+  )
 
-#TODO ditto
-func newDocumentFragment*(document: Document): DocumentFragment {.jsctor.} =
-  new(result)
-  result.nodeType = DOCUMENT_FRAGMENT_NODE
-  result.document = document
+func newDocumentFragment(document: Document): DocumentFragment =
+  return DocumentFragment(
+    nodeType: DOCUMENT_FRAGMENT_NODE,
+    document: document
+  )
 
-#TODO ditto
-func newComment*(document: Document = nil, data: string = ""): Comment {.jsctor.} =
-  new(result)
-  result.nodeType = COMMENT_NODE
-  result.document = document
-  result.data = data
+func newDocumentFragment(window: Window): DocumentFragment {.jsgctor.} =
+  return window.document.newDocumentFragment()
+
+func newComment(document: Document, data: string): Comment =
+  return Comment(
+    nodeType: COMMENT_NODE,
+    document: document,
+    data: data
+  )
+
+func newComment(window: Window, data: string = ""): Comment {.jsgctor.} =
+  return window.document.newComment(data)
 
 proc attr*(element: Element, name, value: string)
 
@@ -1155,18 +1171,21 @@ func newHTMLElement*(document: Document, localName: string, namespace = Namespac
     result.localName = localName
 
 func newDocument*(): Document {.jsctor.} =
-  new(result)
-  result.nodeType = DOCUMENT_NODE
+  result = Document(
+    nodeType: DOCUMENT_NODE
+  )
   result.document = result
-  result.contentType = "text/html"
-
-func newDocumentType*(document: Document, name: string, publicId = "", systemId = ""): DocumentType {.jsctor.} =
-  new(result)
-  result.nodeType = DOCUMENT_TYPE_NODE
-  result.document = document
-  result.name = name
-  result.publicId = publicId
-  result.systemId = systemId
+  result.implementation = DOMImplementation(document: result)
+  result.contentType = "application/xml"
+
+func newDocumentType*(document: Document, name: string, publicId = "", systemId = ""): DocumentType =
+  return DocumentType(
+    nodeType: DOCUMENT_TYPE_NODE,
+    document: document,
+    name: name,
+    publicId: publicId,
+    systemId: systemId
+  )
 
 func inHTMLNamespace*(element: Element): bool = element.namespace == Namespace.HTML
 func inMathMLNamespace*(element: Element): bool = element.namespace == Namespace.MATHML
@@ -1687,11 +1706,14 @@ proc replaceAll(parent, node: Node) =
       parent.append(node)
   #TODO tree mutation record
 
+proc createTextNode*(document: Document, data: string): Text {.jsfunc.} =
+  return newText(document, data)
+
 proc textContent*(node: Node, data: Option[string]) {.jsfset.} =
   case node.nodeType
   of DOCUMENT_FRAGMENT_NODE, ELEMENT_NODE:
     let x = if data.isSome:
-      node.document.newText(data.get)
+      node.document.createTextNode(data.get)
     else:
       nil
     node.replaceAll(x)
@@ -1942,8 +1964,27 @@ proc createElement(document: Document, localName: string): Element {.jserr, jsfu
 proc createDocumentFragment(document: Document): DocumentFragment {.jsfunc.} =
   return newDocumentFragment(document)
 
-proc createTextNode(document: Document, data: string): Text {.jsfunc.} =
-  return newText(document, data)
+proc createDocumentType(implementation: DOMImplementation, qualifiedName, publicId, systemId: string): DocumentType {.jserr, jsfunc.} =
+  if not qualifiedName.matchQNameProduction():
+    #TODO should be DOMException
+    JS_ERR JS_TypeError, "InvalidCharacterError"
+  return implementation.document.newDocumentType(qualifiedName, publicId, systemId)
+
+proc createHTMLDocument(implementation: DOMImplementation, title = none(string)): Document {.jsfunc.} =
+  let doc = newDocument()
+  doc.contentType = "text/html"
+  doc.append(doc.newDocumentType("html"))
+  let html = doc.newHTMLElement(TAG_HTML, Namespace.HTML)
+  doc.append(html)
+  let head = doc.newHTMLElement(TAG_HEAD, Namespace.HTML)
+  html.append(head)
+  if title.isSome:
+    let titleElement = doc.newHTMLElement(TAG_TITLE, Namespace.HTML)
+    titleElement.append(doc.newText(title.get))
+    head.append(titleElement)
+  html.append(doc.newHTMLElement(TAG_BODY, Namespace.HTML))
+  #TODO set origin
+  return doc
 
 proc createCDATASection(document: Document, data: string): CDATASection {.jserr, jsfunc.} =
   if not document.isxml:
@@ -1954,7 +1995,7 @@ proc createCDATASection(document: Document, data: string): CDATASection {.jserr,
     JS_ERR JS_TypeError, "InvalidCharacterError"
   return newCDATASection(document, data)
 
-proc createComment(document: Document, data: string): Comment {.jsfunc.} =
+proc createComment*(document: Document, data: string): Comment {.jsfunc.} =
   return newComment(document, data)
 
 proc createProcessingInstruction(document: Document, target, data: string): ProcessingInstruction {.jsfunc.} =
@@ -1983,6 +2024,7 @@ proc addDOMModule*(ctx: JSContext) =
   ctx.registerType(NodeList)
   ctx.registerType(HTMLCollection)
   ctx.registerType(Document, parent = nodeCID)
+  ctx.registerType(DOMImplementation)
   let characterDataCID = ctx.registerType(CharacterData, parent = nodeCID)
   ctx.registerType(Comment, parent = characterDataCID)
   ctx.registerType(CDATASection, parent = characterDataCID)
diff --git a/src/html/htmlparser.nim b/src/html/htmlparser.nim
index f306d5f4..310a11aa 100644
--- a/src/html/htmlparser.nim
+++ b/src/html/htmlparser.nim
@@ -327,7 +327,7 @@ template insert_character_impl(parser: var HTML5Parser, data: typed) =
   if insertNode != nil and insertNode.nodeType == TEXT_NODE:
     dom.Text(insertNode).data &= data
   else:
-    let text = location.inside.document.newText($data)
+    let text = location.inside.document.createTextNode($data)
     location.insert(text)
 
   if location.inside.nodeType == ELEMENT_NODE:
@@ -346,11 +346,11 @@ proc insertCharacter(parser: var HTML5Parser, data: Rune) =
   insert_character_impl(parser, data)
 
 proc insertComment(parser: var HTML5Parser, token: Token, position: AdjustedInsertionLocation) =
-  position.insert(position.inside.document.newComment(token.data))
+  position.insert(position.inside.document.createComment(token.data))
 
 proc insertComment(parser: var HTML5Parser, token: Token) =
   let position = parser.appropriatePlaceForInsert()
-  position.insert(position.inside.document.newComment(token.data))
+  position.insert(position.inside.document.createComment(token.data))
 
 const PublicIdentifierEquals = [
   "-//W3O//DTD W3 HTML Strict 3.0//EN//",
@@ -2212,6 +2212,7 @@ proc parseHTML*(inputStream: Stream, cs = none(Charset), fallbackcs = CHARSET_UT
   for c in bom:
     decoder.prepend(cast[uint32](c))
   parser.document = newDocument()
+  parser.document.contentType = "text/html"
   if window != nil:
     parser.document.window = window
     window.document = parser.document