pub struct MD060TableFormat { /* private fields */ }Expand description
Rule MD060: Table Column Alignment
See docs/md060.md for full documentation, configuration, and examples.
This rule enforces consistent column alignment in Markdown tables for improved readability in source form. When enabled, it ensures table columns are properly aligned with appropriate padding.
§Purpose
- Readability: Aligned tables are significantly easier to read in source form
- Maintainability: Properly formatted tables are easier to edit and review
- Consistency: Ensures uniform table formatting throughout documents
- Developer Experience: Makes working with tables in plain text more pleasant
§Configuration Options
The rule supports the following configuration options:
[MD013]
line-length = 100 # MD060 inherits this by default
[MD060]
enabled = false # Default: opt-in for conservative adoption
style = "aligned" # Can be "aligned", "compact", "tight", or "any"
max-width = 0 # Default: inherit from MD013's line-length§Style Options
- aligned: Columns are padded with spaces for visual alignment (default)
- compact: Minimal spacing with single spaces
- tight: No spacing, pipes directly adjacent to content
- any: Preserve existing formatting style
§Max Width (auto-compact threshold)
Controls when tables automatically switch from aligned to compact formatting:
max-width = 0(default): Smart inheritance from MD013max-width = N: Explicit threshold, independent of MD013
When max-width = 0:
- If MD013 is disabled → unlimited (no auto-compact)
- If MD013.tables = false → unlimited (no auto-compact)
- If MD013.line_length = 0 → unlimited (no auto-compact)
- Otherwise → inherits MD013’s line-length
This matches the behavior of Prettier’s table formatting.
§Examples
# Inherit from MD013 (recommended)
[MD013]
line-length = 100
[MD060]
style = "aligned"
max-width = 0 # Tables exceeding 100 chars will be compacted# Explicit threshold
[MD060]
style = "aligned"
max-width = 120 # Independent of MD013§Examples
§Aligned Style (Good)
| Name | Age | City |
|-------|-----|-----------|
| Alice | 30 | Seattle |
| Bob | 25 | Portland |§Unaligned (Bad)
| Name | Age | City |
|---|---|---|
| Alice | 30 | Seattle |
| Bob | 25 | Portland |§Unicode Support
This rule properly handles:
- CJK Characters: Chinese, Japanese, Korean characters are correctly measured as double-width
- Basic Emoji: Most emoji are handled correctly
- Inline Code: Pipes in inline code blocks are properly masked
§Known Limitations
Complex Unicode Sequences: Tables containing certain Unicode characters are automatically skipped to prevent alignment corruption. These include:
- Zero-Width Joiner (ZWJ) emoji: 👨👩👧👦, 👩💻
- Zero-Width Space (ZWS): Invisible word break opportunities
- Zero-Width Non-Joiner (ZWNJ): Ligature prevention marks
- Word Joiner (WJ): Non-breaking invisible characters
These characters have inconsistent or zero display widths across terminals and fonts, making accurate alignment impossible. The rule preserves these tables as-is rather than risk corrupting them.
This is an honest limitation of terminal display technology, similar to what other tools like markdownlint experience.
§Fix Behavior
When applying automatic fixes, this rule:
- Calculates proper display width for each column using Unicode width measurements
- Pads cells with trailing spaces to align columns
- Preserves cell content exactly (only spacing is modified)
- Respects alignment indicators in delimiter rows (
:---,:---:,---:) - Automatically switches to compact mode for tables exceeding max_width
- Skips tables with ZWJ emoji to prevent corruption
Implementations§
Source§impl MD060TableFormat
impl MD060TableFormat
pub fn new(enabled: bool, style: String) -> Self
pub fn from_config_struct( config: MD060Config, md013_config: MD013Config, md013_disabled: bool, ) -> Self
Trait Implementations§
Source§impl Clone for MD060TableFormat
impl Clone for MD060TableFormat
Source§fn clone(&self) -> MD060TableFormat
fn clone(&self) -> MD060TableFormat
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for MD060TableFormat
impl Debug for MD060TableFormat
Source§impl Default for MD060TableFormat
impl Default for MD060TableFormat
Source§fn default() -> MD060TableFormat
fn default() -> MD060TableFormat
Source§impl Rule for MD060TableFormat
impl Rule for MD060TableFormat
fn name(&self) -> &'static str
fn description(&self) -> &'static str
Source§fn should_skip(&self, ctx: &LintContext<'_>) -> bool
fn should_skip(&self, ctx: &LintContext<'_>) -> bool
fn check(&self, ctx: &LintContext<'_>) -> LintResult
fn fix(&self, ctx: &LintContext<'_>) -> Result<String, LintError>
fn as_any(&self) -> &dyn Any
Source§fn default_config_section(&self) -> Option<(String, Value)>
fn default_config_section(&self) -> Option<(String, Value)>
impl Rule for ... block,
not just the inherent impl.Source§fn from_config(config: &Config) -> Box<dyn Rule>where
Self: Sized,
fn from_config(config: &Config) -> Box<dyn Rule>where
Self: Sized,
Source§fn category(&self) -> RuleCategory
fn category(&self) -> RuleCategory
Source§fn config_aliases(&self) -> Option<HashMap<String, String>>
fn config_aliases(&self) -> Option<HashMap<String, String>>
Source§fn fix_capability(&self) -> FixCapability
fn fix_capability(&self) -> FixCapability
Source§fn cross_file_scope(&self) -> CrossFileScope
fn cross_file_scope(&self) -> CrossFileScope
Source§fn contribute_to_index(
&self,
_ctx: &LintContext<'_>,
_file_index: &mut FileIndex,
)
fn contribute_to_index( &self, _ctx: &LintContext<'_>, _file_index: &mut FileIndex, )
Source§fn cross_file_check(
&self,
_file_path: &Path,
_file_index: &FileIndex,
_workspace_index: &WorkspaceIndex,
) -> LintResult
fn cross_file_check( &self, _file_path: &Path, _file_index: &FileIndex, _workspace_index: &WorkspaceIndex, ) -> LintResult
Auto Trait Implementations§
impl Freeze for MD060TableFormat
impl RefUnwindSafe for MD060TableFormat
impl Send for MD060TableFormat
impl Sync for MD060TableFormat
impl Unpin for MD060TableFormat
impl UnwindSafe for MD060TableFormat
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more