-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: open usage of data-* and aria-* attributes in CSS #632
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,11 @@ import { | |
} from 'postcss-selector-parser'; | ||
|
||
import { | ||
GLOBAL_ATTRIBUTE_SET, | ||
isValidAttribute, | ||
} from './html-attributes'; | ||
isGlobalAttribute, | ||
isAriaAttribute, | ||
isDataAttribute, | ||
isKnowAttributeOnElement, | ||
} from '../helpers/html-attributes'; | ||
|
||
const DEPRECATED_SELECTORS = new Set(['/deep/', '::shadow', '>>>']); | ||
const UNSUPPORTED_SELECTORS = new Set(['::slotted', ':root', ':host-context']); | ||
|
@@ -47,18 +49,17 @@ function validateSelectors(root: Root) { | |
function validateAttribute(root: Root) { | ||
root.walk(node => { | ||
if (isAttribute(node)) { | ||
const { attribute, sourceIndex } = node; | ||
const { attribute: attributeName, sourceIndex } = node; | ||
|
||
// Global HTML attributes are valid on all the element, custom or not. | ||
const isGlobalHTMLAttribute = GLOBAL_ATTRIBUTE_SET.has(attribute); | ||
if (isGlobalHTMLAttribute) { | ||
// Let's check if the attribute name is either a Global HTML attribute, an ARIA attribute | ||
// or a data-* attribute since those are available on all the elements. | ||
if (isGlobalAttribute(attributeName) || isAriaAttribute(attributeName) || isDataAttribute(attributeName)) { | ||
return; | ||
} | ||
|
||
// If the attribute is not a global one we need to validate it's usage. Walking | ||
// backward the selector chain to find a tag selector in the compound selector. | ||
// The lookup stop when either a tag is found or when reaching the next | ||
// combinator - which indicates the end of the compound selector. | ||
// If the attribute name is not a globally available attribute, the attribute selector is required | ||
// to be associated with a tag selector, so we can validate it's usage. Let's walk the compound selector | ||
// backward to find the associated tag selector. | ||
let tagSelector: Tag | undefined = undefined; | ||
let runner = node.prev(); | ||
|
||
|
@@ -74,31 +75,35 @@ function validateAttribute(root: Root) { | |
} | ||
} | ||
|
||
// Error out when not tag selector is present in the compound selector. | ||
if (!tagSelector) { | ||
// If the tag selector is not present in the compound selector, we need to warn the user that | ||
// the compound selector need to be more specific. | ||
if (tagSelector === undefined) { | ||
const message = [ | ||
`Attribute selector "${node}" is too generic. `, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Add a tag selector to validate the usage of the attribute selector" doesn't sound quite right because it sounds vague without the right context. What do you think about:
|
||
`Add a tag selector to validate the usage of the attribute selector.`, | ||
]; | ||
|
||
throw root.error( | ||
`Selector "${node}" is too generic, add a tag selector.`, | ||
message.join(''), | ||
{ | ||
index: sourceIndex, | ||
word: attribute, | ||
}, | ||
word: attributeName, | ||
} | ||
); | ||
} | ||
|
||
// Check if the attribute is permitted for the considered tag. | ||
const isValidSelector = isValidAttribute( | ||
tagSelector.value, | ||
attribute, | ||
); | ||
if (!isValidSelector) { | ||
// If compound selector is associated with a tag selector, we can validate the usage of the | ||
// attribute against the specific tag. | ||
const { value: tagName } = tagSelector; | ||
if (!isKnowAttributeOnElement(tagName, attributeName)) { | ||
const message = [ | ||
`Attribute selector "${node}" can't be applied to match on <${tagSelector}>. `, | ||
`Attribute selector "${node}" can't be applied to match on <${tagSelector.value}>. `, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about something like:
|
||
`Use another method to match on the element.`, | ||
]; | ||
|
||
throw root.error(message.join(''), { | ||
index: sourceIndex, | ||
word: attribute, | ||
word: attributeName, | ||
}); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
it's
=>its