{
  "schema": "https://bars.commonsware.com/conformance/schema/render-fixture.schema.json",
  "version": "0.1.0",
  "cases": [
    {
      "name": "standalone-with-block-strips-indentation-and-newline-without-tilde",
      "description": "A #with block open/close tag alone on its own line (only surrounding whitespace) has that line's leading indentation and trailing newline stripped implicitly, with no ~ marker.",
      "template": "before\n  {{#with y }}\n  Z\n  {{/with}}\nafter",
      "context": {
        "y": {}
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  Z\nafter"
      }
    },
    {
      "name": "standalone-each-block-strips-indentation-and-newline-every-iteration",
      "description": "A standalone #each block's open/close lines are stripped once from the loop body's own AST, so every iteration renders without the extra indentation/newline.",
      "template": "{{#each items }}\n  {{ this }}\n{{/each}}\n",
      "context": {
        "items": ["a", "b"]
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "  a\n  b\n"
      }
    },
    {
      "name": "nested-standalone-blocks-each-stripped-independently",
      "description": "Nested standalone blocks each have their own line's indentation and trailing newline removed.",
      "template": "{{#if a }}\n  {{#if b }}\n  X\n  {{/if}}\n{{/if}}",
      "context": {
        "a": true,
        "b": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "  X\n"
      }
    },
    {
      "name": "standalone-else-strips-indentation-and-newlines-without-tilde",
      "description": "A standalone {{else}} tag has the indentation before it and the newline after it stripped implicitly, matching the {{#each}}/{{/each}} standalone stripping on the same block.",
      "template": "{{#each items }}\nX\n{{else}}\nY\n{{/each}}",
      "context": {
        "items": []
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "Y\n"
      }
    },
    {
      "name": "standalone-comment-strips-indentation-and-newline-without-tilde",
      "description": "A comment tag alone on its own line is stripped implicitly; the comment itself never renders anything regardless.",
      "template": "before\n  {{! a note }}\nafter",
      "expect": {
        "kind": "output",
        "expectedOutput": "before\nafter"
      }
    },
    {
      "name": "standalone-assign-strips-indentation-and-newline-without-tilde",
      "description": "An assign tag alone on its own line is stripped implicitly; the tag itself never renders anything regardless.",
      "template": "before\n  {{= @local/t = \"Lo\" }}\nafter{{ @local/t }}",
      "expect": {
        "kind": "output",
        "expectedOutput": "before\nafterLo"
      }
    },
    {
      "name": "non-standalone-block-tag-is-not-stripped",
      "description": "A block tag that shares its line with real template text on both sides is not standalone, so no implicit stripping happens on either side, even without ~.",
      "template": "before  {{#with y }}Z{{/with}}  after",
      "context": {
        "y": {}
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before  Z  after"
      }
    },
    {
      "name": "non-standalone-open-tag-still-standalone-close-tag",
      "description": "A block open tag that shares its line with body text is not standalone, but its close tag — alone on its own line — is independently evaluated and still gets stripped.",
      "template": "before\n  {{#with y }}Z\n  {{/with}}\nafter",
      "context": {
        "y": {}
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  Z\nafter"
      }
    },
    {
      "name": "interpolation-is-exempt-from-standalone-stripping",
      "description": "An interpolation alone on its own line is never treated as standalone (Mustache rule); the surrounding indentation and newlines are left untouched.",
      "template": "before\n  {{ x }}\nafter",
      "context": {
        "x": "X"
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  X\nafter"
      }
    },
    {
      "name": "standalone-comment-strips-indentation-and-newline-over-crlf",
      "description": "Standalone detection and stripping work the same over CRLF line endings as over LF: the carriage return immediately before the tag's newline is treated as part of the newline sequence, not as line content, and is removed along with the newline it belongs to.",
      "template": "before\r\n  {{! a note }}\r\nafter",
      "expect": {
        "kind": "output",
        "expectedOutput": "before\r\nafter"
      }
    },
    {
      "name": "standalone-tag-at-start-of-template-has-no-leading-text-to-strip",
      "description": "A standalone tag with no preceding template text at all (the very start of the template) is standalone regardless — a missing neighbor counts as whitespace on that side, the same as an empty Text segment would.",
      "template": "{{! a note }}\nafter",
      "expect": {
        "kind": "output",
        "expectedOutput": "after"
      }
    },
    {
      "name": "standalone-tag-at-end-of-template-has-no-trailing-text-to-strip",
      "description": "A standalone tag with no following template text at all (the very end of the template) is standalone regardless — a missing neighbor counts as whitespace on that side, the same as an empty Text segment would. Standalone stripping only removes the *preceding* line's indentation (space/tab) and the tag's *own* trailing newline (via the following text); it never removes the newline ending the line before the tag, so that newline survives here since there is no following text to strip a newline from.",
      "template": "before\n  {{! a note }}",
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n"
      }
    },
    {
      "name": "raw-block-on-shared-line-prevents-standalone-detection",
      "description": "A raw block is real line content, not whitespace: a block-close tag that would otherwise be standalone is not standalone when it shares its line with a raw block, so neither tag's surrounding whitespace is stripped.",
      "template": "{{#if a }}\nX\n{{{{ raw content }}}}{{/if}}\nafter",
      "context": {
        "a": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "X\n raw content \nafter"
      }
    },
    {
      "name": "escaped-delimiter-on-shared-line-prevents-standalone-detection",
      "description": "An escaped delimiter (\\{{) is real line content, not whitespace: a block-close tag sharing its line with one is not standalone, so its surrounding whitespace is left untouched.",
      "template": "{{#if a }}\nX\n{{/if}}\\{{ literal\nafter",
      "context": {
        "a": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "X\n{{ literal\nafter"
      }
    },
    {
      "name": "if-block-empty-arm-body-and-non-empty-else-not-standalone",
      "description": "An empty if-arm body places the #if tag adjacent to the {{else}} tag on the same line (content, not a boundary), so neither is standalone: no implicit stripping happens on either side.",
      "template": "before\n  {{#if b }}{{else}}Y{{/if}}\nafter",
      "context": {
        "b": false
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  Y\nafter"
      }
    },
    {
      "name": "if-block-empty-body-no-else-not-standalone",
      "description": "An empty if body places the #if tag adjacent to the {{/if}} tag on the same line (content, not a boundary), so neither is standalone: no implicit stripping happens on either side.",
      "template": "before\n  {{#if a }}{{/if}}\nafter",
      "context": {
        "a": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "if-block-else-and-close-share-line-with-empty-else-body-open-side-still-standalone",
      "description": "An empty else body places the {{else}} tag adjacent to the {{/if}} tag on the same line, so that boundary is not standalone; but the #if open tag's own line is unaffected and remains standalone.",
      "template": "{{#if a }}\nX\n  {{else}}{{/if}}\nafter",
      "context": {
        "a": false
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "\nafter"
      }
    },
    {
      "name": "each-block-empty-body-no-else-not-standalone",
      "description": "An empty each body places the #each tag adjacent to the {{/each}} tag on the same line (content, not a boundary), so neither is standalone: no implicit stripping happens on either side.",
      "template": "before\n  {{#each xs }}{{/each}}\nafter",
      "context": {
        "xs": []
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "unless-block-empty-body-no-else-not-standalone",
      "description": "An empty unless body places the #unless tag adjacent to the {{/unless}} tag on the same line (content, not a boundary), so neither is standalone: no implicit stripping happens on either side.",
      "template": "before\n  {{#unless a }}{{/unless}}\nafter",
      "context": {
        "a": false
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "if-block-else-if-two-empty-arm-bodies-no-else-not-standalone",
      "description": "Two consecutive empty if/else-if arm bodies place every flanking tag adjacent to its neighbor on the same line, so no boundary in the chain is standalone.",
      "template": "before\n  {{#if a }}{{else if b }}{{/if}}\nafter",
      "context": {
        "a": false,
        "b": false
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "if-block-else-if-following-non-empty-prior-arm-not-standalone",
      "description": "An empty else-if arm body places the {{else if b}} tag adjacent to the {{/if}} tag on the same line, so that boundary is not standalone, regardless of the prior arm's body content.",
      "template": "before\n  {{#if a }}X{{else if b }}{{/if}}\nafter",
      "context": {
        "a": false,
        "b": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "each-block-empty-body-non-empty-else-else-still-standalone-both-sides",
      "description": "An empty each body places the #each tag adjacent to the {{else}} tag on the same line, so that boundary is not standalone; but the {{else}}/{{/each}} boundary is unaffected and remains standalone on both sides.",
      "template": "{{#each xs }}{{else}}\nZ\n{{/each}}",
      "context": {
        "xs": []
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "\nZ\n"
      }
    },
    {
      "name": "with-block-empty-body-not-standalone",
      "description": "An empty with body places the #with tag adjacent to the {{/with}} tag on the same line (content, not a boundary), so neither is standalone: no implicit stripping happens on either side.",
      "template": "before\n  {{#with y }}{{/with}}\nafter",
      "context": {
        "y": {}
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "before\n  \nafter"
      }
    },
    {
      "name": "nested-block-close-abutting-parent-close-stays-standalone",
      "description": "A guard against over-fixing the empty-region rule: a nested block's close tag abutting its parent's close tag is parent-adjacency (an outer-sibling boundary), not an empty inner region, so the nested block's own standalone stripping still applies.",
      "template": "{{#with y }}\n{{#if a }}\nX\n{{/if}}{{/with}}\nafter",
      "context": {
        "y": {},
        "a": true
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "\nafter"
      }
    }
  ]
}
