about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-12-30 19:28:33 +0100
committerbptato <nincsnevem662@gmail.com>2024-12-30 19:28:33 +0100
commitbc3b11ebd3c2554f4f30e9afb4d46328c748e9be (patch)
tree619bb135cce1e9af3fa058c9fc6c7bd4ee017773 /src
parentde759debe31d67776a7a70d3d4dc41a89591cdfc (diff)
downloadchawan-bc3b11ebd3c2554f4f30e9afb4d46328c748e9be.tar.gz
dom, cssvalues: add getComputedStyle
Only available in "app" mode.
Diffstat (limited to 'src')
-rw-r--r--src/css/cascade.nim5
-rw-r--r--src/css/cssvalues.nim107
-rw-r--r--src/html/dom.nim28
-rw-r--r--src/html/env.nim8
-rw-r--r--src/types/color.nim9
5 files changed, 113 insertions, 44 deletions
diff --git a/src/css/cascade.nim b/src/css/cascade.nim
index 3a983a63..60d59a04 100644
--- a/src/css/cascade.nim
+++ b/src/css/cascade.nim
@@ -294,8 +294,9 @@ proc applyDeclarations(styledNode: StyledNode; parent: CSSValues;
   rules[coUser].add(map.user[peNone])
   for rule in map.author:
     rules[coAuthor].add(rule[peNone])
+  var element: Element = nil
   if styledNode.node != nil:
-    let element = Element(styledNode.node)
+    element = Element(styledNode.node)
     let style = element.cachedStyle
     if window.styling and style != nil:
       for decl in style.decls:
@@ -306,6 +307,8 @@ proc applyDeclarations(styledNode: StyledNode; parent: CSSValues;
           rules[coAuthor].normal.add(vals)
     presHints = element.calcPresHints(window.attrsp[])
   styledNode.computed = rules.buildComputedValues(presHints, parent)
+  if element != nil and window.settings.scripting == smApp:
+    element.computed = styledNode.computed
 
 func hasValues(rules: CSSValueEntryMap): bool =
   for origin in CSSOrigin:
diff --git a/src/css/cssvalues.nim b/src/css/cssvalues.nim
index 35487dfd..a88ae814 100644
--- a/src/css/cssvalues.nim
+++ b/src/css/cssvalues.nim
@@ -499,44 +499,79 @@ func valueType*(prop: CSSPropertyType): CSSValueType =
 func isSupportedProperty*(s: string): bool =
   return propertyType(s) != cptNone
 
-when defined(debug):
-  func `$`*(length: CSSLength): string =
-    if length.u == clAuto:
-      return "auto"
-    return $length.num & $length.u
-
-  func `$`*(content: CSSContent): string =
-    if content.s != "":
-      return "url(" & content.s & ")"
-    return "none"
-
-  func `$`(quotes: CSSQuotes): string =
-    if quotes.auto:
-      return "auto"
-    return "auto" #TODO
-
-  func `$`(counterreset: seq[CSSCounterReset]): string =
-    result = ""
-    for it in counterreset:
-      result &= $it.name
-      result &= ' '
-      result &= $it.num
+func `$`*(length: CSSLength): string =
+  if length.u == clAuto:
+    return "auto"
+  return $length.num & $length.u
+
+func `$`*(content: CSSContent): string =
+  if content.t == ContentImage:
+    #TODO
+    return ""
+  if content.s != "":
+    return "url(" & content.s & ")"
+  return "none"
+
+func `$`(quotes: CSSQuotes): string =
+  if quotes.auto:
+    return "auto"
+  return "auto" #TODO
+
+func `$`(counterreset: seq[CSSCounterReset]): string =
+  result = ""
+  for it in counterreset:
+    result &= $it.name
+    result &= ' '
+    result &= $it.num
+
+func serialize*(val: CSSValue): string =
+  case val.v
+  of cvtNone: return "none"
+  of cvtColor: return $val.color
+  of cvtImage: return $val.image
+  of cvtLength: return $val.length
+  of cvtInteger: return $val.integer
+  of cvtTextDecoration: return $val.textDecoration
+  of cvtVerticalAlign: return $val.verticalAlign
+  of cvtLength2: return $val.length2.a & " " & $val.length2.b
+  of cvtContent:
+    var s = ""
+    for x in val.content:
+      if s.len > 0:
+        s &= ' '
+      s &= $x
+    return s
+  of cvtQuotes: return $val.quotes
+  of cvtCounterReset: return $val.counterReset
+  of cvtNumber: return $val.number
+  else: assert false
+
+func serialize*(val: CSSValueBit; t: CSSValueType): string =
+  case t
+  of cvtDisplay: return $val.display
+  of cvtFontStyle: return $val.fontStyle
+  of cvtWhiteSpace: return $val.whiteSpace
+  of cvtWordBreak: return $val.wordBreak
+  of cvtListStyleType: return $val.listStyleType
+  of cvtTextAlign: return $val.textAlign
+  of cvtListStylePosition: return $val.listStylePosition
+  of cvtPosition: return $val.position
+  of cvtCaptionSide: return $val.captionSide
+  of cvtBorderCollapse: return $val.borderCollapse
+  of cvtFloat: return $val.float
+  of cvtVisibility: return $val.visibility
+  of cvtBoxSizing: return $val.boxSizing
+  of cvtClear: return $val.clear
+  of cvtTextTransform: return $val.textTransform
+  of cvtBgcolorIsCanvas: return $val.bgcolorIsCanvas
+  of cvtFlexDirection: return $val.flexDirection
+  of cvtFlexWrap: return $val.flexWrap
+  of cvtOverflow: return $val.overflow
+  else: assert false
 
+when defined(debug):
   func `$`*(val: CSSValue): string =
-    case val.v
-    of cvtNone: return "none"
-    of cvtColor: return $val.color
-    of cvtImage: return $val.image
-    of cvtLength: return $val.length
-    of cvtInteger: return $val.integer
-    of cvtTextDecoration: return $val.textDecoration
-    of cvtVerticalAlign: return $val.verticalAlign
-    of cvtLength2: return $val.length2.a & " " & $val.length2.b
-    of cvtContent: return $val.content
-    of cvtQuotes: return $val.quotes
-    of cvtCounterReset: return $val.counterReset
-    of cvtNumber: return $val.number
-    else: assert false
+    return val.serialize()
 
 macro `{}`*(vals: CSSValues; s: static string): untyped =
   let t = propertyType(s)
diff --git a/src/html/dom.nim b/src/html/dom.nim
index 759191a8..61b406b4 100644
--- a/src/html/dom.nim
+++ b/src/html/dom.nim
@@ -260,10 +260,13 @@ type
     attrs*: seq[AttrData] # sorted by int(qualifiedName)
     cachedAttributes: NamedNodeMap
     cachedStyle*: CSSStyleDeclaration
+    cachedComputedStyle*: CSSStyleDeclaration
+    computed*: CSSValues
 
   AttrDummyElement = ref object of Element
 
   CSSStyleDeclaration* = ref object
+    computed: bool
     decls*: seq[CSSDeclaration]
     element: Element
 
@@ -3300,7 +3303,10 @@ func find(this: CSSStyleDeclaration; s: string): int =
 
 proc getPropertyValue(this: CSSStyleDeclaration; s: string): string {.jsfunc.} =
   if (let i = this.find(s); i != -1):
-    return $this.decls[i].value
+    var s = ""
+    for it in this.decls[i].value:
+      s &= $it
+    return move(s)
   return ""
 
 # https://drafts.csswg.org/cssom/#idl-attribute-to-css-property
@@ -3347,7 +3353,10 @@ proc setValue(this: CSSStyleDeclaration; i: int; cvals: seq[CSSComponentValue]):
   return ok()
 
 proc setter(ctx: JSContext; this: CSSStyleDeclaration; atom: JSAtom;
-    value: string): Opt[void] {.jssetprop.} =
+    value: string): DOMResult[void] {.jssetprop.} =
+  if this.computed:
+    return errDOMException("Cannot modify computed value",
+      "NoModificationAllowedError")
   let cvals = parseComponentValues(value)
   var u: uint32
   if ctx.fromJS(atom, u).isSome:
@@ -3374,6 +3383,21 @@ proc style*(element: Element): CSSStyleDeclaration {.jsfget.} =
     element.cachedStyle = CSSStyleDeclaration(element: element)
   return element.cachedStyle
 
+proc getComputedStyle*(element: Element): CSSStyleDeclaration =
+  if element.cachedComputedStyle == nil:
+    var s = ""
+    for p in CSSPropertyType:
+      if p != cptNone:
+        s &= $p & ':'
+        if p.isBit:
+          s &= element.computed.bits[p].serialize(valueType(p))
+        else:
+          s &= element.computed.objs[p].serialize()
+        s &= ';'
+    element.cachedComputedStyle = newCSSStyleDeclaration(element, move(s))
+    element.cachedComputedStyle.computed = true
+  return element.cachedComputedStyle
+
 proc corsFetch(window: Window; input: Request): FetchPromise =
   if not window.images and input.url.scheme.startsWith("img-codec+"):
     return newResolvedPromise(JSResult[Response].err(newFetchTypeError()))
diff --git a/src/html/env.nim b/src/html/env.nim
index 588aa897..91e82f30 100644
--- a/src/html/env.nim
+++ b/src/html/env.nim
@@ -283,9 +283,11 @@ callback(new Event("").timeStamp);
   return ctx.toJS(window.setTimeout(handler, 0, callback))
 
 proc getComputedStyle(window: Window; element: Element;
-    pseudoElt = none(string)): JSResult[CSSStyleDeclaration] {.jsfunc.} =
-  #TODO implement this properly
-  return ok(element.style)
+    pseudoElt = none(string)): CSSStyleDeclaration {.jsfunc.} =
+  if window.settings.scripting == smApp:
+    return element.getComputedStyle()
+  # Maybe it works.
+  return element.style
 
 proc postMessage(window: Window) {.jsfunc.} =
   window.console.log("postMessage: Stub")
diff --git a/src/types/color.nim b/src/types/color.nim
index f78b3e28..7f49aa74 100644
--- a/src/types/color.nim
+++ b/src/types/color.nim
@@ -287,8 +287,13 @@ func serialize*(color: ARGBColor): string =
   return "rgba(" & $color.r & ", " & $color.g & ", " & $color.b & ", " & $a &
     ")"
 
-func `$`*(argbcolor: ARGBColor): string =
-  return argbcolor.serialize()
+func `$`*(c: ARGBColor): string =
+  return c.serialize()
+
+func `$`*(c: CSSColor): string =
+  if c.isCell:
+    return "-cha-ansi(" & $c.n & ")"
+  return c.argb().serialize()
 
 # Divide each component by 255, multiply them by n, and discard the fractions.
 # See https://arxiv.org/pdf/2202.02864.pdf for details.