diff --git a/docs/cstyle/plugins/index.html b/docs/cstyle/plugins/index.html
index 83c462b..414cfe5 100644
--- a/docs/cstyle/plugins/index.html
+++ b/docs/cstyle/plugins/index.html
@@ -265 +265 @@ v.Handler(n)
-142func (c*CSS) ComputeNodeStyle(n*element.Node, state*map[string]element.State) *element.Node {
+142func (c*CSS) ComputeNodeStyle(node*element.Node, state*map[string]element.State) *element.Node {
@@ -268,2 +268,2 @@ v.Handler(n)
-145ifutils.IsParent(*n, "head") {
-146returnn
+145ifutils.IsParent(*node, "head") {
+146returnnode
@@ -277,21 +277,21 @@ v.Handler(n)
-154self:=s[n.Properties.Id]
-155parent:=s[n.Parent.Properties.Id]
-156self.Style = c.GetStyles(*n)
-157
-158self.Background = color.Parse(self.Style, "background")
-159self.Border, _ = CompleteBorder(self.Style, self, parent)
-160
-161fs, _:=utils.ConvertToPixels(self.Style["font-size"], parent.EM, parent.Width)
-162self.EM = fs
-163
-164ifself.Style["display"] =="none" {
-165self.X = 0
-166self.Y = 0
-167self.Width = 0
-168self.Height = 0
-169returnn
-170 }
-171
-172ifself.Style["width"] ==""&&self.Style["display"] =="block" {
-173self.Style["width"] = "100%"
-174 }
+154self:=s[node.Properties.Id]
+155parent:=s[node.Parent.Properties.Id]
+156
+157varn*element.Node
+158
+159// !ISSUE: For some reason node is still being tainted
+160// + if the user changes the innerText of the swap parent then how does the swap get updated????
+161// + in theory it should be invalided when the main invalidator runs
+162ifself.Swap.Properties.Id!="" {
+163n = &self.Swap
+164// fmt.Println("Swapped: ", n.Properties.Id, n.InnerText)
+165// CheckNode(node, state)
+166// CheckNode(&self.Swap, state)
+167 } else {
+168n = node
+169// fmt.Println("Back: ", n.Properties.Id, n.InnerText)
+170self.Style = c.GetStyles(*n)
+171 }
+172
+173self.Background = color.Parse(self.Style, "background")
+174self.Border, _ = CompleteBorder(self.Style, self, parent)
@@ -299,26 +299,26 @@ v.Handler(n)
-176// Set Z index value to be sorted in window
-177ifself.Style["z-index"] !="" {
-178z, _:=strconv.Atoi(self.Style["z-index"])
-179self.Z = float32(z)
-180 }
-181
-182ifparent.Z > 0 {
-183self.Z = parent.Z+1
-184 }
-185
-186 (*state)[n.Properties.Id] = self
-187
-188wh:=utils.GetWH(*n, state)
-189width:=wh.Width
-190height:=wh.Height
-191
-192x, y:=parent.X, parent.Y
-193// !NOTE: Would like to consolidate all XY function into this function like WH
-194offsetX, offsetY:=utils.GetXY(n, state)
-195x+=offsetX
-196y+=offsetY
-197
-198vartop, left, right, bottombool = false, false, false, false
-199
-200m:=utils.GetMP(*n, wh, state, "margin")
-201p:=utils.GetMP(*n, wh, state, "padding")
+176fs, _:=utils.ConvertToPixels(self.Style["font-size"], parent.EM, parent.Width)
+177self.EM = fs
+178
+179ifself.Style["display"] =="none" {
+180self.X = 0
+181self.Y = 0
+182self.Width = 0
+183self.Height = 0
+184returnn
+185 }
+186
+187ifself.Style["width"] ==""&&self.Style["display"] =="block" {
+188self.Style["width"] = "100%"
+189 }
+190
+191// Set Z index value to be sorted in window
+192ifself.Style["z-index"] !="" {
+193z, _:=strconv.Atoi(self.Style["z-index"])
+194self.Z = float32(z)
+195 }
+196
+197ifparent.Z > 0 {
+198self.Z = parent.Z+1
+199 }
+200
+201 (*state)[n.Properties.Id] = self
@@ -326,25 +326,25 @@ v.Handler(n)
-203self.Margin = m
-204self.Padding = p
-205
-206ifself.Style["position"] =="absolute" {
-207bas:=utils.GetPositionOffsetNode(n, state)
-208base:=s[bas.Properties.Id]
-209ifself.Style["top"] !="" {
-210v, _:=utils.ConvertToPixels(self.Style["top"], self.EM, parent.Width)
-211y = v+base.Y
-212top = true
-213 }
-214ifself.Style["left"] !="" {
-215v, _:=utils.ConvertToPixels(self.Style["left"], self.EM, parent.Width)
-216x = v+base.X
-217left = true
-218 }
-219ifself.Style["right"] !="" {
-220v, _:=utils.ConvertToPixels(self.Style["right"], self.EM, parent.Width)
-221x = (base.Width-width) -v
-222right = true
-223 }
-224ifself.Style["bottom"] !="" {
-225v, _:=utils.ConvertToPixels(self.Style["bottom"], self.EM, parent.Width)
-226y = (base.Height-height) -v
-227bottom = true
+203wh:=utils.GetWH(*n, state)
+204width:=wh.Width
+205height:=wh.Height
+206
+207x, y:=parent.X, parent.Y
+208// !NOTE: Would like to consolidate all XY function into this function like WH
+209offsetX, offsetY:=utils.GetXY(n, state)
+210x+=offsetX
+211y+=offsetY
+212
+213vartop, left, right, bottombool = false, false, false, false
+214
+215m:=utils.GetMP(*n, wh, state, "margin")
+216p:=utils.GetMP(*n, wh, state, "padding")
+217
+218self.Margin = m
+219self.Padding = p
+220
+221ifself.Style["position"] =="absolute" {
+222bas:=utils.GetPositionOffsetNode(n, state)
+223base:=s[bas.Properties.Id]
+224ifself.Style["top"] !="" {
+225v, _:=utils.ConvertToPixels(self.Style["top"], self.EM, parent.Width)
+226y = v+base.Y
+227top = true
@@ -352,122 +352,122 @@ v.Handler(n)
-229
-230 } else {
-231fori, v:=rangen.Parent.Children {
-232vState:=s[v.Properties.Id]
-233ifvState.Style["position"] !="absolute" {
-234ifv.Properties.Id==n.Properties.Id {
-235ifi-1 > 0 {
-236sib:=n.Parent.Children[i-1]
-237sibling:=s[sib.Properties.Id]
-238ifsibling.Style["position"] !="absolute" {
-239ifself.Style["display"] =="inline" {
-240ifsibling.Style["display"] =="inline" {
-241y = sibling.Y
-242 } else {
-243y = sibling.Y+sibling.Height
-244 }
-245 } else {
-246y = sibling.Y+sibling.Height+ (sibling.Border.Width*2) +sibling.Margin.Bottom
-247 }
-248 }
-249
-250 }
-251break
-252 } elseifself.Style["display"] !="inline" {
-253vState:=s[v.Properties.Id]
-254y+=vState.Margin.Top+vState.Margin.Bottom+vState.Padding.Top+vState.Padding.Bottom+vState.Height+ (self.Border.Width)
-255 }
-256 }
-257 }
-258 }
-259
-260// Display modes need to be calculated here
-261
-262relPos:= !top&& !left&& !right&& !bottom
-263
-264ifleft||relPos {
-265x+=m.Left
-266 }
-267iftop||relPos {
-268y+=m.Top
-269 }
-270ifright {
-271x-=m.Right
-272 }
-273ifbottom {
-274y-=m.Bottom
-275 }
-276
-277self.X = x
-278self.Y = y
-279self.Width = width
-280self.Height = height
-281 (*state)[n.Properties.Id] = self
-282
-283if !utils.ChildrenHaveText(n) && len(n.InnerText) > 0 {
-284// Confirm text exists
-285words:=strings.Split(strings.TrimSpace(n.InnerText), " ")
-286if len(words) !=1 {
-287ifself.Style["display"] =="inline" {
-288n.InnerText = words[0]
-289n.Style["inlineText"] = "true"
-290el:=*n
-291el.InnerText = strings.Join(words[1:], " ")
-292n.Parent.InsertAfter(el, *n)
-293 } else {
-294el:=n.CreateElement("notaspan")
-295el.InnerText = n.InnerText
-296n.AppendChild(el)
-297self.Style["font-size"] = parent.Style["font-size"]
-298self.EM = parent.EM
-299n.InnerText = ""
-300 }
-301 (*state)[n.Properties.Id] = self
-302 }
-303if len(strings.TrimSpace(n.InnerText)) > 0 {
-304n.InnerText = strings.TrimSpace(n.InnerText)
-305self = genTextNode(n, state)
-306 }
-307 }
-308
-309 (*state)[n.Properties.Id] = self
-310 (*state)[n.Parent.Properties.Id] = parent
-311
-312// Call children here
-313
-314varchildYOffsetfloat32
-315fori:=0; i < len(n.Children); i++ {
-316v:=n.Children[i]
-317v.Parent = n
-318// This is were the tainting comes from
-319n.Children[i] = *c.ComputeNodeStyle(&v, state)
-320
-321cState:= (*state)[n.Children[i].Properties.Id]
-322ifself.Style["height"] =="" {
-323ifcState.Style["position"] !="absolute"&&cState.Y+cState.Height > childYOffset {
-324childYOffset = cState.Y+cState.Height
-325self.Height = (cState.Y-self.Border.Width) - (self.Y) +cState.Height
-326self.Height+=cState.Margin.Top
-327self.Height+=cState.Margin.Bottom
-328self.Height+=cState.Padding.Top
-329self.Height+=cState.Padding.Bottom
-330 }
-331 }
-332ifcState.Width > self.Width {
-333self.Width = cState.Width
-334 }
-335 }
-336
-337self.Height+=self.Padding.Bottom
-338
-339 (*state)[n.Properties.Id] = self
-340
-341// Sorting the array by the Level field
-342sort.Slice(plugins, func(i, jint) bool {
-343returnplugins[i].Level < plugins[j].Level
-344 })
-345
-346for_, v:=rangeplugins {
-347matches:=true
-348forname, value:=rangev.Styles {
-349ifself.Style[name] !=value&& !(value=="*") &&self.Style[name] !="" {
-350matches = false
+229ifself.Style["left"] !="" {
+230v, _:=utils.ConvertToPixels(self.Style["left"], self.EM, parent.Width)
+231x = v+base.X
+232left = true
+233 }
+234ifself.Style["right"] !="" {
+235v, _:=utils.ConvertToPixels(self.Style["right"], self.EM, parent.Width)
+236x = (base.Width-width) -v
+237right = true
+238 }
+239ifself.Style["bottom"] !="" {
+240v, _:=utils.ConvertToPixels(self.Style["bottom"], self.EM, parent.Width)
+241y = (base.Height-height) -v
+242bottom = true
+243 }
+244
+245 } else {
+246fori, v:=rangen.Parent.Children {
+247vState:=s[v.Properties.Id]
+248ifvState.Style["position"] !="absolute" {
+249ifv.Properties.Id==n.Properties.Id {
+250ifi-1 > 0 {
+251sib:=n.Parent.Children[i-1]
+252sibling:=s[sib.Properties.Id]
+253ifsibling.Style["position"] !="absolute" {
+254ifself.Style["display"] =="inline" {
+255ifsibling.Style["display"] =="inline" {
+256y = sibling.Y
+257 } else {
+258y = sibling.Y+sibling.Height
+259 }
+260 } else {
+261y = sibling.Y+sibling.Height+ (sibling.Border.Width*2) +sibling.Margin.Bottom
+262 }
+263 }
+264
+265 }
+266break
+267 } elseifself.Style["display"] !="inline" {
+268vState:=s[v.Properties.Id]
+269y+=vState.Margin.Top+vState.Margin.Bottom+vState.Padding.Top+vState.Padding.Bottom+vState.Height+ (self.Border.Width)
+270 }
+271 }
+272 }
+273 }
+274
+275// Display modes need to be calculated here
+276
+277relPos:= !top&& !left&& !right&& !bottom
+278
+279ifleft||relPos {
+280x+=m.Left
+281 }
+282iftop||relPos {
+283y+=m.Top
+284 }
+285ifright {
+286x-=m.Right
+287 }
+288ifbottom {
+289y-=m.Bottom
+290 }
+291
+292self.X = x
+293self.Y = y
+294self.Width = width
+295self.Height = height
+296 (*state)[n.Properties.Id] = self
+297
+298if !utils.ChildrenHaveText(n) && len(n.InnerText) > 0 {
+299// Confirm text exists
+300words:=strings.Split(strings.TrimSpace(n.InnerText), " ")
+301if len(words) !=1 {
+302// !ISSUE: Still doesn't work great
+303ifself.Swap.Properties.Id=="" {
+304self.Swap = *n
+305n = &self.Swap
+306n.Style["inlineText"] = "true"
+307 }
+308ifself.Style["display"] =="inline" {
+309n.InnerText = words[0]
+310n.Style["inlineText"] = "true"
+311el:=*n
+312el.InnerText = strings.Join(words[1:], " ")
+313n.Parent.InsertAfter(el, *n)
+314 } else {
+315el:=n.CreateElement("notaspan")
+316el.InnerText = n.InnerText
+317n.AppendChild(el)
+318self.Style["font-size"] = parent.Style["font-size"]
+319self.EM = parent.EM
+320n.InnerText = ""
+321 }
+322 (*state)[n.Properties.Id] = self
+323 }
+324if len(strings.TrimSpace(n.InnerText)) > 0 {
+325n.InnerText = strings.TrimSpace(n.InnerText)
+326self = genTextNode(n, state)
+327 }
+328 }
+329
+330 (*state)[n.Properties.Id] = self
+331 (*state)[n.Parent.Properties.Id] = parent
+332
+333// Call children here
+334
+335varchildYOffsetfloat32
+336fori:=0; i < len(n.Children); i++ {
+337v:=n.Children[i]
+338v.Parent = n
+339// This is were the tainting comes from
+340n.Children[i] = *c.ComputeNodeStyle(&v, state)
+341
+342cState:= (*state)[n.Children[i].Properties.Id]
+343ifself.Style["height"] =="" {
+344ifcState.Style["position"] !="absolute"&&cState.Y+cState.Height > childYOffset {
+345childYOffset = cState.Y+cState.Height
+346self.Height = (cState.Y-self.Border.Width) - (self.Y) +cState.Height
+347self.Height+=cState.Margin.Top
+348self.Height+=cState.Margin.Bottom
+349self.Height+=cState.Padding.Top
+350self.Height+=cState.Padding.Bottom
@@ -476,129 +476,129 @@ v.Handler(n)
-353ifmatches {
-354// !NOTE: Might save memory by making a state map tree and passing that instead of the node it's self
-355v.Handler(n, state)
-356 }
-357 }
-358
-359// n.InnerHTML = utils.InnerHTML(*n)
-360// tag, closing := utils.NodeToHTML(*n)
-361// n.OuterHTML = tag + n.InnerHTML + closing
-362
-363returnn
-364}
-365
-366funcCompleteBorder(cssPropertiesmap[string]string, self, parentelement.State) (element.Border, error) {
-367// Split the shorthand into components
-368borderComponents:=strings.Fields(cssProperties["border"])
-369
-370// Ensure there are at least 1 component (width or style or color)
-371if len(borderComponents) >=1 {
-372width:="0px"// Default width
-373style:="solid"
-374borderColor:="#000000"// Default color
-375
-376// Extract style and color if available
-377if len(borderComponents) >=1 {
-378width = borderComponents[0]
-379 }
-380
-381// Extract style and color if available
-382if len(borderComponents) >=2 {
-383style = borderComponents[1]
-384 }
-385if len(borderComponents) >=3 {
-386borderColor = borderComponents[2]
-387 }
-388
-389parsedColor, _:=color.Color(borderColor)
-390
-391w, _:=utils.ConvertToPixels(width, self.EM, parent.Width)
-392
-393returnelement.Border{
-394Width: w,
-395Style: style,
-396Color: parsedColor,
-397Radius: cssProperties["border-radius"],
-398 }, nil
-399 }
-400
-401returnelement.Border{}, fmt.Errorf("invalid border shorthand format")
-402}
-403
-404funcgenTextNode(n*element.Node, state*map[string]element.State) element.State {
-405s:=*state
-406self:=s[n.Properties.Id]
-407parent:=s[n.Parent.Properties.Id]
-408
-409text:=element.Text{}
-410
-411bold, italic:=false, false
-412
-413ifself.Style["font-weight"] =="bold" {
-414bold = true
-415 }
-416
-417ifself.Style["font-style"] =="italic" {
-418italic = true
-419 }
-420
-421iftext.Font==nil {
-422f, _:=font.LoadFont(self.Style["font-family"], int(self.EM), bold, italic)
-423text.Font = f
-424 }
-425
-426letterSpacing, _:=utils.ConvertToPixels(self.Style["letter-spacing"], self.EM, parent.Width)
-427wordSpacing, _:=utils.ConvertToPixels(self.Style["word-spacing"], self.EM, parent.Width)
-428lineHeight, _:=utils.ConvertToPixels(self.Style["line-height"], self.EM, parent.Width)
-429iflineHeight==0 {
-430lineHeight = self.EM+3
-431 }
-432
-433text.LineHeight = int(lineHeight)
-434text.WordSpacing = int(wordSpacing)
-435text.LetterSpacing = int(letterSpacing)
-436wb:=" "
-437
-438ifself.Style["word-wrap"] =="break-word" {
-439wb = ""
-440 }
-441
-442ifself.Style["text-wrap"] =="wrap"||self.Style["text-wrap"] =="balance" {
-443wb = ""
-444 }
-445
-446vardtfloat32
-447
-448ifself.Style["text-decoration-thickness"] =="auto"||self.Style["text-decoration-thickness"] =="" {
-449dt = self.EM/7
-450 } else {
-451dt, _ = utils.ConvertToPixels(self.Style["text-decoration-thickness"], self.EM, parent.Width)
-452 }
-453
-454col:=color.Parse(self.Style, "font")
-455
-456self.Color = col
-457
-458text.Color = col
-459text.DecorationColor = color.Parse(self.Style, "decoration")
-460text.Align = self.Style["text-align"]
-461text.WordBreak = wb
-462text.WordSpacing = int(wordSpacing)
-463text.LetterSpacing = int(letterSpacing)
-464text.WhiteSpace = self.Style["white-space"]
-465text.DecorationThickness = int(dt)
-466text.Overlined = self.Style["text-decoration"] =="overline"
-467text.Underlined = self.Style["text-decoration"] =="underline"
-468text.LineThrough = self.Style["text-decoration"] =="linethrough"
-469text.EM = int(self.EM)
-470text.Width = int(parent.Width)
-471text.Text = n.InnerText
-472
-473ifself.Style["word-spacing"] =="" {
-474text.WordSpacing = font.MeasureSpace(&text)
-475 }
-476
-477img, width:=font.Render(&text)
-478self.Texture = img
-479
-480ifself.Style["height"] =="" {
-481self.Height = float32(text.LineHeight)
+353ifcState.Width > self.Width {
+354self.Width = cState.Width
+355 }
+356 }
+357
+358self.Height+=self.Padding.Bottom
+359
+360 (*state)[n.Properties.Id] = self
+361
+362// Sorting the array by the Level field
+363sort.Slice(plugins, func(i, jint) bool {
+364returnplugins[i].Level < plugins[j].Level
+365 })
+366
+367for_, v:=rangeplugins {
+368matches:=true
+369forname, value:=rangev.Styles {
+370ifself.Style[name] !=value&& !(value=="*") &&self.Style[name] !="" {
+371matches = false
+372 }
+373 }
+374ifmatches {
+375// !NOTE: Might save memory by making a state map tree and passing that instead of the node it's self
+376v.Handler(n, state)
+377 }
+378 }
+379
+380// !IMPORTAINT: Tomorrow the way textt should work is all free standing text should be in text elements, then the words should be notaspan
+381// + so in theory the inner/outerhtml methods can clean those and after the notspans are rendered (I don't know if removing them will do the same)
+382// + (thing as below) but the text should be a text element so it shows childNodes bc just children is repetitive
+383// n.InnerHTML = utils.InnerHTML(*n)
+384// tag, closing := utils.NodeToHTML(*n)
+385// n.OuterHTML = tag + n.InnerHTML + closing
+386
+387// !NOTE: I think that .Children can just act like .childNodes but the text needs to be joined into one "text" node for each line
+388// + So it is ok to modifey the DOM but only to make text nodes and do the innerHTML
+389// + also I think innerHTML should be the main source of truth, but if innerHTML == "" then generate the html and if it changes update the node
+390// + but if the DOM under it changes then you would need to update it aswell
+391
+392CheckNode(n, state)
+393// toRemove := make([]int, 0)
+394// for i := len(n.Children) - 1; i >= 1; i-- {
+395// v := n.Children[i]
+396// next := n.Children[i-1]
+397// if v.TagName == next.TagName {
+398// matches := true
+399// for k, t := range v.Style {
+400// if next.Style[k] != t {
+401// matches = false
+402// }
+403// }
+404// if matches {
+405// // fmt.Println(n.Properties.Id)
+406// n.Children[i-1].InnerText = n.Children[i-1].InnerText + " " + v.InnerText
+407
+408// toRemove = append(toRemove, i)
+409// }
+410// }
+411// }
+412// for _, index := range toRemove {
+413// n.Children = append(n.Children[:index], n.Children[index+1:]...)
+414// }
+415// if len(toRemove) > 0 {
+416// for _, v := range n.Children {
+417// fmt.Println(v.InnerText)
+418// }
+419// }
+420
+421returnn
+422}
+423
+424funcCompleteBorder(cssPropertiesmap[string]string, self, parentelement.State) (element.Border, error) {
+425// Split the shorthand into components
+426borderComponents:=strings.Fields(cssProperties["border"])
+427
+428// Ensure there are at least 1 component (width or style or color)
+429if len(borderComponents) >=1 {
+430width:="0px"// Default width
+431style:="solid"
+432borderColor:="#000000"// Default color
+433
+434// Extract style and color if available
+435if len(borderComponents) >=1 {
+436width = borderComponents[0]
+437 }
+438
+439// Extract style and color if available
+440if len(borderComponents) >=2 {
+441style = borderComponents[1]
+442 }
+443if len(borderComponents) >=3 {
+444borderColor = borderComponents[2]
+445 }
+446
+447parsedColor, _:=color.Color(borderColor)
+448
+449w, _:=utils.ConvertToPixels(width, self.EM, parent.Width)
+450
+451returnelement.Border{
+452Width: w,
+453Style: style,
+454Color: parsedColor,
+455Radius: cssProperties["border-radius"],
+456 }, nil
+457 }
+458
+459returnelement.Border{}, fmt.Errorf("invalid border shorthand format")
+460}
+461
+462funcgenTextNode(n*element.Node, state*map[string]element.State) element.State {
+463s:=*state
+464self:=s[n.Properties.Id]
+465parent:=s[n.Parent.Properties.Id]
+466
+467text:=element.Text{}
+468
+469bold, italic:=false, false
+470
+471ifself.Style["font-weight"] =="bold" {
+472bold = true
+473 }
+474
+475ifself.Style["font-style"] =="italic" {
+476italic = true
+477 }
+478
+479iftext.Font==nil {
+480f, _:=font.LoadFont(self.Style["font-family"], int(self.EM), bold, italic)
+481text.Font = f
@@ -607,6 +607,64 @@ v.Handler(n)
-484ifself.Style["width"] =="" {
-485self.Width = float32(width)
-486 }
-487
-488returnself
-489}
+484letterSpacing, _:=utils.ConvertToPixels(self.Style["letter-spacing"], self.EM, parent.Width)
+485wordSpacing, _:=utils.ConvertToPixels(self.Style["word-spacing"], self.EM, parent.Width)
+486lineHeight, _:=utils.ConvertToPixels(self.Style["line-height"], self.EM, parent.Width)
+487iflineHeight==0 {
+488lineHeight = self.EM+3
+489 }
+490
+491text.LineHeight = int(lineHeight)
+492text.WordSpacing = int(wordSpacing)
+493text.LetterSpacing = int(letterSpacing)
+494wb:=" "
+495
+496ifself.Style["word-wrap"] =="break-word" {
+497wb = ""
+498 }
+499
+500ifself.Style["text-wrap"] =="wrap"||self.Style["text-wrap"] =="balance" {
+501wb = ""
+502 }
+503
+504vardtfloat32
+505
+506ifself.Style["text-decoration-thickness"] =="auto"||self.Style["text-decoration-thickness"] =="" {
+507dt = self.EM/7
+508 } else {
+509dt, _ = utils.ConvertToPixels(self.Style["text-decoration-thickness"], self.EM, parent.Width)
+510 }
+511
+512col:=color.Parse(self.Style, "font")
+513
+514self.Color = col
+515
+516text.Color = col
+517text.DecorationColor = color.Parse(self.Style, "decoration")
+518text.Align = self.Style["text-align"]
+519text.WordBreak = wb
+520text.WordSpacing = int(wordSpacing)
+521text.LetterSpacing = int(letterSpacing)
+522text.WhiteSpace = self.Style["white-space"]
+523text.DecorationThickness = int(dt)
+524text.Overlined = self.Style["text-decoration"] =="overline"
+525text.Underlined = self.Style["text-decoration"] =="underline"
+526text.LineThrough = self.Style["text-decoration"] =="linethrough"
+527text.EM = int(self.EM)
+528text.Width = int(parent.Width)
+529text.Text = n.InnerText
+530
+531ifself.Style["word-spacing"] =="" {
+532text.WordSpacing = font.MeasureSpace(&text)
+533 }
+534
+535img, width:=font.Render(&text)
+536self.Texture = img
+537
+538ifself.Style["height"] =="" {
+539self.Height = float32(text.LineHeight)
+540 }
+541
+542ifself.Style["width"] =="" {
+543self.Width = float32(width)
+544 }
+545
+546returnself
+547}
GRIM UI
CStyle Plugins
Plugins add the ability to choose what parts of the HTML/CSS spec you add to your application. If you are trying to keep compile sizes small you can remove as many as you need to reach your target size. Here we will go over the basics of how they work and how to use them.
The first step in processing the plugins before running there handler functions is to sort them by their levels. We need to sort the plugins by their level because in the example of flex, it relys on a parent element being block position so it can compute styles based of the positioning of its parent elements. If flex was ran before block then it would have nothing to build apon. This is also the reason that if you are building a custom plugin it is reccomended to keep the level above 2 as anything after 2 will have the assumed styles to build apon.
// Sorting the array by the Level field
sort.Slice(plugins, func(i, j int) bool {
return plugins[i].Level < plugins[j].Level
})
After we have the sorted plugins we can check if the current element matches the Styles of the plugin. The matching is a all of nothing matching system, if one property is missing then the plugin wil not be ran. If it does match then a pointer to the element.Node (n) is passed to the handler.
for _, v := range plugins {
matches := true
for name, value := range v.Styles {
if styleMap[name] != value && !(value == "*") {
matches = false
}
}
if matches {
v.Handler(n)
}
}