# `Gherkin.Markdown`
[🔗](https://github.com/huddlz-hq/cucumber/blob/main/lib/gherkin/markdown.ex#L1)

Parser for Markdown feature files — "Markdown with Gherkin" (MDG).

MDG embeds Gherkin in ordinary Markdown (`.feature.md` files):

  * Section headers are ATX headings whose text is a Gherkin keyword —
    `# Feature: Name`, `## Rule: Name`, `### Scenario: Name`,
    `#### Examples: Name`. The heading level is decorative; nesting comes
    from the keywords alone.
  * Steps are bullet-list items: `* Given a step` (`-` and `+` bullets
    also work). The `*` step keyword is not available — a bare `* text`
    bullet is ordinary prose.
  * Docstrings are fenced code blocks (three or more backticks) under a
    step. The info string becomes the media type, the fence's indentation
    is stripped from the content, and the closing fence must repeat the
    opening backticks exactly, so a longer fence can wrap a shorter one.
  * Data tables and Examples tables are Markdown tables indented two to
    five spaces. GFM separator rows (`| --- |`) are skipped. Tables
    without the indent are ordinary prose and ignored.
  * Tags are inline code spans on their own line before the section they
    tag: `` `@wip` `@slow` ``. Bare `@wip` text is prose, not a tag.
  * Everything else — prose, unindented tables, headings without a
    Gherkin keyword — is ignored. Section descriptions are therefore
    always empty, and there are no comment lines (`#` starts a heading,
    so `feature.comments` is always empty).

Mirroring the reference tokenizer (`@cucumber/gherkin`'s
`GherkinInMarkdownTokenMatcher`), the first line of the file becomes the
feature line even when it is not a `# Feature:` heading — the whole
trimmed line is taken as the feature name — and any later `# Feature:`
heading is ignored.

Three deliberate divergences from the reference tokenizer, all lenient:

  * A fenced code block with no step to attach to (in prose) is skipped
    entirely, so code samples containing `* Given ...` lines don't parse
    as steps.
  * The reference captures prose that follows a GFM separator row as a
    section description — an emergent quirk of its error-tolerant token
    matching, not MDG behavior. This parser captures no descriptions.
  * The reference treats any line *containing* a backticked tag span as
    a tag line; here a tag line must consist solely of tag spans, so
    prose that merely mentions `` `@wip` `` stays prose.

Produces the same `Gherkin.Feature` structs as `Gherkin.NimbleParser`,
with 0-based line numbers referring to the original Markdown source, so
everything downstream — compiler, runtime, Cucumber Messages — behaves
exactly as it does for `.feature` files.

# `markdown_path?`

```elixir
@spec markdown_path?(String.t()) :: boolean()
```

Whether a path names a Markdown feature file.

The single authority for the `.feature.md` extension — parser dispatch
(`Gherkin.Parser.parse/2`) and the Cucumber Messages media type both use
it, so they cannot disagree.

## Examples

    Gherkin.Markdown.markdown_path?("test/features/cheese.feature.md")
    # => true

    Gherkin.Markdown.markdown_path?("test/features/cheese.feature")
    # => false

# `parse`

```elixir
@spec parse(String.t()) :: Gherkin.Feature.t()
```

Parses a Markdown feature file string into a `Gherkin.Feature` struct.

Raises `Gherkin.ParseError` when the Gherkin structure is invalid (a step
outside a scenario, an Examples table outside a Scenario Outline, an
unclosed code fence, a table row whose cell count differs from its first
row, and similar).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
