diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/css/parser.nim | 4 | ||||
-rw-r--r-- | src/css/values.nim | 10 | ||||
-rw-r--r-- | src/html/parser.nim | 24 | ||||
-rw-r--r-- | src/layout/engine.nim | 130 | ||||
-rw-r--r-- | src/utils/twtstr.nim | 23 |
5 files changed, 90 insertions, 101 deletions
diff --git a/src/css/parser.nim b/src/css/parser.nim index 2fdefef2..b594abc3 100644 --- a/src/css/parser.nim +++ b/src/css/parser.nim @@ -286,7 +286,7 @@ proc consumeURL(state: var CSSTokenizerState): CSSToken = proc consumeIdentLikeToken(state: var CSSTokenizerState): CSSToken = let s = state.consumeName() - if s.toAsciiLower() == "url" and state.has() and state.curr() == Rune('('): + if s.equalsIgnoreCase("url") and state.has() and state.curr() == Rune('('): discard state.consume() while state.has(1) and state.curr().isWhitespace() and state.peek(1).isWhitespace(): discard state.consume() @@ -516,7 +516,7 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = if decl.value[i] != CSS_WHITESPACE_TOKEN: dec j if decl.value[i] == CSS_IDENT_TOKEN and k == 0: - if CSSToken(decl.value[i]).value.toAsciiLower() == "important": + if CSSToken(decl.value[i]).value.equalsIgnoreCase("important"): inc k l = i elif k == 1 and decl.value[i] == CSS_DELIM_TOKEN: diff --git a/src/css/values.nim b/src/css/values.nim index 8a66b863..df80e60d 100644 --- a/src/css/values.nim +++ b/src/css/values.nim @@ -529,15 +529,15 @@ func cssDisplay(d: CSSDeclaration): CSSDisplay = of "block": return DISPLAY_BLOCK of "inline": return DISPLAY_INLINE of "list-item": return DISPLAY_LIST_ITEM - # of "inline-block": return DISPLAY_INLINE_BLOCK - # of "table": return DISPLAY_TABLE + of "table": return DISPLAY_TABLE + of "inline-block": return DISPLAY_INLINE_BLOCK + of "table-row": return DISPLAY_TABLE_ROW + of "table-cell": return DISPLAY_TABLE_CELL + # of "table-column": return DISPLAY_TABLE_COLUMN # of "table-row-group": return DISPLAY_TABLE_ROW_GROUP # of "table-header-group": return DISPLAY_TABLE_HEADER_GROUP # of "table-footer-group": return DISPLAY_TABLE_FOOTER_GROUP # of "table-column-group": return DISPLAY_TABLE_COLUMN_GROUP - # of "table-row": return DISPLAY_TABLE_ROW - # of "table-column": return DISPLAY_TABLE_COLUMN - # of "table-cell": return DISPLAY_TABLE_CELL of "none": return DISPLAY_NONE else: return DISPLAY_INLINE raise newException(CSSValueError, "Invalid display") diff --git a/src/html/parser.nim b/src/html/parser.nim index 0e0fbaa0..74ec68b7 100644 --- a/src/html/parser.nim +++ b/src/html/parser.nim @@ -127,11 +127,15 @@ proc parse_tag(buf: string, at: var int): DOMParsedTag = var value = "" var attrname = "" while at < buf.len and buf[at] != '=' and not buf[at].isWhitespace() and buf[at] != '>': - attrname &= buf[at].tolower() - at += buf.runeLenAt(at) + var r: Rune + fastRuneAt(buf, at, r) + if r.isAscii(): + attrname &= char(r).tolower() + else: + attrname &= r at = skipBlanks(buf, at) - if buf[at] == '=': + if at < buf.len and buf[at] == '=': inc at at = skipBlanks(buf, at) if at < buf.len and (buf[at] == '"' or buf[at] == '\''): @@ -142,9 +146,8 @@ proc parse_tag(buf: string, at: var int): DOMParsedTag = inc at value &= getescapecmd(buf, at) else: - var r: Rune - fastRuneAt(buf, at, r) - value &= r + value &= buf[at] + inc at if at < buf.len: inc at elif at < buf.len: @@ -416,15 +419,14 @@ proc processDocumentPart(state: var HTMLParseState, buf: string) = state.commentNode.data &= buf[at] inc at else: - var r: Rune - fastRuneAt(buf, at, r) if state.in_comment: - state.commentNode.data &= $r + state.commentNode.data &= buf[at] else: - if not (state.skip_lf and r == Rune('\n')): + if not (state.skip_lf and buf[at] == '\n'): processDocumentText(state) - state.textNode.data &= $r + state.textNode.data &= buf[at] state.skip_lf = false + inc at proc parseHtml*(inputStream: Stream): Document = let document = newDocument() diff --git a/src/layout/engine.nim b/src/layout/engine.nim index 523b7bff..b2dfe8dd 100644 --- a/src/layout/engine.nim +++ b/src/layout/engine.nim @@ -301,23 +301,22 @@ proc add(state: var LayoutState, parent: CSSBox, box: CSSBox) = parent.children.add(box) -func isBlock(node: Node): bool = - if node.nodeType != ELEMENT_NODE: - return false - let elem = Element(node) - return elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_BLOCK or - elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM - proc processComputedValueBox(state: var LayoutState, parent: CSSBox, values: CSSComputedValues): CSSBox = case values[PROPERTY_DISPLAY].display of DISPLAY_BLOCK: - #eprint "START", elem.tagType, parent.icontext.fromy result = state.newBlockBox(parent, values) - #CSSBlockBox(result).tag = $elem.tagType + of DISPLAY_INLINE_BLOCK: + result = state.newInlineBox(parent, values) of DISPLAY_INLINE: result = state.newInlineBox(parent, values) of DISPLAY_LIST_ITEM: result = state.newBlockBox(parent, values) + of DISPLAY_TABLE: + result = state.newBlockBox(parent, values) + of DISPLAY_TABLE_ROW: + result = state.newBlockBox(parent, values) + of DISPLAY_TABLE_CELL: + result = state.newInlineBox(parent, values) of DISPLAY_NONE: return nil else: @@ -343,16 +342,17 @@ proc processElemBox(state: var LayoutState, parent: CSSBox, elem: Element): CSSB if result != nil: result.node = elem -proc processNodes(state: var LayoutState, parent: CSSBox, node: Node) +proc processElemChildren(state: var LayoutState, parent: CSSBox, elem: Element) proc processNode(state: var LayoutState, parent: CSSBox, node: Node): CSSBox = case node.nodeType of ELEMENT_NODE: + let elem = Element(node) result = state.processElemBox(parent, Element(node)) if result == nil: return - state.processNodes(result, node) + state.processElemChildren(result, elem) of TEXT_NODE: let text = Text(node) result = state.processInlineBox(parent, text.data) @@ -360,75 +360,59 @@ proc processNode(state: var LayoutState, parent: CSSBox, node: Node): CSSBox = result.node = node else: discard -# ugh this is ugly, but it works... -# basically this -# * checks if there's a ::before pseudo element -# * checks if we need to wrap things in anonymous block boxes -# * in case we do, it adds the text to the anonymous box -# * in case we don't, it tries to add the text to a new parent box -# * but only if a new parent box is needed. -proc processBeforePseudoElem(state: var LayoutState, parent: CSSBox, node: Node) = - if node.nodeType == ELEMENT_NODE: - let elem = Element(node) - - if elem.cssvalues_before != nil: - var box: CSSBox - box = state.processComputedValueBox(parent, elem.cssvalues_before) - if box != nil: - box.node = node +proc processBeforePseudoElem(state: var LayoutState, parent: CSSBox, elem: Element) = + if elem.cssvalues_before != nil: + var box: CSSBox + box = state.processComputedValueBox(parent, elem.cssvalues_before) + if box != nil: + box.node = elem - let text = elem.cssvalues_before[PROPERTY_CONTENT].content - var inline = state.processInlineBox(box, $text) - if inline != nil: - inline.node = node - state.add(box, inline) + let text = elem.cssvalues_before[PROPERTY_CONTENT].content + var inline = state.processInlineBox(box, $text) + if inline != nil: + inline.node = elem + state.add(box, inline) - state.add(parent, box) - -# same as before except it's after -proc processAfterPseudoElem(state: var LayoutState, parent: CSSBox, node: Node) = - if node.nodeType == ELEMENT_NODE: - let elem = Element(node) - - if elem.cssvalues_after != nil: - let box = state.processComputedValueBox(parent, elem.cssvalues_after) - if box != nil: - box.node = node - - let text = elem.cssvalues_after[PROPERTY_CONTENT].content - var inline = state.processInlineBox(box, $text) - if inline != nil: - inline.node = node - state.add(box, inline) - - state.add(parent, box) - -proc processMarker(state: var LayoutState, parent: CSSBox, node: Node) = - if node.nodeType == ELEMENT_NODE: - let elem = Element(node) - if elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM: - var ordinalvalue = 1 - if elem.tagType == TAG_LI: - ordinalvalue = HTMLLIElement(elem).ordinalvalue - - let text = elem.cssvalues[PROPERTY_LIST_STYLE_TYPE].liststyletype.listMarker(ordinalvalue) - let tlen = text.width() - parent.icontext.fromx -= tlen - let marker = state.processInlineBox(parent, text) - state.add(parent, marker) + state.add(parent, box) -proc processNodes(state: var LayoutState, parent: CSSBox, node: Node) = - state.nodes.add(node) +proc processAfterPseudoElem(state: var LayoutState, parent: CSSBox, elem: Element) = + if elem.cssvalues_after != nil: + let box = state.processComputedValueBox(parent, elem.cssvalues_after) + if box != nil: + box.node = elem - state.processBeforePseudoElem(parent, node) + let text = elem.cssvalues_after[PROPERTY_CONTENT].content + var inline = state.processInlineBox(box, $text) + if inline != nil: + inline.node = elem + state.add(box, inline) - state.processMarker(parent, node) + state.add(parent, box) - for c in node.childNodes: - let box = state.processNode(parent, c) +proc processMarker(state: var LayoutState, parent: CSSBox, elem: Element) = + if elem.cssvalues[PROPERTY_DISPLAY].display == DISPLAY_LIST_ITEM: + var ordinalvalue = 1 + if elem.tagType == TAG_LI: + ordinalvalue = HTMLLIElement(elem).ordinalvalue + + let text = elem.cssvalues[PROPERTY_LIST_STYLE_TYPE].liststyletype.listMarker(ordinalvalue) + let tlen = text.width() + parent.icontext.fromx -= tlen + let marker = state.processInlineBox(parent, text) + state.add(parent, marker) + +proc processNodes(state: var LayoutState, parent: CSSBox, nodes: seq[Node]) = + for node in nodes: + let box = state.processNode(parent, node) state.add(parent, box) - state.processAfterPseudoElem(parent, node) +proc processElemChildren(state: var LayoutState, parent: CSSBox, elem: Element) = + state.nodes.add(elem) + + state.processBeforePseudoElem(parent, elem) + state.processMarker(parent, elem) + state.processNodes(parent, elem.childNodes) + state.processAfterPseudoElem(parent, elem) discard state.nodes.pop() @@ -441,5 +425,5 @@ proc alignBoxes*(document: Document, term: TermAttributes): CSSBox = rootbox.bcontext = newBlockContext() rootbox.bcontext.width = term.width state.nodes.add(document.root) - state.processNodes(rootbox, document.root) + state.processElemChildren(rootbox, document.root) return rootbox diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim index f20b0bbe..ef81edc4 100644 --- a/src/utils/twtstr.nim +++ b/src/utils/twtstr.nim @@ -139,31 +139,34 @@ func decValue*(c: char): int = return decCharMap[int(c)] func isAscii*(r: Rune): bool = - return int(r) <= int(high(char)) + return int(r) < 128 func hexValue*(r: Rune): int = - if isAscii(r): + if int(r) < 256: return hexValue(char(r)) return -1 func decValue*(r: Rune): int = - if isAscii(r): + if int(r) < 256: return decValue(char(r)) return -1 -func toAsciiLower*(s: seq[Rune]): string = - for r in s: - if isAscii(r): - result &= lowerChars[int(r)] +func equalsIgnoreCase*(s1: seq[Rune], s2: string): bool = + var i = 0 + while i < min(s1.len, s2.len): + if not s1[i].isAscii() or cast[char](s1[i]).tolower() != s2[i]: + return false + inc i + return true func breaksWord*(r: Rune): bool = return r in breakWord func isAlphaAscii*(r: Rune): bool = - return isAscii(r) and isAlphaAscii(char(r)) + return int(r) < 256 and isAlphaAscii(char(r)) func isDigitAscii*(r: Rune): bool = - return isAscii(r) and isDigit(char(r)) + return int(r) < 256 and isDigit(char(r)) func substr*(s: seq[Rune], i: int, j: int): seq[Rune] = if s.len == 0: @@ -214,7 +217,7 @@ func japaneseNumber*(i: int): string = return "〇" var n = i if i < 0: - result &= "ス" + result &= "マイナス" n *= -1 let o = n |