docs: function transform (tag, props, children) {
        if (tag === '!--') {
          return createComment(props.comment)
        }
  
        const id = path.scope.generateUidIdentifier(getElementName(props, tag))
        path.scope.push({ id })
  
        const result = []
  
        if (tag === 'nanohtml-fragment') {
          result.push(t.assignmentExpression('=', id, createFragment()))
        } else {
          var isCustomElement = props.is
          delete props.is
  
          // Use the SVG namespace for svg elements.
          if (SVG_TAGS.includes(tag)) {
            state.svgNamespaceId.used = true
  
            if (isCustomElement) {
              result.push(t.assignmentExpression('=', id, createNsCustomBuiltIn(state.svgNamespaceId, tag, isCustomElement)))
            } else {
              result.push(t.assignmentExpression('=', id, createNsElement(state.svgNamespaceId, tag)))
            }
          } else if (isCustomElement) {
            result.push(t.assignmentExpression('=', id, createCustomBuiltIn(tag, isCustomElement)))
          } else {
            result.push(t.assignmentExpression('=', id, createElement(tag)))
          }
        }
  
        Object.keys(props).forEach((propName) => {
          const dynamicPropName = convertPlaceholders(propName).filter(isNotEmptyString)
          // Just use the normal propName if there are no placeholders
          if (dynamicPropName.length === 1 && t.isStringLiteral(dynamicPropName[0])) {
            propName = dynamicPropName[0].value
          } else {
            state.setAttributeId.used = true
            result.push(addDynamicAttribute(state.setAttributeId, id, dynamicPropName.reduce(concatAttribute),
              convertPlaceholders(props[propName]).filter(isNotEmptyString).reduce(concatAttribute)))
            return
          }
  
          // don’t convert to lowercase, since some attributes are case-sensetive
          let attrName = propName
  
          if (attrName === 'className') {
            attrName = 'class'
          }
  
          if (attrName === 'htmlFor') {
            attrName = 'for'
          }
  
          // abc.onclick = xyz
          if (attrName.slice(0, 2) === 'on' || DIRECT_PROPS.indexOf(attrName) > -1) {
            const value = convertPlaceholders(props[propName]).filter(isNotEmptyString)
            result.push(setDomProperty(id, attrName,
              value.length === 1
                ? value[0]
                : value.map(ensureString).reduce(concatAttribute)
            ))
  
            return
          }
  
          // Dynamic boolean attributes
          if (BOOL_PROPS.indexOf(attrName) !== -1 && props[propName] !== attrName) {
            // if (xyz) abc.setAttribute('disabled', 'disabled')
            result.push(setBooleanAttribute(id, attrName,
              convertPlaceholders(props[propName])
                .filter(isNotEmptyString)[0]))
            return
          }
  
          // use proper xml namespace for svg use links
          if (attrName === 'xlink:href') {
            const value = convertPlaceholders(props[propName])
              .map(ensureString)
              .reduce(concatAttribute)
  
            state.xlinkNamespaceId.used = true
            result.push(setDomAttributeNS(id, attrName, value, state.xlinkNamespaceId))
  
            return
          }
  
          // abc.setAttribute('class', xyz)
          result.push(setDomAttribute(id, attrName,
            convertPlaceholders(props[propName])
              .map(ensureString)
              .reduce(concatAttribute)
          ))
        })
  
        if (Array.isArray(children)) {
          const realChildren = children.map(convertPlaceholders)
            // Flatten
            .reduce((flat, arr) => flat.concat(arr), [])
            // Remove empty strings since they don't affect output
            .filter(isNotEmptyString)
  
          if (realChildren.length > 0) {
            state.appendChildId.used = true
            result.push(appendChild(state.appendChildId, id, realChildren))
          }
        }
  
        result.push(id)
        return t.sequenceExpression(result)
      }