     @key? and @key.match ...args
   row: (di = 0) ->
     i = @i + di
-    for tile, j in @drawing.keys[i] ? []
+    for key, j in @drawing.keys[i] ? []
       new Context @render, i, j
   column: (dj = 0) ->
     j = @j + dj

## Tile to fall back to when encountering an unrecognized key.
## Path from https://commons.wikimedia.org/wiki/File:Replacement_character.svg
## by Amit6, released into the public domain.
unrecognizedTile = new Tile '_unrecognized', '''
  <symbol viewBox="0 0 200 200" preserveAspectRatio="none" width="auto" height="auto">
    <rect width="200" height="200" fill="yellow"/>
    <path stroke="none" fill="red" d="M 200,100 100,200 0,100 100,0 200,100 z M 135.64709,74.70585 q 0,-13.52935 -10.00006,-22.52943 -9.99999,-8.99999 -24.35289,-8.99999 -17.29415,0 -30.117661,5.29409 L 69.05879,69.52938 q 9.764731,-6.23528 21.52944,-6.23528 8.82356,0 14.58824,4.82351 5.76469,4.82351 5.76469,12.70589 0,8.5883 -9.94117,21.70588 -9.94117,13.11766 -9.94117,26.76473 l 17.88236,0 q 0,-6.3529 6.9412,-14.9412 11.76471,-14.58816 12.82351,-16.35289 6.9412,-11.05887 6.9412,-23.29417 z m -22.00003,92.11771 0,-24.70585 -27.29412,0 0,24.70585 27.29412,0 z"/>
  </symbol>
'''
unrecognizedTile.id = '_unrecognized' # cannot be output of escapeId()
unrecognizedTile.isStatic = true      # need to clone on use

class Input extends HasSettings
  ###

        false
      else
        true
    @dom
  useDOM: ->
    @makeDOM()
    ## Clone if content is static, to enable later re-use
    if @isStatic
      @dom.documentElement.cloneNode true
    else
      @dom.documentElement

class SVGTopLevel extends SVGContent
  ###
  Abstract base class for `SVGSymbol` and `SVGSVG` which have support for
  `viewBox`, `overflowBox`, and `z-index`.
  Subclass should define `wrapper` of 'symbol' or 'svg'.
  Parser will enforce that the content is wrapped in this element.
  ###
  makeDOM: ->
    super()
    ## Wrap XML in <wrapper>.
    symbol = @dom.createElementNS SVGNS, @wrapper
    ## Force `id` to be first attribute.
    symbol.setAttribute 'id', @id if @id?
    ## Avoid a layer of indirection for <symbol>/<svg> at top level
    if @dom.documentElement.nodeName in ['symbol', 'svg'] and
       not @dom.documentElement.nextSibling?
      for attribute in @dom.documentElement.attributes
        unless attribute.name in ['version', 'id'] or attribute.name.startsWith 'xmlns'
          symbol.setAttribute attribute.name, attribute.value
      @dom.removeChild doc = @dom.documentElement
    else
      doc = @dom
      ## Allow top-level object to specify <symbol> data.
      for attribute in ['z-index', 'viewBox', 'overflowBox']
        if doc.documentElement.hasAttribute attribute
          symbol.setAttribute attribute,
            doc.documentElement.getAttribute attribute
          doc.documentElement.removeAttribute attribute
    for child in (node for node in doc.childNodes)
      symbol.appendChild child
    @dom.appendChild symbol

    ## Compute viewBox attribute if absent and wrapping in <symbol>.
    @viewBox = svgBBox @dom, @wrapper == 'symbol'

    ## Overflow behavior
    overflow = attributeOrStyle @dom.documentElement, 'overflow'
