# [PackageDev] target_format: json, ext: tmLanguage.json
# https://github.com/microsoft/vscode/blob/master/extensions/html/syntaxes/html.tmLanguage.json
# https://github.com/microsoft/TypeScript-TmLanguage/blob/master/TypeScriptReact.YAML-tmLanguage
# TODOS
# HTML entities (&quote;)

name: Paperclip Template
scopeName: text.html.paperclip-html
fileTypes: []
uuid: 3e3ce414-c385-42ea-a2ba-451a37ca6fd1
patterns:
  - include: "#topNodes"
variables:
  tagName: ([\w\-\.]+)
  tagOpen: (<){{tagName}}(?=((<\s*)|(\s+))(?!\?)|\/?>)
  # tagOpen: (<){{tagName}}(?=((<\s*)|(\s+))(?!\?)|\/?>)
  tagClose: (</){{tagName}}(>)
  tagOpenLookahead: (?={{tagOpen}})
repository:
  topNodes:
    patterns:
      - include: "#nodes"
  nodes:
    patterns:
      - include: "#elements"
      - include: "#blocks"
      - include: "#comments"
      - include: "#entities"
      - include: "#slots"
  elements:
    patterns:
      # Void tag elements
      - begin: (<)(meta|import)
        beginCaptures:
          "1": { name: punctuation.definition.tag.begin.html }
          "2": { name: entity.name.tag.html }
        patterns:
          - include: "#attribute"
        end: (/?>)
        endCaptures:
          "1": { name: punctuation.definition.tag.end.html }

      # <style /> elements
      - begin: (<)(style)([^>]*)(>)
        contentName: "source.pcss"
        beginCaptures:
          "1": { name: punctuation.definition.tag.begin.html }
          "2": { name: entity.name.tag.html }
          "3":
            patterns:
              - include: "#attribute"
          "4": { name: punctuation.definition.tag.end.html }
        end: (</)(style)(?:\s*)(>)
        endCaptures:
          "1": { name: punctuation.definition.tag.end.html }
          "2": { name: entity.name.tag.html }
          "3": { name: punctuation.definition.tag.end.html }
        patterns:
          - include: "source.pcss"

      - begin: "{{tagOpenLookahead}}"
        end: "(/>)|({{tagClose}})"
        endCaptures:
          "1": { name: punctuation.definition.tag.end.html }
          "3": { name: punctuation.definition.tag.begin.html }
          "4": { name: entity.name.tag.html }
          "5": { name: punctuation.definition.tag.end.html }
        patterns:
          - begin: "{{tagOpen}}"
            end: (?=[/]?>)
            beginCaptures:
              "1": { name: punctuation.definition.tag.begin.html }
              "2": { name: entity.name.tag.html }
              "3": { name: punctuation.definition.tag.end.html }
            patterns:
              - include: "#attribute"
          - begin: (>)
            beginCaptures:
              "1": { name: punctuation.definition.tag.end.html }
            end: (?=</)
            patterns:
              - include: "#nodes"

  # HTML Attribute
  attribute:
    # attribute="value"
    patterns:
      - begin: (?<=\s)(component|export)(?=\s)
        beginCaptures:
          "1": { name: keyword.control }
        end: (?=\s*+[^=\s])
      - begin: \s(as)(?=\=)
        beginCaptures:
          "1": { name: keyword.control }
        end: (?=\s*+[^=\s])
        patterns:
          - include: "#attributes-interior"
      - begin: ([\w\$_\-]+)
        beginCaptures:
          "1": { name: entity.other.attribute-name.html }
        end: (?=\s*+[^=\s])
        patterns:
          - include: "#attributes-interior"

      # <div {slot} />f
      - include: "#slots"

  attributes-interior:
    # ="value" | ={value}
    patterns:
      - begin: (=)
        beginCaptures:
          "1": { name: punctuation.separator.key-value.html }
        end: (?<=[^\s=])(?!\s*=)|(?=/?>)
        patterns:
          # a="something"
          # a='something'
          - include: "#dynamic-strings"

          # a={b}
          - include: "#slots"

      # <div {slot} />
      - include: "#slots"

  comments:
    patterns:
      # <!-- comment -->
      - name: comment.block.html
        begin: (<!--)
        beginCaptures:
          "1": { name: punctuation.definition.comment.html }
        end: (-->)
        endCaptures:
          "1": { name: punctuation.definition.comment.html }

  slots:
    patterns:
      # {someJavascript > 5}
      # Make sure not to capture blocks
      - begin: ({)
        beginCaptures:
          "1": { name: punctuation.definition.tag.begin.html }
        end: (})
        endCaptures:
          "1": { name: punctuation.definition.tag.end.html }
        patterns:
          - include: "#operators"
          - include: "#nodes"
          - include: "#dynamic-strings"

  operators:
    patterns:
      - match: (&&|!|\|\|)
        name: keyword.control
  blocks:
    patterns:
      # {#if}something{/}
      - begin: ({\#)
        beginCaptures:
          "1": { name: punctuation }
        end: (})
        endCaptures:
          "1": { name: punctuation }
        patterns:
          - include: "#block-interior"

      - match: ({/})
        name: punctuation

      # {/else if
      - begin: (({/)(else)\s)
        beginCaptures:
          "2": { name: punctuation }
          "3": { name: keyword.control }
        end: (})
        endCaptures:
          "1": { name: punctuation }
        patterns:
          - include: "#block-interior"

      # {/else}
      - name: string.quoted.double
        match: ({/)(else)(})
        captures:
          "1": { name: punctuation }
          "2": { name: keyword.control }
          "3": { name: punctuation }

  block-interior:
    patterns:
      - name: punctuation.definition.comment.html
        begin: (if|each)
        beginCaptures:
          "1": { name: keyword.control }
        end: (?=})
        patterns:
          - include: "source.js"
  dynamic-strings:
    patterns:
      - name: string.quoted.double
        begin: '"'
        end: '"'
        beginCaptures:
          "1": { name: punctuation.separator.key-value.html }
        patterns:
          - include: "#class-pierce"
          - include: "#slots"
      - name: string.quoted.single
        begin: "'"
        end: "'"
        beginCaptures:
          "1": { name: punctuation.separator.key-value.html }
        patterns:
          - include: "#class-pierce"
          - include: "#slots"

  class-pierce:
    patterns:
      - match: (>>>|\$)([^\s"'>{]+)
        captures:
          "0": { name: keyword.control }
  strings:
    patterns:
      - name: string.quoted.double
        begin: '"'
        end: '"'
      - name: string.quoted.single
        begin: "'"
        end: "'"
  entities:
    patterns:
      - match: (&)([^;]+?)(;)
        captures:
          "1": { name: punctuation.definition.entity.html }
          "2": { name: constant.character.entity.named.$2.html }
          "3": { name: punctuation.definition.entity.html }
