Lint a file before publishing

Anchorify surfaces authoring warnings ("your slide deck frontmatter isn't going to be detected", "this CSV is semicolon-delimited", "this JSON has a syntax error") on three surfaces:

  1. Share-render owner banner — visible only to you (the share's org admin) inline above the rendered share.
  2. CLI publish — printed to stderr after a successful publish.
  3. Lint API — pre-publish check via POST /api/v1/lint.

All three use the same analyzer, so the warnings are consistent across surfaces.

CLI: anchorify lint <file>#

anchorify lint deck.md

Returns one of:

  • Exit 0 with ok — deck.md lints clean as slides_marp when there are no issues.
  • Exit 0 with one or more warn/info lines when the file will preview but is worth tightening up.
  • Exit 1 with one or more error lines when the file will look broken to recipients.

Use --type to lint as a specific content type when the filename doesn't match:

anchorify lint data.txt --type csv

API: POST /api/v1/lint#

Auth: per-user bearer token (same as other write endpoints). Request body:

{
  "content": "---\nmarp: true\n---\n# Slide one",
  "filename": "deck.md",
  "content_type": "slides_marp"
}
  • content (required): the file contents as a string.
  • filename (optional): used for filename-extension content-type detection.
  • content_type (optional): override; one of markdown, code, json, yaml, csv, tsv, html, slides_marp, slides_reveal.

Response (200):

{
  "effective_content_type": "slides_marp",
  "warnings": [
    {
      "kind": "slide_deck_no_separators",
      "severity": "warn",
      "message": "This deck has no `---` slide separators after the frontmatter — everything will render as a single slide.",
      "doc_url": "/docs/guide-slides#slide-separators",
      "location": { "line": 4 }
    }
  ]
}

effective_content_type is the type the publish would actually use — handy when the API caller wants to confirm the sniffer's decision.

warnings is always present (an empty array means the file is clean).

Warning kinds#

kind severity What it means
empty warn Content is empty / whitespace only.
slide_frontmatter_unrecognized error File contains marp: true / reveal: true but the frontmatter is malformed (e.g. no closing ---, blocked by content before the opener).
slide_deck_no_separators warn Marp/reveal deck with no --- slide separators — renders as a single slide.
unclosed_frontmatter warn File opens with --- but the block never closes; renders as <hr> followed by content.
json_parse_failed error JSON is unparseable (after trailing-comma recovery). Pretty-print won't fire.
csv_likely_wrong_delimiter info File is stored as CSV but the header row looks semicolon/tab-delimited. The renderer auto-detects, but the file isn't portable.
markdown_looks_like_html warn Content begins with <!DOCTYPE> / <html>. Switch to --type html so DOMPurify sanitizes.
code_no_language info Code with no filename → no language detection → no syntax highlighting.
binary_under_text_type error NUL bytes detected in content stored as a text type. Re-publish the file itself (anchorify <file>, the /new form, or POST /api/v1/shares/upload) so it lands in the blob tier.

Severity meanings#

  • error — the file will look broken to recipients (raw frontmatter visible, JSON parse failed, etc.). Fix before publishing.
  • warn — the file might look subtly wrong. Renders but worth a look.
  • info — the file renders correctly; this is a portability/best-practice note.

What the lint does NOT check#

  • The actual rendered output (we don't run Marp or marked just to verify).
  • Spelling, grammar, broken links inside the content.
  • File size (the upload form enforces that separately).
  • Whether the filename + slug are clean (slug rules are enforced at publish time).

Next steps#