mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 03:49:42 +00:00
Bug 1121792 - Use more complete BCP47/RFC4647 language-range matching rather than simple prefix-dash match for the :lang() pseudo. r=emilio
This is a Selectors-4 enhancement to the spec for the :lang() pseudo-class. It seems Safari has been shipping this behavior for some time. Differential Revision: https://phabricator.services.mozilla.com/D174999
This commit is contained in:
parent
a69748ae88
commit
86e7ebd055
@ -774,9 +774,8 @@ bool Gecko_MatchLang(const Element* aElement, nsAtom* aOverrideLang,
|
||||
// from the parent we have to be prepared to look at all parent
|
||||
// nodes. The language itself is encoded in the LANG attribute.
|
||||
if (auto* language = aHasOverrideLang ? aOverrideLang : aElement->GetLang()) {
|
||||
return nsStyleUtil::DashMatchCompare(
|
||||
nsDependentAtomString(language), nsDependentString(aValue),
|
||||
nsASCIICaseInsensitiveStringComparator);
|
||||
return nsStyleUtil::LangTagCompare(nsAtomCString(language),
|
||||
NS_ConvertUTF16toUTF8(aValue));
|
||||
}
|
||||
|
||||
// Try to get the language from the HTTP header or if this
|
||||
@ -786,11 +785,10 @@ bool Gecko_MatchLang(const Element* aElement, nsAtom* aOverrideLang,
|
||||
nsAutoString language;
|
||||
aElement->OwnerDoc()->GetContentLanguage(language);
|
||||
|
||||
nsDependentString langString(aValue);
|
||||
NS_ConvertUTF16toUTF8 langString(aValue);
|
||||
language.StripWhitespace();
|
||||
for (auto const& lang : language.Split(char16_t(','))) {
|
||||
if (nsStyleUtil::DashMatchCompare(lang, langString,
|
||||
nsASCIICaseInsensitiveStringComparator)) {
|
||||
if (nsStyleUtil::LangTagCompare(NS_ConvertUTF16toUTF8(lang), langString)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/ExpandedPrincipal.h"
|
||||
#include "mozilla/intl/MozLocaleBindings.h"
|
||||
#include "mozilla/TextUtils.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -51,6 +53,63 @@ bool nsStyleUtil::DashMatchCompare(const nsAString& aAttributeValue,
|
||||
return result;
|
||||
}
|
||||
|
||||
bool nsStyleUtil::LangTagCompare(const nsACString& aAttributeValue,
|
||||
const nsACString& aSelectorValue) {
|
||||
class AutoLangId {
|
||||
public:
|
||||
AutoLangId() = delete;
|
||||
AutoLangId(const AutoLangId& aOther) = delete;
|
||||
explicit AutoLangId(const nsACString& aLangTag) : mIsValid(false) {
|
||||
mLangId = intl::ffi::unic_langid_new(&aLangTag, &mIsValid);
|
||||
}
|
||||
|
||||
~AutoLangId() { intl::ffi::unic_langid_destroy(mLangId); }
|
||||
|
||||
operator intl::ffi::LanguageIdentifier*() const { return mLangId; }
|
||||
bool IsValid() const { return mIsValid; }
|
||||
|
||||
void Reset(const nsACString& aLangTag) {
|
||||
intl::ffi::unic_langid_destroy(mLangId);
|
||||
mLangId = intl::ffi::unic_langid_new(&aLangTag, &mIsValid);
|
||||
}
|
||||
|
||||
private:
|
||||
intl::ffi::LanguageIdentifier* mLangId;
|
||||
bool mIsValid;
|
||||
};
|
||||
|
||||
if (aAttributeValue.IsEmpty() || aSelectorValue.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoLangId attrLangId(aAttributeValue);
|
||||
if (!attrLangId.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AutoLangId selectorId(aSelectorValue);
|
||||
if (!selectorId.IsValid()) {
|
||||
// If it was "invalid" because of a wildcard language subtag, replace that
|
||||
// with 'und' and try again.
|
||||
// XXX Should unic_langid_new handle the wildcard internally?
|
||||
if (aSelectorValue[0] == '*') {
|
||||
nsAutoCString temp(aSelectorValue);
|
||||
temp.Replace(0, 1, "und");
|
||||
selectorId.Reset(temp);
|
||||
if (!selectorId.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
intl::ffi::unic_langid_clear_language(selectorId);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return intl::ffi::unic_langid_matches(attrLangId, selectorId,
|
||||
/* match addrLangId as range */ false,
|
||||
/* match selectorId as range */ true);
|
||||
}
|
||||
|
||||
bool nsStyleUtil::ValueIncludes(const nsAString& aValueList,
|
||||
const nsAString& aValue,
|
||||
const nsStringComparator& aComparator) {
|
||||
|
@ -37,6 +37,9 @@ class nsStyleUtil {
|
||||
const nsAString& aSelectorValue,
|
||||
const nsStringComparator& aComparator);
|
||||
|
||||
static bool LangTagCompare(const nsACString& aAttributeValue,
|
||||
const nsACString& aSelectorValue);
|
||||
|
||||
static bool ValueIncludes(const nsAString& aValueList,
|
||||
const nsAString& aValue,
|
||||
const nsStringComparator& aComparator);
|
||||
|
Loading…
x
Reference in New Issue
Block a user