Table of Contents

Ignored Markdown Diagnostic

Note

Status: implemented. DLG1114 is an Info note for each Markdown construct the front end ignores, so a table or divider that never reaches the script does not disappear without a word.

Ubiquitous language

Term Meaning
Unmodeled construct Markdown DialogueDown does not model as dialogue, classified as an UnmodeledNodeKind.
Handling What the policy decides for a kind: Keep or Ignore (see Unmodeled Markdown Handling).
Front end The Markdown stage: IMarkdownParser, the converter, and the unmodeled-node handler.

Writer-facing behavior

# The Tavern

| Rumor | Source |
| --- | --- |
| The bridge is out | The miller |

Innkeeper: Ask around.
scene.dialogue.md(3,1): info DLG1114: This table is not dialogue, so the compiler
left it out of the script. That is expected for notes and diagrams; write it as
dialogue if it should be spoken.

The message names the kind in a writer's words ("table", not Table) and states the fact without implying a mistake. The error-code reference offers two labeled fixes — write it as dialogue, or remove it if it arrived by accident — and keeping it is the triggering example unchanged. A test forbids an unlabeled first fix whenever a second exists.

Where it is reported

MarkdigUnmodeledNodeHandler owns the whole unmodeled decision — classify, ask the policy, keep or ignore — and ignoring is where the note is written:

public MarkdownBlock? Handle(MarkdigBlock block)
{
    if (_policy.ShouldIgnore(block))
    {
        Ignore(MarkdigUnmodeledNodeClassifier.ClassifyBlock(block), block.Span);
        return null;
    }

    if (_policy.ShouldKeep(block))
    {
        return Keep(block);
    }

    throw UnknownHandling(block);
}

MarkdigMarkdownParser builds the handler per parse with the source, the policy, and the compilation's sink, and hands it to MarkdigToMarkdownAstConverter, which converts only the constructs that are dialogue. An inline overload does the same for unmodeled inlines.

Key design decisions

D1 — The parser seam takes a diagnostics context

IMarkdownParser.Parse(string, DiagnosticsContext) matches every other stage, so the front end reports for itself. Returning the omissions as data would keep Parse pure but make the front end the one stage that cannot report, and move its internals into the compiler.

D2 — One code, with the kind as an argument

A writer asks "why did my Markdown vanish?" once, so one DLG1114 carries the kind as {0} instead of a code per kind that grows with UnmodeledNodeKind.

D3 — Info, not Warning

Ignoring is usually what the writer wanted; a warning would fire on every deliberate code block. Info never affects HasErrors or an exit code.

D4 — Report ignored inlines too

The default policy keeps every inline kind, but a project policy may ignore one, and it gets the same account with no second code path.

D5 — A syntax diagnostic

The Syntax category covers the script's surface: text that does not parse as intended, or Markdown that never becomes dialogue. The summary appears in the DiagnosticCategory documentation and on the error-code page, which must agree.

D6 — ShouldIgnore and ShouldKeep are not negations

A handling the code has never seen answers "no" to both, so the handler throws instead of guessing whether to keep or drop the writer's content.

Error and boundary cases

Case Behavior
A table, code block, ---, or link reference definition Ignored by default; one Info at the construct.
Several ignored constructs One Info each, in source order.
A construct the policy keeps Nothing reported.
Front matter or an HTML comment Discarded before the policy; nothing reported.
Inside a list item or blockquote Reported; the converter recurses.
A policy answering neither keep nor ignore NotSupportedException naming the construct.

Testability

  • Handler: every ignored kind is noted once, with the writer's word and the right span, including kinds only a configured policy ignores — no parsing needed.
  • Policy extensions: both answer "no" to an unknown handling.
  • Parser and pipeline: a real parse notes a nested construct; a script with a table yields one DLG1114 and still succeeds; front matter and comments stay silent.
  • The error-code reference's examples are compiled: the trigger reports DLG1114, both fixes do not.