Skip to content

Commit bcdebff

Browse files
committed
Resolve <system-color> and <deprecated-color> with the element color scheme
w3c/csswg-drafts#13857 updated the algorithm to determine the color scheme that must be used to resolve <system-color> and <deprecated-color>. Besides, the implementation used the cascading value instead of the specified value of "color-scheme", and was not really making an effort to show that the user preferred and UA supported color schemes must be defined somehow in jsdom by its user and resolved somehow in this library. Similarly, the color scheme of embedded elements must consider the color scheme of the embedding element, which is specified as being received by the embedding document. So this part is also the responsibility of jsdom, since access to ".frameElement" may be disallowed by the cross-origin policy (which does not seem to be implemented in jsdom though).
1 parent dc2dcf5 commit bcdebff

1 file changed

Lines changed: 99 additions & 26 deletions

File tree

lib/resolve.js

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -655,52 +655,125 @@ function getSpecifiedValue(property, element, declared = getDeclaredValues(prope
655655

656656
// Resolving the computed and used value
657657

658+
/**
659+
* @param {string[]} UASupport
660+
* @param {object[]|null} support
661+
* @param {string|null} preference
662+
* @returns {*[]}
663+
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme}
664+
*/
665+
function getUsedColorScheme(UASupport, support = null, preference = null) {
666+
667+
// Assert: the first UA supported color scheme is its default color scheme
668+
669+
if (!support?.some(scheme => UASupport.includes(scheme[0].value))) {
670+
return [UASupport[0], true]
671+
}
672+
673+
const [schemes, only] = support
674+
675+
if (!preference) {
676+
return [schemes[0].value]
677+
}
678+
679+
preference = preference.split('overriding-')
680+
let overriding
681+
if (preference.length === 2) {
682+
overriding = true
683+
preference = preference[1]
684+
} else {
685+
overriding = false
686+
preference = preference[0]
687+
}
688+
689+
if (schemes.some(scheme => scheme.value === preference)) {
690+
return [preference]
691+
}
692+
if (!isOmitted(only)) {
693+
return [schemes[0].value]
694+
}
695+
if (overriding) {
696+
return [preference]
697+
}
698+
return [schemes[0].value]
699+
}
700+
658701
/**
659702
* @param {Element} element
660-
* @returns {object|object[][]|undefined}
703+
* @returns {string|null}
704+
*/
705+
function getEmbbedingElementColorScheme(element) {
706+
return null
707+
}
708+
709+
/**
710+
* @param {Element} element
711+
* @returns {object[]|null}
712+
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#pages-supported-color-scheme}
661713
* @see {@link https://html.spec.whatwg.org/multipage/semantics.html#meta-color-scheme}
662714
*/
663-
function getPageSupportedColorSchemes(element) {
664-
const { ownerDocument } = element
665-
if (!ownerDocument) {
666-
return
667-
}
715+
function getPageSupportedColorSchemes({ ownerDocument }) {
668716
const selector = parseGrammar('meta[name=color-scheme][content]', '<selector-list>')
669717
const definition = properties['color-scheme'].value
670718
for (const meta of matchTreesAgainstSelectors([ownerDocument], selector)) {
671719
const colorScheme = parseGrammar(meta.getAttribute('content'), definition)
672-
if (!isFailure(colorScheme)) {
673-
return colorScheme
720+
if (isFailure(colorScheme)) {
721+
continue
722+
}
723+
if (colorScheme.value === 'normal') {
724+
return null
674725
}
726+
return colorScheme
675727
}
728+
if (ownerDocument.defaultView.frameElement) {
729+
return getEmbbedingElementColorScheme(element)
730+
}
731+
return null
732+
}
733+
734+
/**
735+
* @param {Element} element
736+
* @returns {string|null}
737+
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#preferred-color-scheme}
738+
*/
739+
function getUserPreferredColorScheme(element) {
740+
return null
741+
}
742+
743+
/**
744+
* @param {Element} element
745+
* @returns {string[]}
746+
*/
747+
function getUASupportedColorScheme(element) {
748+
return ['light', 'dark']
676749
}
677750

678751
/**
679752
* @param {Element} element
680-
* @returns {string|undefined}
681-
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#propdef-color-scheme}
753+
* @returns {*[]}
754+
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#page-color-scheme}
682755
*/
683-
function getElementSupportedColorSchemes(element) {
684-
return getCascadedValue('color-scheme', element)?.value
756+
function getPageColorScheme(element) {
757+
return getUsedColorScheme(
758+
getUASupportedColorScheme(element),
759+
getPageSupportedColorSchemes(element),
760+
getUserPreferredColorScheme(element))
685761
}
686762

687763
/**
688764
* @param {Element} element
689765
* @returns {string}
690-
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#determine-the-used-color-scheme}
766+
* @see {@link https://drafts.csswg.org/css-color-adjust-1/#element-color-scheme}
691767
*/
692-
function getUsedColorScheme(element) {
693-
const supported = getElementSupportedColorSchemes(element) || getPageSupportedColorSchemes(element)
694-
if (supported) {
695-
if (supported.value === 'normal') {
696-
return 'light'
697-
}
698-
const preferred = supported[0].find(({ value }) => value === 'dark' || value === 'light')
699-
if (preferred) {
700-
return preferred.value
701-
}
768+
function getElementColorScheme(element) {
769+
const support = getSpecifiedValue('color-scheme', element)
770+
if (support.value === 'normal') {
771+
return getPageColorScheme(element)[0]
702772
}
703-
return 'light'
773+
return getUsedColorScheme(
774+
getUASupportedColorScheme(element),
775+
support,
776+
getUserPreferredColorScheme(element))[0]
704777
}
705778

706779
/**
@@ -714,13 +787,13 @@ function getComputedColor(value, element) {
714787
return parseGrammar('rgb(0, 0, 0, 0)', '<color>')
715788
}
716789
if (value.types.includes('<deprecated-color>')) {
717-
return parseGrammar(colors.system[colors.deprecated[value.value]][getUsedColorScheme(element)], '<color>')
790+
return parseGrammar(colors.system[colors.deprecated[value.value]][getElementColorScheme(element)], '<color>')
718791
}
719792
if (value.types.includes('<named-color>')) {
720793
return parseGrammar(colors.named[value.value], '<color>')
721794
}
722795
if (value.types.includes('<system-color>')) {
723-
return parseGrammar(colors.system[value.value][getUsedColorScheme(element)], '<color>')
796+
return parseGrammar(colors.system[value.value][getElementColorScheme(element)], '<color>')
724797
}
725798
return value
726799
}

0 commit comments

Comments
 (0)