{
  "schema": "https://bars.commonsware.com/conformance/schema/render-fixture.schema.json",
  "version": "0.1.0",
  "cases": [
    {
      "name": "at-foo-literal-property-via-dot-slash",
      "description": "{{ ./@foo }} reads a literal '@foo' property via RFC 6901 Pointer in the root context.",
      "template": "{{ ./@foo }}",
      "context": {
        "@foo": "bar"
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "bar"
      }
    },
    {
      "name": "at-foo-literal-property-via-this-dot",
      "description": "{{ this.@foo }} reads a literal '@foo' property via dot-notation Pointer in the root context.",
      "template": "{{ this.@foo }}",
      "context": {
        "@foo": "bar"
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "bar"
      }
    },
    {
      "name": "at-foo-literal-property-via-this-slash",
      "description": "{{ this/@foo }} reads a literal '@foo' property via RFC 6901 Pointer in the root context.",
      "template": "{{ this/@foo }}",
      "context": {
        "@foo": "bar"
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "bar"
      }
    },
    {
      "name": "at-index-outside-each-is-null",
      "description": "@index outside any {{#each}} block resolves to null.",
      "template": "{{ @index }}",
      "context": {},
      "expect": {
        "kind": "output",
        "expectedOutput": "null"
      }
    },
    {
      "name": "at-key-html-escaped",
      "description": "@key inside an object each is HTML-escaped when rendered with {{ }} interpolation.",
      "template": "{{#each m }}{{ @key }};{{/each}}",
      "context": {
        "m": {
          "<a>": 1
        }
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "&lt;a&gt;;"
      }
    },
    {
      "name": "at-key-outside-each-is-null",
      "description": "@key outside any {{#each}} block resolves to null.",
      "template": "{{ @key }}",
      "context": {},
      "expect": {
        "kind": "output",
        "expectedOutput": "null"
      }
    },
    {
      "name": "at-key-unescaped-triple-mustache",
      "description": "@key inside an object each is emitted verbatim (unescaped) when rendered with {{{ }}} interpolation.",
      "template": "{{#each m }}{{{ @key }}};{{/each}}",
      "context": {
        "m": {
          "<a>": 1
        }
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "<a>;"
      }
    },
    {
      "name": "at-unknown-is-null",
      "description": "An unrecognised @name identifier (forward-compat) renders as null.",
      "template": "{{#each items }}{{ @bogus }};{{/each}}",
      "context": {
        "items": [
          1,
          2
        ]
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "null;null;"
      }
    },
    {
      "name": "each-index-array-zero-based",
      "description": "@index inside an array {{#each}} renders the 0-based element index.",
      "template": "{{#each items }}{{ @index }}-{{ this }};{{/each}}",
      "context": {
        "items": [
          10,
          20,
          30
        ]
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "0-10;1-20;2-30;"
      }
    },
    {
      "name": "each-index-inside-object-is-null",
      "description": "@index inside an object {{#each}} is null because objects iterate by key, not index.",
      "template": "{{#each scores }}{{ @index }};{{/each}}",
      "context": {
        "scores": {
          "a": 1
        }
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "null;"
      }
    },
    {
      "name": "each-key-inside-array-is-null",
      "description": "@key inside an array {{#each}} is null because arrays iterate by index, not key.",
      "template": "{{#each items }}{{ @key }};{{/each}}",
      "context": {
        "items": [
          1
        ]
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "null;"
      }
    },
    {
      "name": "each-key-object-insertion-order",
      "description": "@key inside an object {{#each}} renders each key; keys are iterated in insertion order.",
      "template": "{{#each scores }}{{ @key }}={{ this }};{{/each}}",
      "context": {
        "scores": {
          "c": 3,
          "a": 1,
          "b": 2
        }
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "c=3;a=1;b=2;"
      }
    },
    {
      "name": "each-parent-index-from-nested-each",
      "description": "{{ ../@index }} inside a nested {{#each}} reaches the outer each's @index.",
      "template": "{{#each outer }}{{#each inner }}{{ ../@index }}.{{ @index }};{{/each}}{{/each}}",
      "context": {
        "outer": [
          {
            "inner": [
              "a",
              "b"
            ]
          },
          {
            "inner": [
              "c"
            ]
          }
        ]
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "0.0;0.1;1.0;"
      }
    },
    {
      "name": "each-parent-key-from-nested-each",
      "description": "{{ ../@key }} inside a nested {{#each}} over an array reaches the outer each's @key (if the outer is an object each).",
      "template": "{{#each groups }}{{#each this }}{{ ../@key }}/{{ this }};{{/each}}{{/each}}",
      "context": {
        "groups": {
          "x": [
            "a",
            "b"
          ],
          "y": [
            "c"
          ]
        }
      },
      "expect": {
        "kind": "output",
        "expectedOutput": "x/a;x/b;y/c;"
      }
    },
    {
      "name": "each-parent-special-overflow-throws",
      "description": "{{ ../@index }} at the root depth (with no enclosing each) throws kbParseException.",
      "template": "{{ ../@index }}",
      "context": {},
      "expect": {
        "kind": "error"
      }
    }
  ]
}
