use crate::context::LintContext;
use crate::diagnostic::Severity;
use vize_relief::ast::{DirectiveNode, ElementNode, ForNode, IfNode, InterpolationNode, RootNode};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RuleCategory {
Essential,
StronglyRecommended,
Recommended,
Vapor,
Musea,
Accessibility,
HtmlConformance,
TypeAware,
}
pub struct RuleMeta {
pub name: &'static str,
pub description: &'static str,
pub category: RuleCategory,
pub fixable: bool,
pub default_severity: Severity,
}
pub trait Rule: Send + Sync {
fn meta(&self) -> &'static RuleMeta;
#[allow(unused_variables)]
fn run_on_template<'a>(&self, ctx: &mut LintContext<'a>, root: &RootNode<'a>) {}
#[allow(unused_variables)]
fn enter_element<'a>(&self, ctx: &mut LintContext<'a>, element: &ElementNode<'a>) {}
#[allow(unused_variables)]
fn exit_element<'a>(&self, ctx: &mut LintContext<'a>, element: &ElementNode<'a>) {}
#[allow(unused_variables)]
fn check_directive<'a>(
&self,
ctx: &mut LintContext<'a>,
element: &ElementNode<'a>,
directive: &DirectiveNode<'a>,
) {
}
#[allow(unused_variables)]
fn check_for<'a>(&self, ctx: &mut LintContext<'a>, for_node: &ForNode<'a>) {}
#[allow(unused_variables)]
fn check_if<'a>(&self, ctx: &mut LintContext<'a>, if_node: &IfNode<'a>) {}
#[allow(unused_variables)]
fn check_interpolation<'a>(
&self,
ctx: &mut LintContext<'a>,
interpolation: &InterpolationNode<'a>,
) {
}
}
pub struct RuleRegistry {
rules: Vec<Box<dyn Rule>>,
}
impl RuleRegistry {
pub fn new() -> Self {
Self { rules: Vec::new() }
}
pub fn register(&mut self, rule: Box<dyn Rule>) {
self.rules.push(rule);
}
pub fn add(&mut self, rule: Box<dyn Rule>) {
self.register(rule);
}
pub fn rules(&self) -> &[Box<dyn Rule>] {
&self.rules
}
pub fn with_recommended() -> Self {
let mut registry = Self::new();
registry.register(Box::new(crate::rules::vue::RequireVForKey));
registry.register(Box::new(crate::rules::vue::ValidVFor));
registry.register(Box::new(crate::rules::vue::NoUseVIfWithVFor));
registry.register(Box::new(crate::rules::vue::NoUnusedVars::default()));
registry.register(Box::new(crate::rules::vue::NoDuplicateAttributes::default()));
registry.register(Box::new(crate::rules::vue::NoTemplateKey));
registry.register(Box::new(crate::rules::vue::NoTextareaMustache));
registry.register(Box::new(crate::rules::vue::ValidVElse));
registry.register(Box::new(crate::rules::vue::ValidVIf));
registry.register(Box::new(crate::rules::vue::ValidVOn));
registry.register(Box::new(crate::rules::vue::ValidVBind));
registry.register(Box::new(crate::rules::vue::ValidVModel));
registry.register(Box::new(crate::rules::vue::ValidVShow));
registry.register(Box::new(crate::rules::vue::NoDupeVElseIf));
registry.register(Box::new(
crate::rules::vue::NoReservedComponentNames::default(),
));
registry.register(Box::new(crate::rules::vue::ValidVSlot));
registry.register(Box::new(
crate::rules::vue::MultiWordComponentNames::default(),
));
registry.register(Box::new(crate::rules::vue::NoChildContent));
registry.register(Box::new(crate::rules::vue::ValidAttributeName));
registry.register(Box::new(crate::rules::vue::NoVTextVHtmlOnComponent));
registry.register(Box::new(crate::rules::vue::RequireComponentIs));
registry.register(Box::new(crate::rules::vue::NoUselessTemplateAttributes));
registry.register(Box::new(crate::rules::vue::ValidVMemo));
registry.register(Box::new(crate::rules::vue::UseVOnExact));
registry.register(Box::new(crate::rules::vue::NoVHtml));
registry.register(Box::new(crate::rules::vue::NoUnsafeUrl));
registry.register(Box::new(crate::rules::vue::NoTemplateShadow));
registry.register(Box::new(crate::rules::vue::VBindStyle::default()));
registry.register(Box::new(crate::rules::vue::VOnStyle::default()));
registry.register(Box::new(crate::rules::vue::HtmlSelfClosing));
registry.register(Box::new(
crate::rules::vue::MustacheInterpolationSpacing::default(),
));
registry.register(Box::new(crate::rules::vue::AttributeHyphenation::default()));
registry.register(Box::new(crate::rules::vue::VSlotStyle::default()));
registry.register(Box::new(crate::rules::vue::PropNameCasing));
registry.register(Box::new(crate::rules::vue::HtmlQuotes::default()));
registry.register(Box::new(crate::rules::vue::ComponentDefinitionNameCasing));
registry.register(Box::new(crate::rules::vue::NoLoneTemplate));
registry.register(Box::new(crate::rules::vue::AttributeOrder));
registry.register(Box::new(crate::rules::vue::SfcElementOrder));
registry.register(Box::new(crate::rules::vue::ScopedEventNames));
registry.register(Box::new(crate::rules::vue::PreferPropsShorthand));
registry.register(Box::new(crate::rules::vapor::NoSuspense));
registry.register(Box::new(crate::rules::vapor::NoInlineTemplate));
registry.register(Box::new(crate::rules::vapor::NoVueLifecycleEvents));
registry.register(Box::new(crate::rules::vapor::PreferStaticClass));
registry.register(Box::new(
crate::rules::vapor::RequireVaporAttribute::default(),
));
registry.register(Box::new(crate::rules::a11y::ImgAlt));
registry.register(Box::new(crate::rules::a11y::AnchorHasContent));
registry.register(Box::new(crate::rules::a11y::HeadingHasContent));
registry.register(Box::new(crate::rules::a11y::IframeHasTitle));
registry.register(Box::new(crate::rules::a11y::NoDistractingElements));
registry.register(Box::new(crate::rules::a11y::TabindexNoPositive));
registry.register(Box::new(crate::rules::a11y::ClickEventsHaveKeyEvents));
registry.register(Box::new(crate::rules::a11y::FormControlHasLabel));
registry.register(Box::new(crate::rules::a11y::AriaProps));
registry.register(Box::new(crate::rules::a11y::AriaRole::default()));
registry.register(Box::new(crate::rules::a11y::NoAriaHiddenOnFocusable));
registry.register(Box::new(crate::rules::a11y::NoAccessKey));
registry.register(Box::new(crate::rules::a11y::NoAutofocus));
registry.register(Box::new(crate::rules::a11y::NoRolePresentationOnFocusable));
registry.register(Box::new(crate::rules::a11y::AriaUnsupportedElements));
registry.register(Box::new(crate::rules::a11y::NoRedundantRoles));
registry.register(Box::new(crate::rules::a11y::MouseEventsHaveKeyEvents));
registry.register(Box::new(crate::rules::a11y::AltText));
registry.register(Box::new(crate::rules::a11y::AnchorIsValid));
registry.register(Box::new(crate::rules::a11y::LabelHasFor));
registry.register(Box::new(crate::rules::a11y::InteractiveSupportsFocus));
registry.register(Box::new(crate::rules::a11y::RoleHasRequiredAriaProps));
registry.register(Box::new(crate::rules::a11y::MediaHasCaption));
registry.register(Box::new(crate::rules::a11y::NoStaticElementInteractions));
registry.register(Box::new(crate::rules::a11y::NoIForIcon));
registry.register(Box::new(crate::rules::a11y::NoReferToNonExistentId));
registry.register(Box::new(crate::rules::vue::UseUniqueElementIds::default()));
registry.register(Box::new(crate::rules::vue::PermittedContents));
registry.register(Box::new(crate::rules::a11y::HeadingLevels));
registry.register(Box::new(crate::rules::a11y::LandmarkRoles));
registry.register(Box::new(crate::rules::a11y::PlaceholderLabelOption));
registry.register(Box::new(crate::rules::html::DeprecatedElement));
registry.register(Box::new(crate::rules::html::DeprecatedAttr));
registry.register(Box::new(crate::rules::html::NoConsecutiveBr));
registry.register(Box::new(crate::rules::html::IdDuplication));
registry.register(Box::new(crate::rules::html::NoDuplicateDt));
registry.register(Box::new(crate::rules::html::RequireDatetime));
registry.register(Box::new(crate::rules::ssr::NoBrowserGlobalsInSsr));
registry.register(Box::new(crate::rules::ssr::NoHydrationMismatch));
registry.register(Box::new(crate::rules::vue::NoUnusedComponents::default()));
registry.register(Box::new(crate::rules::vue::NoUnusedProperties::default()));
registry.register(Box::new(crate::rules::vue::NoMutatingProps));
registry
}
pub fn with_essential() -> Self {
let mut registry = Self::new();
registry.register(Box::new(crate::rules::vue::RequireVForKey));
registry.register(Box::new(crate::rules::vue::ValidVFor));
registry.register(Box::new(crate::rules::vue::NoUseVIfWithVFor));
registry.register(Box::new(crate::rules::vue::NoUnusedVars::default()));
registry.register(Box::new(crate::rules::vue::NoDuplicateAttributes::default()));
registry.register(Box::new(crate::rules::vue::NoTemplateKey));
registry.register(Box::new(crate::rules::vue::NoTextareaMustache));
registry.register(Box::new(crate::rules::vue::ValidVElse));
registry.register(Box::new(crate::rules::vue::ValidVIf));
registry.register(Box::new(crate::rules::vue::ValidVOn));
registry.register(Box::new(crate::rules::vue::ValidVBind));
registry.register(Box::new(crate::rules::vue::ValidVModel));
registry.register(Box::new(crate::rules::vue::ValidVShow));
registry.register(Box::new(crate::rules::vue::NoDupeVElseIf));
registry.register(Box::new(
crate::rules::vue::NoReservedComponentNames::default(),
));
registry.register(Box::new(crate::rules::vue::ValidVSlot));
registry.register(Box::new(
crate::rules::vue::MultiWordComponentNames::default(),
));
registry.register(Box::new(crate::rules::vue::NoChildContent));
registry.register(Box::new(crate::rules::vue::ValidAttributeName));
registry.register(Box::new(crate::rules::vue::NoVTextVHtmlOnComponent));
registry.register(Box::new(crate::rules::vue::RequireComponentIs));
registry.register(Box::new(crate::rules::vue::NoUselessTemplateAttributes));
registry.register(Box::new(crate::rules::vue::ValidVMemo));
registry.register(Box::new(crate::rules::vue::UseVOnExact));
registry.register(Box::new(crate::rules::vue::NoVHtml));
registry.register(Box::new(crate::rules::vue::NoUnsafeUrl));
registry.register(Box::new(crate::rules::html::IdDuplication));
registry
}
pub fn with_all() -> Self {
let mut registry = Self::with_recommended();
registry.register(Box::new(crate::rules::vue::NoMultiSpaces::default()));
registry.register(Box::new(
crate::rules::vue::ComponentNameInTemplateCasing::default(),
));
registry.register(Box::new(crate::rules::vue::NoPreprocessorLang));
registry.register(Box::new(crate::rules::vue::NoScriptNonStandardLang));
registry.register(Box::new(crate::rules::vue::NoTemplateLang));
registry.register(Box::new(crate::rules::vue::NoSrcAttribute));
registry.register(Box::new(crate::rules::vue::SingleStyleBlock));
registry.register(Box::new(
crate::rules::vue::RequireComponentRegistration::default(),
));
registry.register(Box::new(crate::rules::vue::NoInlineStyle));
registry.register(Box::new(crate::rules::vue::RequireScopedStyle));
registry.register(Box::new(crate::rules::vue::WarnCustomBlock));
registry.register(Box::new(crate::rules::vue::WarnCustomDirective));
registry.register(Box::new(crate::rules::a11y::UseList));
registry.register(Box::new(crate::rules::vue::NoBooleanAttrValue));
registry.register(Box::new(crate::rules::html::NoEmptyPalpableContent));
registry
}
pub fn with_nuxt() -> Self {
let mut registry = Self::with_recommended();
registry.register(Box::new(crate::rules::vue::NoMultiSpaces::default()));
registry.register(Box::new(
crate::rules::vue::ComponentNameInTemplateCasing::default(),
));
registry.register(Box::new(crate::rules::vue::NoPreprocessorLang));
registry.register(Box::new(crate::rules::vue::NoScriptNonStandardLang));
registry.register(Box::new(crate::rules::vue::NoTemplateLang));
registry.register(Box::new(crate::rules::vue::NoSrcAttribute));
registry.register(Box::new(crate::rules::vue::SingleStyleBlock));
registry
}
}
impl Default for RuleRegistry {
fn default() -> Self {
Self::with_recommended()
}
}