So far this is what I've got:
    
    
    import macros, htmlgen
    
    
    macro traverseTree(body: untyped): untyped =
      proc processNode(node: NimNode): NimNode =
        case node.kind
          of nnkCall:
            let callee = node[0]
            
            var children: seq[NimNode] = @[]
            for arg in node[1..^1]:
              children.add(processNode(arg))
            
            var tag = ""
            case callee.repr
              of "dv":  tag = "div"
              else: tag = callee.repr
            
            return newCall(tag, children)
          
          of nnkStmtList, nnkStmtListExpr:
            var processedChildren = newSeq[NimNode]()
            for child in node:
              processedChildren.add(processNode(child))
            return newNimNode(nnkStmtList).add(processedChildren)
          
          else:
            return node
      
      let processedBody = processNode(body)
      return processedBody
    
    # Usage example
    let html = traverseTree:
      dv(id = "1"):
        h1(style = "value"):
          "hello world"
    
    echo html
    
    
    
    Run

Output:
    
    
    <div id="1"><h1 style="value">hello world</h1></div>
    
    
    Run

So far so good! But when I attempt to add a sibling to h1:
    
    
    let html = traverseTree:
      dv(id = "1"):
        h1(style = "value"):
          "hello world"
        p: "this is a paragraph"
    
    
    Run

The following error occurs:
    
    
    (35, 12) template/generic instantiation of `traverseTree` from here
    (39, 8) template/generic instantiation of `div` from here
    (38, 7) Error: expression '"<h1 style=\"value\">hello world</h1>"' is of 
type 'string' and has to be used (or discarded)
    
    
    Run

I think the problem is here:
    
    
            var children: seq[NimNode] = @[]
            for arg in node[1..^1]:
              children.add(processNode(arg))
    
    
    Run

I think whats happening is that when it finds a child call it goes down into 
that node without accounting for the greater context (such as siblings). This 
is supported (I thnk) by the fact that I can get longer chains of html to be 
produced so long as I keep passing nodes as children. For example:
    
    
    let html = traverseTree:
      dv(id = "1"):
        dv:
          dv:
            dv:
              h1(style = "value"):
                "hello world"
    
    
    Run

output:
    
    
    <div id="1"><div><div><div><h1 style="value">hello 
world</h1></div></div></div></div>
    
    
    Run

I am however at a loss at how to solve this. Any help is appreciated!

Reply via email to