From 72e171f6bee469ecc0086357f83fe4dc678023f3 Mon Sep 17 00:00:00 2001 From: bptato Date: Tue, 14 Dec 2021 17:31:00 +0100 Subject: Add lists, function selector fixes --- src/html/dom.nim | 96 ++++++++++++++++++++++++++++++++++++++++++----------- src/html/parser.nim | 42 +++++++++++++---------- 2 files changed, 102 insertions(+), 36 deletions(-) (limited to 'src/html') diff --git a/src/html/dom.nim b/src/html/dom.nim index f2c98bd0..0c7d385a 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -1,5 +1,7 @@ import uri import tables +import options +import strutils import css/values import types/enums @@ -70,40 +72,46 @@ type cssapplied*: bool rendered*: bool - HTMLElement* = ref HTMLElementObj - HTMLElementObj = object of ElementObj + HTMLElement* = ref object of ElementObj - HTMLInputElement* = ref HTMLInputElementObj - HTMLInputElementObj = object of HTMLElementObj + HTMLInputElement* = ref object of HTMLElement itype*: InputType autofocus*: bool required*: bool value*: string size*: int - HTMLAnchorElement* = ref HTMLAnchorElementObj - HTMLAnchorElementObj = object of HTMLElementObj + HTMLAnchorElement* = ref object of HTMLElement href*: string - HTMLSelectElement* = ref HTMLSelectElementObj - HTMLSelectElementObj = object of HTMLElementObj + HTMLSelectElement* = ref object of HTMLElement name*: string value*: string valueSet*: bool - HTMLSpanElement* = ref HTMLSpanElementObj - HTMLSpanElementObj = object of HTMLElementObj + HTMLSpanElement* = ref object of HTMLElement - HTMLOptionElement* = ref HTMLOptionElementObj - HTMLOptionElementObj = object of HTMLElementObj + HTMLOptionElement* = ref object of HTMLElement value*: string - HTMLHeadingElement* = ref HTMLHeadingElementObj - HTMLHeadingElementObj = object of HTMLElementObj + HTMLHeadingElement* = ref object of HTMLElement rank*: uint16 - HTMLBRElement* = ref HTMLBRElementObj - HTMLBRElementObj = object of HTMLElementObj + HTMLBRElement* = ref object of HTMLElement + + HTMLMenuElement* = ref object of HTMLElement + ordinalcounter*: int + + HTMLUListElement* = ref object of HTMLElement + ordinalcounter*: int + + HTMLOListElement* = ref object of HTMLElement + start*: Option[int] + ordinalcounter*: int + + HTMLLIElement* = ref object of HTMLElement + value*: Option[int] + ordinalvalue*: int func firstChild(node: Node): Node = if node.childNodes.len == 0: @@ -191,6 +199,49 @@ func toInputType*(str: string): InputType = of "week": INPUT_WEEK else: INPUT_UNKNOWN +func ancestor(node: Node, tagTypes: set[TagType]): Element = + var elem = node.parentElement + while elem != nil: + if elem.tagType in tagTypes: + return elem + + elem = elem.parentElement + return nil + +func attr*(element: Element, s: string): string = + return element.attributes.getOrDefault(s, "") + +func attri*(element: Element, s: string): Option[int] = + let a = element.attr(s) + try: + return some(parseInt(a)) + except ValueError: + return none(int) + +proc applyOrdinal*(elem: HTMLLIElement) = + let val = elem.attri("value") + if val.issome: + elem.ordinalvalue = val.get + else: + let owner = elem.ancestor({TAG_OL, TAG_UL, TAG_MENU}) + if owner == nil: + elem.ordinalvalue = 1 + else: + case owner.tagType + of TAG_OL: + let ol = HTMLOListElement(owner) + elem.ordinalvalue = ol.ordinalcounter + inc ol.ordinalcounter + of TAG_UL: + let ul = HTMLUListElement(owner) + elem.ordinalvalue = ul.ordinalcounter + inc ul.ordinalcounter + of TAG_MENU: + let menu = HTMLMenuElement(owner) + elem.ordinalvalue = menu.ordinalcounter + inc menu.ordinalcounter + else: discard + func newText*(): Text = new(result) result.nodeType = TEXT_NODE @@ -215,6 +266,16 @@ func newHtmlElement*(tagType: TagType): HTMLElement = result = new(HTMLBRElement) of TAG_SPAN: result = new(HTMLSpanElement) + of TAG_OL: + result = new(HTMLOListElement) + of TAG_UL: + result = new(HTMLUListElement) + HTMLUListElement(result).ordinalcounter = 1 + of TAG_MENU: + result = new(HTMLMenuElement) + HTMLMenuElement(result).ordinalcounter = 1 + of TAG_LI: + result = new(HTMLLIElement) else: result = new(HTMLElement) @@ -235,6 +296,3 @@ func newAttr*(parent: Element, key: string, value: string): Attr = result.ownerElement = parent result.name = key result.value = value - -func attr*(element: Element, s: string): string = - return element.attributes.getOrDefault(s, "") diff --git a/src/html/parser.nim b/src/html/parser.nim index a3a6885d..70b749a6 100644 --- a/src/html/parser.nim +++ b/src/html/parser.nim @@ -3,6 +3,7 @@ import unicode import strutils import tables import json +import options import types/enums import types/tagtypes @@ -250,6 +251,11 @@ proc processDocumentStartElement(state: var HTMLParseState, element: Element, ta HTMLAnchorElement(element).href = element.attr("href") of TAG_OPTION: HTMLOptionElement(element).value = element.attr("href") + of TAG_OL: + HTMLOListElement(element).start = element.attri("start") + HTMLOListElement(element).ordinalcounter = HTMLOListElement(element).start.get(1) + of TAG_LI: + HTMLLIElement(element).value = element.attri("value") of TAG_HTML: add = false of TAG_HEAD: @@ -261,29 +267,27 @@ proc processDocumentStartElement(state: var HTMLParseState, element: Element, ta add = false of TAG_PRE: state.skip_lf = true + of TAG_H1: + HTMLHeadingElement(element).rank = 1 + of TAG_H2: + HTMLHeadingElement(element).rank = 2 + of TAG_H3: + HTMLHeadingElement(element).rank = 3 + of TAG_H4: + HTMLHeadingElement(element).rank = 4 + of TAG_H5: + HTMLHeadingElement(element).rank = 5 + of TAG_H6: + HTMLHeadingElement(element).rank = 6 else: discard if not state.in_body and not (element.tagType in HeadTagTypes): processDocumentBody(state) if state.elementNode.nodeType == ELEMENT_NODE: - case element.tagType - of SelfClosingTagTypes: + if element.tagType in SelfClosingTagTypes: if state.elementNode.tagType == element.tagType: processDocumentEndNode(state) - of TAG_H1: - HTMLHeadingElement(element).rank = 1 - of TAG_H2: - HTMLHeadingElement(element).rank = 2 - of TAG_H3: - HTMLHeadingElement(element).rank = 3 - of TAG_H4: - HTMLHeadingElement(element).rank = 4 - of TAG_H5: - HTMLHeadingElement(element).rank = 5 - of TAG_H6: - HTMLHeadingElement(element).rank = 6 - else: discard if state.elementNode.tagType == TAG_P and element.tagType in PClosingTagTypes: processDocumentEndNode(state) @@ -292,8 +296,12 @@ proc processDocumentStartElement(state: var HTMLParseState, element: Element, ta processDocumentAddNode(state, element) state.elementNode = element - if element.tagType in VoidTagTypes: - processDocumentEndNode(state) + case element.tagType + of VoidTagTypes: + processDocumentEndNode(state) + of TAG_LI: + HTMLLIElement(element).applyOrdinal() #needs to know parent + else: discard proc processDocumentEndElement(state: var HTMLParseState, tag: DOMParsedTag) = if tag.tagid in VoidTagTypes: -- cgit 1.4.1-2-gfad0