AI Demos Research — the structured-intelligence platform. Every verdict on these pages opens to the execution behind it.
Graded 18 October 2026

Does Extend AI preserve code blocks and indentation when converting PDFs to Markdown?

Extend AI flattened the PDF’s two code snippets into ordinary text rather than preserving their line structure and indentation. Code characters also changed, and neither snippet would run as returned.

1 of 1 test case failed

Every test case in this scenario has a result.

Pass rate0%0 of 1 gradable
Coverage1 of 1test case with a result
0PassNo test case passed.
1FailMissed at least one thing it was expected to do; the reason and proof are with each test case below.
0Not gradableEvery result here could be graded.
0UntestedEvery test case in this scenario has a result.
The pass rate is a summary. The evidence is the test case below: what we sent, what we checked, what the tool returned, and the proof.

The test case

Each test case is judged on its own: Pass, Fail, Not gradable, or Untested. The scenario result above is based on this test case.

Code block — fenced, structure intactFailEvidence
What we sent
InputDocument (PDF)
Input PDF: shaded Python and shell code blocks on page 2
Open the PDF ↗
What the tool returned
Markdown
from tarnbeck. stations import Export, reload_window

def reload_after_reset(station, reset_at): export = Export. open(station) window = reload_window(reset_at, margin_minutes=45)

for block in export.blocks(window): if block. checksum_ok(): continue export.requeue (block, reason="gauge reset")

return export. commit(dry_run=False)

Returned Markdown: unfenced code with merged statements and lost indentation

Copied from Output file (Markdown), lines 33–39

Open the Markdown file ↗
Markdown
$ ssh loader-01. tarnbeck. example $ tarnbeck-maint reload-after-reset -- station VQ1 | -- reset-at '2026-01-29T09:15' -- confirm

Copied from Output file (Markdown), line 49

Output file (JSON)
API response: both snippets classified as ordinary text rather than code
JSONlong text shortened; the file holds every character
{
  "parse_run": {
    "object": "parse_run",
    "id": "pr_HbkENnP4XWJ7adkx2mXu3",
    "file": {
      "object": "file",
      "id": "file_ffmzz11xz5imXPxtY0uNJ",
      "name": "operations_note_DS-OP-07.pdf",
      "type": "PDF",
      "parentFileId": null,
      "metadata": {
        "pageCount": 3
      },
      "dataRetention": {
        "mode": "workspace_default",
        "status": "available"
      },
      "createdAt": "2026-09-09T12:41:15.258Z",
      "updatedAt": "2026-09-09T12:41:21.669Z"
    },
    "status": "PROCESSED",
    "failureReason": null,
    "failureMessage": null,
    "metadata": null,
    "dataRetention": {
      "mode": "workspace_default",
      "status": "available"
    },
    "output": {
      "chunks": [
        {
          "object": "chunk",
          "id": "chunk_1_XzYQdE",
          "type": "page",
          "content": "Tarnbeck Institute of Hydrology · Data Services\n\nReloading a station export after a gauge reset\n\nOperations note DS/OP/07 · Data services · Reviewed 14 January 2026\n\n### Symptoms\n\nThe station's daily total is short and the loader's own log … [2,328 characters in the file]",
          "metadata": {
            "pageRange": "{… 2 fields in the file}",
            "minOcrConfidence": 0.332,
            "avgOcrConfidence": 0.99
          },
          "blocks": [
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}"
          ]
        },
        {
          "object": "chunk",
          "id": "chunk_2_4jBDcQ",
          "type": "page",
          "content": "Tarnbeck Institute of Hydrology · Data Services\n\nDS/OP/07\n\nfrom tarnbeck. stations import Export, reload_window\n\ndef reload_after_reset(station, reset_at): export = Export. open(station) window = reload_window(reset_at, margin_minutes=45) … [2,400 characters in the file]",
          "metadata": {
            "pageRange": "{… 2 fields in the file}",
            "minOcrConfidence": 0.492,
            "avgOcrConfidence": 0.989
          },
          "blocks": [
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}"
          ]
        },
        {
          "object": "chunk",
          "id": "chunk_3_BiTzmx",
          "type": "page",
          "content": "Tarnbeck Institute of Hydrology · Data Services\n\nDS/OP/07\n\n# If the count is short\n\nA short count means blocks were rejected for a second reason and the reload has not found out what it was. Do not run it again: a second pass requeues the s … [1,939 characters in the file]",
          "metadata": {
            "pageRange": "{… 2 fields in the file}",
            "minOcrConfidence": 0.39,
            "avgOcrConfidence": 0.992
          },
          "blocks": [
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}",
            "{… 8 fields in the file}"
          ]
        }
      ],
      "metadata": {
        "originalMimeType": "application/pdf",
        "finalMimeType": "application/pdf",
        "pages": [
          {
            "number": 1,
            "rotationApplied": 0,
            "originalPageWidth": 596,
            "originalPageHeight": 842,
            "dpi": 150
          },
          {
            "number": 2,
            "rotationApplied": 0,
            "originalPageWidth": 596,
            "originalPageHeight": 842,
            "dpi": 150
          },
          {
            "number": 3,
            "rotationApplied": 0,
            "originalPageWidth": 596,
            "originalPageHeight": 842,
            "dpi": 150
          }
        ]
      }
    },
    "outputUrl": null,
    "metrics": {
      "processingTimeMs": 4906,
      "pageCount": 3
    },
    "config": {
      "engine": "parse_performance",
      "engineVersion": "2.0.0"
    },
    "batchId": null,
    "usage": {
      "credits": 6,
      "totalCredits": 6,
      "breakdown": [
        {
          "object": "parse_run",
          "id": "pr_HbkENnP4XWJ7adkx2mXu3",
          "credits": 6,
          "charges": ["{… 4 fields in the file}"]
        }
      ]
    }
  },
  "file": {
    "object": "file",
    "id": "file_ffmzz11xz5imXPxtY0uNJ",
    "name": "operations_note_DS-OP-07.pdf",
    "type": "PDF",
    "parentFileId": null,
    "presignedUrl": null,
    "contents": null,
    "metadata": {},
    "dataRetention": {
      "mode": "workspace_default",
      "status": "available"
    },
    "createdAt": "2026-09-09T12:41:15.258Z",
    "updatedAt": "2026-09-09T12:41:15.282Z"
  },
  "figure_assets": []
}

