Skip to content

Table Specification: What Makes a Table Formattable

What You'll Learn

  • Know what kinds of tables can be formatted by the plugin
  • Understand the causes of invalid structure errors
  • Write Markdown tables that conform to specifications

Your Current Problem

AI generated a table, but the plugin didn't format it and added this comment at the end:

markdown
<!-- table not formatted: invalid structure -->

What is "invalid structure"? Why doesn't my table work?

When to Use This Approach

  • You encounter an invalid structure error and want to know what went wrong
  • You want to ensure AI-generated tables are formatted correctly
  • You want to hand-write a Markdown table that conforms to specifications

Core Concept

The plugin performs three layers of validation before formatting:

Layer 1: Is it a table row? → isTableRow()
Layer 2: Does it have a separator row? → isSeparatorRow()
Layer 3: Is the structure valid? → isValidTable()

Only when all three layers pass will it format. If any layer fails, it keeps the original and adds an error comment.

4 Conditions for a Valid Table

Condition 1: Each row must start and end with |

This is the most basic requirement. Every row of a Markdown pipe table must be wrapped with |.

markdown
✅ Correct
| Name | Description |

❌ Wrong
Name | Description      ← Missing leading |
| Name | Description     ← Missing trailing |
Source Code Implementation
typescript
function isTableRow(line: string): boolean {
  const trimmed = line.trim()
  return trimmed.startsWith("|") && trimmed.endsWith("|") && trimmed.split("|").length > 2
}

Source location: index.ts:58-61

Condition 2: Each row must have at least 2 separators

split("|").length > 2 means there must be at least 2 | separating content.

markdown
✅ Correct (3 |, 2 separators)
| Name | Description |

❌ Wrong (only 2 |, 1 separator)
| Name |

In other words, single-column tables are valid, but must be written in the form | content |.

Condition 3: Must have a separator row

The separator row is the line between the header and data rows, used to define alignment methods.

markdown
| Name | Description |
| --- | --- |      ← This is the separator row
| Value 1 | Value 2 |

Syntax rules for separator rows:

Each cell must match the regex /^\s*:?-+:?\s*$/, which translates to:

ComponentMeaningExample
\s*Optional whitespaceAllows `
:?Optional colonUsed to specify alignment method
-+At least one dash-, ---, ------ all work

Valid separator row examples:

markdown
| --- | --- |           ← Simplest form
| :--- | ---: |         ← With alignment markers
| :---: | :---: |       ← Center alignment
|---|---|               ← No spaces also works
| -------- | -------- | ← Long dashes also work

Invalid separator row examples:

markdown
| === | === |           ← Used equals sign, not dash
| - - | - - |           ← Spaces between dashes
| ::: | ::: |           ← Only colons, no dashes
Source Code Implementation
typescript
function isSeparatorRow(line: string): boolean {
  const trimmed = line.trim()
  if (!trimmed.startsWith("|") || !trimmed.endsWith("|")) return false
  const cells = trimmed.split("|").slice(1, -1)
  return cells.length > 0 && cells.every((cell) => /^\s*:?-+:?\s*$/.test(cell))
}

Source location: index.ts:63-68

Condition 4: All rows must have the same number of columns

If the first row has 3 columns, every subsequent row must also have 3 columns.

markdown
✅ Correct (each row has 3 columns)
| A | B | C |
|--- | --- | ---|
| 1 | 2 | 3 |

❌ Wrong (third row only has 2 columns)
| A | B | C |
|--- | --- | ---|
| 1 | 2 |
Source Code Implementation
typescript
function isValidTable(lines: string[]): boolean {
  if (lines.length < 2) return false

  const rows = lines.map((line) =>
    line.split("|").slice(1, -1).map((cell) => cell.trim()),
  )

  if (rows.length === 0 || rows[0].length === 0) return false

  const firstRowCellCount = rows[0].length
  const allSameColumnCount = rows.every((row) => row.length === firstRowCellCount)
  if (!allSameColumnCount) return false

  const hasSeparator = lines.some((line) => isSeparatorRow(line))
  return hasSeparator
}

Source location: index.ts:70-88

Alignment Syntax Quick Reference

The separator row is not only for separation, but also for specifying alignment methods:

SyntaxAlignmentEffect
--- or :---Left-alignedText aligned left (default)
:---:Center-alignedText centered
---:Right-alignedText aligned right

Example:

markdown
| Left-aligned | Center | Right-aligned |
|--- | --- | ---|
| Text | Text | Text |

After formatting:

markdown
| Left-aligned |  Center  | Right-aligned |
|--- | --- | ---|
| Text         |  Text    |          Text |
Source Code Implementation
typescript
function getAlignment(delimiterCell: string): "left" | "center" | "right" {
  const trimmed = delimiterCell.trim()
  const hasLeftColon = trimmed.startsWith(":")
  const hasRightColon = trimmed.endsWith(":")

  if (hasLeftColon && hasRightColon) return "center"
  if (hasRightColon) return "right"
  return "left"
}

Source location: index.ts:141-149

Common Error Troubleshooting

Error SymptomPossible CauseSolution
invalid structureMissing separator rowAdd | --- | --- | after the header
invalid structureInconsistent column countCheck if each row has the same number of |
invalid structureMissing leading/trailing |Add the missing |
Table not detectedOnly 1 columnEnsure at least 2 | separators
Alignment not workingSeparator row syntax errorCheck if - is used instead of other characters

Checkpoints

After completing this lesson, you should be able to answer:

  • [ ] What conditions must table rows meet? (Answer: Start and end with |, at least 2 separators)
  • [ ] What does the separator row regex mean? (Answer: Optional colon + at least one dash + optional colon)
  • [ ] Why does invalid structure occur? (Answer: Missing separator row, inconsistent column count, or missing leading/trailing |)
  • [ ] What alignment does :---: represent? (Answer: Center alignment)

Lesson Summary

ConditionRequirement
Leading/trailingMust start and end with |
Separator countAt least 2 |
Separator rowMust have, format is :?-+:?
Consistent columnsAll rows must have the same number of columns

Memory Mnemonic:

Pipe wrapped on both sides, separator row has dashes, consistent columns can't be missing, keep these four rules in mind.

Next Lesson Preview

In the next lesson, we'll dive into Alignment Details.

You'll learn:

  • Detailed usage of the three alignment methods
  • Implementation principles of separator row formatting
  • Cell padding algorithm

Appendix: Source Code Reference

Click to expand source code locations

Last updated: 2026-01-26

FunctionFile pathLine number
Table row detectionindex.ts58-61
Separator row detectionindex.ts63-68
Table validationindex.ts70-88
Alignment method parsingindex.ts141-149
Invalid table handlingindex.ts44-47

Key regex:

  • /^\s*:?-+:?\s*$/: Separator row cell matching rule

Key functions:

  • isTableRow(): Determine if a row is a table row
  • isSeparatorRow(): Determine if a row is a separator row
  • isValidTable(): Verify if table structure is valid
  • getAlignment(): Parse alignment method