From 9c34f7226b3adbd52381ffbc645fc729701d9a7e Mon Sep 17 00:00:00 2001 From: leaysgur <6259812+leaysgur@users.noreply.github.com> Date: Mon, 16 Feb 2026 05:05:08 +0000 Subject: [PATCH] feat(formatter/sort_imports)!: Report invalid group name with renaming `side-effect` > `side_effect` (#19416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Breaking: Rename ambiguous modifier/selector names - `side-effect` → `side_effect` - `side-effect-style` → `side_effect_style` - Now `-` is used only for joiner (`modifier-modifier-selector`) - before: `value-side-effect-style` 🆚 after: `value-side_effect_style` - Breaking: Add config-time validation for invalid group names - previously silently ignored... - or wrongly applied (and user didn't notice) --- apps/oxfmt/src/core/oxfmtrc.rs | 128 +++++++++++++----- .../ir_transform/sort_imports/group_config.rs | 65 +++++---- .../sort_imports/group_matcher.rs | 29 ++-- .../src/ir_transform/sort_imports/options.rs | 24 ++-- .../oxc_formatter/tests/ir_transform/mod.rs | 20 ++- .../sort_imports/custom_groups.rs | 8 +- .../tests/ir_transform/sort_imports/groups.rs | 24 ++-- napi/playground/src/lib.rs | 26 +++- npm/oxfmt/configuration_schema.json | 12 +- .../src/snapshots/schema_json.snap | 12 +- .../src/snapshots/schema_markdown.snap | 20 +-- 11 files changed, 230 insertions(+), 138 deletions(-) diff --git a/apps/oxfmt/src/core/oxfmtrc.rs b/apps/oxfmt/src/core/oxfmtrc.rs index 30352ea3961a9..5bb3b4185d831 100644 --- a/apps/oxfmt/src/core/oxfmtrc.rs +++ b/apps/oxfmt/src/core/oxfmtrc.rs @@ -1,14 +1,15 @@ use std::path::Path; +use rustc_hash::FxHashSet; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_json::Value; use oxc_formatter::{ ArrowParentheses, AttributePosition, BracketSameLine, BracketSpacing, CustomGroupDefinition, - EmbeddedLanguageFormatting, Expand, FormatOptions, ImportModifier, ImportSelector, IndentStyle, - IndentWidth, LineEnding, LineWidth, QuoteProperties, QuoteStyle, Semicolons, - SortImportsOptions, SortOrder, TailwindcssOptions, TrailingCommas, + EmbeddedLanguageFormatting, Expand, FormatOptions, GroupEntry, GroupName, ImportModifier, + ImportSelector, IndentStyle, IndentWidth, LineEnding, LineWidth, QuoteProperties, QuoteStyle, + Semicolons, SortImportsOptions, SortOrder, TailwindcssOptions, TrailingCommas, }; use oxc_toml::Options as TomlFormatterOptions; @@ -419,7 +420,46 @@ impl FormatConfig { if let Some(v) = config.internal_pattern { sort_imports.internal_pattern = v; } + // Validate and parse `customGroups` first, since `groups` may refer to custom group names. + if let Some(v) = config.custom_groups { + let mut custom_groups = Vec::with_capacity(v.len()); + for cg in v { + let CustomGroupItemConfig { group_name, element_name_pattern, .. } = cg; + let selector = match cg.selector.as_deref() { + Some(s) => match ImportSelector::parse(s) { + Some(parsed) => Some(parsed), + None => { + return Err(format!( + "Invalid `sortImports` configuration: unknown selector: `{s}` in customGroups: `{group_name}`" + )); + } + }, + None => None, + }; + let raw_modifiers = cg.modifiers.unwrap_or_default(); + let mut modifiers = Vec::with_capacity(raw_modifiers.len()); + for m in &raw_modifiers { + match ImportModifier::parse(m) { + Some(parsed) => modifiers.push(parsed), + None => { + return Err(format!( + "Invalid `sortImports` configuration: unknown modifier: `{m}` in customGroups: `{group_name}`" + )); + } + } + } + custom_groups.push(CustomGroupDefinition { + group_name, + element_name_pattern, + selector, + modifiers, + }); + } + sort_imports.custom_groups = custom_groups; + } if let Some(v) = config.groups { + let custom_group_names: FxHashSet<&str> = + sort_imports.custom_groups.iter().map(|g| g.group_name.as_str()).collect(); let mut groups = Vec::new(); let mut newline_boundary_overrides: Vec> = Vec::new(); let mut pending_override: Option = None; @@ -437,15 +477,24 @@ impl FormatConfig { } other => { if !groups.is_empty() { - // Record the boundary between the previous group and this one. - // `pending_override` is - // - `Some(bool)` if a marker preceded this group - // - or `None` (= use global `newlines_between`) otherwise - // For the very first group (`groups.is_empty()`), - // there is no preceding boundary, so we skip this entirely. newline_boundary_overrides.push(pending_override.take()); } - groups.push(other.into_vec()); + let mut entries = Vec::new(); + for name in other.into_vec() { + let entry = if name == "unknown" { + GroupEntry::Unknown + } else if custom_group_names.contains(name.as_str()) { + GroupEntry::Custom(name) + } else if let Some(group_name) = GroupName::parse(&name) { + GroupEntry::Predefined(group_name) + } else { + return Err(format!( + "Invalid `sortImports` configuration: unknown group name `{name}` in `groups`" + )); + }; + entries.push(entry); + } + groups.push(entries); } } } @@ -463,22 +512,6 @@ impl FormatConfig { { return Err("Invalid `sortImports` configuration: `partitionByNewline` and per-group `{ \"newlinesBetween\" }` markers cannot be used together".to_string()); } - if let Some(v) = config.custom_groups { - sort_imports.custom_groups = v - .into_iter() - .map(|c| CustomGroupDefinition { - group_name: c.group_name, - element_name_pattern: c.element_name_pattern, - selector: c.selector.as_deref().and_then(ImportSelector::parse), - modifiers: c - .modifiers - .unwrap_or_default() - .iter() - .filter_map(|s| ImportModifier::parse(s)) - .collect(), - }) - .collect(); - } // `partition_by_newline: true` and `newlines_between: true` cannot be used together if sort_imports.partition_by_newline && sort_imports.newlines_between { @@ -679,8 +712,8 @@ pub struct SortImportsConfig { /// /// The list of selectors is sorted from most to least important: /// - `type` — TypeScript type imports. - /// - `side-effect-style` — Side effect style imports. - /// - `side-effect` — Side effect imports. + /// - `side_effect_style` — Side effect style imports. + /// - `side_effect` — Side effect imports. /// - `style` — Style imports. /// - `index` — Main file from the current directory. /// - `sibling` — Modules from the same directory. @@ -692,7 +725,7 @@ pub struct SortImportsConfig { /// - `import` — Any import. /// /// The list of modifiers is sorted from most to least important: - /// - `side-effect` — Side effect imports. + /// - `side_effect` — Side effect imports. /// - `type` — TypeScript type imports. /// - `value` — Value imports. /// - `default` — Imports containing the default specifier. @@ -776,14 +809,14 @@ pub struct CustomGroupItemConfig { pub element_name_pattern: Vec, /// Selector to match the import kind. /// - /// Possible values: `"type"`, `"side-effect-style"`, `"side-effect"`, `"style"`, `"index"`, + /// Possible values: `"type"`, `"side_effect_style"`, `"side_effect"`, `"style"`, `"index"`, /// `"sibling"`, `"parent"`, `"subpath"`, `"internal"`, `"builtin"`, `"external"`, `"import"` #[serde(skip_serializing_if = "Option::is_none")] pub selector: Option, /// Modifiers to match the import characteristics. /// All specified modifiers must be present (AND logic). /// - /// Possible values: `"side-effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` + /// Possible values: `"side_effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` #[serde(skip_serializing_if = "Option::is_none")] pub modifiers: Option>, } @@ -1259,9 +1292,21 @@ mod tests { let oxfmt_options = config.into_oxfmt_options().unwrap(); let sort_imports = oxfmt_options.format_options.experimental_sort_imports.unwrap(); assert_eq!(sort_imports.groups.len(), 5); - assert_eq!(sort_imports.groups[0], vec!["builtin".to_string()]); - assert_eq!(sort_imports.groups[1], vec!["external".to_string(), "internal".to_string()]); - assert_eq!(sort_imports.groups[4], vec!["index".to_string()]); + assert_eq!( + sort_imports.groups[0], + vec![GroupEntry::Predefined(GroupName::parse("builtin").unwrap())] + ); + assert_eq!( + sort_imports.groups[1], + vec![ + GroupEntry::Predefined(GroupName::parse("external").unwrap()), + GroupEntry::Predefined(GroupName::parse("internal").unwrap()) + ] + ); + assert_eq!( + sort_imports.groups[4], + vec![GroupEntry::Predefined(GroupName::parse("index").unwrap())] + ); // Test groups with newlinesBetween overrides let config: FormatConfig = serde_json::from_str( @@ -1280,9 +1325,18 @@ mod tests { let oxfmt_options = config.into_oxfmt_options().unwrap(); let sort_imports = oxfmt_options.format_options.experimental_sort_imports.unwrap(); assert_eq!(sort_imports.groups.len(), 3); - assert_eq!(sort_imports.groups[0], vec!["builtin".to_string()]); - assert_eq!(sort_imports.groups[1], vec!["external".to_string()]); - assert_eq!(sort_imports.groups[2], vec!["parent".to_string()]); + assert_eq!( + sort_imports.groups[0], + vec![GroupEntry::Predefined(GroupName::parse("builtin").unwrap())] + ); + assert_eq!( + sort_imports.groups[1], + vec![GroupEntry::Predefined(GroupName::parse("external").unwrap())] + ); + assert_eq!( + sort_imports.groups[2], + vec![GroupEntry::Predefined(GroupName::parse("parent").unwrap())] + ); assert_eq!(sort_imports.newline_boundary_overrides.len(), 2); assert_eq!(sort_imports.newline_boundary_overrides[0], Some(false)); assert_eq!(sort_imports.newline_boundary_overrides[1], None); diff --git a/crates/oxc_formatter/src/ir_transform/sort_imports/group_config.rs b/crates/oxc_formatter/src/ir_transform/sort_imports/group_config.rs index 6e933aa0720d5..7232e9701982e 100644 --- a/crates/oxc_formatter/src/ir_transform/sort_imports/group_config.rs +++ b/crates/oxc_formatter/src/ir_transform/sort_imports/group_config.rs @@ -1,5 +1,16 @@ use std::cmp::Ordering; +/// A parsed entry in a group configuration. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum GroupEntry { + /// A predefined group name (e.g. "type-external", "value-builtin"). + Predefined(GroupName), + /// The special "unknown" catch-all group. + Unknown, + /// A reference to a user-defined custom group by name. + Custom(String), +} + /// Represents a group name pattern for matching imports. /// A group name consists of 1 selector and N modifiers. #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -17,38 +28,34 @@ impl GroupName { /// Parse a group name string into a GroupName. /// /// Format: `(modifier-)*selector` + /// + /// Since no selector or modifier name contains `-`, + /// we can simply split by `-`: the last element is the selector, + /// and all preceding elements are modifiers. + /// /// Examples: /// - "external" -> modifiers: (empty), selector: External /// - "type-external" -> modifiers: Type, selector: External /// - "value-builtin" -> modifiers: Value, selector: Builtin - /// - "side-effect-import" -> modifiers: SideEffect, selector: Import - /// - "side-effect-type-external" -> modifiers: SideEffect, Type, selector: External - /// - "named-side-effect-type-builtin" -> modifiers: SideEffect, Type, Named, selector: Builtin + /// - "side_effect-import" -> modifiers: SideEffect, selector: Import + /// - "side_effect-type-external" -> modifiers: SideEffect, Type, selector: External pub fn parse(s: &str) -> Option { - // Try to parse as a selector without modifiers first - if let Some(selector) = ImportSelector::parse(s) { + let parts: Vec<&str> = s.split('-').collect(); + let selector = ImportSelector::parse(parts.last()?)?; + + if parts.len() == 1 { return Some(Self { modifiers: vec![], selector }); } - // Last part should be the selector - let selector = - *ImportSelector::ALL_SELECTORS.iter().find(|selector| s.ends_with(selector.name()))?; - - // The remaining part represents a sequence of modifiers joined by "-". - // Since modifiers themselves may contain "-", splitting by "-" would be ambiguous. - // Instead, we iterate over modifiers in a predefined order and check - // whether they appear in the remaining string. - // This guarantees the extracted modifiers are already ordered - // and no additional sorting is required. - // - // The trade-off is that this approach may tolerate invalid input, - // as unmatched or malformed segments are not strictly rejected. - let mut modifiers = Vec::with_capacity(ImportModifier::ALL_MODIFIERS.len()); - for m in ImportModifier::ALL_MODIFIERS { - if s.contains(m.name()) { - modifiers.push(*m); - } + let mut modifiers = Vec::with_capacity(parts.len() - 1); + for part in &parts[..parts.len() - 1] { + modifiers.push(ImportModifier::parse(part)?); } + // Normalize modifier order so that + // "type-value-external" and "value-type-external" are treated as the same. + // Also deduplicate in case the user wrote "type-type-external". + modifiers.sort_unstable(); + modifiers.dedup(); Some(Self { selector, modifiers }) } @@ -121,8 +128,8 @@ impl ImportSelector { pub fn parse(s: &str) -> Option { match s { "type" => Some(Self::Type), - "side-effect-style" => Some(Self::SideEffectStyle), - "side-effect" => Some(Self::SideEffect), + "side_effect_style" => Some(Self::SideEffectStyle), + "side_effect" => Some(Self::SideEffect), "style" => Some(Self::Style), "index" => Some(Self::Index), "sibling" => Some(Self::Sibling), @@ -154,8 +161,8 @@ impl ImportSelector { pub fn name(&self) -> &str { match self { ImportSelector::Type => "type", - ImportSelector::SideEffectStyle => "side-effect-style", - ImportSelector::SideEffect => "side-effect", + ImportSelector::SideEffectStyle => "side_effect_style", + ImportSelector::SideEffect => "side_effect", ImportSelector::Style => "style", ImportSelector::Index => "index", ImportSelector::Sibling => "sibling", @@ -200,7 +207,7 @@ impl ImportModifier { /// Parse a string into an ImportModifier. pub fn parse(s: &str) -> Option { match s { - "side-effect" => Some(Self::SideEffect), + "side_effect" => Some(Self::SideEffect), "type" => Some(Self::Type), "value" => Some(Self::Value), "default" => Some(Self::Default), @@ -212,7 +219,7 @@ impl ImportModifier { pub fn name(&self) -> &str { match self { - ImportModifier::SideEffect => "side-effect", + ImportModifier::SideEffect => "side_effect", ImportModifier::Type => "type", ImportModifier::Value => "value", ImportModifier::Default => "default", diff --git a/crates/oxc_formatter/src/ir_transform/sort_imports/group_matcher.rs b/crates/oxc_formatter/src/ir_transform/sort_imports/group_matcher.rs index 07f03eeebf70b..e54e374db0e1d 100644 --- a/crates/oxc_formatter/src/ir_transform/sort_imports/group_matcher.rs +++ b/crates/oxc_formatter/src/ir_transform/sort_imports/group_matcher.rs @@ -1,6 +1,6 @@ -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashMap; -use super::group_config::{GroupName, ImportModifier, ImportSelector}; +use super::group_config::{GroupEntry, GroupName, ImportModifier, ImportSelector}; use super::options::CustomGroupDefinition; // Intermediate import metadata that is used for group matching @@ -21,22 +21,23 @@ pub struct GroupMatcher { } impl GroupMatcher { - pub fn new(groups: &[Vec], custom_groups: &[CustomGroupDefinition]) -> Self { - let custom_group_name_set = - custom_groups.iter().map(|g| g.group_name.clone()).collect::>(); - + pub fn new(groups: &[Vec], custom_groups: &[CustomGroupDefinition]) -> Self { let mut unknown_group_index: Option = None; let mut used_custom_group_index_map = FxHashMap::default(); let mut predefined_groups = Vec::new(); for (index, group_union) in groups.iter().enumerate() { - for group in group_union { - if group == "unknown" { - unknown_group_index = Some(index); - } else if custom_group_name_set.contains(group) { - used_custom_group_index_map.insert(group.to_owned(), index); - } else if let Some(group_name) = GroupName::parse(group) { - predefined_groups.push((group_name, index)); + for entry in group_union { + match entry { + GroupEntry::Unknown => { + unknown_group_index = Some(index); + } + GroupEntry::Custom(name) => { + used_custom_group_index_map.insert(name.as_str(), index); + } + GroupEntry::Predefined(group_name) => { + predefined_groups.push((group_name.clone(), index)); + } } } } @@ -44,7 +45,7 @@ impl GroupMatcher { let mut used_custom_groups: Vec<(CustomGroupDefinition, usize)> = Vec::with_capacity(used_custom_group_index_map.len()); for custom_group in custom_groups { - if let Some(index) = used_custom_group_index_map.get(&custom_group.group_name) { + if let Some(index) = used_custom_group_index_map.get(custom_group.group_name.as_str()) { used_custom_groups.push((custom_group.clone(), *index)); } } diff --git a/crates/oxc_formatter/src/ir_transform/sort_imports/options.rs b/crates/oxc_formatter/src/ir_transform/sort_imports/options.rs index a8136e57e37f5..4bf1fd90fd0b5 100644 --- a/crates/oxc_formatter/src/ir_transform/sort_imports/options.rs +++ b/crates/oxc_formatter/src/ir_transform/sort_imports/options.rs @@ -1,7 +1,7 @@ use std::fmt; use std::str::FromStr; -pub use super::group_config::{ImportModifier, ImportSelector}; +pub use super::group_config::{GroupEntry, GroupName, ImportModifier, ImportSelector}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct SortImportsOptions { @@ -30,9 +30,9 @@ pub struct SortImportsOptions { /// Defaults to `["~/", "@/"]`. pub internal_pattern: Vec, /// Groups configuration for organizing imports. - /// Each inner `Vec` represents a group, and multiple group names in the same `Vec` are treated as one. + /// Each inner `Vec` represents a group, and multiple entries in the same `Vec` are treated as one. /// Default is defined by [`default_groups()`] function. - pub groups: Vec>, + pub groups: Vec>, /// Define your own groups for matching very specific imports. /// Default is `[]`. pub custom_groups: Vec, @@ -120,14 +120,16 @@ pub fn default_internal_patterns() -> Vec { } /// Returns default groups configuration for organizing imports. -pub fn default_groups() -> Vec> { +pub fn default_groups() -> Vec> { + // Helper to parse a predefined group name, panicking on invalid names. + let p = |s: &str| GroupEntry::Predefined(GroupName::parse(s).unwrap()); vec![ - vec!["type-import".to_string()], - vec!["value-builtin".to_string(), "value-external".to_string()], - vec!["type-internal".to_string()], - vec!["value-internal".to_string()], - vec!["type-parent".to_string(), "type-sibling".to_string(), "type-index".to_string()], - vec!["value-parent".to_string(), "value-sibling".to_string(), "value-index".to_string()], - vec!["unknown".to_string()], + vec![p("type-import")], + vec![p("value-builtin"), p("value-external")], + vec![p("type-internal")], + vec![p("value-internal")], + vec![p("type-parent"), p("type-sibling"), p("type-index")], + vec![p("value-parent"), p("value-sibling"), p("value-index")], + vec![GroupEntry::Unknown], ] } diff --git a/crates/oxc_formatter/tests/ir_transform/mod.rs b/crates/oxc_formatter/tests/ir_transform/mod.rs index 9d7ddf9878a2e..eeab895d44116 100644 --- a/crates/oxc_formatter/tests/ir_transform/mod.rs +++ b/crates/oxc_formatter/tests/ir_transform/mod.rs @@ -1,8 +1,8 @@ mod sort_imports; use oxc_formatter::{ - CustomGroupDefinition, FormatOptions, ImportModifier, ImportSelector, QuoteStyle, Semicolons, - SortImportsOptions, SortOrder, + CustomGroupDefinition, FormatOptions, GroupEntry, GroupName, ImportModifier, ImportSelector, + QuoteStyle, Semicolons, SortImportsOptions, SortOrder, }; use serde::Deserialize; @@ -84,10 +84,20 @@ struct TestSortImportsConfig { #[derive(Debug, Default)] struct ParsedGroups { - groups: Vec>, + groups: Vec>, newline_boundary_overrides: Vec>, } +fn parse_group_name(name: &str) -> GroupEntry { + if name == "unknown" { + GroupEntry::Unknown + } else if let Some(group_name) = GroupName::parse(name) { + GroupEntry::Predefined(group_name) + } else { + GroupEntry::Custom(name.to_string()) + } +} + fn deserialize_groups<'de, D>(deserializer: D) -> Result, D::Error> where D: serde::Deserializer<'de>, @@ -110,9 +120,9 @@ where newline_boundary_overrides.push(pending_override.take()); } let group = match item { - Value::String(s) => vec![s], + Value::String(s) => vec![parse_group_name(&s)], Value::Array(a) => { - a.into_iter().filter_map(|v| v.as_str().map(String::from)).collect() + a.into_iter().filter_map(|v| v.as_str().map(parse_group_name)).collect() } _ => continue, }; diff --git a/crates/oxc_formatter/tests/ir_transform/sort_imports/custom_groups.rs b/crates/oxc_formatter/tests/ir_transform/sort_imports/custom_groups.rs index d4fac97320c98..2ac3787a1f1fe 100644 --- a/crates/oxc_formatter/tests/ir_transform/sort_imports/custom_groups.rs +++ b/crates/oxc_formatter/tests/ir_transform/sort_imports/custom_groups.rs @@ -13,13 +13,13 @@ import { t } from "t"; { "experimentalSortImports": { "groups": [ - "side-effect-style", + "side_effect_style", "type-external", "type-internal", "type-builtin", "type-sibling", "type-parent", - "side-effect", + "side_effect", "type-index", "internal", "external", @@ -141,7 +141,7 @@ import CartComponentB from "./cart/CartComponentB.vue"; "assets", "parent", "sibling", - "side-effect", + "side_effect", "index", "style", "unknown" @@ -256,7 +256,7 @@ import ComponentC from "~/components/ComponentC.vue"; "assets", "parent", "sibling", - "side-effect", + "side_effect", "index", "style", "unknown" diff --git a/crates/oxc_formatter/tests/ir_transform/sort_imports/groups.rs b/crates/oxc_formatter/tests/ir_transform/sort_imports/groups.rs index c177936890953..5c8d61d990d7f 100644 --- a/crates/oxc_formatter/tests/ir_transform/sort_imports/groups.rs +++ b/crates/oxc_formatter/tests/ir_transform/sort_imports/groups.rs @@ -168,7 +168,7 @@ import "../d"; "#, r#"{ "experimentalSortImports": { - "groups": ["external", "side-effect", "unknown"], + "groups": ["external", "side_effect", "unknown"], "sortSideEffects": false } }"#, @@ -191,7 +191,7 @@ import "../d"; "#, r#"{ "experimentalSortImports": { - "groups": ["external", "side-effect", "unknown"], + "groups": ["external", "side_effect", "unknown"], "sortSideEffects": false } }"#, @@ -212,7 +212,7 @@ import "aaa"; "#, r#"{ "experimentalSortImports": { - "groups": ["external", "side-effect", "unknown"], + "groups": ["external", "side_effect", "unknown"], "sortSideEffects": true } }"#, @@ -258,7 +258,7 @@ import a from "./a"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect", "unknown"] + "groups": ["side_effect", "unknown"] } }"#, r#" @@ -283,7 +283,7 @@ import a from "./a"; "#, r#"{ "experimentalSortImports": { - "groups": [["side-effect", "side-effect-style"], "unknown"] + "groups": [["side_effect", "side_effect_style"], "unknown"] } }"#, r#" @@ -308,7 +308,7 @@ import a from "./a"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect", "side-effect-style", "unknown"] + "groups": ["side_effect", "side_effect_style", "unknown"] } }"#, r#" @@ -334,7 +334,7 @@ import a from "./a"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect-style", "unknown"] + "groups": ["side_effect_style", "unknown"] } }"#, r#" @@ -395,7 +395,7 @@ import "style.css"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect-style", "side-effect"] + "groups": ["side_effect_style", "side_effect"] } }"#, r#" @@ -413,7 +413,7 @@ import "something"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect", "style"] + "groups": ["side_effect", "style"] } }"#, r#" @@ -449,7 +449,7 @@ import "./z"; "#, r#"{ "experimentalSortImports": { - "groups": ["side-effect-import", "external", "value-import"], + "groups": ["side_effect-import", "external", "value-import"], "sortSideEffects": true } }"#, @@ -617,7 +617,7 @@ import "~/css/globals.css"; "#, r#"{ "experimentalSortImports": { - "groups": ["internal", "side-effect-style", "side-effect"] + "groups": ["internal", "side_effect_style", "side_effect"] } }"#, r#" @@ -639,7 +639,7 @@ import "node:os"; "#, r#"{ "experimentalSortImports": { - "groups": ["builtin", "external", "side-effect"] + "groups": ["builtin", "external", "side_effect"] } }"#, r#" diff --git a/napi/playground/src/lib.rs b/napi/playground/src/lib.rs index bed9607dd9a80..951277192da40 100644 --- a/napi/playground/src/lib.rs +++ b/napi/playground/src/lib.rs @@ -30,9 +30,9 @@ use oxc::{ }; use oxc_formatter::{ ArrowParentheses, AttributePosition, BracketSameLine, BracketSpacing, Expand, FormatOptions, - Formatter, IndentStyle, IndentWidth, LineEnding, LineWidth, QuoteProperties, QuoteStyle, - Semicolons, SortImportsOptions, SortOrder, TrailingCommas, default_groups, - default_internal_patterns, get_parse_options, + Formatter, GroupEntry, GroupName, IndentStyle, IndentWidth, LineEnding, LineWidth, + QuoteProperties, QuoteStyle, Semicolons, SortImportsOptions, SortOrder, TrailingCommas, + default_groups, default_internal_patterns, get_parse_options, }; use oxc_linter::{ ConfigStore, ConfigStoreBuilder, ContextSubHost, ExternalPluginStore, LintOptions, Linter, @@ -527,7 +527,25 @@ impl Oxc { .internal_pattern .clone() .unwrap_or_else(default_internal_patterns), - groups: sort_imports_config.groups.clone().unwrap_or_else(default_groups), + groups: sort_imports_config.groups.as_ref().map_or_else(default_groups, |groups| { + groups + .iter() + .map(|group| { + group + .iter() + .map(|name| { + if name == "unknown" { + GroupEntry::Unknown + } else if let Some(gn) = GroupName::parse(name) { + GroupEntry::Predefined(gn) + } else { + GroupEntry::Custom(name.clone()) + } + }) + .collect() + }) + .collect() + }), custom_groups: vec![], newline_boundary_overrides: vec![], }); diff --git a/npm/oxfmt/configuration_schema.json b/npm/oxfmt/configuration_schema.json index 80eaf309894d6..a6a616efb40b5 100644 --- a/npm/oxfmt/configuration_schema.json +++ b/npm/oxfmt/configuration_schema.json @@ -280,7 +280,7 @@ "markdownDescription": "Name of the custom group, used in the `groups` option." }, "modifiers": { - "description": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side-effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`", + "description": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side_effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`", "type": [ "array", "null" @@ -288,15 +288,15 @@ "items": { "type": "string" }, - "markdownDescription": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side-effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`" + "markdownDescription": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side_effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`" }, "selector": { - "description": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side-effect-style\"`, `\"side-effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`", + "description": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side_effect_style\"`, `\"side_effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`", "type": [ "string", "null" ], - "markdownDescription": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side-effect-style\"`, `\"side-effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`" + "markdownDescription": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side_effect_style\"`, `\"side_effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`" } } }, @@ -666,7 +666,7 @@ "markdownDescription": "Define your own groups for matching very specific imports.\n\nThe `customGroups` list is ordered: The first definition that matches an element will be used.\nCustom groups have a higher priority than any predefined group.\n\nIf you want a predefined group to take precedence over a custom group,\nyou must write a custom group definition that does the same as what the predefined group does, and put it first in the list.\n\nIf you specify multiple conditions like `elementNamePattern`, `selector`, and `modifiers`,\nall conditions must be met for an import to match the custom group (AND logic).\n\n- Default: `[]`" }, "groups": { - "description": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side-effect-style` — Side effect style imports.\n- `side-effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side-effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```", + "description": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side_effect_style` — Side effect style imports.\n- `side_effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side_effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```", "type": [ "array", "null" @@ -674,7 +674,7 @@ "items": { "$ref": "#/definitions/SortGroupItemConfig" }, - "markdownDescription": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side-effect-style` — Side effect style imports.\n- `side-effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side-effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```" + "markdownDescription": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side_effect_style` — Side effect style imports.\n- `side_effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side_effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```" }, "ignoreCase": { "description": "Specifies whether sorting should be case-sensitive.\n\n- Default: `true`", diff --git a/tasks/website_formatter/src/snapshots/schema_json.snap b/tasks/website_formatter/src/snapshots/schema_json.snap index 657a7b1937c76..adb8ed22c9213 100644 --- a/tasks/website_formatter/src/snapshots/schema_json.snap +++ b/tasks/website_formatter/src/snapshots/schema_json.snap @@ -284,7 +284,7 @@ expression: json "markdownDescription": "Name of the custom group, used in the `groups` option." }, "modifiers": { - "description": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side-effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`", + "description": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side_effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`", "type": [ "array", "null" @@ -292,15 +292,15 @@ expression: json "items": { "type": "string" }, - "markdownDescription": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side-effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`" + "markdownDescription": "Modifiers to match the import characteristics.\nAll specified modifiers must be present (AND logic).\n\nPossible values: `\"side_effect\"`, `\"type\"`, `\"value\"`, `\"default\"`, `\"wildcard\"`, `\"named\"`" }, "selector": { - "description": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side-effect-style\"`, `\"side-effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`", + "description": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side_effect_style\"`, `\"side_effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`", "type": [ "string", "null" ], - "markdownDescription": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side-effect-style\"`, `\"side-effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`" + "markdownDescription": "Selector to match the import kind.\n\nPossible values: `\"type\"`, `\"side_effect_style\"`, `\"side_effect\"`, `\"style\"`, `\"index\"`,\n`\"sibling\"`, `\"parent\"`, `\"subpath\"`, `\"internal\"`, `\"builtin\"`, `\"external\"`, `\"import\"`" } } }, @@ -670,7 +670,7 @@ expression: json "markdownDescription": "Define your own groups for matching very specific imports.\n\nThe `customGroups` list is ordered: The first definition that matches an element will be used.\nCustom groups have a higher priority than any predefined group.\n\nIf you want a predefined group to take precedence over a custom group,\nyou must write a custom group definition that does the same as what the predefined group does, and put it first in the list.\n\nIf you specify multiple conditions like `elementNamePattern`, `selector`, and `modifiers`,\nall conditions must be met for an import to match the custom group (AND logic).\n\n- Default: `[]`" }, "groups": { - "description": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side-effect-style` — Side effect style imports.\n- `side-effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side-effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```", + "description": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side_effect_style` — Side effect style imports.\n- `side_effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side_effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```", "type": [ "array", "null" @@ -678,7 +678,7 @@ expression: json "items": { "$ref": "#/definitions/SortGroupItemConfig" }, - "markdownDescription": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side-effect-style` — Side effect style imports.\n- `side-effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side-effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```" + "markdownDescription": "Specifies a list of predefined import groups for sorting.\n\nEach import will be assigned a single group specified in the groups option (or the `unknown` group if no match is found).\nThe order of items in the `groups` option determines how groups are ordered.\n\nWithin a given group, members will be sorted according to the type, order, ignoreCase, etc. options.\n\nIndividual groups can be combined together by placing them in an array.\nThe order of groups in that array does not matter.\nAll members of the groups in the array will be sorted together as if they were part of a single group.\n\nPredefined groups are characterized by a single selector and potentially multiple modifiers.\nYou may enter modifiers in any order, but the selector must always come at the end.\n\nThe list of selectors is sorted from most to least important:\n- `type` — TypeScript type imports.\n- `side_effect_style` — Side effect style imports.\n- `side_effect` — Side effect imports.\n- `style` — Style imports.\n- `index` — Main file from the current directory.\n- `sibling` — Modules from the same directory.\n- `parent` — Modules from the parent directory.\n- `subpath` — Node.js subpath imports.\n- `internal` — Your internal modules.\n- `builtin` — Node.js Built-in Modules.\n- `external` — External modules installed in the project.\n- `import` — Any import.\n\nThe list of modifiers is sorted from most to least important:\n- `side_effect` — Side effect imports.\n- `type` — TypeScript type imports.\n- `value` — Value imports.\n- `default` — Imports containing the default specifier.\n- `wildcard` — Imports containing the wildcard (`* as`) specifier.\n- `named` — Imports containing at least one named specifier.\n\n- Default: See below\n```json\n[\n\"type-import\",\n[\"value-builtin\", \"value-external\"],\n\"type-internal\",\n\"value-internal\",\n[\"type-parent\", \"type-sibling\", \"type-index\"],\n[\"value-parent\", \"value-sibling\", \"value-index\"],\n\"unknown\",\n]\n```" }, "ignoreCase": { "description": "Specifies whether sorting should be case-sensitive.\n\n- Default: `true`", diff --git a/tasks/website_formatter/src/snapshots/schema_markdown.snap b/tasks/website_formatter/src/snapshots/schema_markdown.snap index e66a318bcf0c9..38efe74c52fb4 100644 --- a/tasks/website_formatter/src/snapshots/schema_markdown.snap +++ b/tasks/website_formatter/src/snapshots/schema_markdown.snap @@ -134,7 +134,7 @@ type: `string[]` Modifiers to match the import characteristics. All specified modifiers must be present (AND logic). -Possible values: `"side-effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` +Possible values: `"side_effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` ##### experimentalSortImports.customGroups[n].selector @@ -144,7 +144,7 @@ type: `string` Selector to match the import kind. -Possible values: `"type"`, `"side-effect-style"`, `"side-effect"`, `"style"`, `"index"`, +Possible values: `"type"`, `"side_effect_style"`, `"side_effect"`, `"style"`, `"index"`, `"sibling"`, `"parent"`, `"subpath"`, `"internal"`, `"builtin"`, `"external"`, `"import"` @@ -169,8 +169,8 @@ You may enter modifiers in any order, but the selector must always come at the e The list of selectors is sorted from most to least important: - `type` — TypeScript type imports. -- `side-effect-style` — Side effect style imports. -- `side-effect` — Side effect imports. +- `side_effect_style` — Side effect style imports. +- `side_effect` — Side effect imports. - `style` — Style imports. - `index` — Main file from the current directory. - `sibling` — Modules from the same directory. @@ -182,7 +182,7 @@ The list of selectors is sorted from most to least important: - `import` — Any import. The list of modifiers is sorted from most to least important: -- `side-effect` — Side effect imports. +- `side_effect` — Side effect imports. - `type` — TypeScript type imports. - `value` — Value imports. - `default` — Imports containing the default specifier. @@ -635,7 +635,7 @@ type: `string[]` Modifiers to match the import characteristics. All specified modifiers must be present (AND logic). -Possible values: `"side-effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` +Possible values: `"side_effect"`, `"type"`, `"value"`, `"default"`, `"wildcard"`, `"named"` ######## overrides[n].options.experimentalSortImports.customGroups[n].selector @@ -645,7 +645,7 @@ type: `string` Selector to match the import kind. -Possible values: `"type"`, `"side-effect-style"`, `"side-effect"`, `"style"`, `"index"`, +Possible values: `"type"`, `"side_effect_style"`, `"side_effect"`, `"style"`, `"index"`, `"sibling"`, `"parent"`, `"subpath"`, `"internal"`, `"builtin"`, `"external"`, `"import"` @@ -670,8 +670,8 @@ You may enter modifiers in any order, but the selector must always come at the e The list of selectors is sorted from most to least important: - `type` — TypeScript type imports. -- `side-effect-style` — Side effect style imports. -- `side-effect` — Side effect imports. +- `side_effect_style` — Side effect style imports. +- `side_effect` — Side effect imports. - `style` — Style imports. - `index` — Main file from the current directory. - `sibling` — Modules from the same directory. @@ -683,7 +683,7 @@ The list of selectors is sorted from most to least important: - `import` — Any import. The list of modifiers is sorted from most to least important: -- `side-effect` — Side effect imports. +- `side_effect` — Side effect imports. - `type` — TypeScript type imports. - `value` — Value imports. - `default` — Imports containing the default specifier.