The whole file (72 KB) is too large to print here; open it from its link below.

Open the JSON file ↗
Expected vs. Found
✗Expected: Emit the code as preformatted or fenced blocks, preserving line breaks and the source’s indentation.Found: Source indentation of 4, 8 and 12 spaces became flush-left text; statements merged and characters changed. Neither snippet was fenced or runnable; loop and conditional nesting was unrecoverable.
Supporting proof
Proof 1Screenshot
Side-by-side comparison: page 2’s shaded code boxes and the flattened Markdown
Open original ↗
Proof 2Screenshot
Conversion summary card: input, default pipeline, timing and completion status
Open original ↗
Why this result

The default pipeline completed the conversion of the full PDF without an error, yet treated genuine code as prose. It did not preserve the required code blocks, line breaks or indentation.

Also observed in this test case

Headings retained. The “Running it” section title remained a Markdown heading.

Headers and footers retained. The Markdown included a page-number tag for each page, alongside the running headers and footers.

Tested by Chandresh Bisht · evidence dated 9 September 2026

Configuration and setup

How this tool was set up for the run and what the test needed in place. Each row is a fact from the run's records; a fact the records do not hold is left out, not guessed.

Software that produced the output
Extend AI
Build or version
x-extend-api-version 2026-02-09; engine parse_performance 2.0.0
Plan or tier
free tier (10,000 starter credits, Pay As You Go)
Surface
API
Set up before the run
A complete operations-note PDF about reloading a station export after a gauge reset contained shaded Python and shell code. Conversion to Markdown had to use the default pipeline in one pass, without tool-specific tuning.
Pipeline
no configuration settings set (the product's defaults); no processor; no extraction schema
Tested
9 September 2026 · Chandresh Bisht

How this scenario is graded

How we decide Pass, Fail and Not gradable. The same rules apply to every tool tested on this scenario.

How results are decided

Each test case gets one result per tool: Pass, Fail or Not gradable. A test case we haven't run yet shows Untested. There are no partial results.

The rules
  • Pass: the tool did everything the test expected, and nothing it said contradicts the correct answer.
  • Fail: at least one expected behaviour clearly didn't happen; the test case's result says which one and quotes the tool.
  • Not gradable: our evidence couldn't settle the outcome (for example a record we needed is missing). It is never counted as a fail, and the test case's result says what's missing.

Where this sits in the benchmark

This page is one cell of a larger study: one tool, one scenario. Only this benchmark's frame appears here.

History of this result

What has happened to this result since it was first published. Runs and grades are never overwritten: a retest or a re-grade publishes a new result and keeps the earlier one readable.

from the publication record
11 November 2026First publishedConverting a complex PDF into clean Markdown with a hosted API v1

Act on this result

Nothing filed here edits the run or the grade. A challenge opens a review, and a review can produce a new run or a re-grade — which becomes the current result and leaves this one in the history.

This matches what I see

You run the same kind of test against your own setup and get the same behaviour.

Agree →
This does not match

Yours behaves differently. Tell us what you got, with a screenshot if you have one.

Disagree →
Point out an issue

Something here is wrong — a reference value, a transcription, a grade.

Report an issue →
Request a retest

On a newer build, a larger dataset, or your own setup.

Request a retest →
We have fixed this

Tell us what changed and we schedule a rerun of the failing test case. The old result stays as history.

Vendor notice →
Filed against this evidenceNothing yet. Challenges, counter-evidence and fix notices appear here with their outcome, and stay on the page after they are resolved.
Cite this result
aidemos.com/benchmarks/pdf-to-markdown-apis/results/extend-ai/a-document-containing-a-code-block · 0 pass · 1 fail · coverage 1/1 · graded 2026-10-18

The same record is available as structured data through the AI Demos MCP server, with the counts, the coverage and every per-test-case reason carried as fields.

Verify the proof files

These files support this result. Open a file to inspect the original evidence.

Input · Document (PDF) ↗application/pdf · 78 KB
Output file (Markdown) ↗text/markdown · 7 KB
Output file (JSON) ↗application/json · 72 KB
Proof 1 · Screenshot ↗image/png · 215 KB
Proof 2 · Screenshot ↗image/png · 53 KB
File fingerprints (SHA-256)

A fingerprint identifies the exact file used for this result.

Input · Document (PDF)cd27d1e77ec9818ff769bde1b49d95e711373888507af4b007054c27b7a52db8
Output file (Markdown)09bb5bfebde02936899ec68e3dbddb63e6376d27cde85ba6a090400fdd4594de
Output file (JSON)d4931c54ab8cb73aeda24e1016c75ebfd79c100d2e4c4cc4efb81bb48c7eb016
Proof 1 · Screenshot8f91bde651c10fa07498bf56b5628983a069f8ef4671122016203502875177ae
Proof 2 · Screenshot3508f6c1b378d00574f9dc3f9d21ab7259272d891fe84c86d35a235ebfb63ef6