=======
Package
=======

package foobar

---

(source_file
  (package_clause
    (package_identifier)))

=========
Empty component without arguments
=========

package foobar

templ Foo() {}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    (component_identifier)
    (parameter_list)
    (component_block)))

=========
Empty component with arguments
=========

package foobar

templ Foo(name string, foo int, bar []string) {}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (slice_type
          element: (type_identifier))))
    (component_block)))

=========
Component with a single element taking a parameter
=========

package foobar

templ Foo(text string) {
  <button class="button">FOO</button>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier)
          (attribute
            name: (attribute_name)
            value: (quoted_attribute_value
              (attribute_value))))
        (element_text)
        (tag_end
          name: (element_identifier))))))

====
Component with multiple elements and an expression
====

package testhtml

templ BasicTemplate(url string) {
  <div>
    <a href={ templ.URL(url) } class="red">text</a>
  </div>
  <hr/>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (element
          (tag_start
            name: (element_identifier)
            (attribute
              name: (attribute_name)
              value: (expression
                (call_expression
                  function: (selector_expression
                    operand: (identifier)
                    field: (field_identifier))
                  arguments: (argument_list
                    (identifier)))))
            (attribute
              name: (attribute_name)
              value: (quoted_attribute_value
                (attribute_value))))
          (element_text)
          (tag_end
            name: (element_identifier)))
        (tag_end
          name: (element_identifier)))
      (element
        (self_closing_tag
          name: (element_identifier))))))

====
Component with if / else
====

package foobar

templ MyComponent(loggedIn bool) {
  if loggedIn {
    <a href="/logout">Logout</a>
  } else {
    <a href="/login">Login</a>
  }
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (component_if_statement
        condition: (identifier)
        consequence: (component_block
          (element
            (tag_start
              name: (element_identifier)
              (attribute
                name: (attribute_name)
                value: (quoted_attribute_value
                  (attribute_value))))
            (element_text)
            (tag_end
              name: (element_identifier))))
        alternative: (component_block
          (element
            (tag_start
              name: (element_identifier)
              (attribute
                name: (attribute_name)
                value: (quoted_attribute_value
                  (attribute_value))))
            (element_text)
            (tag_end
              name: (element_identifier))))))))

====
Component with if / else if / else
====

package foobar

templ MyComponent() {
  if true {
    <a href="/A">A</a>
  } else if false {
    <a href="/B">B</a>
  } else {
    <a href="/C">C</a>
  }
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    (component_identifier)
    (parameter_list)
    (component_block
      (component_if_statement
        (true)
        (component_block
          (element
            (tag_start
              (element_identifier)
              (attribute
                (attribute_name)
                (quoted_attribute_value
                  (attribute_value))))
            (element_text)
            (tag_end
              (element_identifier))))
        (component_if_statement
          (false)
          (component_block
            (element
              (tag_start
                (element_identifier)
                (attribute
                  (attribute_name)
                  (quoted_attribute_value
                    (attribute_value))))
              (element_text)
              (tag_end
                (element_identifier))))
          (component_block
            (element
              (tag_start
                (element_identifier)
                (attribute
                  (attribute_name)
                  (quoted_attribute_value
                    (attribute_value))))
              (element_text)
              (tag_end
                (element_identifier)))))))))

====
Component with nested ifs
====

package foobar

templ MyComponent(loggedIn bool, n int) {
  if loggedIn {
    if n > 10 {
      <hr/>
    }
  } else {
    if n > 20 {
      <hr/>
    }
  }
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (component_if_statement
        condition: (identifier)
        consequence: (component_block
          (component_if_statement
            condition: (binary_expression
              left: (identifier)
              right: (identifier))
            consequence: (component_block
              (element
                (self_closing_tag
                  name: (element_identifier))))))
        alternative: (component_block
          (component_if_statement
            condition: (binary_expression
              left: (identifier)
              right: (identifier))
            consequence: (component_block
              (element
                (self_closing_tag
                  name: (element_identifier))))))))))

====
If in an element
====

package foobar

templ MyComponent(n int) {
	<ul>
  if n > 10 {
      <hr/>
  }
  </ul>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (component_if_statement
          condition: (binary_expression
            left: (identifier)
            right: (identifier))
          consequence: (component_block
            (element
              (self_closing_tag
                name: (element_identifier)))))
        (tag_end
          name: (element_identifier))))))

====
Composition of components
====

package foobar

templ Header(title string) {
  <h1>{ title }</h1>
}

templ Body(body string) {
  <p>{ body }</p>
}

templ Page(title string, body string) {
  @Header(title)
  @Body(body)
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (expression
          (identifier))
        (tag_end
          name: (element_identifier)))))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (expression
          (identifier))
        (tag_end
          name: (element_identifier)))))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (component_import
        name: (component_identifier)
        arguments: (argument_list
          (identifier)))
      (component_import
        name: (component_identifier)
        arguments: (argument_list
          (identifier))))))

=====
Long text
=====

package main

templ Foobar() {
  <div>
    foobar_foobar_foobariflolhahah
    hello if hello
    </div>
  <div>if</div>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (element_text)
        (element_text)
        (tag_end
          name: (element_identifier)))
      (element
        (tag_start
          name: (element_identifier))
        (element_text)
        (tag_end
          name: (element_identifier))))))

====
Component as parameter
====

package main

templ Foobar(component templ.Component) {
  <hr/>
  {! component }
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (qualified_type
          package: (package_identifier)
          name: (type_identifier))))
    (component_block
      (element
        (self_closing_tag
          name: (element_identifier)))
      (component_render
        expression: (identifier)))))

====
Render with argument
====

package main

