https://bugs.webkit.org/show_bug.cgi?id=141477
Reviewed by David Hyatt.
Source/WebCore:
Implements the ::marker pseudo element as per the CSS Pseudo-Element Module Level 4
spec., <https://drafts.csswg.org/css-pseudo-4> (Editor's Draft, 24 July 2017).
The ::marker pseudo element is a convenience pseudo element that allows a person to
style the appearance of a list item marker. For example, to render all list item
markers in bolded, blue text you would define a stylesheet with the following content:
li::marker {
color: blue;
font-weight: bold;
}
and this could be applied to a page that contains markup of the form:
<ol>
<li>Item 1</li>
<li>Item 2</li>
...
<li>Item N-1</li>
<li>Item N</li>
</ol>
Formerly to the achieve the same effect you would need to use a stylesheet of the form:
li {
color: blue;
font-weight: bold;
}
.list-item-content {
all: initial;
}
and then write your markup to have the form:
<ol>
<li><span class="list-item-content">Item 1</span></li>
<li><span class="list-item-content">Item 2</span></li>
...
<li><span class="list-item-content">Item N-1</span></li>
<li><span class="list-item-content">Item N</span></li>
</ol>
The ::marker pseudo element only supports stylizing all font properties and the color property
of a list item marker.
Tests: fast/lists/list-marker-with-display.html
http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements.html
http/wpt/css/css-pseudo-4/marker-color.html
http/wpt/css/css-pseudo-4/marker-font-properties.html
http/wpt/css/css-pseudo-4/marker-inherit-values.html
* css/CSSSelector.cpp:
(WebCore::CSSSelector::pseudoId): Return the pseudo id for the ::marker pseudo element.
* css/CSSSelector.h: Add enumerator PseudoElementMarker to the pseudo element enum.
* css/RuleSet.cpp:
(WebCore::determinePropertyWhitelistType): Return whitelist type PropertyWhitelistMarker for ::marker
so that we match rules against the acceptable rules for ::marker.
* css/RuleSet.h: Add enumerator PropertyWhitelistMarker to the property whitelist type enum.
* css/SelectorPseudoElementTypeMap.in: Add "marker" to the list of pseudo element types.
* css/StyleResolver.cpp:
(WebCore::isValidMarkerStyleProperty): Determines if the specified CSS property is valid inside ::marker.
(WebCore::StyleResolver::CascadedProperties::addMatch): Only recognize CSS properties in the content block
of ::marker that match the ::marker whitelist policy.
* rendering/RenderListItem.cpp:
(WebCore::RenderListItem::computeMarkerStyle): Computes the style object for the list item marker. We
apply the user-agent style to the marker here as opposed to defining ::marker in the UA sheet as per
the spec. as an optimization to avoid having the style resolver apply the pseudo element to all elements.
For now, we always inherit style from the originating element (list item). Added FIXME to selectively
inherit styles.
(WebCore::RenderListItem::styleDidChange): Always apply the list marker style to the list marker renderer.
* rendering/RenderListItem.h:
* rendering/style/RenderStyleConstants.h: Add pseudo ID for the ::marker pseudo element.
LayoutTests:
Add tests that check we respect ::marker when rendering the list item marker. I will
submit all the tests in http/wpt/css/css-pseudo-4 to the Web Platform Tests repository
shortly and then import them into the WebKit repository in a subsequent commit.
* fast/lists/list-marker-with-display-expected.html: Added.
* fast/lists/list-marker-with-display.html: Added.
* http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements-expected.html: Added.
* http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements.html: Added.
* http/wpt/css/css-pseudo-4/marker-color-expected.html: Added.
* http/wpt/css/css-pseudo-4/marker-color.html: Added.
* http/wpt/css/css-pseudo-4/marker-font-properties-expected.html: Added.
* http/wpt/css/css-pseudo-4/marker-font-properties.html: Added.
* http/wpt/css/css-pseudo-4/marker-inherit-values-expected.html: Added.
* http/wpt/css/css-pseudo-4/marker-inherit-values.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@220207
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-08-03 Daniel Bates <dabates@apple.com>
+
+ Support ::marker pseudo-element
+ https://bugs.webkit.org/show_bug.cgi?id=141477
+
+ Reviewed by David Hyatt.
+
+ Add tests that check we respect ::marker when rendering the list item marker. I will
+ submit all the tests in http/wpt/css/css-pseudo-4 to the Web Platform Tests repository
+ shortly and then import them into the WebKit repository in a subsequent commit.
+
+ * fast/lists/list-marker-with-display-expected.html: Added.
+ * fast/lists/list-marker-with-display.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements-expected.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-color-expected.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-color.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-font-properties-expected.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-font-properties.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-inherit-values-expected.html: Added.
+ * http/wpt/css/css-pseudo-4/marker-inherit-values.html: Added.
+
2017-08-03 Ms2ger <Ms2ger@igalia.com>
[GTK] Remove obsolete failure expectation for narrow-non-breaking-space.html.
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+ color: green;
+ display: list-item;
+ left: 40px;
+ position: absolute;
+}
+</style>
+</head>
+<body>
+<div>PASS</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+ color: green;
+ display: list-item;
+ left: 40px;
+ position: absolute;
+}
+
+div::marker {
+ display: list-item; /* Should be ignored. */
+}
+</style>
+</head>
+<body>
+<div>PASS</div>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker interaction with ::before, ::after, and ::first-letter pseudo elements reference file</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<style>
+li {
+ color: green;
+ font-size: 20px;
+}
+
+.first-letter {
+ color: white;
+ background-color: green;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li><span class="first-letter">P</span>ASSED if the list marker is green.</li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker interaction with ::before, ::after, and ::first-letter pseudo elements</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<link ref="match" href="marker-and-other-pseudo-elements-expected.html">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<meta name="assert" content="Tests ::marker interaction with ::before, ::after, and ::first-letter pseudo elements">
+<style>
+li {
+ color: red;
+ font-size: 20px;
+}
+
+li::before {
+ color: green;
+ content: "PA";
+}
+
+li::after {
+ color: green;
+ content: "SSED if the list marker is green.";
+}
+
+li::marker {
+ color: green;
+}
+
+li::first-letter {
+ color: white;
+ background-color: green;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker formatting with color property reference file</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<style>
+li {
+ color: green;
+ font-size: 40px;
+ list-style-type: square;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li><!-- The list marker should be a green square.--></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker formatting with color property</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<link ref="match" href="marker-color-expected.html">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<meta name="assert" content="Tests ::marker rendering with color property">
+<style>
+li {
+ color: red;
+ font-size: 40px;
+ list-style-type: square;
+}
+
+li::marker {
+ color: green;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li><!-- The list marker should be a green square.--></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker formatting with font properties reference file</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<style>
+li {
+ font-family: sans-serif;
+ font-size: 24px;
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ list-style-type: lower-alpha;
+ font-variant-numeric: tabular-nums;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker formatting with font properties</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<link ref="match" href="marker-font-properties-expected.html">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<meta name="assert" content="Tests ::marker rendering with font properties">
+<style>
+li {
+ list-style-type: lower-alpha;
+}
+
+li::marker {
+ font-family: sans-serif;
+ font-size: 24px;
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li><span style="font-size: 24px"><!-- FIXME: Needed to ensure consistent baseline position with expected result (why?). --></span></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker inherits values from originating element reference file</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<style>
+li {
+ color: green;
+ font-family: sans-serif;
+ font-size: x-large;
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ list-style-type: lower-alpha;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li></li>
+</ol>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Test: ::marker inherits values from originating element</title>
+<link rel="author" title="Daniel Bates" href="mailto:dbates@webkit.org">
+<link ref="match" href="marker-inherit-values-expected.html">
+<link rel="help" href="https://drafts.csswg.org/css-pseudo-4/#marker-pseudo">
+<meta name="assert" content="Tests ::marker inherits values from originating element">
+<style>
+ol {
+ color: red;
+}
+
+li { /* Originating element */
+ color: green;
+ font-family: sans-serif;
+ font-size: x-large;
+ font-style: italic;
+ font-variant: small-caps;
+ font-weight: bold;
+ list-style-type: lower-alpha;
+}
+
+li::marker {
+ color: inherit;
+ font-family: inherit;
+ font-size: inherit;
+ font-style: inherit;
+ font-variant: inherit;
+ font-weight: inherit;
+}
+</style>
+</head>
+<body>
+<ol>
+ <li></li>
+</ol>
+</body>
+</html>
+2017-08-03 Daniel Bates <dabates@apple.com>
+
+ Support ::marker pseudo-element
+ https://bugs.webkit.org/show_bug.cgi?id=141477
+
+ Reviewed by David Hyatt.
+
+ Implements the ::marker pseudo element as per the CSS Pseudo-Element Module Level 4
+ spec., <https://drafts.csswg.org/css-pseudo-4> (Editor's Draft, 24 July 2017).
+
+ The ::marker pseudo element is a convenience pseudo element that allows a person to
+ style the appearance of a list item marker. For example, to render all list item
+ markers in bolded, blue text you would define a stylesheet with the following content:
+
+ li::marker {
+ color: blue;
+ font-weight: bold;
+ }
+
+ and this could be applied to a page that contains markup of the form:
+
+ <ol>
+ <li>Item 1</li>
+ <li>Item 2</li>
+ ...
+ <li>Item N-1</li>
+ <li>Item N</li>
+ </ol>
+
+ Formerly to the achieve the same effect you would need to use a stylesheet of the form:
+
+ li {
+ color: blue;
+ font-weight: bold;
+ }
+
+ .list-item-content {
+ all: initial;
+ }
+
+ and then write your markup to have the form:
+
+ <ol>
+ <li><span class="list-item-content">Item 1</span></li>
+ <li><span class="list-item-content">Item 2</span></li>
+ ...
+ <li><span class="list-item-content">Item N-1</span></li>
+ <li><span class="list-item-content">Item N</span></li>
+ </ol>
+
+ The ::marker pseudo element only supports stylizing all font properties and the color property
+ of a list item marker.
+
+ Tests: fast/lists/list-marker-with-display.html
+ http/wpt/css/css-pseudo-4/marker-and-other-pseudo-elements.html
+ http/wpt/css/css-pseudo-4/marker-color.html
+ http/wpt/css/css-pseudo-4/marker-font-properties.html
+ http/wpt/css/css-pseudo-4/marker-inherit-values.html
+
+ * css/CSSSelector.cpp:
+ (WebCore::CSSSelector::pseudoId): Return the pseudo id for the ::marker pseudo element.
+ * css/CSSSelector.h: Add enumerator PseudoElementMarker to the pseudo element enum.
+ * css/RuleSet.cpp:
+ (WebCore::determinePropertyWhitelistType): Return whitelist type PropertyWhitelistMarker for ::marker
+ so that we match rules against the acceptable rules for ::marker.
+ * css/RuleSet.h: Add enumerator PropertyWhitelistMarker to the property whitelist type enum.
+ * css/SelectorPseudoElementTypeMap.in: Add "marker" to the list of pseudo element types.
+ * css/StyleResolver.cpp:
+ (WebCore::isValidMarkerStyleProperty): Determines if the specified CSS property is valid inside ::marker.
+ (WebCore::StyleResolver::CascadedProperties::addMatch): Only recognize CSS properties in the content block
+ of ::marker that match the ::marker whitelist policy.
+ * rendering/RenderListItem.cpp:
+ (WebCore::RenderListItem::computeMarkerStyle): Computes the style object for the list item marker. We
+ apply the user-agent style to the marker here as opposed to defining ::marker in the UA sheet as per
+ the spec. as an optimization to avoid having the style resolver apply the pseudo element to all elements.
+ For now, we always inherit style from the originating element (list item). Added FIXME to selectively
+ inherit styles.
+ (WebCore::RenderListItem::styleDidChange): Always apply the list marker style to the list marker renderer.
+ * rendering/RenderListItem.h:
+ * rendering/style/RenderStyleConstants.h: Add pseudo ID for the ::marker pseudo element.
+
2017-08-03 Antti Koivisto <antti@apple.com>
Factor common code in Style::*ChangeInvalidation into helper functions
return FIRST_LETTER;
case PseudoElementSelection:
return SELECTION;
+ case PseudoElementMarker:
+ return MARKER;
case PseudoElementBefore:
return BEFORE;
case PseudoElementAfter:
#endif
PseudoElementFirstLetter,
PseudoElementFirstLine,
+ PseudoElementMarker,
PseudoElementResizer,
PseudoElementScrollbar,
PseudoElementScrollbarButton,
{
if (addRuleFlags & RuleIsInRegionRule)
return PropertyWhitelistRegion;
-#if ENABLE(VIDEO_TRACK)
for (const CSSSelector* component = selector; component; component = component->tagHistory()) {
+#if ENABLE(VIDEO_TRACK)
if (component->match() == CSSSelector::PseudoElement && (component->pseudoElementType() == CSSSelector::PseudoElementCue || component->value() == TextTrackCue::cueShadowPseudoId()))
return PropertyWhitelistCue;
- }
-#else
- UNUSED_PARAM(selector);
#endif
+ if (component->match() == CSSSelector::PseudoElement && component->pseudoElementType() == CSSSelector::PseudoElementMarker)
+ return PropertyWhitelistMarker;
+ }
return PropertyWhitelistNone;
}
enum PropertyWhitelistType {
PropertyWhitelistNone = 0,
+ PropertyWhitelistMarker,
PropertyWhitelistRegion,
#if ENABLE(VIDEO_TRACK)
PropertyWhitelistCue
#endif
first-letter
first-line
+marker
placeholder, PseudoElementWebKitCustom
-webkit-input-placeholder, PseudoElementWebKitCustomLegacyPrefixed
-webkit-resizer
return false;
}
+// https://www.w3.org/TR/css-pseudo-4/#marker-pseudo (Editor's Draft, 25 July 2017)
+static inline bool isValidMarkerStyleProperty(CSSPropertyID id)
+{
+ switch (id) {
+ case CSSPropertyColor:
+ case CSSPropertyFontFamily:
+ case CSSPropertyFontFeatureSettings:
+ case CSSPropertyFontSize:
+ case CSSPropertyFontStretch:
+ case CSSPropertyFontStyle:
+ case CSSPropertyFontSynthesis:
+ case CSSPropertyFontVariantAlternates:
+ case CSSPropertyFontVariantCaps:
+ case CSSPropertyFontVariantEastAsian:
+ case CSSPropertyFontVariantLigatures:
+ case CSSPropertyFontVariantNumeric:
+ case CSSPropertyFontVariantPosition:
+ case CSSPropertyFontWeight:
+#if ENABLE(VARIATION_FONTS)
+ case CSSPropertyFontOpticalSizing:
+ case CSSPropertyFontVariationSettings:
+#endif
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
// http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
// FIXME: Add incremental support for other region styling properties.
static inline bool isValidRegionStyleProperty(CSSPropertyID id)
if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(propertyID))
continue;
#endif
+ if (propertyWhitelistType == PropertyWhitelistMarker && !isValidMarkerStyleProperty(propertyID))
+ continue;
if (shouldApplyPropertyInParseOrder(propertyID))
setDeferred(propertyID, *current.value(), matchedProperties.linkMatchType, cascadeLevel, matchedProperties.styleScopeOrdinal);
#include "config.h"
#include "RenderListItem.h"
+#include "CSSFontSelector.h"
#include "ElementTraversal.h"
#include "HTMLNames.h"
#include "HTMLOListElement.h"
RenderBlockFlow::willBeDestroyed();
}
+RenderStyle RenderListItem::computeMarkerStyle() const
+{
+ // The marker always inherits from the list item, regardless of where it might end
+ // up (e.g., in some deeply nested line box). See CSS3 spec.
+ // FIXME: The marker should only inherit all font properties and the color property
+ // according to the CSS Pseudo-Elements Module Level 4 spec.
+ //
+ // Although the CSS Pseudo-Elements Module Level 4 spec. saids to add ::marker to the UA sheet
+ // we apply it here as an optimization because it only applies to markers. That is, it does not
+ // apply to all elements.
+ RenderStyle parentStyle = RenderStyle::clone(style());
+ auto fontDescription = style().fontDescription();
+ fontDescription.setVariantNumericSpacing(FontVariantNumericSpacing::TabularNumbers);
+ parentStyle.setFontDescription(fontDescription);
+ parentStyle.fontCascade().update(&document().fontSelector());
+
+ if (auto markerStyle = getCachedPseudoStyle(MARKER, &parentStyle))
+ return RenderStyle::clone(*markerStyle);
+ auto markerStyle = RenderStyle::create();
+ markerStyle.inheritFrom(parentStyle);
+ return markerStyle;
+}
+
void RenderListItem::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlockFlow::styleDidChange(diff, oldStyle);
return;
}
- auto newStyle = RenderStyle::create();
- // The marker always inherits from the list item, regardless of where it might end
- // up (e.g., in some deeply nested line box). See CSS3 spec.
- newStyle.inheritFrom(style());
- if (!m_marker) {
+ auto newStyle = computeMarkerStyle();
+ if (m_marker)
+ m_marker->setStyle(WTFMove(newStyle));
+ else {
m_marker = createRenderer<RenderListMarker>(*this, WTFMove(newStyle)).leakPtr();
m_marker->initializeStyle();
- } else {
- // Do not alter our marker's style unless our style has actually changed.
- if (diff != StyleDifferenceEqual)
- m_marker->setStyle(WTFMove(newStyle));
}
}
void updateValueNow() const;
void explicitValueChanged();
+ RenderStyle computeMarkerStyle() const;
+
int m_explicitValue;
RenderListMarker* m_marker;
mutable int m_value;
// Static pseudo styles. Dynamic ones are produced on the fly.
enum PseudoId : unsigned char {
// The order must be NOP ID, public IDs, and then internal IDs.
- NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, SCROLLBAR,
+ NOPSEUDO, FIRST_LINE, FIRST_LETTER, MARKER, BEFORE, AFTER, SELECTION, SCROLLBAR,
// Internal IDs follow:
SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
AFTER_LAST_INTERNAL_PSEUDOID,