Skip to content

Commit

Permalink
WIP: Counters
Browse files Browse the repository at this point in the history
  • Loading branch information
AtkinsSJ committed Jul 15, 2024
1 parent 2ba69ac commit 92bcb5a
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 9 deletions.
13 changes: 9 additions & 4 deletions Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
Expand All @@ -11,6 +11,7 @@
#include <LibWeb/CSS/StyleProperties.h>
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
Expand Down Expand Up @@ -646,7 +647,7 @@ Optional<CSS::Clear> StyleProperties::clear() const
return value_id_to_clear(value->to_identifier());
}

StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 initial_quote_nesting_level) const
StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(DOM::Element& element, u32 initial_quote_nesting_level) const
{
auto value = property(CSS::PropertyID::Content);
auto quotes_data = quotes();
Expand Down Expand Up @@ -709,8 +710,10 @@ StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 in
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
break;
}
} else if (item->is_counter()) {
builder.append(item->as_counter().resolve(element.ensure_counters_set()));
} else {
// TODO: Implement counters, images, and other things.
// TODO: Implement images, and other things.
dbgln("`{}` is not supported in `content` (yet?)", item->to_string());
}
}
Expand All @@ -722,8 +725,10 @@ StyleProperties::ContentDataAndQuoteNestingLevel StyleProperties::content(u32 in
for (auto const& item : content_style_value.alt_text()->values()) {
if (item->is_string()) {
alt_text_builder.append(item->as_string().string_value());
} else if (item->is_counter()) {
alt_text_builder.append(item->as_counter().resolve(element.ensure_counters_set()));
} else {
// TODO: Implement counters
dbgln("`{}` is not supported in `content` alt-text (yet?)", item->to_string());
}
}
content_data.alt_text = MUST(alt_text_builder.to_string());
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/CSS/StyleProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class StyleProperties : public RefCounted<StyleProperties> {
CSS::ContentData content_data;
u32 final_quote_nesting_level { 0 };
};
ContentDataAndQuoteNestingLevel content(u32 initial_quote_nesting_level) const;
ContentDataAndQuoteNestingLevel content(DOM::Element&, u32 initial_quote_nesting_level) const;
Optional<CSS::Cursor> cursor() const;
Optional<CSS::WhiteSpace> white_space() const;
Optional<CSS::LineStyle> line_style(CSS::PropertyID) const;
Expand Down
19 changes: 19 additions & 0 deletions Userland/Libraries/LibWeb/CSS/StyleValues/CounterStyleValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ CounterStyleValue::CounterStyleValue(CounterFunction function, ValueComparingNon

CounterStyleValue::~CounterStyleValue() = default;

String CounterStyleValue::resolve(CountersSet& counters_set) const
{
// counter( <counter-name>, <counter-style>? )
if (m_properties.function == CounterFunction::Counter) {
StringBuilder stb;
auto counter = counters_set.last_counter_with_name(m_properties.counter_name->to_string());
if (!counter.has_value()) {
// "If no counter named <counter-name> exists on an element where counter() or counters() is used,
// one is first instantiated with a starting value of 0."
counters_set.
}

return stb.to_string_without_validation();
}
// counters( <counter-name>, <string>, <counter-style>? )
StringBuilder stb;
return stb.to_string_without_validation();
}

// https://drafts.csswg.org/cssom-1/#ref-for-typedef-counter
String CounterStyleValue::to_string() const
{
Expand Down
3 changes: 3 additions & 0 deletions Userland/Libraries/LibWeb/CSS/StyleValues/CounterStyleValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include "LibWeb/CSS/CountersSet.h"
#include <LibWeb/CSS/StyleValue.h>

namespace Web::CSS {
Expand Down Expand Up @@ -33,6 +34,8 @@ class CounterStyleValue : public StyleValueWithDefaultOperators<CounterStyleValu
auto counter_style() const { return m_properties.counter_style; }
auto join_string() const { return m_properties.join_string; }

String resolve(CountersSet&) const;

virtual String to_string() const override;

bool properties_equal(CounterStyleValue const& other) const;
Expand Down
11 changes: 8 additions & 3 deletions Userland/Libraries/LibWeb/DOM/Element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2671,14 +2671,19 @@ Optional<CSS::CountersSet const&> Element::counters_set()
return *m_counters_set;
}

CSS::CountersSet& Element::ensure_counters_set()
{
if (!m_counters_set)
m_counters_set = make<CSS::CountersSet>();
return *m_counters_set;
}

// https://drafts.csswg.org/css-lists-3/#instantiate-counter
void Element::instantiate_a_counter(FlyString name, bool reversed, Optional<CSS::CounterValue> value)
{
// 1. Let counters be element’s CSS counters set.
// NOTE: We use nullptr for an empty CountersSet, so must ensure it exists here.
if (!has_non_empty_counters_set())
m_counters_set = make<CSS::CountersSet>();
auto& counters = *m_counters_set;
auto& counters = ensure_counters_set();

// 2. Let innermost counter be the last counter in counters with the name name.
// If innermost counter’s originating element is element or a previous sibling of element,
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/DOM/Element.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ class Element

bool has_non_empty_counters_set() const { return m_counters_set; }
Optional<CSS::CountersSet const&> counters_set();
CSS::CountersSet& ensure_counters_set();
void instantiate_a_counter(FlyString name, bool reversed, Optional<CSS::CounterValue>);
void inherit_counters();

Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ void TreeBuilder::create_pseudo_element_if_needed(DOM::Element& element, CSS::Se
return;

auto initial_quote_nesting_level = m_quote_nesting_level;
auto [pseudo_element_content, final_quote_nesting_level] = pseudo_element_style->content(initial_quote_nesting_level);
auto [pseudo_element_content, final_quote_nesting_level] = pseudo_element_style->content(element, initial_quote_nesting_level);
m_quote_nesting_level = final_quote_nesting_level;
auto pseudo_element_display = pseudo_element_style->display();
// ::before and ::after only exist if they have content. `content: normal` computes to `none` for them.
Expand Down

0 comments on commit 92bcb5a

Please sign in to comment.