;; GraphQL: parser — live parse against /api.parse-demo
(defcomp
  ()
  (~docs/page
    :title "GraphQL · Parser"
    (p
      (~tw :tokens "text-lg text-gray-600 mb-2")
      "The tokenizer and recursive-descent parser live in "
      (code "lib/graphql.sx")
      ". Feed them any GraphQL source and get an s-expression AST.")
    (p
      (~tw :tokens "text-gray-500 mb-6")
      "The server endpoint below parses the query, pretty-prints the AST, "
      "and round-trips it back through "
      (code "gql-serialize")
      ".")
    (~docs/section
      :title "Server endpoint"
      :id "endpoint"
      (p
        (~tw :tokens "text-gray-600 mb-3")
        "This is the live handler. It's the same bytecode the test suite exercises.")
      (~docs/code
        :src "(defhandler\n  gql-parse-demo\n  :path \"/sx/(applications.(graphql.(api.parse-demo)))\"\n  :method :get\n  :returns \"text\"\n  (&key source)\n  (if (or (nil? source) (empty? source))\n    \"<p>Enter a GraphQL query and click Parse.</p>\"\n    (let ((doc (gql-parse source)))\n      (str\n        \"<pre>\" (escape (sx-serialize doc)) \"</pre>\"\n        \"<pre>\" (escape (gql-serialize doc)) \"</pre>\")))))"))
    (~docs/section
      :title "Try it"
      :id "try"
      (p
        (~tw :tokens "text-gray-600 mb-3")
        "Type a query, click Parse. The form posts via HTMX to the handler above — "
        "response drops straight into "
        (code "#parse-out")
        ".")
      (form
        (~tw :tokens "space-y-3")
        :hx-get "/sx/(applications.(graphql.(api.parse-demo)))"
        :hx-target "#parse-out"
        :hx-swap "innerHTML"
        :hx-trigger "submit, input from:textarea[name='source'] changed delay:400ms"
        (textarea
          :name "source"
          :rows "6"
          (~tw
            :tokens "w-full font-mono text-sm p-3 border border-gray-300 rounded-lg")
          "{\n  user(id: 1) {\n    name\n    email\n  }\n}")
        (button
          :type "submit"
          (~tw
            :tokens "px-4 py-2 bg-violet-600 text-white rounded hover:bg-violet-700")
          "Parse"))
      (div
        :id "parse-out"
        (~tw :tokens "mt-4")
        (span
          (~tw :tokens "text-gray-400 text-sm")
          "Output will appear here.")))
    (~docs/section
      :title "AST node types"
      :id "nodes"
      (p
        (~tw :tokens "text-gray-600 mb-3")
        "Every GraphQL concept becomes a named s-expression:")
      (~docs/code
        :src "(gql-doc definitions...)\n(gql-query name vars directives selections)\n(gql-mutation name vars directives selections)\n(gql-subscription name vars directives selections)\n(gql-field name args directives selections [alias])\n(gql-fragment name on-type directives selections)\n(gql-fragment-spread name directives)\n(gql-inline-fragment on-type directives selections)\n(gql-var name)\n(gql-var-def name type default)\n(gql-directive name args)"))))
