home readme diff tree note docs

0commit 9f7ae2da7f08cbd42be7564b57bf21a0a8d17760
1Author: Mason Wright <mason@lakefox.net>
2Date:   Sat Nov 22 15:05:40 2025 -0700
3
4    CSS selectors pass all tests
5
6diff --git a/Makefile b/Makefile
7index 76a1577..474cc43 100755
8--- a/Makefile
9+++ b/Makefile
10@@ -1,8 +1,8 @@
11 # --- Variables ---
12-CCFLAGS = -Wall -Wextra -std=c++2b -g
13+CCFLAGS = -Wall -Wextra -std=c++2b -g -O0 -fsanitize=address,undefined -fno-omit-frame-pointer
14 CC = clang++
15 
16-.PHONY: all clean docs serve all_tests
17+.PHONY: all clean all_tests
18 
19 all: main
20 
21@@ -18,8 +18,6 @@ build/grim.o: src/grim.cc include/grim.h | build
22 build/parser.o: src/parser.cc include/parser.h | build
23 	${CC} ${CCFLAGS} -Iinclude/ -c src/parser.cc -o build/parser.o
24 
25-
26-
27 # --- Tests ---
28 
29 all_tests: build/html_node_test build/css_selector_test build/html_parser_test build/query_select_test
30@@ -50,6 +48,14 @@ build/query_select_test: tests/query_select.cc build/grim.o build/parser.o build
31 build/catch.o: ./include/catch_amalgamated.cpp ./include/catch_amalgamated.hpp | build
32 	${CC} ${CCFLAGS} -Iinclude/ -c include/catch_amalgamated.cpp -o build/catch.o
33 
34+# --- Playground ---
35+build/parseselectorparts_playground: playground/parseselectorparts.cc build/grim.o build/parser.o | build
36+	${CC} ${CCFLAGS} -Iinclude/ playground/parseselectorparts.cc build/grim.o build/parser.o -o build/parseselectorparts_playground
37+
38+build/testselector_playground: playground/testselector.cc build/grim.o build/parser.o | build
39+	${CC} ${CCFLAGS} -Iinclude/ playground/testselector.cc build/grim.o build/parser.o -o build/testselector_playground
40+
41+
42 # --- Prebuild ---
43 
44 # use to prebuild the master.css
45@@ -59,36 +65,3 @@ build/catch.o: ./include/catch_amalgamated.cpp ./include/catch_amalgamated.hpp |
46 
47 clean:
48 	rm -f main build/*.o
49-
50-MD_FILES := $(shell find docs/content -name "*.md")
51-HTML_FILES := $(MD_FILES:docs/content/%.md=docs/dist/%.html)
52-
53-docs: $(HTML_FILES)
54-	@printf "\
55-<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
56-<rss version=\"2.0\">\n\
57-  <channel>\n\
58-    <title>Grim Git Feed</title>\n\
59-    <link>https://grimui.com</link>\n\
60-    <description>A feed of recent commits.</description>\n\
61-    <language>en-us</language>\n\
62-    <pubDate>" > docs/dist/rss.xml
63-	date -R >> docs/dist/rss.xml
64-	@printf "</pubDate>\n" >> docs/dist/rss.xml
65-	git log --pretty=format:'<item><title>%s</title><guid isPermaLink="false">%H</guid><author>%ae (%an)</author><pubDate>%aI</pubDate><description><![CDATA[<p><strong>Author:</strong> %an</p><p><strong>Commit:</strong> %H</p><p>%b</p><p style="white-space: pre;">%N</p>]]></description></item>' --date=iso >> docs/dist/rss.xml
66-	@printf "\
67-  </channel>\n\
68-</rss>" >> docs/dist/rss.xml
69-
70-# See 080f729 note for the template command
71-docs/dist/%.html: docs/content/%.md docs/components/navbar.html
72-	pandoc $< | template docs/components/navbar.html --stdin docs/template.html > $@
73-
74-# Will want to move to groff for docs
75-# groff -Thtml -man
76-
77-serve:
78-	cd docs/dist && python3 -m http.server 8000
79-
80-man: 
81-	@man -l docs/manpage/grim.3
82diff --git a/docs/components/navbar.html b/docs/components/navbar.html
83deleted file mode 100755
84index daf8399..0000000
85--- a/docs/components/navbar.html
86+++ /dev/null
87@@ -1,32 +0,0 @@
88-<aside style="min-width: 200px">
89-	<img src="/logo.webp"/ width="150px">
90-	<ul>
91-		<li>
92-			<strong><a href="/">Home</a></strong>
93-		</li>
94-	</ul>
95-	<details open>
96-		<summary>Links</summary>
97-		<ul>
98-			<li><a href="sftp://share@grimui.com">Source</a></li>
99-			<li><a href="https://web.libera.chat/gamja/?autojoin=#grim">IRC</a>
100-			<li><a href="/rss.xml">RSS</a>
101-		</ul>
102-	</details>
103-	<details open>
104-		<summary>Feature Support</summary>
105-		<ul>
106-			<li><a href="/features/supported-css-selectors.html">CSS Selectors</a></li>
107-			<li><a href="/features/supported-html-tags.html">HTML Tags</a></li>
108-			<li><a href="/features/supported-dom-apis.html">DOM APIs</a></li>
109-		</ul>
110-	</details>
111-	<details open>
112-		<summary>About</summary>
113-		<ul>
114-			<li><a href="/about/general.html">General</a></li>
115-			<li><a href="/about/parsing.html">Parsing</a></li>
116-			<li><a href="/about/events.html">Events</a></li>
117-		</ul>
118-	</details>
119-</aside>
120diff --git a/docs/content/features/supported-css-selectors.md b/docs/content/features/supported-css-selectors.md
121deleted file mode 100755
122index 00ceea9..0000000
123--- a/docs/content/features/supported-css-selectors.md
124+++ /dev/null
125@@ -1,239 +0,0 @@
126-# Supported Selectors
127-
128-## Support
129-* (\*) parsing supported, not implemented
130-* \(X\) fully supported, implemented
131-* (/) No support planned
132-
133-## Selectors 
134-| Name | Support | Test Case | Section | Test File |
135-|-|-|-|-| - |
136-| Type | X | testSelector | testSelector can match a element given it's tagName | tests/css_selector.cc |
137-| Attribute | X | testSelector | testSelector can match a element by it's attributes only | tests/css_selector.cc |
138-| ID | X | testSelector | testSelector can match a element by it's id only | tests/css_selector.cc |
139-| Class | X | testSelector | testSelector can match a element by it's class and not match on a non class | tests/css_selector.cc |
140-| Universal | X | testSelector | testSelector can match a universal selector | tests/css_selector.cc |
141-| Nesting | X | parseCSS can parse a CSS sheet, parseCSS can parse multiple selectors nested | parseCSS can parse a nested CSS rule without a &, parseCSS can parse a the parent of a nested CSS rule, parseCSS can parse a nested CSS rule with a pseudo element, parseCSS can parse a parent CSS rule with a property in between sub-classes, multi selector test | tests/css_parser.cc |
142-| & Nesting | X | parseCSS can parse a CSS sheet, parseCSS can parse multiple selectors nested | parseCSS can parse a nested CSS rule without a &, parseCSS can parse a the parent of a nested CSS rule, parseCSS can parse a nested CSS rule with a pseudo element, parseCSS can parse a double nested CSS rule with a pseudo element and &, parseCSS can parse a nested CSS rule with a &, parseCSS can parse a parent CSS rule with a property in between sub-classes, multi selector test | tests/css_parser.cc |
143-
144-## Combinator
145-| Name | Support | Test Case | Section | Test File |
146-|-|-|-|-| - |
147-| Child Combinator | X | testSelector | testSelector can match a child combinator | tests/css_selector.cc |
148-| Next-Sibling Combinator | X | testSelector | testSelector can match a next sibling combinator | tests/css_selector.cc |
149-| Descendant Combinator | X | testSelector | testSelector can match a descendant combinator | tests/css_selector.cc |
150-| Subsequent-Sibling Combinator | X | testSelector | testSelector can match a subsequent-sibling combinator | tests/css_selector.cc |
151-
152-## Pseudo Classes
153-| Name | Support | Test Case | Section | Test File | Note |
154-|-|-|-|-| - | - |
155-| :active | | | | | Will be added when links are|
156-| :any-link | | | | | Will be added when links are|
157-| :autofill | | | | | Will be added when inputs are added |
158-| :buffering | | | | | Videos are not currently supported |
159-| :checked | X | testSelector | testSelector can match a element with a pseudo class | tests/css_selector.cc | |
160-| :default | | | | | Will be added when inputs are added |
161-| :defined | | |  |  | |
162-| :dir() | | |  |  | |
163-| :disabled | X | testSelector | testSelector can match a element with a pseudo class | tests/css_selector.cc | |
164-| :empty | | |  |  | Will be added when inputs are added |
165-| :enabled | X | testSelector | testSelector can match a element with a pseudo class | tests/css_selector.cc | |
166-| :first | / | |  |  | Will not be supported, currently there are no plans to support printing |
167-| :first-child | X | testSelector | testSelector can match a element with first-child | tests/css_selector.cc | |
168-| :first-of-type | X | testSelector | testSelector can match a element with first-of-type | tests/css_selector.cc | |
169-| :focus | | |  |  | |
170-| :focus-visible | | |  |  | |
171-| :focus-within | | |  |  | |
172-| :fullscreen | | |  |  | Videos are not currently supported |
173-| :future | | |  |  | |
174-| :has-slotted | | |  |  | |
175-| :has() | X | testSelector | testSelector can match a :has() selector with a child combinator, testSelector can match a :has() selector with a next-sibling combinator, testSelector can match a :has() selector with a subsequent-sibling combinator, testSelector can match a :has() selector with a decendent combinator | tests/css_selector.cc | |
176-| :host | | | | | |
177-| :host-context() | | | | | |
178-| :host() | | | | | |
179-| :hover | | | | | |
180-| :in-range | | | | | Will be added when inputs are added |
181-| :indeterminate | | | | | Will be added when inputs are added |
182-| :invalid | | | | | Will be added when inputs are added |
183-| :is() | X | testSelector | testSelector can match :is() selectors | tests/css_selector.cc | |
184-| :lang() | | | | | |
185-| :last-child | X | testSelector | testSelector can match a element with last-child | tests/css_selector.cc | |
186-| :last-of-type | X | testSelector | testSelector can match a element with last-of-type | tests/css_selector.cc | |
187-| :left | / | | | | Will not be supported, currently there are no plans to support printing |
188-| :local-link | / | | | | Doesn't make sense to add because all links will be local |
189-| :modal | | | | | |
190-| :muted | | | | | Videos are not currently supported |
191-| :not() | X | testSelector | testSelector can match :not() selectors | tests/css_selector.cc | |
192-| :nth-child() | X | testSelector | testSelector can match a :nth-child(even\|odd), testSelector can match a :nth-child(A), testSelector can match a :nth-child(An), testSelector can match a :nth-child(An+B), testSelector can match a :nth-child(An+B of type), testSelector can match a :nth-child(n+B), testSelector can match a :nth-child(A of type), testSelector can match a :nth-child(An of type), testSelector can match a :nth-child(n+B of type) | tests/css_selector.cc | when A is 0 it is changed to a 1, the only case this will cause breaking behavior is if you are trying :nth-child(0n+B) which is the same as calling :nth-child(B). This behavior applies to all nth-*|
193-| :nth-last-child() | X | testSelector | testSelector can match a :nth-last-child(even\|odd), testSelector can match a :nth-last-child(A), testSelector can match a :nth-last-child(An), testSelector can match a :nth-last-child(An+B), testSelector can match a :nth-last-child(n+B), testSelector can match a :nth-last-child(An+B of type), testSelector can match a :nth-last-child(A of type), testSelector can match a :nth-last-child(An of type), testSelector can match a :nth-last-child(n+B of type) | tests/css_selector.cc | |
194-| :nth-last-of-type() | X | testSelector | testSelector can match a :nth-last-of-type(even\|odd), testSelector can match a :nth-last-of-type(A), testSelector can match a :nth-last-of-type(An), testSelector can match a :nth-last-of-type(An+B), testSelector can match a :nth-last-of-type(n+B),  | tests/css_selector.cc | |
195-| :nth-of-type() | X | testSelector | testSelector can match a :nth-of-type(even\|odd), testSelector can match a :nth-of-type(A), testSelector can match a :nth-of-type(An), testSelector can match a :nth-of-type(An+B), testSelector can match a :nth-of-type(n+B),  | tests/css_selector.cc | |
196-| :only-child | X | testSelector | testSelector can match :only-child | tests/css_selector.cc | |
197-| :only-of-type | X | testSelector | testSelector can match :only-of-type | tests/css_selector.cc | |
198-| :open | | | | | |
199-| :optional | | | | | |
200-| :out-of-range | | | | | Will be added when inputs are added |
201-| :past | | | | | |
202-| :paused | | | | | Videos are not currently supported |
203-| :picture-in-picture | | | | | Videos are not currently supported |
204-| :placeholder-shown | | | | | Will be added when inputs are added |
205-| :playing | | | | | Videos are not currently supported |
206-| :popover-open | | | | |  |
207-| :read-only | X | testSelector | testSelector can match :read-only normal element, testSelector can match :read-only on a radio input, testSelector can match :read-only on a readonly text input, testSelector can match :read-only on a disabled text input, testSelector can match :read-only on a readonly textarea, testSelector can match :read-only on a disabled textarea | tests/css_selector.cc | |
208-| :read-write | X | testSelector | testSelector can match :read-write on a text input, testSelector can match :read-write on a textarea, testSelector can match :read-write on a contenteditable div | tests/css_selector.cc | |
209-| :required | X | testSelector | testSelector can match a element with a pseudo class | tests/css_selector.cc | |
210-| :right | / | | | | Will not be supported, currently there are no plans to support printing |
211-| :root | X | testSelector | testSelector can match :root | tests/css_selector.cc | |
212-| :scope | | | | | |
213-| :seeking | | | | | Videos are not currently supported |
214-| :stalled | | | | | Video and Audio are not currently supported |
215-| :state() | | | | | Shadow DOM |
216-| :target | | | | | |
217-| :target-current | | | | | |
218-| :target-within | | | | | |
219-| :user-invalid | | | | | |
220-| :user-valid | | | | | |
221-| :valid | | | | | |
222-| :visited | | | | | |
223-| :volume-locked | | | | | Video and Audio are not currently supported |
224-| :where() | X | testSelector |testSelector can match :where() selectors | tests/css_selector.cc | |
225-## Pseudo Elements
226-
227-## At-rules
228-| Name | Support | Test Case | Section | Test File | Note |
229-|-|-|-|-|-|-|
230-| @charset | / |||| UTF-8/ASCII are the only encodings supported |
231-| @color-profile | / |||| Too new to support |
232-| @container ||||||
233-| @counter-style ||||||
234-| @font-face ||||||
235-| @font-feature-values ||||||
236-| @swash | / |||| Subset of @font-feature-values |
237-| @annotation | / |||| Subset of @font-feature-values |
238-| @ornaments | / |||| Subset of @font-feature-values |
239-| @stylistic | / |||| Subset of @font-feature-values |
240-| @styleset | / |||| Subset of @font-feature-values |
241-| @character-varient | / |||| Subset of @font-feature-values |
242-| @font-palette-values ||||||
243-| @import ||||| Parsed where the first argument after @import is the url and the last non parenthesized value if present is the layer name. Inbetween the url and the layer is the media queries. |
244-| @keyframes ||||||
245-| @layer ||||| Currently setting the layer order via @layer l1, l2; is not supported |
246-| @media ||||||
247-| @namespace ||||||
248-| @page | / |||| Will not be supported, currently there are no plans to support printing |
249-| @position-try ||||| Use this document to check support of features |
250-| @property ||||||
251-| @scope ||||| Implementing this would cause some overhead |
252-| @starting-style ||||||
253-| @supports | / |||| Use this document to check support of features |
254-| @view-transition ||||| This is useful but will not be implemented until later |
255-## Functions
256-## Types
257-| Name | Support | Values | Note |
258-|-|-|-|-|
259-| AnyHover | X | None, Hover | |
260-| AnyPointer | X | None, Fine, Coarse | |
261-| Orientation | X | Landscape, Portrait | |
262-| ColorScheme | X | Light, Dark | |
263-| Contrast | X | NoPreference, More, Less | |
264-| ReducedMotion | X | NoPreference, Reduce | |
265-| ReducedTranparency | X | NoPreference, Reduce | |
266-| Update | X | Fast, Slow | |
267-
268-## Descriptors
269-| Name | Support | Used by | Note |
270-|-|-|-|-|
271-| style | | @container | |
272-| scroll-state | @container | | |
273-| container | | @container | | Computed using the overall container via window properties (orientation: landscape) and the content-box (min-width: 300px). Supports aspect-ratio, height, orientation, width |
274-
275-## Media Queries
276-| Name | Support | Usage | Note |
277-|-|-|-|-|
278-| any-hover | X | window.setMouse(AnyPointer::Fine) | Will be set to AnyHover::Hover if AnyPointer is not AnyPointer::None, default AnyHover::Hover |
279-| any-pointer | X | window.setMouse(AnyPointer::Coarse) | Default AnyPointer::Fine |
280-| aspect-ratio | X | window.getAspectRatio() | Derived from width and height, returned as a double | 
281-| color | * | | All colors are stored as RGBA values | 
282-| color-gamut | * | | Only matches on "srgb" |
283-| color-index | * | | Only matches on 0 |
284-| device-posture | * | | Only matches on "continuous" |
285-| display-mode | * | | All applications will be "standalone" |
286-| dynamic-range | * | | Only matches on "standard" |
287-| forced-colors | * | | Only matches on "none" |
288-| grid | * | | Only matches on 0 |
289-| height | X | window.setHeight(int) | Supports height, min-height, max-height |
290-| hover | X | window.setMouse(AnyPointer::Fine) | Will match any-hover |
291-| inverted-colors | * | | Only matches on "none" |
292-| monochrome | * | | Only matches on 0 |
293-| orientation | X | window.setOrientation(Orientation::Portrait) | Defaults to Orientation::Landscape | 
294-| overflow-block | * | | Only matches on "scroll" |
295-| overflow-inline | * | | Only matches on "scroll" |
296-| pointer | X | window.setMouse(AnyPointer) | Will match any-pointer |
297-| prefers-color-scheme | X | window.setColorScheme(ColorScheme::Dark) | Defaults to ColorScheme::Light |
298-| prefers-contrast | X | window.setContrast(Contrast::Less) | Defaults to ColorScheme::NoPreference |
299-| prefers-reduced-motion | X | window.setReducedMotion(ReducedMotion::Reduce) | Defaults to ReducedMotion::NoPreference |
300-| prefers-reduced-transparency | X | window.setReducedTransparency(ReducedTransparency::Reduce) | Defaults to ReducedTransparency::NoPreference |
301-| resolution | X | window.setResolution(int) | Defaults to 72dpi, accepts a int in dpi |
302-| scripting | / | | Not needed |
303-| update | X | window.setUpdate(Update::Slow) | Defaults to Update::Fast |
304-| video-dynamic-range | * | | Only matches on "standard" |
305-| width | X | window.setWidth(int) | Supports width, min-width, max-width |
306-
307-## Colors
308-| Name | Support | Usage | Note |
309-|-|-|-|-|
310-| rgb | X | rgb(0-255, 0-255, 0-255) | You may use spaces instead of commas |
311-| rgba | X | rgba(0-255, 0-255, 0-255 / 0-100%) | The alpha value MUST be a perent ranging from 0-100. You may also use spaces instead of commas |
312-| hsl | X | hsl(0-360deg, 0-100%, 0-100%) | You may use spaces instead of commas |
313-| hsla | X | hsla(0-360deg, 0-100%, 0-100% / 0-100%) | The alpha value MUST be a perent ranging from 0-100. You may also use spaces instead of commas |
314-| hwb | / | | Use alternative color definition |
315-| lab | / | | Use alternative color definition |
316-| lch | / | | Use alternative color definition |
317-| oklab | / | | Use alternative color definition |
318-| oklch | / | | Use alternative color definition |
319-| color-mix | / | | Use alternative color definition |
320-
321-## Types
322-| Name | Support | Usage | Note |
323-|-|-|-|-|
324-| <absolute-size> | X | xx-small, x-small, small, medium, large, x-large, xx-large, xxx-large | Based off of relative EM value |
325-| <alpha-value> | | | |
326-| <angle-percentage> | | | |
327-| <angle> | | | |
328-| <baseline-position> | X | baseline, first baseline, last baseline | Singular baseline computes to first baseline |
329-| <basic-shape> | / | | Will be impleamented in the future |
330-| <blend-mode> | / | | Will be impleamented in the future |
331-| <box-edge> | X | content-box, padding-box, border-box, margin-box, fill-box, stroke-box, view-box  | |
332-| <calc-keyword> | X | calc(<number>, <dimention>, <percentage>, <function>) | |
333-| <color> | X | | See Colors |
334-| <content-distribution> | X | space-between, space-around, space-evenly, stretch | |
335-| <centent-position> | X | center, start, end, flex-start, flex-end | |
336-| <dimension> | X | px, rem, pt, ms, s, hz | |
337-| <display-box> | X | contents, none | |
338-| <display-inside> | X | flow, flow-root, table, flex, grid, ruby | |
339-| <display-internal> | X | table-row-group, table-header-group, table-footer-group, table-row, table-cell, table-column-group, table-column, table-caption, ruby-base, ruby-text, ruby-base-container, ruby-text-container | |
340-| <display-legacy> | X | inline-block, inline-table, inline-flex, inline-grid | |
341-| <display-listitem> | X | <display-outside>, flow, flow-root, list-item | |
342-| <display-outside> | X | block, inline, run-in | |
343-| <easing-function> |  | <linear-easing-function>, linear, ease, ease-in, ease-out, ease-in-out, <cubic-bezier-function>, step-start, step-end, <steps-function>, jump-start, jump-end, jump-none, jump-both, start, end | |
344-| <filter-function> | X | <blur>, <brightness>, <contrast>, <drop-shadow>, <gray-scale>, <hue-rotate>, <invert>, <opactity>, <sepia>, <saturate> | |
345-| <frequency-percentage> | X | <frequency>, <percentage> | |
346-| <frequency> | X | kHz, Khz, KHz, KHZ, hz, Hz, HZ, hZ | |
347-| <generic-family> | X | serif, sans-serif, monospace, cursive, fantasy, system-ui, ui-serif, ui-sans-serif, ui-monospace, ui-rounded, math, fangsong | |
348-| <gradient> | X | <linear-gradient>, <repeating-linear-gradient>, <radial-gradient>, <repeating-radial-gradient>, <position> | |
349-| <side-or-corner> | / | | Use <position> instead |
350-| <position> | X | top, left, bottom, right, center | |
351-| <shape> | X | circle, ellipse | |
352-| <hex-color> | X | #RGB, #RGBA, #RRGGBB, #RRGGBBAA | |
353-| <hue-interpolation-method> | shorter hue, longer hue, increasing hue, decreasing hue | |
354-| <hue> |  | <number>, <angle> | |
355-| <image> |  | <url>, <image>, <image-set>, <cross-fade>, <element>, <gradient> | | 
356-| <integer> |  | | |
357-| <length-percentage> |  | | |
358-| <length> | 
359-| <>
360-
361-## Other
362-| Name | Support | Usage | Note |
363-|-|-|-|-|
364-| Variables | X | --<name> | |
365diff --git a/docs/content/index.md b/docs/content/index.md
366deleted file mode 100755
367index 06e37bb..0000000
368--- a/docs/content/index.md
369+++ /dev/null
370@@ -1,31 +0,0 @@
371-# Getting Started
372-
373-## Cloning
374-
375-```sh
376-git clone https://grimui.com/grim.git
377-```
378-
379-
380-## Installing
381-
382-### Adding to a project
383-```sh
384-cd my_project/
385-git submodule add https://grimui.com/grim.git
386-```
387-
388-### Including
389-```c++
390-#include "grim.h";
391-```
392-
393-```sh
394-clang++ -Igrim/include grim/build/grim.o
395-```
396-
397-### Make
398-```sh
399-cd grim
400-make all
401-```
402diff --git a/docs/manpage/grim.html b/docs/manpage/grim.html
403deleted file mode 100755
404index e69de29..0000000
405diff --git a/docs/template.html b/docs/template.html
406deleted file mode 100755
407index 3c56f6a..0000000
408--- a/docs/template.html
409+++ /dev/null
410@@ -1,37 +0,0 @@
411-<!DOCTYPE html>
412-<html lang="en">
413-	<head>
414-		<meta charset="UTF-8" />
415-		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
416-		<title>Grim</title>
417-		<meta name="description" content="Grim is a new implementation of HTML/CSS/DOM API.">
418-		<style>
419-body {
420-	margin-bottom: 100px;
421-}
422-table {
423-      width: 100%%;
424-      border-collapse: collapse;
425-}
426-th,
427-td {
428-      text-align: center;
429-      border: 1px solid #ddd;
430-      padding: 8px;
431-}
432-th {
433-      background-color: #f2f2f2;
434-}
435-		</style>
436-	</head>
437-	<body>
438-		<main style="margin: 0 4rem 0 4rem">
439-			<div style="display: flex; gap: 1rem">
440-				%s
441-				<div style="width: 100%%">
442-					<section>%s</section>
443-				</div>
444-			</div>
445-		</main>
446-	</body>
447-</html>
448diff --git a/include/grim.h b/include/grim.h
449index 4fd2493..4a4dd77 100755
450--- a/include/grim.h
451+++ b/include/grim.h
452@@ -130,6 +130,7 @@ class Node {
453 		Node* createElement(std::string name);
454 
455 		void setAttribute(const std::string& name, const std::string& value);
456+		void deleteAttribute(const std::string& name);
457 		std::optional<Attribute> getAttribute(const std::string& name) const;
458 
459 		const std::unordered_map<std::string, std::string>& getAttributes() const;
460@@ -218,7 +219,7 @@ enum class KeyType : short {
461 
462 enum class UnitType : short {
463 	// Color
464-		HEX, RGB, RGBA, HSL,
465+		TEST, HEX, RGB, RGBA, HSL,
466 	// Logic
467 		AND, OR, NOT, ONLY, COMMA,
468 	// Length 
469@@ -297,7 +298,7 @@ enum class UnitType : short {
470 		SKEW, SKEWX, SKEWY,
471 
472 	// Keyword
473-		PRINT, SCREEN, TOKEN, FUNC, GROUP, NO_SUPPORT, IMAGE
474+		PRINT, SCREEN, TOKEN, FUNC, GROUP, NO_SUPPORT, IMAGE, STRING
475 };
476 
477 // 4 bytes
478@@ -307,6 +308,7 @@ union UnitValue {
479 	unsigned int UINT;
480 	float FLOAT;
481 	bool BOOL;
482+	char CHAR;
483 };
484 
485 // 6 bytes 
486@@ -324,18 +326,17 @@ class Style {
487 	public:
488 		Window* window;
489 
490-		std::unordered_map<std::string, std::vector<size_t>> basemap;
491-		std::vector<int> indexes;
492+		std::unordered_map<std::string, std::vector<size_t>> basemap{};
493 
494 		StyleType type;
495 		std::string name;
496-		std::vector<std::vector<std::string>> selector;
497+		std::vector<std::vector<std::string>> selector{};
498 		
499-		std::unordered_map<KeyType, std::vector<Unit>> properties;
500-		std::unordered_map<std::string, std::vector<Unit>> variables;
501+		std::unordered_map<KeyType, std::vector<Unit>> properties{};
502+		std::unordered_map<std::string, std::vector<Unit>> variables{};
503 
504 		// Nesting
505-		std::vector<Style> children;
506+		std::vector<Style> children{};
507 
508 		// Functions
509 		void addChild(Style s);
510diff --git a/docs/content/adding/adding-css-properties.3 b/man/adding-css-properties.3
511similarity index 100%
512rename from docs/content/adding/adding-css-properties.3
513rename to man/adding-css-properties.3
514diff --git a/docs/manpage/grim.3 b/man/grim.3
515similarity index 100%
516rename from docs/manpage/grim.3
517rename to man/grim.3
518diff --git a/docs/content/features/supported-css-selectors.1 b/man/supported-css-selectors.1
519similarity index 100%
520rename from docs/content/features/supported-css-selectors.1
521rename to man/supported-css-selectors.1
522diff --git a/playground/parseselectorparts.cc b/playground/parseselectorparts.cc
523new file mode 100644
524index 0000000..ba0065d
525--- /dev/null
526+++ b/playground/parseselectorparts.cc
527@@ -0,0 +1,12 @@
528+#include "../include/grim.h"
529+#include "../include/parser.h" 
530+#include <string>
531+#include <vector>
532+#include <iostream>
533+
534+int main() {
535+	std::vector<std::vector<std::string>> parts = parseSelectorParts("2n + 3");
536+
537+	std::cout << std::stoi(parts[0][0].substr(0,parts[0][0].length()-1)) << std::endl;
538+}
539+
540diff --git a/playground/testselector.cc b/playground/testselector.cc
541new file mode 100644
542index 0000000..db55f05
543--- /dev/null
544+++ b/playground/testselector.cc
545@@ -0,0 +1,45 @@
546+#include "../include/grim.h"
547+#include "../include/parser.h" 
548+#include <string>
549+#include <sstream>
550+#include <vector>
551+#include <iostream>
552+
553+int main() {
554+	std::string html = "<!DOCTYPE html>"
555+			"<html>"
556+				"<head>"
557+					"<title>This is a simple test</title>"
558+					"<link rel=\"stylesheet\" href=\'/style.css\'/>"
559+				"</head>"
560+				"<body>"
561+					"<h1 id=\"h1Tag\">Header</h1>"
562+					"<p id=\"paragraph\" class=\"class1 class2\">This is some text for a simple test</p>"
563+					"<div contenteditable=\"true\">"
564+						"<p>this is a only child</p>"
565+					"</div>"
566+					"<input type=\"text\" checked required/>"
567+					"<ul>"
568+						"<li>one</li>"
569+						"<li>two</li>"
570+						"<li>three</li>"
571+						"<li>four</li>"
572+					"</ul>"
573+					"<input type=\"radio\" checked required/>"
574+					"<input type=\"text\" readonly/>"
575+					"<input type=\"text\" disabled/>"
576+					"<textarea></textarea>"
577+					"<textarea readonly></textarea>"
578+					"<textarea disabled></textarea>"
579+				"</body>"
580+			"</html>";
581+
582+
583+	std::stringstream ss(html);
584+	Node document = parseHTML(ss);
585+
586+	
587+	auto li = document.children[0]->children[1]->children[4]->children[3].get();
588+
589+	std::cout << testSelector(li, parseSelectorParts(":nth-last-child(even)")) << std::endl;
590+}
591diff --git a/src/grim.cc b/src/grim.cc
592index 05133af..832596b 100755
593--- a/src/grim.cc
594+++ b/src/grim.cc
595@@ -106,6 +106,10 @@ void Node::setAttribute(const std::string& name, const std::string& value) {
596 	attributes[name] = value;
597 }
598 
599+void Node::deleteAttribute(const std::string& name) {
600+	attributes.erase(name);
601+}
602+
603 std::optional<Attribute> Node::getAttribute(const std::string& name) const {
604 	// First check in the user set attributes
605 	auto it = attributes.find(name);
606@@ -561,21 +565,29 @@ std::vector<std::vector<std::string>> parseSelectorParts(std::string_view select
607 	for (size_t i = start; i < end; i++) {
608 		char s = selector[i];
609 		if (s == '\'') s = '"';
610-		if (s == '(' || s == '[' || s == '{') {
611-			if (!current.empty()) {
612+
613+		if ((s == '(' || s == '[' || s == '{')) {
614+			if (!current.empty() && nesting == 0) {
615 				buffer.push_back(current);
616 				current.clear();
617 			}
618+
619+			current.push_back(s);
620 			nesting++;
621+			continue;
622 		}
623 		
624-		if (s == ')' || s == ']' || s == '}') {
625-			current.push_back(s);
626-			buffer.push_back(current);
627-			current.clear();
628+		if ((s == ')' || s == ']' || s == '}')) {
629 			nesting--;
630+			current.push_back(s);
631+			if (!current.empty() && nesting == 0) {
632+				
633+				buffer.push_back(current);
634+				current.clear();
635+			}
636 			continue;
637 		} else {
638+
639 			if (nesting > 0) {
640 				current.push_back(s);
641 				continue;
642@@ -588,6 +600,7 @@ std::vector<std::vector<std::string>> parseSelectorParts(std::string_view select
643 			} else {
644 				if (!current.empty()) {
645 					buffer.push_back(current);
646+					buffer.push_back(" ");
647 					current.clear();
648 				}
649 			}
650@@ -604,8 +617,14 @@ std::vector<std::vector<std::string>> parseSelectorParts(std::string_view select
651 					buffer.push_back(current);
652 					current.clear();
653 				}
654-				buffer.push_back("");
655-				buffer.back() += s;
656+				// A few lines above we add a empty space when the next char is not a space
657+				// and the current is not empty. This is to create the decendant combinator
658+				// but if one of the symbols in the statement are folling then we need to replace
659+				// the empty space with the correct combinator
660+				if (buffer.size() == 0) {
661+					buffer.push_back("");
662+				}
663+				buffer.back() = s;
664 			} else if (s == ':' || s == '#' || s == '.') {
665 				if (i < end-1 && selector[i+1] == ':') continue; 
666 				if (!current.empty()) {
667@@ -791,8 +810,8 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
668 	// This is setup code for the rest of the process
669 	// parts is the part of the selector that applies to
670 	// the current node: If we had div > h1 we would get
671-	// "h1" and the div part would be stored in trimmed.
672-	// then the symbol we split at is symbol. See below
673+	// "h1" and the div part would be stored in "trimmed".
674+	// then the symbol we split at is "symbol". See below
675 	for (int i = selector[0].size()-1; i >= 0; i--) {
676 		std::string part = selector[0][i];
677 		if (symbolFound) {
678@@ -812,7 +831,7 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
679 	// trimmed = {"div"}
680 	// parts = {"h1"}
681 	// symbol = ">"
682-	
683+
684 	// matched is true here because the node matching logic
685 	// returns if matched is false
686 	bool matched = true;
687@@ -847,7 +866,8 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
688 
689 	// Find the index of the child relative to it's parent
690 
691-	// the children variable is the PARENTS CHILDREN the the current node's children
692+	// the children variable is the PARENTS CHILDREN not the current node's children
693+	// aka siblings
694 	// if you want those, node->children
695 	const std::vector<std::unique_ptr<Node>>& children = (node->parent != nullptr) ? node->parent->children : EMPTY_NODE_CHILDREN_VECTOR;
696 	size_t childIndex = 0;
697@@ -869,25 +889,25 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
698 
699 	// Add the auto pseudo classes like first-child/last-child
700 	if (childIndex == 0) {
701-		attrs.push_back("first-child");
702+		attributes["first-child"] = "true";
703 	}
704 	if (childIndex == children.size()-1) {
705-		attrs.push_back("last-child");
706+		attributes["last-child"] = "true";
707 	}
708 	if (childTypeIndex == 0) {
709-		attrs.push_back("first-of-type");
710+		attributes["first-of-type"] = "true";
711 	}
712 	if (childTypeIndex == childTypeCount-1) {
713-		attrs.push_back("last-of-type");
714+		attributes["last-of-type"] = "true";
715 	}
716 	if (childIndex == 0 && children.size() == 1) {
717-		attrs.push_back("only-child");
718+		attributes["only-child"] = "true";
719 	}
720 	if (childTypeIndex == 0 && childTypeCount == 1) {
721-		attrs.push_back("only-of-type");
722+		attributes["only-of-type"] = "true";
723 	}
724 	if (tagName == "html") {
725-		attrs.push_back("root");
726+		attributes["root"] = "true";
727 	}
728 	
729 	if (tagName == "input") {
730@@ -898,27 +918,27 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
731 				|| type == "password" || type == "date" || type == "month" || type == "week" 
732 				|| type == "time" || type == "datetime-local" || type == "number") {
733 			if (readonly || disabled) {
734-				attrs.push_back("read-only");
735+				attributes["read-only"] = "true";
736 			} else {
737-				attrs.push_back("read-write");
738+				attributes["read-write"] = "true";
739 			}
740 		} else {
741-			attrs.push_back("read-only");
742+			attributes["read-only"] = "true";
743 		}
744 	} else if (tagName == "textarea") {
745 		bool readonly = attributes.find("readonly") != attributes.end();
746 		bool disabled = attributes.find("disabled") != attributes.end();
747 		if (readonly || disabled) {
748-			attrs.push_back("read-only");
749+			attributes["read-only"] = "true";
750 		} else {
751-			attrs.push_back("read-write");
752+			attributes["read-write"] = "true";
753 		}
754 	} else {
755 		std::string contentEditable = attributes["contenteditable"];
756 		if (contentEditable == "true") {
757-			attrs.push_back("read-write");
758+			attributes["read-write"] = "true";
759 		} else {
760-			attrs.push_back("read-only");
761+			attributes["read-only"] = "true";
762 		}
763 	}
764 
765@@ -948,6 +968,8 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
766 			// as parseSelectorParts converts any attribute
767 			// without a ending ) to [name]: 
768 			// See tests/css_selector.cc for examples
769+			// For CSS selectors like :checked that are also attributes, they
770+			// are matched at the last else of the next block
771 			bool found = false;
772 
773 			p.erase(0,1);
774@@ -961,31 +983,34 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
775 			matched = found;
776 		} // !TODO: Need a case for : , this will run the :has... logic
777 		else if (p[0] == ':') {
778-			if (p.starts_with(":is(")) {
779-				std::string value = p.substr(4,p.length()-5);
780-				matched = testSelector(node, parseSelectorParts(value));
781-			} else if (p.starts_with(":where(")) {
782+
783+			// need to get the ext one and shave off 1,-1
784+
785+			std::vector<std::vector<std::string>> next;
786+			if (i+1 < parts.size()) {
787+				next = parseSelectorParts(parts[i+1].substr(1,parts[i+1].length()-2));
788+			}
789+
790+			if (p.starts_with(":is")) {
791+				matched = testSelector(node, next);
792+			} else if (p.starts_with(":where")) {
793 				// Per specification where and is differ in specificity only
794 				// however, grim does not support specificity
795 				// https://developer.mozilla.org/en-US/docs/Web/CSS/:is#difference_between_is_and_where
796-				std::string value = p.substr(7,p.length()-8);
797-				matched = testSelector(node, parseSelectorParts(value));
798-			} else if (p.starts_with(":not(")) {
799-				std::string value = p.substr(5,p.length()-6);
800+				matched = testSelector(node, next);
801+			} else if (p.starts_with(":not")) {
802 				// Just inverts the output of testSelector
803-				matched = !testSelector(node, parseSelectorParts(value));
804-			} else if (p.starts_with(":has(")) {
805+				matched = !testSelector(node, next);
806+			} else if (p.starts_with(":has")) {
807 // +------------------------------------------------------+
808 // |(jhsfk) Has selection                                 |
809 // +------------------------------------------------------+
810 				// We have to do a little work to get :has working
811 				// once we parse the inner parts of the selector,
812 				// we need to find what the selector is targeting
813-				std::string value = p.substr(5,p.length()-6);
814-				auto innerParts = parseSelectorParts(value);
815 				bool found = false;
816 
817-				for (auto ip : innerParts) {
818+				for (auto ip : next) {
819 					// if the selector was :has(+ p, div, > video)
820 					// ip contains each comma seperated value like {"+", "p"} 
821 					// these differ from how we parse the parts below
822@@ -1078,95 +1103,92 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
823 // Instead of moving these up a layer I'm putting them 
824 // here because most selectors will not be "nth-" so why 
825 // check against every case
826-				std::string pattern;
827 				bool last = false;
828 				bool ofType = false;
829-				if (p.starts_with(":nth-child")) {
830-					pattern = p.substr(11, p.length()-12);
831-				} else if (p.starts_with(":nth-last-child(")) {
832+				if (p == ":nth-last-child") {
833 					last = true;
834-					pattern = p.substr(16,p.length()-17);
835-				} else if (p.starts_with(":nth-of-type(")) {
836+				} else if (p == ":nth-of-type") {
837 					ofType = true;
838-					pattern = p.substr(13,p.length()-14);
839-				} else if (p.starts_with(":nth-last-of-type(")) {
840+				} else if (p == ":nth-last-of-type") {
841 					ofType = true;
842 					last = true;
843-					pattern = p.substr(18, p.length()-19);
844 				}
845 	// +------------------------------------------------------+
846 	// |Parsing the pattern                                   |
847 	// +------------------------------------------------------+
848-				// If you look closely these are reversed
849-				// its because the vector index starts with 0
850-				// and CSS starts with 1
851-				if (pattern == "even") {
852-					if (childIndex%2 == 1) {
853-						matched = true;
854-					} else {
855-						matched = false;
856-					}
857-				} else
858-				if (pattern == "odd") {
859-					if (childIndex%2 == 0) {
860-						matched = true;
861-					} else {
862-						matched = false;
863-					}
864-				} else {
865-					// loop through 
866-					// first check if theres a symbol before any 0-9
867-					// go until n is found (if there is a n)
868-					// then find another symbol or "of"
869-					// if symbol find numbers
870-					// then of get that.
871-					// the of syntax can be used to make nth-of-type as well
872-					bool negFound = false;
873-					bool negative = false;
874-					bool Afound = false;
875-					bool nfound = false;
876-					int A = 0;
877-					int B = 0;
878-					char symbol = '+';
879-					bool symbolFound = false;
880-					std::string ofSelector = "";
881-
882-					for (size_t i = 0; i < pattern.length(); i++) {
883-						if (!std::isspace(pattern[i])) {
884-							if (pattern[i] == '-' && !negFound) {
885-								negFound = true;
886-								negative = true;
887-							} else if (pattern[i] == '+' && !negFound) {
888+						
889+				// loop through 
890+				// first check if theres a symbol before any 0-9
891+				// go until n is found (if there is a n)
892+				// then find another symbol or "of"
893+				// if symbol find numbers
894+				// then of get that.
895+				// the of syntax can be used to make nth-of-type as well
896+				bool negFound = false;
897+				bool negative = false;
898+				bool Afound = false;
899+				bool nfound = false;
900+				int A = 0;
901+				int B = 0;
902+				char symbol = '+';
903+				bool symbolFound = false;
904+				bool isBool = false;
905+				bool isEven = false;
906+				std::string ofSelector = "";
907+
908+				std::string pattern = parts[i+1].substr(1,parts[i+1].length()-2);
909+
910+				std::cout << "################################" << std::endl;
911+				std::cout << pattern << std::endl;
912+
913+				for (size_t i = 0; i < pattern.length(); i++) {
914+					if (!std::isspace(pattern[i])) {
915+						if (pattern[i] == '-' && !negFound) {
916+							negFound = true;
917+							negative = true;
918+						} else if (pattern[i] == '+' && !negFound) {
919+							negFound = true;
920+						} else if (pattern[i] == 'e' && !nfound && !Afound && pattern.substr(i, 4) == "even") {
921+							i += 4;
922+							isEven = true;
923+							Afound = true;
924+							nfound = true;
925+							isBool = true;
926+						} else if (pattern[i] == 'o' && !nfound && !Afound && pattern.substr(i, 3) == "odd") {
927+							i += 3;
928+							isEven = false;
929+							Afound = true;
930+							nfound = true;
931+							isBool = true;
932+						} else if (pattern[i] == 'n' && !nfound && !Afound ) {
933+							nfound = true;
934+							// At n stop adding to A
935+							Afound = true;
936+							negFound = true;
937+						} else if (Afound && nfound && !symbolFound && (pattern[i] == '-' || pattern[i] == '+')) {
938+							symbol = pattern[i];
939+							symbolFound = true;
940+						} else if (pattern[i]-'0' < 10) {
941 								negFound = true;
942-							} else if (pattern[i] == 'n' && !nfound && !Afound ) {
943-								nfound = true;
944-								// At n stop adding to A
945-								Afound = true;
946-								negFound = true;
947-							} else if (Afound && nfound && !symbolFound && (pattern[i] == '-' || pattern[i] == '+')) {
948-								symbol = pattern[i];
949-								symbolFound = true;
950-							} else if (pattern[i]-'0' < 10) {
951-									negFound = true;
952-									if (!Afound && !nfound) {
953-										A *= 10;
954-										A += (pattern[i]-'0');
955-									} else if (nfound && symbolFound && Afound) {
956-										B *= 10;
957-										B += (pattern[i]-'0');
958-									}
959-							} else {
960-								ofSelector += pattern[i];
961-							}
962+								if (!Afound && !nfound) {
963+									A *= 10;
964+									A += (pattern[i]-'0');
965+								} else if (nfound && symbolFound && Afound) {
966+									B *= 10;
967+									B += (pattern[i]-'0');
968+								}
969+						} else {
970+							ofSelector += pattern[i];
971 						}
972 					}
973+				}
974 
975-					if (negative) {
976-						A *= -1;
977-					}
978-					if (symbol == '-') {
979-						B *= -1;
980-					}
981+				if (negative) {
982+					A *= -1;
983+				}
984+				if (symbol == '-') {
985+					B *= -1;
986+				}
987 
988 	// Now we have:
989 	// polarity of A: negative
990@@ -1183,87 +1205,114 @@ bool testSelector(Node* node, std::vector<std::vector<std::string>> selector) {
991 	// +------------------------------------------------------+
992 	// |Finding the index of node                             |
993 	// +------------------------------------------------------+
994-					int index = 0;
995-					// We have the index of the current element (childIndex)
996-					// if ofSelector is "" we can use it if not we need to run 
997-					// testSelector on all children until we find it
998-					// and if "last" we need to do it in reverse
999-					//
1000-					// If the nth child selector has -of-type we need to add of+tagname
1001-					// the of is added because thats how the parser parses the rest of them
1002-					if (ofType) {
1003-						ofSelector = "of"+tagName;
1004-					}
1005+				int index = 0;
1006+				// We have the index of the current element (childIndex)
1007+				// if ofSelector is "" we can use it if not we need to run 
1008+				// testSelector on all children until we find it
1009+				// and if "last" we need to do it in reverse
1010+				//
1011+				// If the nth child selector has -of-type we need to add of+tagname
1012+				// the of is added because thats how the parser parses the rest of them
1013+				if (ofType) {
1014+					ofSelector = "of"+tagName;
1015+				}
1016 
1017-					if (ofSelector == "") {
1018-						if (last) {
1019-							// If we are checking from the back we need to invert the
1020-							// childIndex
1021-							index = children.size() - 1 - childIndex;
1022-						} else {
1023-							index = childIndex;
1024-						}
1025+				if (ofSelector == "") {
1026+					if (last) {
1027+						// If we are checking from the back we need to invert the
1028+						// childIndex
1029+						index = children.size() - 1 - childIndex;
1030+						if (isBool) {
1031+								index--;
1032+							}
1033 					} else {
1034-						// Parse the of selector
1035-						auto pOS = parseSelectorParts(ofSelector.substr(2));
1036-						if (testSelector(node, pOS)) {
1037-							if (last) {
1038-								// Reverse through the siblings
1039-								for (size_t i = children.size() - 1; i >= 0; i--) {
1040-									Node* child_ptr = children[i].get();
1041-									if (child_ptr != node) {
1042-										if (testSelector(child_ptr, pOS)) {
1043-											// if the selector matches the ofSelector add one
1044-											index++;
1045-										}
1046-									} else {
1047-										// We are at the pointer address of the target node
1048-										break;
1049+						index = childIndex;
1050+					}
1051+				} else {
1052+					std::cout << "Has of: " << ofSelector << std::endl;
1053+					// Parse the of selector
1054+					auto pOS = parseSelectorParts(ofSelector.substr(2));
1055+					if (testSelector(node, pOS)) {
1056+						if (last) {
1057+							// Reverse through the siblings
1058+							for (size_t i = children.size() - 1; i >= 0; i--) {
1059+								Node* child_ptr = children[i].get();
1060+								if (child_ptr != node) {
1061+									if (testSelector(child_ptr, pOS)) {
1062+										// if the selector matches the ofSelector add one
1063+										index++;
1064 									}
1065+								} else {
1066+									// We are at the pointer address of the target node
1067+									break;
1068 								}
1069-							} else {
1070-								for (size_t i = 0; i < children.size(); i++) {
1071-									Node* child_ptr = children[i].get();
1072-									if (child_ptr != node) {
1073-										if (testSelector(child_ptr, pOS)) {
1074-											// if the selector matches the ofSelector add one
1075-											index++;
1076-										}
1077-									} else {
1078-										// We are at the pointer address of the target node
1079-										break;
1080+							}
1081+							if (isBool) {
1082+								index--;
1083+							}
1084+						} else {
1085+							for (size_t i = 0; i < children.size(); i++) {
1086+								Node* child_ptr = children[i].get();
1087+								if (child_ptr != node) {
1088+									if (testSelector(child_ptr, pOS)) {
1089+										// if the selector matches the ofSelector add one
1090+										index++;
1091 									}
1092+								} else {
1093+									// We are at the pointer address of the target node
1094+									break;
1095 								}
1096 							}
1097-						} else {
1098-							// the target node doesn't match the of selector then it can not
1099-							// be a match so return false no need to set matched to false and continue
1100-							return false;
1101 						}
1102+					} else {
1103+						// the target node doesn't match the of selector then it can not
1104+						// be a match so return false no need to set matched to false and continue
1105+						return false;
1106 					}
1107+				}
1108 
1109-					// Add one to index because CSS starts at 1
1110-					index++;
1111-	// Now we have the index of the node and we can compute if its a match
1112-	// this is done by calculating the An+B
1113-	// The An+B is calculated based on two things
1114-	// 	n must be >= 0
1115-	// 	n cannot be a float
1116-	// so we solve for n with (index-B)/A then we check those two conditions
1117-	// if nfound is false and A != 0 then we can just compare the two numbers
1118-	
1119-					// Given n+B A is implicitly 1, this will fail if A is set to 0
1120-					if (A == 0) {
1121-						A = 1;
1122+				// Add one to index because CSS starts at 1
1123+				index++;
1124+// Now we have the index of the node and we can compute if its a match
1125+// this is done by calculating the An+B
1126+// The An+B is calculated based on two things
1127+// 	n must be >= 0
1128+// 	n cannot be a float
1129+// so we solve for n with (index-B)/A then we check those two conditions
1130+// if nfound is false and A != 0 then we can just compare the two numbers
1131+
1132+				// Given n+B A is implicitly 1, this will fail if A is set to 0
1133+				if (A == 0) {
1134+					A = 1;
1135+				}
1136+
1137+				std::cout << "A: " << A << std::endl;
1138+				std::cout << "B: " << B << std::endl;
1139+				std::cout << "Sym: " << symbol << std::endl;
1140+				std::cout << "OF: " << ofSelector << std::endl;
1141+				std::cout << "Index: " << index << std::endl;
1142+
1143+				if (isBool) {
1144+					if (isEven) {
1145+						matched = index%2 == 0;
1146+					} else {
1147+						matched = index%2 != 0;
1148 					}
1149+				} else {
1150 					if (!nfound) {
1151 						matched = A == index;
1152 					} else {
1153 						matched = (index-B)/A >= 0 && (index-B)%A == 0;
1154 					}
1155-
1156 				}
1157+			} else {
1158+				// Here we didn't get a hit on any function selector, so we can assume its probally a attribute selector like focus or :checked
1159+
1160+				p.erase(0,1);
1161+
1162+				matched = attributes[p] == "true";
1163 			}
1164+
1165 			// If there are any pseudo elements we will just skip them
1166 			// with the transformers being replaced with pseudo elements
1167 			// we won't know all of them. Will need to have a function to strip 
1168diff --git a/src/parser.cc b/src/parser.cc
1169index 3cff12a..5b750e1 100755
1170--- a/src/parser.cc
1171+++ b/src/parser.cc
1172@@ -96,6 +96,10 @@ std::unordered_map<std::string, std::string> parseAttributes(std::string_view to
1173 				}
1174 			}
1175 
1176+			if (trimmedValue.length() == 0) {
1177+				trimmedValue = "true";
1178+			}
1179+
1180 			attrs[trimmedName] = trimmedValue;
1181 		}
1182 	}
1183@@ -1369,6 +1373,15 @@ std::vector<Unit> getUnit(std::string value) {
1184 				buffer.clear();
1185 			}
1186 
1187+		} else if (inQuotes) {
1188+			if (v == '"') continue;
1189+			Unit u;
1190+			u.type = UnitType::STRING;
1191+			UnitValue uv;
1192+			uv.CHAR = v;
1193+			u.value = uv;
1194+
1195+			units.push_back(u);
1196 		} else {
1197 			buffer.push_back(v);
1198 		}
1199@@ -1385,11 +1398,9 @@ Style parseCSS(std::istream& inputStream) {
1200 	// nowhitespace: value(can have whitespace); = property
1201 	// a selector name is anything before a { up to a ; or a }
1202 	std::vector<Style*> stack;
1203+	Style root{};
1204+	Style* current = &root;
1205 
1206-			//		change to a stack based tree
1207-
1208-	Style current{};
1209-	stack.push_back(&current);
1210 	// how to handle @import
1211 
1212 	std::string buffer;
1213@@ -1424,7 +1435,7 @@ Style parseCSS(std::istream& inputStream) {
1214 			// Parse the selector into its parts
1215 			std::vector<std::vector<std::string>> parts = parseSelectorParts(buffer);
1216 
1217-			if (current.selector.size() > 0) {
1218+			if (current->selector.size() > 0) {
1219 				// To be able to handle a substitution with a parent that has h1, h2
1220 				// we need to rebuild the selector so we can add new copies
1221 				std::vector<std::vector<std::string>> subd;
1222@@ -1446,11 +1457,11 @@ Style parseCSS(std::istream& inputStream) {
1223 						// Child: [[& .class, &, &]]
1224 						// Result: [[h1 .class, h1, h1]]
1225 						// 	   [[h2 .class, h2, h2]]
1226-						for (size_t e = 0; e < current.selector.size(); e++) {
1227+						for (size_t e = 0; e < current->selector.size(); e++) {
1228 							std::vector<std::string> temp;
1229 							for (size_t f = 0; f < parts[i].size(); f++) {
1230 								if (parts[i][f] == "&") {
1231-									for (auto p : current.selector[e]) {
1232+									for (auto p : current->selector[e]) {
1233 										temp.push_back(p);
1234 									}
1235 								} else {
1236@@ -1468,18 +1479,19 @@ Style parseCSS(std::istream& inputStream) {
1237 				parts = subd;
1238 			}
1239 
1240-			// Find who the parent is
1241+			stack.push_back(current);
1242+
1243 			Style newSheet{};
1244 			newSheet.selector = parts;
1245-			current.addChild(newSheet);
1246+			current->addChild(newSheet);
1247 
1248-			current = current.children.back();
1249+			current = &current->children.back();
1250 
1251 			// here we need to take the selector (buffer)
1252 			// and find out what type it is. Also need to manage the nesting
1253 			if (parts[0][0][0] == '@') {
1254 				if (parts[0][0] == "@container") {
1255-					current.type = StyleType::CONTAINER;
1256+					current->type = StyleType::CONTAINER;
1257 					bool hasName = false;
1258 					if (parts[0].size() >= 3) {
1259 						// @container not (width < 400px)
1260@@ -1487,7 +1499,7 @@ Style parseCSS(std::istream& inputStream) {
1261 							// @container (width > 400px) or|and (height > 400px)
1262 							if (parts[0].size() >= 5) {
1263 								if (parts[0][5] != "and" || parts[0][5] != "or") {
1264-									current.name = parts[0][2];
1265+									current->name = parts[0][2];
1266 									hasName = true;
1267 								}
1268 							}
1269@@ -1496,56 +1508,55 @@ Style parseCSS(std::istream& inputStream) {
1270 					// If a name is present then remove the name and tag from the selector
1271 					// else just remove the @container
1272 					if (hasName) {
1273-						current.selector[0] = std::vector<std::string>(current.selector[0].begin() + 3, current.selector[0].end());
1274+						current->selector[0] = std::vector<std::string>(current->selector[0].begin() + 3, current->selector[0].end());
1275 					} else {
1276-						current.selector[0] = std::vector<std::string>(current.selector[0].begin() + 1, current.selector[0].end());
1277+						current->selector[0] = std::vector<std::string>(current->selector[0].begin() + 1, current->selector[0].end());
1278 					}
1279 				} else if (parts[0][0] == "@counter-style") {
1280-					current.name = parts[0][2];
1281-					current.type = StyleType::COUNTER;
1282+					current->name = parts[0][2];
1283+					current->type = StyleType::COUNTER;
1284 				} else if (parts[0][0] == "@font-face") {
1285-					current.type = StyleType::FONTFACE;
1286+					current->type = StyleType::FONTFACE;
1287 				} else if (parts[0][0] == "@font-feature") {
1288-					current.type = StyleType::FONTFEATURE;
1289+					current->type = StyleType::FONTFEATURE;
1290 				} else if (parts[0][0] == "@swash") {
1291-					current.type = StyleType::SWASH;
1292+					current->type = StyleType::SWASH;
1293 				} else if (parts[0][0] == "@annotation") {
1294-					current.type = StyleType::ANNOTATION;
1295+					current->type = StyleType::ANNOTATION;
1296 				} else if (parts[0][0] == "@ornaments") {
1297-					current.type = StyleType::ORNAMENTS;
1298+					current->type = StyleType::ORNAMENTS;
1299 				} else if (parts[0][0] == "@stylistic") {
1300-					current.type = StyleType::STYLISTIC;
1301+					current->type = StyleType::STYLISTIC;
1302 				} else if (parts[0][0] == "@styleset") {
1303-					current.type = StyleType::STYLESET;
1304+					current->type = StyleType::STYLESET;
1305 				} else if (parts[0][0] == "@character-varient") {
1306-					current.type = StyleType::CHARACTERVARIANT;
1307+					current->type = StyleType::CHARACTERVARIANT;
1308 				} else if (parts[0][0] == "@font-palette-values") {
1309-					current.type = StyleType::FONTPALETTEVALUES;
1310-					current.name = parts[0][2];
1311+					current->type = StyleType::FONTPALETTEVALUES;
1312+					current->name = parts[0][2];
1313 				} else if (parts[0][0] == "@keyframes") {
1314-					current.type = StyleType::KEYFRAMES;
1315-					current.name = parts[0][2];
1316+					current->type = StyleType::KEYFRAMES;
1317+					current->name = parts[0][2];
1318 				} else if (parts[0][0] == "@layer") {
1319-					current.type = StyleType::LAYER;
1320+					current->type = StyleType::LAYER;
1321 				} else if (parts[0][0] == "@media") {
1322-					current.type = StyleType::MEDIA;
1323+					current->type = StyleType::MEDIA;
1324 				} else if (parts[0][0] == "@property") {
1325-					current.type = StyleType::PROPERTY;
1326-					current.name = parts[0][2];
1327+					current->type = StyleType::PROPERTY;
1328+					current->name = parts[0][2];
1329 				} else if (parts[0][0] == "@starting-style") {
1330-					current.type = StyleType::STARTINGSTYLE;
1331+					current->type = StyleType::STARTINGSTYLE;
1332 				}
1333 			} else {
1334-				current.type = StyleType::STYLE;
1335+				current->type = StyleType::STYLE;
1336 			}
1337 			
1338 
1339 			buffer.clear();
1340 		} else if (ch == '}') {
1341 				
1342-
1343-			if (stack.size() > 0) {
1344-				current = *stack.back();
1345+			if (!stack.empty()) {
1346+				current = stack.back();
1347 				stack.pop_back();
1348 			}
1349 
1350@@ -1573,7 +1584,7 @@ Style parseCSS(std::istream& inputStream) {
1351 
1352 				}
1353 
1354-				current.children.push_back(inlineRule);
1355+				current->addChild(inlineRule);
1356 
1357 			} else {
1358 				// end of a style property
1359@@ -1599,7 +1610,7 @@ Style parseCSS(std::istream& inputStream) {
1360 				}
1361 
1362 				if (key.length() > 2 && key[0] == '-' && key[1] == '-') {
1363-					current.variables[key] = getUnit(value);
1364+					current->variables[key] = getUnit(value);
1365 				} else {
1366 					KeyType keyENUM;
1367 
1368@@ -1608,7 +1619,7 @@ Style parseCSS(std::istream& inputStream) {
1369 					} else {
1370 						std::cout << "Invalid property name: " << key << std::endl;
1371 					}
1372-					current.properties[keyENUM] = getUnit(value); 
1373+					current->properties[keyENUM] = getUnit(value); 
1374 				}
1375 			}
1376 			buffer.clear();
1377@@ -1616,6 +1627,8 @@ Style parseCSS(std::istream& inputStream) {
1378 			buffer.push_back(ch);
1379 		}
1380 	}
1381+
1382+	return root;
1383 }
1384 
1385 std::unordered_map<KeyType, std::vector<Unit>> parseCSSInline(std::string inlineStyles) {
1386diff --git a/tests/css_parser.cc b/tests/css_parser.cc
1387index 9150bc3..1f8a086 100755
1388--- a/tests/css_parser.cc
1389+++ b/tests/css_parser.cc
1390@@ -30,16 +30,39 @@ void compareStyle(std::string selector, std::unordered_map<KeyType, std::vector<
1391 		}
1392 	}
1393 
1394+	size_t n = 0;
1395 	for (auto p : props) {
1396-		std::vector<Unit> f = p.second;
1397-		std::vector<Unit> s = style.properties[p.first];
1398+		std::vector<Unit> propsV = p.second;
1399+		std::vector<Unit> styleV = style.properties[p.first];
1400 		
1401-		REQUIRE(f.size() == s.size());
1402+		REQUIRE(propsV.size() == styleV.size());
1403+		INFO("----");
1404+		INFO(n);
1405+		INFO("--");
1406+
1407+		for (size_t i = 0; i < propsV.size(); i++) {
1408+			INFO(i);
1409+
1410+			REQUIRE(propsV[i].type == styleV[i].type);
1411 
1412-		for (size_t i = 0; i < f.size(); i++) {
1413-			REQUIRE(f[i].type == s[i].type);
1414 		}
1415+		n++;
1416+	}
1417+}
1418+
1419+std::vector<Unit> buildString(Unit start, std::string value) {
1420+	std::vector<Unit> units;
1421+	units.push_back(start);
1422+	
1423+	for (size_t i = 0; i < value.length(); i++) {
1424+		Unit u;
1425+		u.type = UnitType::STRING;
1426+		UnitValue uv;
1427+		uv.CHAR = value[i];
1428+		u.value = uv;
1429+		units.push_back(u);
1430 	}
1431+	return units;
1432 }
1433 
1434 void compareInlineStyles(std::string style, std::unordered_map<KeyType, std::vector<Unit>> targetProps) {
1435@@ -124,136 +147,140 @@ html#nested {
1436 	Style style = parseCSS(inputFile);
1437 
1438 	SECTION("parseCSS can parse simple CSS rules") {
1439+		UnitValue uv;
1440+		uv.UINT = 0xff0000;
1441+
1442 		compareStyle("h1", {
1443-				{"color", "red"}
1444-				}, handler.root.children[0],
1445-				SheetType::STYLE
1446+				{KeyType::COLOR, {{UnitType::HEX, uv}}}
1447+				}, style.children[0],
1448+				StyleType::STYLE
1449 				);
1450 	}
1451 
1452-
1453 	SECTION("parseCSS can parse a CSS rule with a child combinator") {
1454+		UnitValue uv;
1455+		uv.UINT = 0x800080;
1456 		compareStyle("h1 > #id", {
1457-				{"background", "purple"}
1458-				}, handler.root.children[1],
1459-				SheetType::STYLE
1460+				{KeyType::BACKGROUND, {{UnitType::HEX, uv}}}
1461+				}, style.children[1],
1462+				StyleType::STYLE
1463 				);
1464 	}
1465 
1466 	SECTION("parseCSS can parse a CSS rule with a pseudo class") {
1467+		UnitValue uv1;
1468+		UnitValue uv2;
1469+		uv2.FLOAT = 1;
1470+		UnitValue uv3;
1471+		uv3.FLOAT = 100;
1472+		UnitValue uv4;
1473+		uv4.FLOAT = 20;
1474 		compareStyle("div:checked", {
1475-				{"display", "flex"},
1476-				{"margin", "1px 100% 20vh"}
1477-				}, handler.root.children[2],
1478-				SheetType::STYLE
1479+				{KeyType::DISPLAY, {{UnitType::FLEX, uv1}}},
1480+				{KeyType::MARGIN, {{UnitType::PX, uv2},{UnitType::PERCENT, uv3},{UnitType::VH, uv4}}}
1481+				}, style.children[2],
1482+				StyleType::STYLE
1483 			);
1484 	}
1485 
1486 	SECTION("parseCSS can parse a the parent of a nested CSS rule") {
1487+		Unit u;
1488+		u.type = UnitType::URL;
1489+		UnitValue uv;
1490+		uv.INT = 19;
1491+		u.value = uv;
1492 		compareStyle("html#nested", {
1493-				{"background", "url(\"https://example.com\")"},
1494-				}, handler.root.children[3],
1495-				SheetType::STYLE
1496+				{KeyType::BACKGROUND, buildString(u,"https://example.com")},
1497+				}, style.children[3],
1498+				StyleType::STYLE
1499 			);
1500 	}
1501 
1502 	SECTION("parseCSS can parse a nested CSS rule without a &") {
1503 		// "html#nested h1[value=\"nested\"]"
1504 		// Child of html#nested
1505+		UnitValue uv;
1506+		uv.UINT = 0xff0000;
1507 		compareStyle("h1[value=\"nested\"]", {
1508-				{"color", "red"},
1509-				}, handler.root.children[3].children[0],
1510-				SheetType::STYLE
1511+				{KeyType::COLOR, {{UnitType::HEX, uv}}},
1512+				}, style.children[3].children[0],
1513+				StyleType::STYLE
1514 			);
1515 	}
1516 
1517 	SECTION("parseCSS can parse a nested CSS rule with a &") {
1518 		// TODO: With nested &, they will have to be computed at testSelector
1519 		// | but the tree structure still works because the parent selector must still match
1520+		UnitValue uv;
1521 		compareStyle("html#nested.class", {
1522-				{"border", "none"},
1523-				}, handler.root.children[3].children[1],
1524-				SheetType::STYLE
1525+				{KeyType::BORDER, {{UnitType::NONE,uv}}},
1526+				}, style.children[3].children[1],
1527+				StyleType::STYLE
1528 			);
1529 	}
1530 
1531 	SECTION("parseCSS can parse a parent CSS rule with a property in between sub-classes") {
1532+		UnitValue uv1;
1533+		uv1.FLOAT = 90;
1534+		UnitValue uv2;
1535+		UnitValue uv3;
1536+		uv3.FLOAT = 1;
1537+		UnitValue uv4;
1538+		uv4.UINT = 0xffc107;
1539+		UnitValue uv5;
1540+		uv5.UINT = 0x000000;
1541+		UnitValue uv6;
1542+		uv6.FLOAT = 10;
1543+		UnitValue uv7;
1544+		uv7.FLOAT = 2;
1545 		compareStyle(".notice", {
1546-				{"width", "90%"},
1547-				{"justify-content", "center"},
1548-				{"border-radius", "1rem"},
1549-				{"border", "black solid 2px"},
1550-				{"background-color", "#ffc107"},
1551-				{"color", "black"},
1552-				{"padding", "1rem"},
1553-				{"font-size", "10px"}
1554-				  }, handler.root.children[4],
1555-					SheetType::STYLE
1556+				{KeyType::WIDTH, {{UnitType::PERCENT, uv1}}},
1557+				{KeyType::JUSTIFY_CONTENT, {{UnitType::CENTER, uv2}}},
1558+				{KeyType::BORDER_RADIUS, {{UnitType::REM, uv3}}},
1559+				{KeyType::BORDER, {{UnitType::COLOR, uv5},{UnitType::SOLID, uv2}, {UnitType::PX, uv7}}},
1560+				{KeyType::BACKGROUND_COLOR, {{UnitType::COLOR, uv4}}},
1561+				{KeyType::COLOR, {{UnitType::COLOR, uv5}}},
1562+				{KeyType::PADDING, {{UnitType::REM, uv3}}},
1563+				{KeyType::FONT_SIZE, {{UnitType::PX, uv6}}}
1564+				  }, style.children[4],
1565+					StyleType::STYLE
1566 				  );
1567 	}
1568 
1569 	SECTION("parseCSS can parse a nested CSS rule with a pseudo element") {
1570+		Unit u1;
1571+		u1.type = UnitType::STRING;
1572+		UnitValue uv1;
1573+		uv1.CHAR = 'i';
1574+		u1.value = uv1;
1575+		Unit u2;
1576+		u2.type = UnitType::STRING;
1577+		UnitValue uv2;
1578+		uv2.CHAR = ' ';
1579+		u2.value = uv2;
1580 		compareStyle(".notice-heading::before", {
1581-				{"content", "\"i \""},
1582-				}, handler.root.children[4].children[0],
1583-				SheetType::STYLE
1584+				{KeyType::CONTENT, {u1,u2}},
1585+				}, style.children[4].children[0],
1586+				StyleType::STYLE
1587 			);
1588 	}
1589 
1590 	SECTION("parseCSS can parse a nested CSS rule with a &") {
1591+		UnitValue uv1;
1592+		uv1.UINT = 0xd81b60;
1593+		UnitValue uv2;
1594+		uv2.UINT = 0xffffff;
1595 		compareStyle(".notice.warning", {
1596-				{"background-color", "#d81b60"},
1597-				{"border-color", "#d81b60"},
1598-				{"color", "white"},
1599-				}, handler.root.children[4].children[1],
1600-				SheetType::STYLE
1601+				{KeyType::BACKGROUND_COLOR, {{UnitType::COLOR, uv1}}},
1602+				{KeyType::BORDER_COLOR, {{UnitType::COLOR, uv1}}},
1603+				{KeyType::COLOR, {{UnitType::COLOR, uv2}}},
1604+				}, style.children[4].children[1],
1605+				StyleType::STYLE
1606 			);
1607 	}
1608 
1609-
1610-
1611 }
1612-
1613-TEST_CASE("parseCSS can parse multiple selectors nested") {
1614-	 std::string cssContent = R"~~~(
1615-div, .class1 {
1616-	.class2 {
1617-		background: red;
1618-	}
1619-	&.class3 {
1620-		background: orange;
1621-	}
1622-}
1623-)~~~";
1624-
1625-	std::istringstream inputFile(cssContent);	
1626-
1627-	Window window;
1628-	window.CSS.parseStream(inputFile);
1629-
1630-	StyleHandler handler = window.CSS;
1631-	SECTION("multi selector test") {
1632-		// This is written kinda weird but it's correct because the CSS above compiles into:
1633-		// div .class2 && .class1 .class2
1634-		// So [0] should only be .class2 becuse if we are going through the tree the node has already matched on
1635-		// div, .class1
1636-		// Then the second case is different because we care about the order they are matched in due to &
1637-		// So we fully compile the selector
1638-		compareStyle(".class2", {
1639-				{"background", "red"}
1640-				  }, handler.root.children[0].children[0],
1641-				  SheetType::STYLE
1642-			    );	
1643-		compareStyle("div.class3, .class1.class3", {
1644-				{"background", "orange"}
1645-				  }, handler.root.children[0].children[1],
1646-				  SheetType::STYLE
1647-			    );
1648-		}
1649-
1650-}
1651-
1652-
1653+/*
1654 TEST_CASE("parseCSSInline can parse inline styles") {
1655 	SECTION("parseCSSInline can parse a single property with a ending ;") {
1656 		std::string inlineStyles = "background: yellow;";
1657@@ -285,4 +312,4 @@ TEST_CASE("parseCSSInline can parse inline styles") {
1658 				{"font-size", "10px"},
1659 				});
1660 	}
1661-}
1662+}*/
1663diff --git a/tests/css_selector.cc b/tests/css_selector.cc
1664index 669a079..518c553 100755
1665--- a/tests/css_selector.cc
1666+++ b/tests/css_selector.cc
1667@@ -77,7 +77,7 @@ TEST_CASE( "CSS Selection", "[css]" ) {
1668 		};
1669 	}
1670 	SECTION("parseSelectorParts can parse a selector with a decendent combinator") {
1671-		checkSelectorParts("div h1", {{"div", "h1"}});
1672+		checkSelectorParts("div h1", {{"div", " ", "h1"}});
1673 		BENCHMARK("div h1") {
1674 			return parseSelectorParts("div h1");
1675 		};
1676@@ -110,7 +110,7 @@ TEST_CASE( "CSS Selection", "[css]" ) {
1677 		checkSelectorParts("h1::before", {{"h1",":before"}});
1678 	}
1679 }
1680-/*
1681+
1682 TEST_CASE("testSelector", "[CSS]") {
1683 	std::string html = "<!DOCTYPE html>"
1684 			"<html>"
1685@@ -142,57 +142,57 @@ TEST_CASE("testSelector", "[CSS]") {
1686 
1687 
1688 	std::stringstream ss(html);
1689-	std::unique_ptr<Node> document = parseHTML(ss);
1690+	Node document = parseHTML(ss);
1691 
1692 	SECTION("testSelector can match a element given it's tagName") {
1693-		auto html = document->children[0].get();
1694+		auto html = document.children[0].get();
1695 		REQUIRE(testSelector(html, parseSelectorParts("html")));
1696 		REQUIRE_FALSE(testSelector(html, parseSelectorParts("h1")));
1697 	}
1698 	SECTION("testSelector can match a element by it's attributes only") {
1699-		auto link = document->children[0]->children[0]->children[1].get();
1700+		auto link = document.children[0]->children[0]->children[1].get();
1701 		REQUIRE(testSelector(link, parseSelectorParts("[rel=\"stylesheet\"]")));
1702 	}
1703 	SECTION("testSelector can match a element by it's attributes and tagName") {
1704-		auto link = document->children[0]->children[0]->children[1].get();
1705+		auto link = document.children[0]->children[0]->children[1].get();
1706 		REQUIRE(testSelector(link, parseSelectorParts("link[rel=\"stylesheet\"]")));
1707 		REQUIRE_FALSE(testSelector(link, parseSelectorParts("title[rel=\"stylesheet\"]")));
1708 	}
1709 	SECTION("testSelector can match a element by it's id only") {
1710-		auto h1 = document->children[0]->children[1]->children[0].get();
1711+		auto h1 = document.children[0]->children[1]->children[0].get();
1712 		REQUIRE(testSelector(h1, parseSelectorParts("#h1Tag")));
1713 	}
1714 	SECTION("testSelector can match a element by it's id and tagName") {
1715-		auto h1 = document->children[0]->children[1]->children[0].get();
1716+		auto h1 = document.children[0]->children[1]->children[0].get();
1717 		REQUIRE(testSelector(h1, parseSelectorParts("h1#h1Tag")));
1718 	}
1719 	SECTION("testSelector can match a element by it's class and not matach on a non class") {
1720-		auto p = document->children[0]->children[1]->children[1].get();
1721+		auto p = document.children[0]->children[1]->children[1].get();
1722 		REQUIRE(testSelector(p, parseSelectorParts(".class1")));
1723 		REQUIRE_FALSE(testSelector(p, parseSelectorParts(".class3")));
1724 	}
1725 	SECTION("testSelector can match a child combinator") {
1726-		auto h1 = document->children[0]->children[1]->children[0].get();
1727+		auto h1 = document.children[0]->children[1]->children[0].get();
1728 		REQUIRE(testSelector(h1, parseSelectorParts("body > h1")));
1729 		REQUIRE_FALSE(testSelector(h1, parseSelectorParts("html > h1")));
1730 	}
1731 	SECTION("testSelector can match a next sibling combinator") {
1732-		auto p = document->children[0]->children[1]->children[1].get();
1733+		auto p = document.children[0]->children[1]->children[1].get();
1734 		REQUIRE(testSelector(p, parseSelectorParts("h1 + p")));
1735 		REQUIRE_FALSE(testSelector(p, parseSelectorParts("h1 + div")));
1736 	}
1737 	SECTION("testSelector can match a descendant combinator") {
1738-		auto p = document->children[0]->children[1]->children[1].get();
1739+		auto p = document.children[0]->children[1]->children[1].get();
1740 		REQUIRE(testSelector(p, parseSelectorParts("body p")));
1741 		REQUIRE_FALSE(testSelector(p, parseSelectorParts("h1 p")));
1742 	}
1743 	SECTION("testSelector can match a subsequent-sibling combinator") {
1744-		auto p = document->children[0]->children[1]->children[1].get();
1745+		auto p = document.children[0]->children[1]->children[1].get();
1746 		REQUIRE(testSelector(p, parseSelectorParts("h1 ~ p")));
1747 		REQUIRE_FALSE(testSelector(p, parseSelectorParts("div ~ p")));
1748 	}
1749 	SECTION("testSelector can match a element with a pseudo class") {
1750-		auto input = document->children[0]->children[1]->children[3].get();
1751+		auto input = document.children[0]->children[1]->children[3].get();
1752 		// While not all pseudo classes are defined here, any that are defined
1753 		// with a attribute will match: ie <input disabled>
1754 		REQUIRE(testSelector(input, parseSelectorParts("input:required")));
1755@@ -200,33 +200,33 @@ TEST_CASE("testSelector", "[CSS]") {
1756 		REQUIRE_FALSE(testSelector(input, parseSelectorParts("input:enabled")));
1757 	}
1758 	SECTION("testSelector can match a element with first-child") {
1759-		auto h1 = document->children[0]->children[1]->children[0].get();
1760+		auto h1 = document.children[0]->children[1]->children[0].get();
1761 		REQUIRE(testSelector(h1, parseSelectorParts(":first-child")));
1762 	}
1763 	SECTION("testSelector can match a element with first-of-type") {
1764-		auto h1 = document->children[0]->children[1]->children[0].get();
1765+		auto h1 = document.children[0]->children[1]->children[0].get();
1766 		REQUIRE(testSelector(h1, parseSelectorParts(":first-of-type")));
1767 
1768-		auto li = document->children[0]->children[1]->children[4]->children[0].get();
1769+		auto li = document.children[0]->children[1]->children[4]->children[0].get();
1770 		REQUIRE(testSelector(li, parseSelectorParts(":first-of-type")));
1771 	}
1772 	SECTION("testSelector can match a element with last-child") {
1773-		auto textarea = document->children[0]->children[1]->children[10].get();
1774+		auto textarea = document.children[0]->children[1]->children[10].get();
1775 		REQUIRE(testSelector(textarea, parseSelectorParts(":last-child")));
1776 	}
1777 	SECTION("testSelector can match a element with last-of-type") {
1778-		auto h1 = document->children[0]->children[1]->children[0].get();
1779+		auto h1 = document.children[0]->children[1]->children[0].get();
1780 		// There is only one h1
1781 		REQUIRE(testSelector(h1, parseSelectorParts(":last-of-type")));
1782 
1783-		auto li = document->children[0]->children[1]->children[4]->children[0].get();
1784+		auto li = document.children[0]->children[1]->children[4]->children[0].get();
1785 		REQUIRE_FALSE(testSelector(li, parseSelectorParts(":last-of-type")));
1786 
1787-		li = document->children[0]->children[1]->children[4]->children[3].get();
1788+		li = document.children[0]->children[1]->children[4]->children[3].get();
1789 		REQUIRE(testSelector(li, parseSelectorParts(":last-of-type")));
1790 	}
1791 	SECTION("testselector can match multiple selectors") {
1792-		auto textarea = document->children[0]->children[1]->children[10].get();
1793+		auto textarea = document.children[0]->children[1]->children[10].get();
1794 		// should only match on :last-child
1795 		REQUIRE(testSelector(textarea, parseSelectorParts("h1, h1 ~p, :last-child")));
1796 		REQUIRE_FALSE(testSelector(textarea, parseSelectorParts("h1, h1 ~p, :first-child")));
1797@@ -241,22 +241,22 @@ TEST_CASE("testSelector", "[CSS]") {
1798 		};
1799 	}
1800 	SECTION("testSelector can match :is() selectors") {
1801-		auto input = document->children[0]->children[1]->children[3].get();
1802+		auto input = document.children[0]->children[1]->children[3].get();
1803 		REQUIRE(testSelector(input, parseSelectorParts(":is(h1, input, div)")));
1804 		REQUIRE_FALSE(testSelector(input, parseSelectorParts(":is(h1, html, div)")));
1805 	}
1806 	SECTION("testSelector can match :where() selectors") {
1807-		auto input = document->children[0]->children[1]->children[3].get();
1808+		auto input = document.children[0]->children[1]->children[3].get();
1809 		REQUIRE(testSelector(input, parseSelectorParts(":where(h1, input, div)")));
1810 		REQUIRE_FALSE(testSelector(input, parseSelectorParts(":where(h1, html, div)")));
1811 	}
1812 	SECTION("testSelector can match :not() selectors") {
1813-		auto input = document->children[0]->children[1]->children[3].get();
1814+		auto input = document.children[0]->children[1]->children[3].get();
1815 		REQUIRE(testSelector(input, parseSelectorParts(":not(h1, html, div)")));
1816 		REQUIRE_FALSE(testSelector(input, parseSelectorParts(":not(h1, input, div)")));
1817 	}
1818 	SECTION("testSelector can match nested :not(:is()) selectors") {
1819-		auto input = document->children[0]->children[1]->children[3].get();
1820+		auto input = document.children[0]->children[1]->children[3].get();
1821 		REQUIRE(testSelector(input, parseSelectorParts(":not(:is(h1, html, div))")));
1822 		REQUIRE_FALSE(testSelector(input, parseSelectorParts(":not(:is(h1, input, div))")));
1823 
1824@@ -265,12 +265,12 @@ TEST_CASE("testSelector", "[CSS]") {
1825 		};
1826 	}
1827 	SECTION("testSelector can match a :has() selector with a child combinator") {
1828-		auto body = document->children[0]->children[1].get();
1829+		auto body = document.children[0]->children[1].get();
1830 		REQUIRE(testSelector(body, parseSelectorParts("body:has(> h1)")));
1831 		REQUIRE_FALSE(testSelector(body, parseSelectorParts("body:has(> h1:required)")));
1832 	}
1833 	SECTION("testSelector can match a :has() selector with a next-sibling combinator") {
1834-		auto h1 = document->children[0]->children[1]->children[0].get();
1835+		auto h1 = document.children[0]->children[1]->children[0].get();
1836 		REQUIRE(testSelector(h1, parseSelectorParts("h1:has(+ p)")));
1837 		REQUIRE_FALSE(testSelector(h1, parseSelectorParts("h1:has(+ p:required)")));
1838 
1839@@ -280,7 +280,7 @@ TEST_CASE("testSelector", "[CSS]") {
1840 		};
1841 	}
1842 	SECTION("testSelector can match a :has() selector with a subsequent-sibling combinator") {
1843-		auto h1 = document->children[0]->children[1]->children[0].get();
1844+		auto h1 = document.children[0]->children[1]->children[0].get();
1845 		REQUIRE(testSelector(h1, parseSelectorParts("h1:has(~ input)")));
1846 		REQUIRE_FALSE(testSelector(h1, parseSelectorParts("h1:has(~ p:required)")));
1847 
1848@@ -291,7 +291,7 @@ TEST_CASE("testSelector", "[CSS]") {
1849 	}
1850 
1851 	SECTION("testSelector can match a :has() selector with a decendent combinator") {
1852-		auto html = document->children[0].get();
1853+		auto html = document.children[0].get();
1854 		REQUIRE(testSelector(html, parseSelectorParts("html:has(input)")));
1855 		REQUIRE_FALSE(testSelector(html, parseSelectorParts("html:has(p:required)")));
1856 
1857@@ -302,7 +302,7 @@ TEST_CASE("testSelector", "[CSS]") {
1858 	}
1859 
1860 	SECTION("testSelector can match a :is():has(:where()) selector") {
1861-		auto html = document->children[0].get();
1862+		auto html = document.children[0].get();
1863 		REQUIRE(testSelector(html, parseSelectorParts(":is(html, div, p):has(:where(html, input:checked, input))")));
1864 		REQUIRE_FALSE(testSelector(html, parseSelectorParts(":is(body, div, p):has(:where(html, input:checked, input))")));
1865 
1866@@ -314,14 +314,14 @@ TEST_CASE("testSelector", "[CSS]") {
1867 // |(d678a) Nth child selection                           |
1868 // +------------------------------------------------------+
1869 	SECTION("testSelector can match a :nth-child(even|odd)") {
1870-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1871+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1872 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(even)")));
1873 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(even)")));
1874 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(odd)")));
1875 	}
1876 
1877 	SECTION("testSelector can match a :nth-child(A)") {
1878-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1879+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1880 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2)")));
1881 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(2)")));
1882 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(1)")));
1883@@ -332,7 +332,7 @@ TEST_CASE("testSelector", "[CSS]") {
1884 	}
1885 
1886 	SECTION("testSelector can match a :nth-child(An)") {
1887-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1888+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1889 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2n)")));
1890 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(2n)")));
1891 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(3n)")));
1892@@ -343,7 +343,7 @@ TEST_CASE("testSelector", "[CSS]") {
1893 	}
1894 
1895 	SECTION("testSelector can match a :nth-child(An+B)") {
1896-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
1897+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
1898 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2n+1)")));
1899 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(2n+1)")));
1900 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(3n+1)")));
1901@@ -354,7 +354,7 @@ TEST_CASE("testSelector", "[CSS]") {
1902 	}
1903 
1904 	SECTION("testSelector can match a :nth-child(n+B)") {
1905-		auto li = document->children[0]->children[1]->children[4]->children[0].get();
1906+		auto li = document.children[0]->children[1]->children[4]->children[0].get();
1907 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(n+1)")));
1908 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(n-3)")));
1909 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(n+2)")));
1910@@ -365,14 +365,14 @@ TEST_CASE("testSelector", "[CSS]") {
1911 	}
1912 
1913 	SECTION("testSelector can match a :nth-child(An+B of type)") {
1914-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
1915+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
1916 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2n+1 of li)")));
1917 		REQUIRE_FALSE(testSelector(li, parseSelectorParts(":nth-child(2n+1 of ul)")));
1918 		REQUIRE_FALSE(testSelector(li, parseSelectorParts(":nth-child(3n+1 of li)")));
1919 	}
1920 
1921 	SECTION("testSelector can match a :nth-child(A of type)") {
1922-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1923+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1924 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2 of li)")));
1925 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(2 of li)")));
1926 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(2 of ul)")));
1927@@ -383,7 +383,7 @@ TEST_CASE("testSelector", "[CSS]") {
1928 	}
1929 
1930 	SECTION("testSelector can match a :nth-child(An of type)") {
1931-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1932+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1933 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(2n of li)")));
1934 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(2n of li)")));
1935 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(2n of ul)")));
1936@@ -394,7 +394,7 @@ TEST_CASE("testSelector", "[CSS]") {
1937 	}
1938 
1939 	SECTION("testSelector can match a :nth-child(n+B of type)") {
1940-		auto li = document->children[0]->children[1]->children[4]->children[0].get();
1941+		auto li = document.children[0]->children[1]->children[4]->children[0].get();
1942 		REQUIRE(testSelector(li, parseSelectorParts(":nth-child(n+1 of li)")));
1943 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-child(n-3 of li)")));
1944 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-child(n+1 of ul)")));
1945@@ -407,14 +407,14 @@ TEST_CASE("testSelector", "[CSS]") {
1946 	// |Nth last child                                        |
1947 	// +------------------------------------------------------+
1948 	SECTION("testSelector can match a :nth-last-child(even|odd)") {
1949-		auto li = document->children[0]->children[1]->children[4]->children[3].get();
1950+		auto li = document.children[0]->children[1]->children[4]->children[3].get();
1951 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(even)")));
1952 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(even)")));
1953 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(odd)")));
1954 	}
1955 
1956 	SECTION("testSelector can match a :nth-last-child(A)") {
1957-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
1958+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
1959 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2)")));
1960 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(2)")));
1961 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(1)")));
1962@@ -425,7 +425,7 @@ TEST_CASE("testSelector", "[CSS]") {
1963 	}
1964 
1965 	SECTION("testSelector can match a :nth-last-child(An)") {
1966-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
1967+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
1968 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2n)")));
1969 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(2n)")));
1970 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(3n)")));
1971@@ -436,7 +436,7 @@ TEST_CASE("testSelector", "[CSS]") {
1972 	}
1973 
1974 	SECTION("testSelector can match a :nth-last-child(An+B)") {
1975-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1976+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1977 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2n+1)")));
1978 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(2n+1)")));
1979 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(3n+1)")));
1980@@ -447,7 +447,7 @@ TEST_CASE("testSelector", "[CSS]") {
1981 	}
1982 
1983 	SECTION("testSelector can match a :nth-last-child(n+B)") {
1984-		auto li = document->children[0]->children[1]->children[4]->children[3].get();
1985+		auto li = document.children[0]->children[1]->children[4]->children[3].get();
1986 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(n+1)")));
1987 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(n-3)")));
1988 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(n+2)")));
1989@@ -458,14 +458,14 @@ TEST_CASE("testSelector", "[CSS]") {
1990 	}
1991 
1992 	SECTION("testSelector can match a :nth-last-child(An+B of type)") {
1993-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
1994+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
1995 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2n+1 of li)")));
1996 		REQUIRE_FALSE(testSelector(li, parseSelectorParts(":nth-last-child(2n+1 of ul)")));
1997 		REQUIRE_FALSE(testSelector(li, parseSelectorParts(":nth-last-child(3n+1 of li)")));
1998 	}
1999 
2000 	SECTION("testSelector can match a :nth-last-child(A of type)") {
2001-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
2002+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
2003 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2 of li)")));
2004 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(2 of li)")));
2005 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(2 of ul)")));
2006@@ -476,7 +476,7 @@ TEST_CASE("testSelector", "[CSS]") {
2007 	}
2008 
2009 	SECTION("testSelector can match a :nth-last-child(An of type)") {
2010-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
2011+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
2012 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(2n of li)")));
2013 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(2n of li)")));
2014 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(2n of ul)")));
2015@@ -487,7 +487,7 @@ TEST_CASE("testSelector", "[CSS]") {
2016 	}
2017 
2018 	SECTION("testSelector can match a :nth-last-child(n+B of type)") {
2019-		auto li = document->children[0]->children[1]->children[4]->children[3].get();
2020+		auto li = document.children[0]->children[1]->children[4]->children[3].get();
2021 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-child(n+1 of li)")));
2022 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-child(n-3 of li)")));
2023 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-child(n+1 of ul)")));
2024@@ -500,14 +500,14 @@ TEST_CASE("testSelector", "[CSS]") {
2025 	// |Nth last of type                                      |
2026 	// +------------------------------------------------------+
2027 	SECTION("testSelector can match a :nth-last-of-type(even|odd)") {
2028-		auto li = document->children[0]->children[1]->children[4]->children[3].get();
2029+		auto li = document.children[0]->children[1]->children[4]->children[3].get();
2030 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-of-type(even)")));
2031 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-of-type(even)")));
2032 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-of-type(odd)")));
2033 	}
2034 
2035 	SECTION("testSelector can match a :nth-last-of-type(A)") {
2036-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
2037+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
2038 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-of-type(2)")));
2039 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-of-type(2)")));
2040 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-of-type(1)")));
2041@@ -518,7 +518,7 @@ TEST_CASE("testSelector", "[CSS]") {
2042 	}
2043 
2044 	SECTION("testSelector can match a :nth-last-of-type(An)") {
2045-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
2046+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
2047 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-of-type(2n)")));
2048 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-of-type(2n)")));
2049 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-of-type(3n)")));
2050@@ -529,7 +529,7 @@ TEST_CASE("testSelector", "[CSS]") {
2051 	}
2052 
2053 	SECTION("testSelector can match a :nth-last-of-type(An+B)") {
2054-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
2055+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
2056 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-of-type(2n+1)")));
2057 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-of-type(2n+1)")));
2058 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-of-type(3n+1)")));
2059@@ -540,7 +540,7 @@ TEST_CASE("testSelector", "[CSS]") {
2060 	}
2061 
2062 	SECTION("testSelector can match a :nth-last-of-type(n+B)") {
2063-		auto li = document->children[0]->children[1]->children[4]->children[3].get();
2064+		auto li = document.children[0]->children[1]->children[4]->children[3].get();
2065 		REQUIRE(testSelector(li, parseSelectorParts(":nth-last-of-type(n+1)")));
2066 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-last-of-type(n-3)")));
2067 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-last-of-type(n+2)")));
2068@@ -555,14 +555,14 @@ TEST_CASE("testSelector", "[CSS]") {
2069 	// +------------------------------------------------------+
2070 
2071 	SECTION("testSelector can match a :nth-of-type(even|odd)") {
2072-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
2073+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
2074 		REQUIRE(testSelector(li, parseSelectorParts(":nth-of-type(even)")));
2075 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-of-type(even)")));
2076 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-of-type(odd)")));
2077 	}
2078 
2079 	SECTION("testSelector can match a :nth-of-type(A)") {
2080-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
2081+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
2082 		REQUIRE(testSelector(li, parseSelectorParts(":nth-of-type(2)")));
2083 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-of-type(2)")));
2084 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-of-type(1)")));
2085@@ -573,7 +573,7 @@ TEST_CASE("testSelector", "[CSS]") {
2086 	}
2087 
2088 	SECTION("testSelector can match a :nth-of-type(An)") {
2089-		auto li = document->children[0]->children[1]->children[4]->children[1].get();
2090+		auto li = document.children[0]->children[1]->children[4]->children[1].get();
2091 		REQUIRE(testSelector(li, parseSelectorParts(":nth-of-type(2n)")));
2092 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-of-type(2n)")));
2093 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-of-type(3n)")));
2094@@ -584,7 +584,7 @@ TEST_CASE("testSelector", "[CSS]") {
2095 	}
2096 
2097 	SECTION("testSelector can match a :nth-of-type(An+B)") {
2098-		auto li = document->children[0]->children[1]->children[4]->children[2].get();
2099+		auto li = document.children[0]->children[1]->children[4]->children[2].get();
2100 		REQUIRE(testSelector(li, parseSelectorParts(":nth-of-type(2n+1)")));
2101 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-of-type(2n+1)")));
2102 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-of-type(3n+1)")));
2103@@ -595,7 +595,7 @@ TEST_CASE("testSelector", "[CSS]") {
2104 	}
2105 
2106 	SECTION("testSelector can match a :nth-of-type(n+B)") {
2107-		auto li = document->children[0]->children[1]->children[4]->children[0].get();
2108+		auto li = document.children[0]->children[1]->children[4]->children[0].get();
2109 		REQUIRE(testSelector(li, parseSelectorParts(":nth-of-type(n+1)")));
2110 		REQUIRE(testSelector(li, parseSelectorParts("li:nth-of-type(n-3)")));
2111 		REQUIRE_FALSE(testSelector(li, parseSelectorParts("li:nth-of-type(n+2)")));
2112@@ -608,26 +608,26 @@ TEST_CASE("testSelector", "[CSS]") {
2113 // | Only child                                           |
2114 // +------------------------------------------------------+
2115 	SECTION("testselector can match :only-child") {
2116-		auto p = document->children[0]->children[1]->children[2]->children[0].get();
2117+		auto p = document.children[0]->children[1]->children[2]->children[0].get();
2118 
2119 		REQUIRE(testSelector(p, parseSelectorParts(":only-child")));
2120 	}
2121 
2122 	SECTION("testselector can match :only-of-type") {
2123-		auto h1 = document->children[0]->children[1]->children[0].get();
2124+		auto h1 = document.children[0]->children[1]->children[0].get();
2125 
2126 		REQUIRE(testSelector(h1, parseSelectorParts(":only-of-type")));
2127 	}
2128 
2129 	SECTION("testSelector can match :root") {
2130-		auto html = document->children[0].get();
2131+		auto html = document.children[0].get();
2132 		REQUIRE(testSelector(html, parseSelectorParts(":root")));
2133 	}
2134 
2135 // +------------------------------------------------------+
2136 // | Input checkes                                        |
2137 // +------------------------------------------------------+
2138-	"<body>"
2139+/*	"<body>"
2140 		"<h1 id=\"h1Tag\">Header</h1>"
2141 		"<p id=\"paragraph\" class=\"class1 class2\">This is some text for a simple test</p>"
2142 		"<div contenteditable=\"true\">"
2143@@ -647,55 +647,54 @@ TEST_CASE("testSelector", "[CSS]") {
2144 		"<textarea readonly></textarea>"
2145 		"<textarea disabled></textarea>"
2146 	"</body>"
2147-
2148+*/
2149 	SECTION("testSelector can match :read-only normal element") {
2150-		auto p = document->children[0]->children[1]->children[1].get();
2151+		auto p = document.children[0]->children[1]->children[1].get();
2152 		REQUIRE(testSelector(p, parseSelectorParts("p:read-only")));
2153 	}
2154 	SECTION("testSelector can match :read-write on a text input") {
2155-		auto input = document->children[0]->children[1]->children[3].get();
2156+		auto input = document.children[0]->children[1]->children[3].get();
2157 		REQUIRE(testSelector(input, parseSelectorParts("input[type=\"text\"]:read-write")));
2158 	}
2159 	SECTION("testSelector can match :read-only on a radio input") {
2160-		auto input = document->children[0]->children[1]->children[5].get();
2161+		auto input = document.children[0]->children[1]->children[5].get();
2162 		REQUIRE(testSelector(input, parseSelectorParts("input[type=\"radio\"]:read-only")));
2163 		REQUIRE_FALSE(testSelector(input, parseSelectorParts("input[type=\"radio\"]:read-write")));
2164 	}
2165 	SECTION("testSelector can match :read-only on a readonly text input") {
2166-		auto input = document->children[0]->children[1]->children[6].get();
2167+		auto input = document.children[0]->children[1]->children[6].get();
2168 		REQUIRE(testSelector(input, parseSelectorParts("input[type=\"text\"]:read-only")));
2169 	}
2170 	SECTION("testSelector can match :read-only on a disabled text input") {
2171-		auto input = document->children[0]->children[1]->children[7].get();
2172+		auto input = document.children[0]->children[1]->children[7].get();
2173 		REQUIRE(testSelector(input, parseSelectorParts("input[type=\"text\"]:read-only")));
2174 		REQUIRE(testSelector(input, parseSelectorParts("input[type=\"text\"]:disabled")));
2175 	}
2176 	SECTION("testSelector can match :read-write on a textarea") {
2177-		auto textarea = document->children[0]->children[1]->children[8].get();
2178+		auto textarea = document.children[0]->children[1]->children[8].get();
2179 		REQUIRE(testSelector(textarea, parseSelectorParts(":read-write")));
2180 	}
2181 	SECTION("testSelector can match :read-only on a readonly textarea") {
2182-		auto textarea = document->children[0]->children[1]->children[9].get();
2183+		auto textarea = document.children[0]->children[1]->children[9].get();
2184 		REQUIRE(testSelector(textarea, parseSelectorParts(":read-only")));
2185 	}
2186 	SECTION("testSelector can match :read-only on a disabled textarea") {
2187-		auto textarea = document->children[0]->children[1]->children[10].get();
2188+		auto textarea = document.children[0]->children[1]->children[10].get();
2189 		REQUIRE(testSelector(textarea, parseSelectorParts(":read-only")));
2190 	}
2191 	SECTION("testSelector can match :read-write on a contenteditable div") {
2192-		auto div = document->children[0]->children[1]->children[2].get();
2193+		auto div = document.children[0]->children[1]->children[2].get();
2194 		REQUIRE(testSelector(div, parseSelectorParts(":read-write")));
2195 	}
2196 // +------------------------------------------------------+
2197 // | Universal selector                                   |
2198 // +------------------------------------------------------+
2199 	SECTION("testSelector can match a universal selector") {
2200-		auto div = document->children[0]->children[1]->children[2].get();
2201+		auto div = document.children[0]->children[1]->children[2].get();
2202 		REQUIRE(testSelector(div, parseSelectorParts("*")));
2203 		REQUIRE(testSelector(div, parseSelectorParts("h1, *")));
2204 	}
2205 	// make for:
2206 	// pseudo elements
2207-	// *
2208 }
2209-*/
2210+