mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 09:00:22 +00:00
Last: LibWeb: Add counter() and counters() functions to content property
These let you format counters' current values as strings for use in generated content.
This commit is contained in:
parent
576a431408
commit
898e3bd898
Notes:
github-actions[bot]
2024-07-26 10:05:28 +00:00
Author: https://github.com/AtkinsSJ Commit: https://github.com/LadybirdBrowser/ladybird/commit/898e3bd8987 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/720 Reviewed-by: https://github.com/tcl3
8 changed files with 553 additions and 6 deletions
134
Tests/LibWeb/Layout/expected/css-counters/basic.txt
Normal file
134
Tests/LibWeb/Layout/expected/css-counters/basic.txt
Normal file
|
@ -0,0 +1,134 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,16) content-size 784x314 children: not-inline
|
||||
BlockContainer <div> at (8,16) content-size 784x149 children: not-inline
|
||||
BlockContainer <p> at (8,16) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [37,16 44.75x17] baseline: 13.296875
|
||||
"Never"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,16 28.8125x17] baseline: 13.296875
|
||||
"1.1: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,49) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [39,49 52.15625x17] baseline: 13.296875
|
||||
"Gonna"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,49 31.28125x17] baseline: 13.296875
|
||||
"1.2: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,82) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 4, rect: [40,82 34.71875x17] baseline: 13.296875
|
||||
"Give"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,82 31.5625x17] baseline: 13.296875
|
||||
"1.3: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,115) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [38,115 31.21875x17] baseline: 13.296875
|
||||
"You"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,115 30.21875x17] baseline: 13.296875
|
||||
"1.4: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,148) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 2, rect: [39,148 20.71875x17] baseline: 13.296875
|
||||
"Up"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,148 30.921875x17] baseline: 13.296875
|
||||
"1.5: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div> at (8,181) content-size 784x149 children: not-inline
|
||||
BlockContainer <p> at (8,181) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [39,181 44.75x17] baseline: 13.296875
|
||||
"Never"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,181 31.28125x17] baseline: 13.296875
|
||||
"2.1: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,214) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [42,214 52.15625x17] baseline: 13.296875
|
||||
"Gonna"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,214 33.75x17] baseline: 13.296875
|
||||
"2.2: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,247) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [42,247 26.4375x17] baseline: 13.296875
|
||||
"Let"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,247 34.03125x17] baseline: 13.296875
|
||||
"2.3: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,280) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [41,280 31.21875x17] baseline: 13.296875
|
||||
"You"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,280 32.6875x17] baseline: 13.296875
|
||||
"2.4: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <p> at (8,313) content-size 784x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 4, rect: [41,313 42.328125x17] baseline: 13.296875
|
||||
"Down"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [8,313 33.390625x17] baseline: 13.296875
|
||||
"2.5: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,346) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
|
||||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,16 784x314] overflow: [8,16 784x330]
|
||||
PaintableWithLines (BlockContainer<DIV>) [8,16 784x149]
|
||||
PaintableWithLines (BlockContainer<P>) [8,16 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,49 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,82 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,115 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,148 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>) [8,181 784x149]
|
||||
PaintableWithLines (BlockContainer<P>) [8,181 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,214 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,247 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,280 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<P>) [8,313 784x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,346 784x0]
|
254
Tests/LibWeb/Layout/expected/css-counters/counters-function.txt
Normal file
254
Tests/LibWeb/Layout/expected/css-counters/counters-function.txt
Normal file
|
@ -0,0 +1,254 @@
|
|||
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||
BlockContainer <body> at (8,8) content-size 784x255 children: not-inline
|
||||
BlockContainer <div.ol> at (24,8) content-size 768x255 children: not-inline
|
||||
BlockContainer <(anonymous)> at (24,8) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,8) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [42,8 14.265625x17] baseline: 13.296875
|
||||
"A"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,8 18.125x17] baseline: 13.296875
|
||||
"1: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,25) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,25) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [45,25 9.34375x17] baseline: 13.296875
|
||||
"B"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,25 20.59375x17] baseline: 13.296875
|
||||
"2: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,42) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,42) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [45,42 10.3125x17] baseline: 13.296875
|
||||
"C"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,42 20.875x17] baseline: 13.296875
|
||||
"3: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,59) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,59) content-size 768x153 children: not-inline
|
||||
BlockContainer <(anonymous)> at (24,59) content-size 768x17 children: inline
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 2, rect: [24,59 11.53125x17] baseline: 13.296875
|
||||
"4:"
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div.ol> at (40,76) content-size 752x136 children: not-inline
|
||||
BlockContainer <(anonymous)> at (40,76) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (40,76) content-size 752x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [70,76 11.140625x17] baseline: 13.296875
|
||||
"D"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [40,76 30.21875x17] baseline: 13.296875
|
||||
"4.1: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,93) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (40,93) content-size 752x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [73,93 11.859375x17] baseline: 13.296875
|
||||
"E"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [40,93 32.6875x17] baseline: 13.296875
|
||||
"4.2: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,110) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (40,110) content-size 752x68 children: not-inline
|
||||
BlockContainer <(anonymous)> at (40,110) content-size 752x17 children: inline
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 4, rect: [40,110 24.96875x17] baseline: 13.296875
|
||||
"4.3:"
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <div.ol> at (56,127) content-size 736x51 children: not-inline
|
||||
BlockContainer <(anonymous)> at (56,127) content-size 736x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (56,127) content-size 736x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [100,127 12.546875x17] baseline: 13.296875
|
||||
"F"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 7, rect: [56,127 43.65625x17] baseline: 13.296875
|
||||
"4.3.1: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (56,144) content-size 736x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (56,144) content-size 736x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [102,144 13.234375x17] baseline: 13.296875
|
||||
"G"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 7, rect: [56,144 46.125x17] baseline: 13.296875
|
||||
"4.3.2: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (56,161) content-size 736x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (56,161) content-size 736x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [102,161 12.234375x17] baseline: 13.296875
|
||||
"H"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 7, rect: [56,161 46.40625x17] baseline: 13.296875
|
||||
"4.3.3: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (56,178) content-size 736x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,178) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,178) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (40,178) content-size 752x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [72,178 4.59375x17] baseline: 13.296875
|
||||
"I"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [40,178 31.625x17] baseline: 13.296875
|
||||
"4.4: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,195) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (40,195) content-size 752x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [72,195 8.90625x17] baseline: 13.296875
|
||||
"J"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 5, rect: [40,195 32.328125x17] baseline: 13.296875
|
||||
"4.5: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (40,212) content-size 752x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,212) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,212) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,212) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [44,212 9.8125x17] baseline: 13.296875
|
||||
"K"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,212 20.234375x17] baseline: 13.296875
|
||||
"5: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,229) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,229) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [45,229 10.859375x17] baseline: 13.296875
|
||||
"L"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,229 20.515625x17] baseline: 13.296875
|
||||
"6: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,246) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <div.li> at (24,246) content-size 768x17 children: inline
|
||||
frag 0 from TextNode start: 0, length: 1, rect: [45,246 11.765625x17] baseline: 13.296875
|
||||
"M"
|
||||
InlineNode <(anonymous)>
|
||||
frag 0 from TextNode start: 0, length: 3, rect: [24,246 20.5x17] baseline: 13.296875
|
||||
"7: "
|
||||
TextNode <#text>
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (24,263) content-size 768x0 children: inline
|
||||
TextNode <#text>
|
||||
BlockContainer <(anonymous)> at (8,263) content-size 784x0 children: inline
|
||||
TextNode <#text>
|
||||
|
||||
ViewportPaintable (Viewport<#document>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<HTML>) [0,0 800x600]
|
||||
PaintableWithLines (BlockContainer<BODY>) [8,8 784x255]
|
||||
PaintableWithLines (BlockContainer<DIV>.ol) [8,8 784x255]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,8 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,8 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,25 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,25 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,42 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,42 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,59 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,59 768x153]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,59 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.ol) [24,76 768x136]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,76 752x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [40,76 752x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,93 752x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [40,93 752x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,110 752x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [40,110 752x68]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,110 752x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer<DIV>.ol) [40,127 752x51]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [56,127 736x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [56,127 736x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [56,144 736x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [56,144 736x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [56,161 736x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [56,161 736x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [56,178 736x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,178 752x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,178 752x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [40,178 752x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,195 752x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [40,195 752x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [40,212 752x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,212 768x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,212 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,212 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,229 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,229 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,246 768x0]
|
||||
PaintableWithLines (BlockContainer<DIV>.li) [24,246 768x17]
|
||||
InlinePaintable (InlineNode(anonymous))
|
||||
TextPaintable (TextNode<#text>)
|
||||
TextPaintable (TextNode<#text>)
|
||||
PaintableWithLines (BlockContainer(anonymous)) [24,263 768x0]
|
||||
PaintableWithLines (BlockContainer(anonymous)) [8,263 784x0]
|
12
Tests/LibWeb/Layout/input/css-counters/basic.html
Normal file
12
Tests/LibWeb/Layout/input/css-counters/basic.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<style>
|
||||
div {
|
||||
counter-increment: line;
|
||||
counter-reset: word;
|
||||
}
|
||||
p {
|
||||
counter-increment: word;
|
||||
}
|
||||
p::before {
|
||||
content: counter(line) "." counter(word) ": ";
|
||||
}
|
||||
</style><div><p>Never<p>Gonna<p>Give<p>You<p>Up</div><div><p>Never<p>Gonna<p>Let<p>You<p>Down</div>
|
|
@ -0,0 +1,36 @@
|
|||
<style>
|
||||
div.ol {
|
||||
counter-reset: index;
|
||||
padding-left: 1em;
|
||||
}
|
||||
div.li {
|
||||
counter-increment: index;
|
||||
}
|
||||
div.li::before {
|
||||
content: counters(index, ".") ": ";
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="ol">
|
||||
<div class="li">A</div>
|
||||
<div class="li">B</div>
|
||||
<div class="li">C</div>
|
||||
<div class="li">
|
||||
<div class="ol">
|
||||
<div class="li">D</div>
|
||||
<div class="li">E</div>
|
||||
<div class="li">
|
||||
<div class="ol">
|
||||
<div class="li">F</div>
|
||||
<div class="li">G</div>
|
||||
<div class="li">H</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="li">I</div>
|
||||
<div class="li">J</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="li">K</div>
|
||||
<div class="li">L</div>
|
||||
<div class="li">M</div>
|
||||
</div>
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
|
||||
* Copyright (c) 2021-2024, Sam Atkins <atkinssj@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -12,6 +12,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
|
||||
|
@ -647,7 +648,7 @@ Optional<CSS::Clear> StyleProperties::clear() const
|
|||
return value_id_to_clear(value->to_identifier());
|
||||
}
|
||||
|
||||
StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 initial_quote_nesting_level) const
|
||||
StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(DOM::Element& element, u32 initial_quote_nesting_level) const
|
||||
{
|
||||
auto value = property(CSS::PropertyID::Content);
|
||||
auto quotes_data = quotes();
|
||||
|
@ -710,8 +711,10 @@ StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 in
|
|||
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
|
||||
break;
|
||||
}
|
||||
} else if (item->is_counter()) {
|
||||
builder.append(item->as_counter().resolve(element));
|
||||
} else {
|
||||
// TODO: Implement counters, images, and other things.
|
||||
// TODO: Implement images, and other things.
|
||||
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
|
||||
}
|
||||
}
|
||||
|
@ -723,8 +726,10 @@ StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 in
|
|||
for (auto const& item : content_style_value.alt_text()->values()) {
|
||||
if (item->is_string()) {
|
||||
alt_text_builder.append(item->as_string().string_value());
|
||||
} else if (item->is_counter()) {
|
||||
alt_text_builder.append(item->as_counter().resolve(element));
|
||||
} else {
|
||||
// TODO: Implement counters
|
||||
dbgln("`{}` is not supported in `content` alt-text (yet?)", item->to_string());
|
||||
}
|
||||
}
|
||||
content_data.alt_text = MUST(alt_text_builder.to_string());
|
||||
|
|
|
@ -85,7 +85,7 @@ public:
|
|||
CSS::ContentData content_data;
|
||||
u32 final_quote_nesting_level { 0 };
|
||||
};
|
||||
ContentDataAndQuoteNestingLevel content(u32 initial_quote_nesting_level) const;
|
||||
ContentDataAndQuoteNestingLevel content(DOM::Element&, u32 initial_quote_nesting_level) const;
|
||||
Optional<CSS::ContentVisibility> content_visibility() const;
|
||||
Optional<CSS::Cursor> cursor() const;
|
||||
Optional<CSS::WhiteSpace> white_space() const;
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
||||
* Copyright (c) 2024, Sam Atkins <sam@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "CounterStyleValue.h"
|
||||
#include <LibWeb/CSS/Enums.h>
|
||||
#include <LibWeb/CSS/Serialize.h>
|
||||
#include <LibWeb/CSS/StyleValues/CustomIdentStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/StringStyleValue.h>
|
||||
#include <LibWeb/CSS/ValueID.h>
|
||||
#include <LibWeb/DOM/Element.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -24,6 +29,107 @@ CounterStyleValue::CounterStyleValue(CounterFunction function, FlyString counter
|
|||
|
||||
CounterStyleValue::~CounterStyleValue() = default;
|
||||
|
||||
// https://drafts.csswg.org/css-counter-styles-3/#generate-a-counter
|
||||
static String generate_a_counter_representation(StyleValue const& counter_style, i32 value)
|
||||
{
|
||||
// When asked to generate a counter representation using a particular counter style for a particular
|
||||
// counter value, follow these steps:
|
||||
// TODO: 1. If the counter style is unknown, exit this algorithm and instead generate a counter representation
|
||||
// using the decimal style and the same counter value.
|
||||
// TODO: 2. If the counter value is outside the range of the counter style, exit this algorithm and instead
|
||||
// generate a counter representation using the counter style’s fallback style and the same counter value.
|
||||
// TODO: 3. Using the counter value and the counter algorithm for the counter style, generate an initial
|
||||
// representation for the counter value.
|
||||
// If the counter value is negative and the counter style uses a negative sign, instead generate an
|
||||
// initial representation using the absolute value of the counter value.
|
||||
// TODO: 4. Prepend symbols to the representation as specified in the pad descriptor.
|
||||
// TODO: 5. If the counter value is negative and the counter style uses a negative sign, wrap the representation
|
||||
// in the counter style’s negative sign as specified in the negative descriptor.
|
||||
// TODO: 6. Return the representation.
|
||||
|
||||
// FIXME: Below is an ad-hoc implementation until we support @counter-style.
|
||||
// It's based largely on the ListItemMarkerBox code, with minimal adjustments.
|
||||
if (counter_style.is_custom_ident()) {
|
||||
auto counter_style_name = counter_style.as_custom_ident().custom_ident();
|
||||
auto identifier = value_id_from_string(counter_style_name);
|
||||
if (identifier.has_value()) {
|
||||
auto list_style_type = value_id_to_list_style_type(*identifier);
|
||||
if (list_style_type.has_value()) {
|
||||
switch (*list_style_type) {
|
||||
case ListStyleType::Square:
|
||||
return "▪"_string;
|
||||
case ListStyleType::Circle:
|
||||
return "◦"_string;
|
||||
case ListStyleType::Disc:
|
||||
return "•"_string;
|
||||
case ListStyleType::DisclosureClosed:
|
||||
return "▸"_string;
|
||||
case ListStyleType::DisclosureOpen:
|
||||
return "▾"_string;
|
||||
case ListStyleType::Decimal:
|
||||
return MUST(String::formatted("{}", value));
|
||||
case ListStyleType::DecimalLeadingZero:
|
||||
// This is weird, but in accordance to spec.
|
||||
if (value < 10)
|
||||
return MUST(String::formatted("0{}", value));
|
||||
return MUST(String::formatted("{}", value));
|
||||
case ListStyleType::LowerAlpha:
|
||||
case ListStyleType::LowerLatin:
|
||||
return MUST(String::from_byte_string(ByteString::bijective_base_from(value - 1).to_lowercase()));
|
||||
case ListStyleType::UpperAlpha:
|
||||
case ListStyleType::UpperLatin:
|
||||
return MUST(String::from_byte_string(ByteString::bijective_base_from(value - 1)));
|
||||
case ListStyleType::LowerRoman:
|
||||
return MUST(String::from_byte_string(ByteString::roman_number_from(value).to_lowercase()));
|
||||
case ListStyleType::UpperRoman:
|
||||
return MUST(String::from_byte_string(ByteString::roman_number_from(value)));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME: Handle `symbols()` function for counter_style.
|
||||
|
||||
dbgln("FIXME: Unsupported counter style '{}'", counter_style.to_string());
|
||||
return MUST(String::formatted("{}", value));
|
||||
}
|
||||
|
||||
String CounterStyleValue::resolve(DOM::Element& element) const
|
||||
{
|
||||
// "If no counter named <counter-name> exists on an element where counter() or counters() is used,
|
||||
// one is first instantiated with a starting value of 0."
|
||||
auto& counters_set = element.ensure_counters_set();
|
||||
if (!counters_set.last_counter_with_name(m_properties.counter_name).has_value())
|
||||
counters_set.instantiate_a_counter(m_properties.counter_name, element.unique_id(), false, 0);
|
||||
|
||||
// counter( <counter-name>, <counter-style>? )
|
||||
// "Represents the value of the innermost counter in the element’s CSS counters set named <counter-name>
|
||||
// using the counter style named <counter-style>."
|
||||
if (m_properties.function == CounterFunction::Counter) {
|
||||
// NOTE: This should always be present because of the handling of a missing counter above.
|
||||
auto& counter = counters_set.last_counter_with_name(m_properties.counter_name).value();
|
||||
return generate_a_counter_representation(m_properties.counter_style, counter.value.value_or(0).value());
|
||||
}
|
||||
|
||||
// counters( <counter-name>, <string>, <counter-style>? )
|
||||
// "Represents the values of all the counters in the element’s CSS counters set named <counter-name>
|
||||
// using the counter style named <counter-style>, sorted in outermost-first to innermost-last order
|
||||
// and joined by the specified <string>."
|
||||
// NOTE: The way counters sets are inherited, this should be the order they appear in the counters set.
|
||||
StringBuilder stb;
|
||||
for (auto const& counter : counters_set.counters()) {
|
||||
if (counter.name != m_properties.counter_name)
|
||||
continue;
|
||||
|
||||
auto counter_string = generate_a_counter_representation(m_properties.counter_style, counter.value.value_or(0).value());
|
||||
if (!stb.is_empty())
|
||||
stb.append(m_properties.join_string);
|
||||
stb.append(counter_string);
|
||||
}
|
||||
return stb.to_string_without_validation();
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom-1/#ref-for-typedef-counter
|
||||
String CounterStyleValue::to_string() const
|
||||
{
|
||||
|
|
|
@ -198,7 +198,7 @@ void TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::Se
|
|||
return;
|
||||
|
||||
auto initial_quote_nesting_level = m_quote_nesting_level;
|
||||
auto [pseudo_element_content, final_quote_nesting_level] = pseudo_element_style->content(initial_quote_nesting_level);
|
||||
auto [pseudo_element_content, final_quote_nesting_level] = pseudo_element_style->content(element, initial_quote_nesting_level);
|
||||
m_quote_nesting_level = final_quote_nesting_level;
|
||||
auto pseudo_element_display = pseudo_element_style->display();
|
||||
// ::before and ::after only exist if they have content. `content: normal` computes to `none` for them.
|
||||
|
|
Loading…
Reference in a new issue