templ email(name string, email string) {
  <a href={ email }>{ name }</a>
}

templ Foobar(name string, email string) {
  <p>{! email(name, email) }</p>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier)
          (attribute
            name: (attribute_name)
            value: (expression
              (identifier))))
        (expression
          (identifier))
        (tag_end
          name: (element_identifier)))))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier))
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (component_render
          expression: (call_expression
            function: (identifier)
            arguments: (argument_list
              (identifier)
              (identifier))))
        (tag_end
          name: (element_identifier))))))

====
Wrap children
====

package main

templ showAll() {
    @wrapChildren() {
        <div>Inserted from the top</div>
    }
}

templ wrapChildren() {
    <div id="wrapper">
        { children... }
    </div>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    (component_identifier)
    (parameter_list)
    (component_block
      (component_import
        (component_identifier)
        (argument_list)
        (component_block
          (element
            (tag_start
              (element_identifier))
            (element_text)
            (tag_end
              (element_identifier)))))))
  (component_declaration
    (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          (element_identifier)
          (attribute
            (attribute_name)
            (quoted_attribute_value
              (attribute_value))))
        (component_children_expression)
        (tag_end
          (element_identifier))))))

===
Doctype element
===

package main

templ Foobar() {
  <!doctype html>
  <!DOCTYPE html>
  <h1>Foobar</h1>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (doctype
          name: (element_identifier)))
      (element
        (doctype
          name: (element_identifier)))
      (element
        (tag_start
          name: (element_identifier))
        (element_text)
        (tag_end
          name: (element_identifier))))))

====
Component with comments
====

package foobar

// This is the greatest component of all time
templ MyComponent(loggedIn bool) {
  if loggedIn {
    <!-- <a href="/logout">Logout</a> -->
    <a href="/logout">Exit</a>
  } else {
    <a href="/login">Login</a>
    <!--
      <div>The login page LOGO</div>
    -->
  }
}

---

(source_file
  (package_clause
    (package_identifier))
  (comment)
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (component_if_statement
        condition: (identifier)
        consequence: (component_block
          (element_comment)
          (element
            (tag_start
              name: (element_identifier)
              (attribute
                name: (attribute_name)
                value: (quoted_attribute_value
                  (attribute_value))))
            (element_text)
            (tag_end
              name: (element_identifier))))
        alternative: (component_block
          (element
            (tag_start
              name: (element_identifier)
              (attribute
                name: (attribute_name)
                value: (quoted_attribute_value
                  (attribute_value))))
            (element_text)
            (tag_end
               name: (element_identifier)))
          (element_comment))))))


====
Component from methods
====

package foobar

type Data struct {
	message string
}

templ (d Data) Method() {
	<div>{ d.message }</div>
}

---

(source_file
  (package_clause
    (package_identifier))
  (type_declaration
    (type_spec
      name: (type_identifier)
      type: (struct_type
        (field_declaration_list
          (field_declaration
            name: (field_identifier)
            type: (type_identifier))))))
  (component_declaration
    receiver: (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (expression
          (selector_expression
            operand: (identifier)
            field: (field_identifier)))
        (tag_end
          name: (element_identifier))))))

====
HTML comment
====

package main

templ Component() {
  <html>
    <head>
      <!--
        <link rel="stylesheet" href="/assets/css/bulma.min.css"/> What is bulma??
        <link rel="apple-touch-icon" sizes="180x180" href="/assets/favicon/apple-touch-icon.png"/>
      -->
      <link href="/style.css" rel="stylesheet"/>
    </head>
  </html>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          (element_identifier))
        (element
          (tag_start
            (element_identifier))
          (element_comment)
          (element
            (self_closing_tag
              (element_identifier)
              (attribute
                (attribute_name)
                (quoted_attribute_value
                  (attribute_value)))
              (attribute
                (attribute_name)
                (quoted_attribute_value
                  (attribute_value)))))
          (tag_end
            (element_identifier)))
          (tag_end
            (element_identifier))))))

===
Component import with package access
===

templ Example() {
  <section>
    @templ.Raw("<div></div>")
  </section>
}

---

(source_file
  (component_declaration
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (component_import
          package: (package_identifier)
          name: (component_identifier)
          arguments: (argument_list
            (interpreted_string_literal)))
        (tag_end
          name: (element_identifier))))))

===
Self closing tag
===

package main

templ Foobar() {
  <input type="text"/>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (self_closing_tag
          name: (element_identifier)
          (attribute
            name: (attribute_name)
            value: (quoted_attribute_value
              (attribute_value))))))))

===
Forward slash in the text between elements
===

package main

templ Foobar() {
  <p>First/given name</p>
}

---

(source_file
  (package_clause
    (package_identifier))
  (component_declaration
    name: (component_identifier)
    (parameter_list)
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (element_text)
        (tag_end
          name: (element_identifier))))))

===
Import expression using struct field
===

package main

type Item struct {
  Icon templ.Component
}

templ Foobar(item Item) {
  <p>
    foo
    @item.Icon
    bar
  </p>
}

---

(source_file
  (package_clause
    (package_identifier))
  (type_declaration
    (type_spec
      name: (type_identifier)
      type: (struct_type
        (field_declaration_list
          (field_declaration
            name: (field_identifier)
            type: (qualified_type
              package: (package_identifier)
              name: (type_identifier)))))))
  (component_declaration
    name: (component_identifier)
    (parameter_list
      (parameter_declaration
        name: (identifier)
        type: (type_identifier)))
    (component_block
      (element
        (tag_start
          name: (element_identifier))
        (element_text)
        (component_import
          package: (package_identifier)
          name: (component_identifier))
        (element_text)
        (tag_end
          name: (element_identifier))))))
