master 4900091e62de cached
375 files
11.4 MB
3.0M tokens
100 symbols
1 requests
Copy disabled (too large) Download .txt
Showing preview only (12,185K chars total). Download the full file to get everything.
Repository: kishikawakatsumi/swift-ast-explorer
Branch: master
Commit: 4900091e62de
Files: 375
Total size: 11.4 MB

Directory structure:
gitextract_tk66xfku/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── renovate.json
│   └── workflows/
│       ├── spm.yml
│       └── test.yml
├── .gitignore
├── .swiftpm/
│   └── xcode/
│       └── package.xcworkspace/
│           └── contents.xcworkspacedata
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CODE_OF_CONDUCT.md
├── DEPLOYMENT.md
├── Dockerfile
├── LICENSE
├── Package.resolved
├── Package.swift
├── Public/
│   ├── css/
│   │   ├── balloon.css
│   │   ├── common.css
│   │   ├── editor.css
│   │   ├── lookup.css
│   │   ├── popover.css
│   │   ├── table.css
│   │   ├── tree_view.css
│   │   └── trivia.css
│   ├── error.html
│   ├── favicons/
│   │   ├── browserconfig.xml
│   │   └── site.webmanifest
│   ├── index.html
│   ├── index.js
│   ├── js/
│   │   ├── app.js
│   │   ├── balloon.js
│   │   ├── debounce.js
│   │   ├── editor.js
│   │   ├── icon.js
│   │   ├── lookup_view.js
│   │   ├── popover.js
│   │   ├── statistics_view.js
│   │   ├── structure_view.js
│   │   ├── tree_view.js
│   │   ├── trivia_view.js
│   │   └── websocket.js
│   ├── robots.txt
│   └── scss/
│       └── default.scss
├── README.md
├── Resources/
│   └── parsers/
│       ├── 50800/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       ├── Main.swift
│       │   │       ├── SyntaxParser.swift
│       │   │       ├── SyntaxResponse.swift
│       │   │       ├── TokenVisitor.swift
│       │   │       ├── TreeNode.swift
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           ├── Fixtures/
│       │           │   ├── test-1-1.html
│       │           │   ├── test-1-1.json
│       │           │   ├── test-1-2.html
│       │           │   ├── test-1-2.json
│       │           │   ├── test-1-3.html
│       │           │   ├── test-1-3.json
│       │           │   ├── test-1-4.html
│       │           │   ├── test-1-4.json
│       │           │   ├── test-1-5.html
│       │           │   ├── test-1-5.json
│       │           │   ├── test-1-6.html
│       │           │   ├── test-1-6.json
│       │           │   ├── test-2-1.html
│       │           │   ├── test-2-1.json
│       │           │   ├── test-2-2.html
│       │           │   ├── test-2-2.json
│       │           │   ├── test-2-3.html
│       │           │   ├── test-2-3.json
│       │           │   ├── test-2-4.html
│       │           │   ├── test-2-4.json
│       │           │   ├── test-2-5.html
│       │           │   ├── test-2-5.json
│       │           │   ├── test-2-6.html
│       │           │   └── test-2-6.json
│       │           └── Tests.swift
│       ├── 50900/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       ├── SyntaxParser.swift
│       │   │       ├── TokenVisitor.swift
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 51000/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60000/
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60100/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60200/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60300/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       └── trunk/
│           ├── .swiftpm/
│           │   └── xcode/
│           │       └── package.xcworkspace/
│           │           └── contents.xcworkspacedata
│           ├── Package.resolved
│           ├── Package.swift
│           ├── Sources/
│           │   └── parser/
│           │       └── Version.swift
│           └── Tests/
│               └── Tests/
│                   └── Fixtures/
│                       ├── test-1-1.html
│                       ├── test-1-1.json
│                       ├── test-1-2.html
│                       ├── test-1-2.json
│                       ├── test-1-3.html
│                       ├── test-1-3.json
│                       ├── test-1-4.html
│                       ├── test-1-4.json
│                       ├── test-1-5.html
│                       ├── test-1-5.json
│                       ├── test-1-6.html
│                       ├── test-1-6.json
│                       ├── test-2-1.html
│                       ├── test-2-1.json
│                       ├── test-2-2.html
│                       ├── test-2-2.json
│                       ├── test-2-3.html
│                       ├── test-2-3.json
│                       ├── test-2-4.html
│                       ├── test-2-4.json
│                       ├── test-2-5.html
│                       ├── test-2-5.json
│                       ├── test-2-6.html
│                       └── test-2-6.json
├── SECURITY.md
├── Sources/
│   └── App/
│       ├── Middlewares/
│       │   ├── CommonErrorMiddleware.swift
│       │   └── CustomHeaderMiddleware.swift
│       ├── configure.swift
│       ├── entrypoint.swift
│       └── routes.swift
├── Tests/
│   └── AppTests/
│       └── AppTests.swift
├── build_pasers.sh
├── deploy/
│   └── Dockerfile
├── dev/
│   ├── .gitignore
│   ├── index.js
│   ├── package.json
│   └── xml-formatter/
│       ├── .eslintignore
│       ├── .eslintrc.json
│       ├── .gitignore
│       ├── .npmignore
│       ├── LICENSE
│       ├── README.md
│       ├── package.json
│       ├── publish.sh
│       ├── src/
│       │   ├── index.d.ts
│       │   └── index.ts
│       ├── test/
│       │   ├── .eslintrc.json
│       │   ├── browser/
│       │   │   ├── README.md
│       │   │   └── index.html
│       │   ├── data1/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   ├── data10/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data11/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   └── xml2-output.xml
│       │   ├── data12/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data13/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data14/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data2/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   ├── data3/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   ├── xml4-output.xml
│       │   │   ├── xml5-input.xml
│       │   │   ├── xml5-output.xml
│       │   │   ├── xml6-input.xml
│       │   │   ├── xml6-output.xml
│       │   │   ├── xml7-input.xml
│       │   │   └── xml7-output.xml
│       │   ├── data4/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   ├── xml4-output.xml
│       │   │   ├── xml5-input.xml
│       │   │   └── xml5-output.xml
│       │   ├── data5/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data6/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   └── xml2-output.xml
│       │   ├── data7/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data8/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data9/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   └── index.ts
│       └── tsconfig.json
├── package.json
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
.build/
.swiftpm/


================================================
FILE: .github/FUNDING.yml
================================================
github: kishikawakatsumi


================================================
FILE: .github/renovate.json
================================================
{
  "extends": [
    "config:recommended"
  ],
  "packageRules": [
    {
      "matchUpdateTypes": [
        "minor",
        "patch",
        "pin",
        "digest"
      ],
      "automerge": true
    }
  ]
}


================================================
FILE: .github/workflows/spm.yml
================================================
name: Update Swift Package

on:
  schedule:
    - cron: "30 22 * * *"
  workflow_dispatch:

jobs:
  update:
    runs-on: ubuntu-24.04

    steps:
      - name: Checkout to the branch
        uses: actions/checkout@v6
      - name: Update Swift Package
        run: |
          set -ex

          export TOOLCHAINS=swift

          swift package update --package-path ./

          swift package update --package-path Resources/parsers/50800
          swift package update --package-path Resources/parsers/50900
          swift package update --package-path Resources/parsers/51000
          swift package update --package-path Resources/parsers/60000
          swift package update --package-path Resources/parsers/trunk
      - name: Create Pull Request
        id: cpr
        uses: peter-evans/create-pull-request@v8
        with:
          token: ${{ secrets.GH_PAT }}
          base: "master"
          commit-message: "Update Swift Packages"
          title: "Update Swift Packages"
          add-paths: |
            Package.resolved
            **/Package.resolved
      - name: Enable Pull Request Automerge
        if: ${{ steps.cpr.outputs.pull-request-url }}
        run: gh pr merge --merge --auto ${{ steps.cpr.outputs.pull-request-url }}
        env:
          GH_TOKEN: ${{ secrets.GH_PAT }}


================================================
FILE: .github/workflows/test.yml
================================================
name: Test
on:
  pull_request:
    branches: [master]
  workflow_dispatch:

env:
  FONTAWESOME_TOKEN: ${{ secrets.FONTAWESOME_TOKEN }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Free Disk Space (Ubuntu)
        uses: jlumbroso/free-disk-space@main
      - name: Test
        run: |
          set -ex

          swift test

          (cd Resources/parsers/50800 && swift test)
          (cd Resources/parsers/50900 && swift test)
          (cd Resources/parsers/51000 && swift test)
          (cd Resources/parsers/60000 && swift test)
          (cd Resources/parsers/60100 && swift test)
          (cd Resources/parsers/60200 && swift test)
          (cd Resources/parsers/trunk && swift test)
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Login to Docker Hub
        uses: docker/login-action@v4
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
      - name: Build and push
        run: |
          set -ex

          IMAGE_TAG=swiftfiddle/swift-ast-explorer.com:latest

          docker build --rm --no-cache --build-arg FONTAWESOME_TOKEN=${{ env.FONTAWESOME_TOKEN }} --tag ${IMAGE_TAG} .
          docker push ${IMAGE_TAG}


================================================
FILE: .gitignore
================================================
### https://raw.github.com/github/gitignore/991e760c1c6d50fdda246e0178b9c58b06770b90/Global/macOS.gitignore

# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk


### https://raw.github.com/github/gitignore/991e760c1c6d50fdda246e0178b9c58b06770b90/Swift.gitignore

# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## User settings
xcuserdata/

## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout

## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3

## Obj-C/Swift specific
*.hmap

## App packaging
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm

.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build/

# Accio dependency management
Dependencies/
.accio/

# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

# Code Injection
#
# After new code Injection tools there's a generated folder /iOSInjectionProject
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/


### https://raw.github.com/github/gitignore/991e760c1c6d50fdda246e0178b9c58b06770b90/Node.gitignore

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test
.env.production

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*




================================================
FILE: .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:">
   </FileRef>
</Workspace>


================================================
FILE: .vscode/launch.json
================================================
{
  "configurations": [
    {
      "type": "swift",
      "request": "launch",
      "sourceLanguages": ["swift"],
      "name": "Debug App",
      "program": "${workspaceFolder:swift-ast-explorer}/.build/debug/App",
      "args": [],
      "cwd": "${workspaceFolder:swift-ast-explorer}",
      "preLaunchTask": "swift: Build Debug App"
    },
    {
      "type": "swift",
      "request": "launch",
      "sourceLanguages": ["swift"],
      "name": "Release App",
      "program": "${workspaceFolder:swift-ast-explorer}/.build/release/App",
      "args": [],
      "cwd": "${workspaceFolder:swift-ast-explorer}",
      "preLaunchTask": "swift: Build Release App"
    }
  ]
}


================================================
FILE: .vscode/settings.json
================================================
{
  "lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB",
  "lldb.launch.expressions": "native"
}


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

- The use of sexualized language or imagery, and sexual attention or
  advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
  address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[@kishikawakatsumi](https://github.com/kishikawakatsumi).
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.


================================================
FILE: DEPLOYMENT.md
================================================
# Deployment Instructions

## Prerequisites

Before deploying, make sure you have the following software installed on your machine:

- Node.js (v14 or newer)
- Docker (v20.10 or newer)

The following environment variables are used for deployment:

- `FONTAWESOME_TOKEN`: This token is used for authentication with the FontAwesome service. You need to obtain a valid token from your FontAwesome account and use it here. Please make sure not to expose this token publicly.

## Local Deployment

### Steps:

1. Install the dependencies:

```bash
npm install
```

2. Run Webpack to build the project:

```bash
npm run prod
```

3. Run the application:

```bash
swift run
```

You should now be able to see the application running at `localhost:8080`.

## Production Deployment

For deploying to production, we recommend using [Railway](https://railway.app/). Railway is a platform that allows you to deploy your application to the cloud with ease. It also provides a free tier that is sufficient for deploying this application.


================================================
FILE: Dockerfile
================================================
FROM node:lts-slim as node

WORKDIR /build

ARG FONTAWESOME_TOKEN
COPY package*.json ./
RUN echo "@fortawesome:registry=https://npm.fontawesome.com/\n//npm.fontawesome.com/:_authToken=${FONTAWESOME_TOKEN}" > ./.npmrc \
    && npm ci \
    && rm -f ./.npmrc

COPY webpack.*.js ./
COPY Public ./Public/
RUN npx webpack --config webpack.prod.js


FROM swift:6.3-jammy as swift
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
    && apt-get -q update \
    && apt-get -q dist-upgrade -y\
    && rm -rf /var/lib/apt/lists/*

WORKDIR /build
COPY --from=node /build /build
COPY ./Package.* ./
RUN swift package resolve

COPY . .
RUN swift build -c release --static-swift-stdlib

RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/50800
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/50900
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/51000
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/60000
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/60100
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/60200
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/60300
RUN swift build -c release --static-swift-stdlib --package-path Resources/parsers/trunk

WORKDIR /staging

RUN cp "$(swift build --package-path /build -c release --show-bin-path)/App" ./

RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \;

RUN [ -d /build/Public ] && { mv /build/Public ./Public && chmod -R a-w ./Public; } || true
RUN [ -d /build/Resources ] && { mv /build/Resources ./Resources && chmod -R a-w ./Resources; } || true


FROM ubuntu:noble
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \
    && apt-get -q update \
    && apt-get -q dist-upgrade -y \
    && apt-get -q install -y \
      ca-certificates \
      tzdata \
    && rm -r /var/lib/apt/lists/*

RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app vapor

WORKDIR /app
COPY --from=swift --chown=vapor:vapor /staging /app

USER vapor:vapor
EXPOSE $PORT

ENTRYPOINT ["./App"]
CMD ["serve", "--env", "production", "--hostname", "0.0.0.0"]


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Package.resolved
================================================
{
  "pins" : [
    {
      "identity" : "async-http-client",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swift-server/async-http-client.git",
      "state" : {
        "revision" : "3a5b74a58782c3b4c1f0bc75e9b67b10c2494e8f",
        "version" : "1.33.1"
      }
    },
    {
      "identity" : "async-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/async-kit.git",
      "state" : {
        "revision" : "6bbb83cbf9d886623a967a965c8fb1b73e6566f9",
        "version" : "1.22.0"
      }
    },
    {
      "identity" : "console-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/console-kit.git",
      "state" : {
        "revision" : "32ad16dfc7677b927b225595ed18f3debb32f577",
        "version" : "4.16.0"
      }
    },
    {
      "identity" : "leaf",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/leaf.git",
      "state" : {
        "revision" : "b70a6108e4917f338f6b8848407bf655aa7e405f",
        "version" : "4.5.1"
      }
    },
    {
      "identity" : "leaf-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/leaf-kit.git",
      "state" : {
        "revision" : "6044b844caa858a0c5f2505ac166f5a057c990dc",
        "version" : "1.14.2"
      }
    },
    {
      "identity" : "multipart-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/multipart-kit.git",
      "state" : {
        "revision" : "3498e60218e6003894ff95192d756e238c01f44e",
        "version" : "4.7.1"
      }
    },
    {
      "identity" : "routing-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/routing-kit.git",
      "state" : {
        "revision" : "1a10ccea61e4248effd23b6e814999ce7bdf0ee0",
        "version" : "4.9.3"
      }
    },
    {
      "identity" : "swift-algorithms",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-algorithms.git",
      "state" : {
        "revision" : "87e50f483c54e6efd60e885f7f5aa946cee68023",
        "version" : "1.2.1"
      }
    },
    {
      "identity" : "swift-asn1",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-asn1.git",
      "state" : {
        "revision" : "eb50cbd14606a9161cbc5d452f18797c90ef0bab",
        "version" : "1.7.0"
      }
    },
    {
      "identity" : "swift-async-algorithms",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-async-algorithms.git",
      "state" : {
        "revision" : "9d349bcc328ac3c31ce40e746b5882742a0d1272",
        "version" : "1.1.3"
      }
    },
    {
      "identity" : "swift-atomics",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-atomics.git",
      "state" : {
        "revision" : "b601256eab081c0f92f059e12818ac1d4f178ff7",
        "version" : "1.3.0"
      }
    },
    {
      "identity" : "swift-certificates",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-certificates.git",
      "state" : {
        "revision" : "bde8ca32a096825dfce37467137c903418c1893d",
        "version" : "1.19.1"
      }
    },
    {
      "identity" : "swift-collections",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-collections.git",
      "state" : {
        "revision" : "6675bc0ff86e61436e615df6fc5174e043e57924",
        "version" : "1.4.1"
      }
    },
    {
      "identity" : "swift-configuration",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-configuration.git",
      "state" : {
        "revision" : "be76c4ad929eb6c4bcaf3351799f2adf9e6848a9",
        "version" : "1.2.0"
      }
    },
    {
      "identity" : "swift-crypto",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-crypto.git",
      "state" : {
        "revision" : "1b6b2e274e85105bfa155183145a1dcfd63331f1",
        "version" : "4.5.0"
      }
    },
    {
      "identity" : "swift-distributed-tracing",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-distributed-tracing.git",
      "state" : {
        "revision" : "dc4030184203ffafbb2ec614352487235d747fe0",
        "version" : "1.4.1"
      }
    },
    {
      "identity" : "swift-http-structured-headers",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-http-structured-headers.git",
      "state" : {
        "revision" : "933538faa42c432d385f02e07df0ace7c5ecfc47",
        "version" : "1.7.0"
      }
    },
    {
      "identity" : "swift-http-types",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-http-types.git",
      "state" : {
        "revision" : "45eb0224913ea070ec4fba17291b9e7ecf4749ca",
        "version" : "1.5.1"
      }
    },
    {
      "identity" : "swift-log",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-log.git",
      "state" : {
        "revision" : "5073617dac96330a486245e4c0179cb0a6fd2256",
        "version" : "1.12.0"
      }
    },
    {
      "identity" : "swift-metrics",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-metrics.git",
      "state" : {
        "revision" : "d51c8d13fa366eec807eedb4e37daa60ff5bfdd5",
        "version" : "2.10.1"
      }
    },
    {
      "identity" : "swift-nio",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio.git",
      "state" : {
        "revision" : "f71c8d2a5e74a2c6d11a0fbe324774b5d6084237",
        "version" : "2.99.0"
      }
    },
    {
      "identity" : "swift-nio-extras",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-extras.git",
      "state" : {
        "revision" : "5a48717e29f62cb8326d6d42e46b562ca93847a6",
        "version" : "1.34.0"
      }
    },
    {
      "identity" : "swift-nio-http2",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-http2.git",
      "state" : {
        "revision" : "81cc18264f92cd307ff98430f89372711d4f6fe9",
        "version" : "1.43.0"
      }
    },
    {
      "identity" : "swift-nio-ssl",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-ssl.git",
      "state" : {
        "revision" : "3f337058ccd7243c4cac7911477d8ad4c598d4da",
        "version" : "2.37.0"
      }
    },
    {
      "identity" : "swift-nio-transport-services",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-nio-transport-services.git",
      "state" : {
        "revision" : "67787bb645a5e67d2edcdfbe48a216cc549222d5",
        "version" : "1.28.0"
      }
    },
    {
      "identity" : "swift-numerics",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-numerics.git",
      "state" : {
        "revision" : "0c0290ff6b24942dadb83a929ffaaa1481df04a2",
        "version" : "1.1.1"
      }
    },
    {
      "identity" : "swift-service-context",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-service-context.git",
      "state" : {
        "revision" : "d0997351b0c7779017f88e7a93bc30a1878d7f29",
        "version" : "1.3.0"
      }
    },
    {
      "identity" : "swift-service-lifecycle",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swift-server/swift-service-lifecycle.git",
      "state" : {
        "revision" : "9829955b385e5bb88128b73f1b8389e9b9c3191a",
        "version" : "2.11.0"
      }
    },
    {
      "identity" : "swift-system",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-system.git",
      "state" : {
        "revision" : "7c6ad0fc39d0763e0b699210e4124afd5041c5df",
        "version" : "1.6.4"
      }
    },
    {
      "identity" : "swift-tools-support-core",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/swiftlang/swift-tools-support-core",
      "state" : {
        "revision" : "e8fbc8b05a155f311b862178d92d043afb216fe3",
        "version" : "0.7.3"
      }
    },
    {
      "identity" : "vapor",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/vapor.git",
      "state" : {
        "revision" : "cfd8f434843ac7850e2d97f46c1aa5ddb906cf1c",
        "version" : "4.121.4"
      }
    },
    {
      "identity" : "websocket-kit",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/vapor/websocket-kit.git",
      "state" : {
        "revision" : "90bbbdab3ede12c803cfbe91646f291c092517a3",
        "version" : "2.16.2"
      }
    }
  ],
  "version" : 2
}


================================================
FILE: Package.swift
================================================
// swift-tools-version:5.8
import PackageDescription

let package = Package(
  name: "swift-ast-explorer",
  platforms: [
    .macOS(.v13)
  ],
  dependencies: [
    .package(url: "https://github.com/vapor/vapor.git", from: "4.121.4"),
    .package(url: "https://github.com/vapor/leaf.git", from: "4.5.1"),
    .package(url: "https://github.com/swiftlang/swift-tools-support-core", from: "0.7.3"),
  ],
  targets: [
    .executableTarget(
      name: "App",
      dependencies: [
        .product(name: "Vapor", package: "vapor"),
        .product(name: "Leaf", package: "leaf"),
        .product(name: "TSCBasic", package: "swift-tools-support-core"),
      ],
      swiftSettings: [
        .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
      ]
    ),
    .testTarget(
      name: "AppTests",
      dependencies: [
        .target(name: "App"),
        .product(name: "XCTVapor", package: "vapor"),
      ]
    )
  ]
)


================================================
FILE: Public/css/balloon.css
================================================
.balloon {
  font-size: 80%;
  white-space: nowrap;
  border-radius: 4px;
  background-color: rgba(85, 85, 85, 0.9);
  color: #fff;
  padding: 2px 10px;
  position: absolute;
  z-index: 1080;
}

.balloon.top::after {
  content: " ";
  position: absolute;
  top: 100%;
  left: 24%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: rgba(85, 85, 85, 0.9) transparent transparent transparent;
}

.balloon.bottom::after {
  content: " ";
  position: absolute;
  bottom: 100%;
  left: 50%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent rgba(85, 85, 85, 0.9) transparent;
}

.balloon.right::after {
  content: " ";
  position: absolute;
  top: 50%;
  right: 100%;
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent rgba(85, 85, 85, 0.9) transparent transparent;
}

.balloon.left::after {
  content: " ";
  position: absolute;
  top: 50%;
  left: 100%;
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent transparent rgba(85, 85, 85, 0.9);
}

.balloon .title {
  color: #fff;
  font-weight: bolder;
  display: inline-block;
}

.balloon .token-kind {
  color: #fff;
  font-weight: normal;
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  max-width: 200px;
  display: inline-block;
  vertical-align: bottom;
}

.balloon .range {
  color: #dcdcdc;
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
}


================================================
FILE: Public/css/common.css
================================================
.svg-inline--fa.fa-fw {
  width: 1em;
}

.nav-tabs {
  border-bottom: none;
}

.dropdown-menu {
  min-width: 260px;
  line-height: 1.2;
  font-feature-settings: "tnum";
}

.active-tick a::after {
  display: block;
  width: 14px;
  height: 10px;
  margin-top: 4px;
  margin-bottom: 4px;
  background-image: url("../images/check-solid.svg");
  background-repeat: no-repeat;
  content: "";
  float: right;
}

.tab-pane {
  overflow: auto;
}

#lookup-container {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  font-size: 11pt;
  line-height: 1.4;
}

#trivia-container {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  font-size: 11pt;
  line-height: 1.4;
}

.alert {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  font-size: 11pt;
}


================================================
FILE: Public/css/editor.css
================================================
.CodeMirror {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  font-size: 11pt;
  line-height: 1.4;
}

.CodeMirror-selected {
  background: #b4d5fe;
}

.editor-marker-start {
  border-left: 1px solid rgb(81, 101, 255);
  background-color: rgba(81, 101, 255, 0.25);
}

.editor-marker {
  border-top: 1px solid rgb(81, 101, 255);
  border-bottom: 1px solid rgb(81, 101, 255);
  background-color: rgba(81, 101, 255, 0.25);
}

.editor-marker-end {
  border-right: 1px solid rgb(81, 101, 255);
  background-color: rgba(81, 101, 255, 0.25);
}


================================================
FILE: Public/css/lookup.css
================================================
.keyword,
.atSign {
  color: #c800a4;
}

.importKeyword {
  color: #1c00cf;
}

.stringLiteral {
  color: #df0002;
}

.StringLiteralExpr {
  color: #df0002;
}

.IntegerLiteralExpr,
.FloatLiteralExpr {
  color: #3a00dc;
}

.integerLiteral,
.floatingLiteral {
  color: #3a00dc;
}

.lineComment,
.blockComment,
.docLineComment,
.docBlockComment {
  color: #008e00;
}

.unexpectedText,
.shebang {
  color: #5d6c79;
}

.token.missing {
  color: #a3a3a3;
}


================================================
FILE: Public/css/popover.css
================================================
.popover {
  position: absolute;
  z-index: 1070;
  font-size: 10pt;
  box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2);
}

.popover-content {
  margin: 0 0 0 0;
  min-width: 400px;
  max-width: 50vw;
  background-clip: padding-box;
  background-color: #fff;
  border: 1px solid rgba(0, 0, 0, 0.2);
  border-radius: 4px;
}

.popover-content .title {
  margin: 0 14px 0 14px;
  padding-top: 8px;
  font-weight: bolder;
  font-size: larger;
}

.popover .arrow {
  position: absolute;
  z-index: 1070;
  top: 50%;
  left: calc(100% + -6px);
  transform: translateY(-50%) rotate(-135deg);
  width: 10px;
  height: 10px;
  content: "";
  background-color: #fff;
  border: 1px solid transparent;
  border-left-color: rgba(0, 0, 0, 0.2);
  border-bottom-color: rgba(0, 0, 0, 0.2);
  box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2);
  pointer-events: none;
}

.popover-content dl {
  margin-top: 0;
  margin-bottom: 0;
  padding: 10px 14px;
  max-height: 100vh;
}

.popover-content dt {
  padding: 0;
}

.popover-content dd {
  margin-bottom: 2px;
  margin-left: 0;
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  word-break: break-all;
}

.popover-content .font-monospace {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace !important;
}

.popover-content .badge {
  margin: 0 8px 0 8px;
  color: #696969;
  background-color: #f2f2f2;
}

.popover-content .badge.ref {
  margin: 0 0 0 -0.65em;
  color: #696969;
  background-color: #f2f2f2;
  font-size: 100%;
  font-weight: normal;
}

.popover-content .badge.annotation {
  width: 56px;
  text-align: end;
  font-size: 0.8rem;
  margin: 0 8px 0 0;
  padding: 0;
  color: #696969;
  background-color: transparent;
}

.popover-content .whitespace {
  color: #cccccc;
}

.popover-content .newline {
  color: #cccccc;
}


================================================
FILE: Public/css/table.css
================================================
table.dataTable {
  margin-top: 0 !important;
}

th.statistics_count {
  text-align: initial !important;
}


================================================
FILE: Public/css/tree_view.css
================================================
.tree-view {
  font-family: Menlo, Consolas, "DejaVu Sans Mono", "Ubuntu Mono", monospace;
  font-size: 11pt;
}

.tree-view ul {
  margin: 0;
  padding-left: 0;
}

.tree-view li {
  position: relative;
  list-style: none;
  margin: 0;
  padding: 5px 5px 0 25px;
  cursor: pointer;
}

.tree-view li .collapsible {
  position: relative;
}

.tree-view li div {
  display: inline-block;
}

.tree-view li.hover {
  background-color: rgb(100, 149, 237, 0.25);
}

.tree-view li.hover > div > div {
  text-decoration: underline;
}

.tree-view li.opened .collapsible::before {
  position: absolute;
  left: -16px;
  top: 50%;
  transform: translateY(-50%);
  padding-top: 2px;
  padding-bottom: 2px;
  width: 7px;
  height: 4px;
  display: inline-block;
  content: "";
  background-image: url("../images/caret-down-solid.svg");
  background-repeat: no-repeat;
}

.tree-view li.collapsed .collapsible::before {
  position: absolute;
  left: -14.5px;
  top: 50%;
  transform: translateY(-50%);
  padding-top: 2px;
  padding-bottom: 2px;
  width: 4px;
  height: 7px;
  display: inline-block;
  content: "";
  background-image: url("../images/caret-right-solid.svg");
  background-repeat: no-repeat;
}

.tree-view .decl-syntax {
  color: #007aff;
}

.tree-view .expr-syntax {
  color: #ff8c00;
}

.tree-view .pattern-syntax {
  color: #008b8b;
}

.tree-view .type-syntax {
  color: #8b0000;
}

.tree-view .token {
  font-weight: bold;
  cursor: auto;
}

.tree-view .token .whitespace {
  color: #cccccc;
}

.tree-view .token .newline {
  color: #cccccc;
}

.tree-view .token .badge {
  color: #696969;
  background-color: #dcdcdc;
}

.tree-view .token.missing {
  color: #a3a3a3;
}

.tree-view .token.missing::after {
  content: "Missing";
  color: #696969;
  background-color: #dcdcdc;
  display: inline-block;
  padding: 0.35em 0.65em;
  margin: 0 8px;
  font-size: 0.75em;
  font-weight: 700;
  line-height: 1;
  color: var(--bs-badge-color);
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
  border-radius: 0.375rem;
  vertical-align: middle;
}


================================================
FILE: Public/css/trivia.css
================================================
#trivia-container span.leading-trivia {
  background-color: #c8e1c8;
}

#trivia-container span.trailing-trivia {
  background-color: #ffd8a8;
}

#trivia-container .br {
  color: #a3a3a3;
}


================================================
FILE: Public/error.html
================================================
<!DOCTYPE html>
<html lang="en">

<head>
  <!-- Simple HttpErrorPages | MIT License | https://github.com/AndiDittrich/HttpErrorPages -->
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />

  <meta name="twitter:card" content="summary" />
  <meta property="twitter:image" content="https://swift-ast-explorer.com/images/ogp_image.png" />
  <meta property="og:image" content="https://swift-ast-explorer.com/images/ogp_image.png" />
  <meta property="og:title" content="Swift AST Explorer">
  <meta property="og:description"
    content="Visualize Swift AST and select nodes within the editor, a great way to learn about the structure of Swift syntax trees." />
  <meta name="description"
    content="Visualize Swift AST and select nodes within the editor, a great way to learn about the structure of Swift syntax trees." />
  <meta property="og:site_name" content="Swift AST Explorer - AST visualizer for Swift source code" />

  <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png">
  <link rel="manifest" href="/favicons/site.webmanifest">
  <link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#5bbad5">
  <link rel="shortcut icon" href="/favicons/favicon.ico">
  <meta name="msapplication-TileColor" content="#da532c">
  <meta name="msapplication-config" content="/favicons/browserconfig.xml">
  <meta name="theme-color" content="#ffffff">

  <title>#(title) | #(status) - #(error)</title>
  <style type="text/css">
    /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */
    html {
      font-family: sans-serif;
      line-height: 1.15;
      -ms-text-size-adjust: 100%;
      -webkit-text-size-adjust: 100%
    }

    body {
      margin: 0
    }

    article,
    aside,
    footer,
    header,
    nav,
    section {
      display: block
    }

    h1 {
      font-size: 2em;
      margin: .67em 0
    }

    figcaption,
    figure,
    main {
      display: block
    }

    figure {
      margin: 1em 40px
    }

    hr {
      box-sizing: content-box;
      height: 0;
      overflow: visible
    }

    pre {
      font-family: monospace, monospace;
      font-size: 1em
    }

    a {
      background-color: transparent;
      -webkit-text-decoration-skip: objects
    }

    a:active,
    a:hover {
      outline-width: 0
    }

    abbr[title] {
      border-bottom: none;
      text-decoration: underline;
      text-decoration: underline dotted
    }

    b,
    strong {
      font-weight: inherit
    }

    b,
    strong {
      font-weight: bolder
    }

    code,
    kbd,
    samp {
      font-family: monospace, monospace;
      font-size: 1em
    }

    dfn {
      font-style: italic
    }

    mark {
      background-color: #ff0;
      color: #000
    }

    small {
      font-size: 80%
    }

    sub,
    sup {
      font-size: 75%;
      line-height: 0;
      position: relative;
      vertical-align: baseline
    }

    sub {
      bottom: -.25em
    }

    sup {
      top: -.5em
    }

    audio,
    video {
      display: inline-block
    }

    audio:not([controls]) {
      display: none;
      height: 0
    }

    img {
      border-style: none
    }

    svg:not(:root) {
      overflow: hidden
    }

    button,
    input,
    optgroup,
    select,
    textarea {
      font-family: sans-serif;
      font-size: 100%;
      line-height: 1.15;
      margin: 0
    }

    button,
    input {
      overflow: visible
    }

    button,
    select {
      text-transform: none
    }

    [type=reset],
    [type=submit],
    button,
    html [type=button] {
      -webkit-appearance: button
    }

    [type=button]::-moz-focus-inner,
    [type=reset]::-moz-focus-inner,
    [type=submit]::-moz-focus-inner,
    button::-moz-focus-inner {
      border-style: none;
      padding: 0
    }

    [type=button]:-moz-focusring,
    [type=reset]:-moz-focusring,
    [type=submit]:-moz-focusring,
    button:-moz-focusring {
      outline: 1px dotted ButtonText
    }

    fieldset {
      border: 1px solid silver;
      margin: 0 2px;
      padding: .35em .625em .75em
    }

    legend {
      box-sizing: border-box;
      color: inherit;
      display: table;
      max-width: 100%;
      padding: 0;
      white-space: normal
    }

    progress {
      display: inline-block;
      vertical-align: baseline
    }

    textarea {
      overflow: auto
    }

    [type=checkbox],
    [type=radio] {
      box-sizing: border-box;
      padding: 0
    }

    [type=number]::-webkit-inner-spin-button,
    [type=number]::-webkit-outer-spin-button {
      height: auto
    }

    [type=search] {
      -webkit-appearance: textfield;
      outline-offset: -2px
    }

    [type=search]::-webkit-search-cancel-button,
    [type=search]::-webkit-search-decoration {
      -webkit-appearance: none
    }

    ::-webkit-file-upload-button {
      -webkit-appearance: button;
      font: inherit
    }

    details,
    menu {
      display: block
    }

    summary {
      display: list-item
    }

    canvas {
      display: inline-block
    }

    template {
      display: none
    }

    [hidden] {
      display: none
    }

    /*! Simple HttpErrorPages | MIT X11 License | https://github.com/AndiDittrich/HttpErrorPages */
    body,
    html {
      width: 100%;
      height: 100%;
      background-color: white
    }

    body {
      color: black;
      text-align: center;
      padding: 0;
      min-height: 100%;
      display: table;
      font-family: "Open Sans", Arial, sans-serif
    }

    h1 {
      font-family: inherit;
      font-weight: 500;
      line-height: 1.1;
      color: inherit;
      font-size: 36px
    }

    h1 small {
      font-size: 68%;
      font-weight: 400;
      line-height: 1;
      color: #777
    }

    a {
      text-decoration: none;
      color: #fff;
      font-size: inherit;
      border-bottom: dotted 1px #707070
    }

    .lead {
      color: silver;
      font-size: 21px;
      line-height: 1.4
    }

    .cover {
      display: table-cell;
      vertical-align: middle;
      padding: 0 20px
    }

    footer {
      position: fixed;
      width: 100%;
      height: 40px;
      left: 0;
      bottom: 0;
      color: #a0a0a0;
      font-size: 14px
    }
  </style>
</head>

<body>
  <div class="cover">
    <h1>#(error) <small>Error #(status)</small></h1>
    <p class="lead">#(reason)</p>
  </div>

</body>

</html>


================================================
FILE: Public/favicons/browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
    <msapplication>
        <tile>
            <square150x150logo src="/favicons/mstile-150x150.png"/>
            <TileColor>#da532c</TileColor>
        </tile>
    </msapplication>
</browserconfig>


================================================
FILE: Public/favicons/site.webmanifest
================================================
{
    "name": "",
    "short_name": "",
    "icons": [
        {
            "src": "/favicons/android-chrome-192x192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "/favicons/android-chrome-512x512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ],
    "theme_color": "#ffffff",
    "background_color": "#ffffff",
    "display": "standalone"
}


================================================
FILE: Public/index.html
================================================
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">

  <meta name="twitter:card" content="summary" />
  <meta property="twitter:image" content="https://swift-ast-explorer.com/images/ogp_image.png" />
  <meta property="og:image" content="https://swift-ast-explorer.com/images/ogp_image.png" />
  <meta property="og:title" content="Swift AST Explorer">
  <meta property="og:description"
    content="Visualize Swift AST and select nodes within the editor, a great way to learn about the structure of Swift syntax trees." />
  <meta name="description"
    content="Visualize Swift AST and select nodes within the editor, a great way to learn about the structure of Swift syntax trees." />
  <meta property="og:site_name" content="Swift AST Explorer - AST visualizer for Swift source code" />

  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
  <link rel="manifest" href="/site.webmanifest">
  <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
  <meta name="msapplication-TileColor" content="#da532c">
  <meta name="theme-color" content="#ffffff">

  <style>
    body {
      height: 100vh;
      height: 100svh;
    }

    .swift-logo {
      width: 2rem;
      height: 2rem;
    }

    .button-pill {
      height: 2rem;
    }

    .button-circle {
      width: 2rem;
      height: 2rem;
    }

    .nav-tabs {
      border-bottom: none !important;
    }

    .nav-item button {
      width: 160px;
    }

    .nav-item.lined .nav-link {
      border: none;
      color: #868e96;
      border-bottom: 3px solid transparent;
    }

    .nav-item.lined .nav-link:hover {
      border: none;
      color: #0d6efd;
      border-bottom: 3px solid transparent;
    }

    .nav-item.lined .nav-link.active {
      background: none;
      color: #0d6efd;
      border-color: #0d6efd;
    }
  </style>

  <title>Swift AST Explorer</title>
</head>

<body>
  <div class="container-fluid d-flex flex-column bg-light g-0 h-100">
    <header class="row row-cols-2 g-0">
      <div class="col">
        <div class="d-inline-block mx-1">
          <a class="text-decoration-none" href="/">
            <span class="fa-brands fa-swift fa-2x text-primary d-inline-block align-middle p-1 swift-logo"></span><span
              class="h4 text-dark d-inline-block align-middle m-0">Swift AST Explorer</span>
          </a>
          <button id="run-button" type="button"
            class="btn btn-primary btn-sm rounded-pill button-pill px-3 m-1 disabled" aria-label="Update">
            <span id="run-button-icon" class="fa-solid fa-play fa-fw"></span>
            <div id="run-button-spinner" class="d-inline-block d-none">
              <span class="fa-duotone fa-spinner-third fa-spin fa-fw"></span>
            </div>
          </button>
          <div class="dropdown d-inline-block">
            <button id="config-button" type="button"
              class="btn btn-outline-primary btn-sm rounded-circle button-circle m-1 disabled" data-bs-toggle="dropdown"
              data-bs-auto-close="outside" data-bs-offset="0,10" aria-label="Options" aria-expanded="false">
              <span class="fa-solid fa-cog fa-fw"></span>
            </button>
            <ul class="dropdown-menu">
              <li class="options-item checkbox parser-options active-tick" data-value="fold">
                <a class="dropdown-item" data-target="#">
                  Fold Sequence Expressions
                </a>
              </li>
              <li class="options-item checkbox parser-options" data-value="showmissing">
                <a class="dropdown-item" data-target="#">
                  Show Missing Tokens
                </a>
              </li>
            </ul>
          </div>
          <button id="format-button" type="button"
            class="btn btn-outline-primary btn-sm rounded-circle button-circle m-1 disabled" data-bs-toggle="tooltip"
            data-bs-placement="bottom" data-bs-container="#format-button" title="Format" aria-label="Format">
            <span class="fa-solid fa-align-left fa-fw"></span>
          </button>
          <span data-bs-toggle="modal" data-bs-target="#help-modal">
            <button id="help-button" type="button" class="btn btn-outline-primary btn-sm rounded-circle button-circle"
              data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-container="#help-button" title="Help"
              aria-label="Help">
              <span class="fa-solid fa-question fa-fw"></span>
            </button>
          </span>
          <div class="dropdown d-inline-block">
            <button id="version-button" type="button"
              class="btn btn-link btn-sm text-decoration-none dropdown-toggle m-1 disabled" data-bs-toggle="dropdown"
              data-bs-auto-close="outside" aria-label="Options" aria-expanded="false">
              <span class="fa-solid fa-code-branch"></span><span id="version-text" class="mx-1">603.0.0</span>
            </button>
            <ul class="dropdown-menu">
              <li>
                <h6 class="dropdown-header">Swift Syntax Version</h6>
              </li>
              <li class="options-item radio parser-version" data-value="50800" data-text="508.0.1">
                <a class="dropdown-item" data-target="#">
                  508.0.1 (Swift 5.8)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="50900" data-text="509.1.1">
                <a class="dropdown-item" data-target="#">
                  509.1.1 (Swift 5.9)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="51000" data-text="510.0.3">
                <a class="dropdown-item" data-target="#">
                  510.0.3 (Swift 5.10)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="60000" data-text="600.0.1">
                <a class="dropdown-item" data-target="#">
                  600.0.1 (Swift 6.0)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="60100" data-text="601.0.1">
                <a class="dropdown-item" data-target="#">
                  601.0.1 (Swift 6.1)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="60200" data-text="602.0.0">
                <a class="dropdown-item" data-target="#">
                  602.0.0 (Swift 6.2)
                </a>
              </li>
              <li class="options-item radio parser-version active-tick" data-value="60300" data-text="603.0.0">
                <a class="dropdown-item" data-target="#">
                  603.0.0 (Swift 6.3)
                </a>
              </li>
              <li class="options-item radio parser-version" data-value="trunk" data-text="main">
                <a class="dropdown-item" data-target="#">
                  main branch
                </a>
              </li>
            </ul>
          </div>
        </div>
      </div>
      <div class="col">
        <nav>
          <ul class="nav nav-tabs" role="tablist">
            <li class="nav-item lined" role="presentation">
              <button type="button" class="nav-link active" data-bs-toggle="tab" data-bs-target="#structure-tab-pane"
                role="tab" aria-controls="structure-tab-pane" aria-selected="true"><span
                  class="fa-regular fa-list-tree"></span><span class="px-3">Structure</span>
              </button>
            </li>
            <li class="nav-item lined" role="presentation">
              <button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#lookup-tab-pane" role="tab"
                aria-controls="lookup-tab-pane" aria-selected="false"><span class="fa-light fa-file-code"></span><span
                  class="px-3">Lookup</span>
              </button>
            </li>
            <li class="nav-item lined" role="presentation">
              <button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#trivia-tab-pane" role="tab"
                aria-controls="trivia-tab-pane" aria-selected="false"><span
                  class="fa-solid fa-slash-forward"></span><span class="px-3">Trivia</span>
              </button>
            </li>
            <li class="nav-item lined" role="presentation">
              <button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#statistics-tab-pane"
                role="tab" aria-controls="statistics-tab-pane" aria-selected="false"><span
                  class="fa-regular fa-table"></span><span class="px-3">Statistics</span>
              </button>
            </li>
          </ul>
        </nav>
      </div>
    </header>
    <main class="flex-grow-1 row row-cols-2 g-0 h-100">
      <div class="col">
        <textarea id="editor-container" class="h-100 d-none">#(code)</textarea>
      </div>
      <div class="col">
        <div class="tab-content">
          <div id="structure-tab-pane" class="tab-pane active" role="tabpanel" aria-labelledby="home-tab" tabindex="0">
            <div id="structure-container" role="document"></div>
          </div>
          <div id="lookup-tab-pane" class="tab-pane" role="tabpanel" aria-labelledby="lookup-tab" tabindex="0">
            <div id="lookup-container" role="document"></div>
          </div>
          <div id="trivia-tab-pane" class="tab-pane" role="tabpanel" aria-labelledby="trivia-tab" tabindex="0">
            <div id="trivia-container" role="document"></div>
          </div>
          <div id="statistics-tab-pane" class="tab-pane" role="tabpanel" aria-labelledby="statistics-tab" tabindex="0">
            <div id="statistics-container" role="document"></div>
          </div>
        </div>
      </div>
    </main>
    <footer class="row row-cols-1 g-0">
      <div class="col p-1 text-center">
        <div class="d-inline-block mx-2">
          <a class="text-reset text-decoration-none small" href="https://status.swift-ast-explorer.com/" target="_blank"
            rel="nofollow noopener noreferrer"><span class="fa-light fa-monitor-heart-rate"></span><span
              class="mx-2">System
              Status</span></a>
        </div>
        <div class="d-inline-block mx-2">
          <a class="text-reset text-decoration-none small"
            href="https://github.com/swiftfiddle/swift-ast-explorer/issues/new" target="_blank"
            rel="nofollow noopener noreferrer"><span class="fa-regular fa-message-smile"></span><span
              class="mx-2">Feedback</span></a>
        </div>
        <div class="d-inline-block mx-2">
          <a class="text-reset text-decoration-none small" href="https://github.com/swiftfiddle/swift-ast-explorer"
            target="_blank" rel="nofollow noopener noreferrer"><span class="fa-brands fa-github"></span><span
              class="mx-2">Source Code</span></a>
        </div>
        <div class="d-inline-block mx-2">
          <a class="text-reset text-decoration-none small" href="https://hachyderm.io/@kishikawakatsumi" target="_blank"
            rel="nofollow noopener noreferrer"><span class="fa-regular fa-at"></span><span
              class="mx-2">Creator</span></a>
        </div>
        <div class="d-inline-block mx-2">
          <a class="text-reset text-decoration-none small" href="https://github.com/sponsors/kishikawakatsumi"
            target="_blank" rel="nofollow noopener noreferrer">
            <span class="fa-solid fa-heart" style="color: #bf3989;"></span></span><span class="mx-2">Donate</span></a>
        </div>
      </div>
    </footer>
  </div>

  <div id="help-modal" class="modal fade" tabindex="-1" aria-labelledby="help-modal-label" aria-hidden="true">
    <div class="modal-dialog modal-dialog-scrollable">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title" id="help-modal-label"><span class="fa-regular fa-question-circle"></span><span
              class="mx-2">Help</span>
          </h5>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
          <dl>
            <dt class="bg-light rounded"><span class="fa-solid fa-code-branch fa-fw"></span><span class="mx-2">Default
                Swift
                Version</span></dt>
          </dl>
          <dd>
            <pre><code>#(swiftVersion)</code></pre>
          </dd>

          <dl>
            <dt class="bg-light rounded"><span class="fa-solid fa-cog fa-fw"></span><span class="mx-2">Parser
                Options</span></dt>
            <dd class="my-2">
              <dl>
                <dt>Fold Sequence Expressions</dt>
                <dd>Use <a
                    href="https://github.com/apple/swift-syntax/blob/main/Sources/SwiftOperators/SwiftOperators.docc/SwiftOperators.md"
                    target="_blank" rel="nofollow noopener noreferrer">SwiftOperators</a>
                  to 'fold' the syntax tree and rebuild the tree structure according to operator
                  precedence. This option is enabled by default.</dd>
              </dl>
            </dd>
            <dd>
              <dl>
                <dt>Show Missing Tokens</dt>
                <dd>The Swift parser often automatically inserts tokens that are not present in the source code to
                  recover from syntax errors. This option makes the missing tokens automatically inserted by the parser
                  visible.</dd>
              </dl>
            </dd>
          </dl>

          <dl>
            <dt class="bg-light rounded"><span class="fa-regular fa-file-import fa-fw"></span><span
                class="mx-2">Import</span></dt>
            <dd>There are a few different ways to import code into the code editor:</dd>
          </dl>
          <ul>
            <li>Drop a file onto the editor</li>
            <li>Append a GitHub gist ID to the URL<br>(e.g. <code>swift-ast-explorer.com/<code
                  style="background-color: #F0F0F0; padding: 2px;">&lt;gist_id_goes_here&gt;</code></code>)</li>
            <li>Or just start typing!</li>
          </ul>

          <dl>
            <dt class="bg-light rounded pt-2"><span class="fa-regular fa-message-smile fa-fw"></span><span
                class="mx-2">Feedback / Bug Report</span>
            </dt>
            <dd>
              <a href="https://github.com/swiftfiddle/swift-ast-explorer/issues/new" target="_blank"
                rel="nofollow noopener noreferrer">github.com/swiftfiddle/swift-ast-explorer
              </a>
            </dd>
          </dl>
        </div>
      </div>
    </div>
  </div>
</body>

</html>


================================================
FILE: Public/index.js
================================================
"use strict";

import "./scss/default.scss";
import "./css/common.css";

import "./js/icon.js";

import { App } from "./js/app.js";
new App();


================================================
FILE: Public/js/app.js
================================================
"use strict";

import { Tooltip } from "bootstrap";
import { Editor } from "./editor.js";
import { Balloon } from "./balloon.js";
import { StructureView } from "./structure_view.js";
import { LookupView } from "./lookup_view.js";
import { TriviaView } from "./trivia_view.js";
import { StatisticsView } from "./statistics_view.js";
import { WebSocketClient } from "./websocket.js";
import { debounce } from "./debounce.js";

export class App {
  get contentViewHeight() {
    const headerHeight = document.querySelector("header").clientHeight;
    const footerHeight = document.querySelector("footer").clientHeight;
    const viewport = CSS.supports("height", "100svh") ? "100svh" : "100vh";
    return `calc(${viewport} - ${headerHeight}px - ${footerHeight}px)`;
  }

  constructor() {
    this.editor = new Editor(document.getElementById("editor-container"));
    this.balloon = new Balloon();

    this.structureView = new StructureView(
      document.getElementById("structure-container")
    );
    this.lookupView = new LookupView(
      document.getElementById("lookup-container")
    );
    this.triviaView = new TriviaView(
      document.getElementById("trivia-container")
    );
    this.statisticsView = new StatisticsView(
      document.getElementById("statistics-container")
    );

    this.init();
  }

  init() {
    [].slice
      .call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
      .map((trigger) => {
        return new Tooltip(trigger);
      });

    const updateOnTextChange = debounce(() => {
      this.update();
    }, 400);
    this.editor.on("change", () => {
      updateOnTextChange();
    });

    document.getElementById("run-button").addEventListener("click", (event) => {
      event.preventDefault();
      this.update();
    });

    document.getElementById("config-button").classList.remove("disabled");
    document.getElementById("version-button").classList.remove("disabled");

    document.querySelectorAll(".options-item.checkbox").forEach((listItem) => {
      listItem.addEventListener("click", (event) => {
        event.preventDefault();
        listItem.classList.toggle("active-tick");
        this.update();
      });
    });
    document.querySelectorAll(".options-item.radio").forEach((listItem) => {
      listItem.addEventListener("click", (event) => {
        event.preventDefault();
        document.querySelectorAll(".options-item.radio").forEach((listItem) => {
          listItem.classList.remove("active-tick");
        });
        listItem.classList.toggle("active-tick");
        document.getElementById("version-text").textContent =
          listItem.dataset.text;
        this.update();
      });
    });

    const formatter = new WebSocketClient("wss://swift-format.com/api/ws");
    formatter.onresponse = (response) => {
      if (!response) {
        return;
      }
      if (response.output) {
        this.editor.setValue(response.output);
      }
    };
    const formatButton = document.getElementById("format-button");
    formatButton.classList.remove("disabled");
    formatButton.addEventListener("click", (event) => {
      event.preventDefault();
      formatter.send({ code: this.editor.getValue() });
    });

    const onresize = debounce(() => {
      this.onresize();
    }, 200);
    new ResizeObserver(() => {
      onresize();
    }).observe(document.body);

    setTimeout(() => {
      this.update();
    }, 100);
  }

  update() {
    showLoading();

    const branch = branchOptions();
    const options = parserOptions();

    const code = this.editor.getValue();
    const json = {
      code,
      options,
      branch,
    };
    fetch("/update", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(json),
    })
      .then((response) => response.json())
      .then((response) => {
        this.response = response;
        this.structureData = JSON.parse(response.syntaxJSON);

        this.updateStructure();
        this.updateLookup();
        this.updateTrivia();
        this.updateStatistics();

        this.onresize();
      })
      .catch((error) => {
        this.structureView.error = error;
        this.lookupView.error = error;
        this.statisticsView.error = error;
      })
      .finally(() => {
        hideLoading();
        this.editor.focus();
      });
  }

  updateStructure() {
    if (this.structureData === undefined) {
      return;
    }
    const data = this.structureData;
    this.structureView.update(data);

    this.structureView.onmouseover = (_event, _target, data) => {
      const title = data.token
        ? `Token <span class="token-kind text-truncate"  style="max-width: 300px;">${data.token.kind}</span>`
        : `${data.text}`;

      const range = data.range;
      this.editor.setSelection(range);

      const formatted = formatRange(range);
      this.balloon.setContent(
        `<div class="title">${title}</div><div class="range">${formatted}</div>`
      );

      const pageCoords = this.editor.charCoords(range, "page");
      const localCoords = this.editor.charCoords(range, "local");
      const rect = {
        left: localCoords.left,
        top: pageCoords.top,
        width: pageCoords.right - pageCoords.left,
        height: pageCoords.bottom - pageCoords.top,
      };
      this.balloon.show(rect, {
        placement: "top",
        offset: { x: 0, y: -6 },
      });
    };
    this.structureView.onmouseout = (_event, _target, _data) => {
      this.balloon.hide();
    };
  }

  updateLookup() {
    if (this.response === undefined || this.response.syntaxHTML === undefined) {
      return;
    }
    const data = this.response.syntaxHTML;
    this.lookupView.update(data);
  }

  updateTrivia() {
    if (this.response === undefined || this.response.syntaxHTML === undefined) {
      return;
    }
    const data = this.response.syntaxHTML;
    this.triviaView.update(data);
  }

  updateStatistics() {
    if (this.structureData === undefined) {
      return;
    }
    const data = this.structureData;

    const statistics = data
      .filter((node) => node.token === undefined)
      .reduce((acc, item) => {
        const existingItem = acc.find((a) => a.text === item.text);
        if (existingItem) {
          existingItem.ranges.push(item.range);
        } else {
          acc.push({ text: item.text, ranges: [item.range] });
        }
        return acc;
      }, []);

    this.statisticsView.update(statistics);

    this.statisticsView.onmouseover = (_event, target, ranges) => {
      const content = ranges
        .map((range) => {
          return {
            startRow: range.startRow
              .toString()
              .padStart(2, " ")
              .replace(" ", "&nbsp;"),
            startColumn: range.startColumn
              .toString()
              .padEnd(2, " ")
              .replace(" ", "&nbsp;"),
            endRow: range.endRow
              .toString()
              .padStart(2, " ")
              .replace(" ", "&nbsp;"),
            endColumn: range.endColumn
              .toString()
              .padEnd(2, " ")
              .replace(" ", "&nbsp;"),
          };
        })
        .map((range) => {
          return `<div class="range">${formatRange(range)}</div>`;
        })
        .join("");
      this.balloon.setContent(content);

      const tabContainer = document.querySelector(".tab-content");

      const rect = target.getBoundingClientRect();
      this.balloon.show(rect, {
        placement: "top",
        offset: { x: 10, y: -6 },
        containerRect: {
          left: tabContainer.offsetLeft,
          top: tabContainer.offsetTop,
          width: tabContainer.clientWidth,
          height: tabContainer.clientHeight,
        },
      });

      for (const range of ranges) {
        this.editor.markText(range);
      }
    };
    this.statisticsView.onmouseout = (_event, _target) => {
      this.balloon.hide();
      this.editor.clearMarks();
    };
  }

  onresize() {
    document.querySelector(".CodeMirror").style.height = this.contentViewHeight;
    this.editor.refresh();

    document.getElementById("structure-container").style.height =
      this.contentViewHeight;
    document.getElementById("lookup-container").style.height =
      this.contentViewHeight;
    document.getElementById("trivia-container").style.height =
      this.contentViewHeight;
    document.getElementById("statistics-container").style.height =
      this.contentViewHeight;
  }
}

function branchOptions() {
  let branch = "60300";
  document
    .querySelectorAll(".options-item.radio.parser-version")
    .forEach((listItem) => {
      if (listItem.classList.contains("active-tick")) {
        branch = listItem.dataset.value;
      }
    });
  return branch;
}

function parserOptions() {
  const options = [];
  document
    .querySelectorAll(".options-item.checkbox.checkbox")
    .forEach((listItem) => {
      if (listItem.classList.contains("active-tick")) {
        options.push(listItem.dataset.value);
      }
    });
  return options;
}

function showLoading() {
  document.getElementById("run-button").classList.add("disabled");
  document.getElementById("run-button-icon").classList.add("d-none");
  document.getElementById("run-button-spinner").classList.remove("d-none");
}

function hideLoading() {
  document.getElementById("run-button").classList.remove("disabled");
  document.getElementById("run-button-icon").classList.remove("d-none");
  document.getElementById("run-button-spinner").classList.add("d-none");
}

function formatRange(range) {
  return `${range.startRow}:${range.startColumn} ... ${range.endRow}:${range.endColumn}`;
}


================================================
FILE: Public/js/balloon.js
================================================
"use strict";

import "../css/balloon.css";

export class Balloon {
  constructor() {
    this.balloon = document.createElement("div");
    this.init();
  }

  init() {
    this.balloon.classList.add("d-none", "balloon");
    document.body.appendChild(this.balloon);
  }

  setContent(content) {
    this.content = content;
    this.balloon.innerHTML = content;
  }

  show(rect, options = {}) {
    let placement = options.placement || "top";
    const containerRect = options.containerRect || {
      left: 0,
      top: 0,
      width: 0,
      height: 0,
    };

    this.balloon.classList.remove("d-none");

    const width = this.balloon.clientWidth;
    const height = this.balloon.clientHeight;

    const top = containerRect.top;
    const bottom = containerRect.top + containerRect.height;

    let fallbackOcurred = 1;
    switch (placement) {
      case "top":
        if (rect.top - height < top) {
          placement = "bottom";
          fallbackOcurred = -1;
        }
        break;
      case "bottom":
        if (rect.top + height > bottom) {
          placement = "top";
          fallbackOcurred = -1;
        }
        break;
      case "left":
        if (rect.left - width < containerRect.left) {
          placement = "right";
          fallbackOcurred = -1;
        }
        break;
      case "right":
        if (rect.left + width > containerRect.left + containerRect.width) {
          placement = "left";
          fallbackOcurred = -1;
        }
        break;
      default:
        break;
    }

    this.balloon.classList.remove("top", "bottom", "left", "right");
    this.balloon.classList.add(placement);

    const offset = (() => {
      const offset = options.offset || { x: 0, y: 0 };
      switch (placement) {
        case "top":
          return { x: offset.x, y: offset.y * fallbackOcurred - height };
        case "bottom":
          return { x: offset.x, y: offset.y * fallbackOcurred + rect.height };
        case "left":
          return { x: offset.x * fallbackOcurred - width, y: offset.y };
        case "right":
          return { x: offset.x * fallbackOcurred + rect.width, y: offset.y };
        default:
          return { x: offset.x, y: offset.y };
      }
    })();

    this.balloon.style.left = `${rect.left + offset.x}px`;
    this.balloon.style.top = `${rect.top + offset.y}px`;
  }

  hide() {
    this.balloon.classList.add("d-none");
  }
}


================================================
FILE: Public/js/debounce.js
================================================
"use strict";

export function debounce(cb, delay = 250) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      cb(...args);
    }, delay);
  };
}


================================================
FILE: Public/js/editor.js
================================================
"use strict";

import "codemirror/lib/codemirror.css";
import "../css/editor.css";

import CodeMirror from "codemirror";
import "codemirror/mode/swift/swift";
import "codemirror/addon/edit/matchbrackets";
import "codemirror/addon/edit/closebrackets";

export class Editor {
  constructor(container) {
    this.container = container;
    this.init();
  }

  init() {
    this.editor = CodeMirror.fromTextArea(this.container, {
      autoCloseBrackets: true,
      lineNumbers: true,
      lineWrapping: true,
      matchBrackets: true,
      mode: "swift",
      screenReaderLabel: "Source code editor",
      tabSize: 2,
    });
    this.editor.setSize("100%", "100%");

    this.editor.on("drop", (editor, event) => {
      event.preventDefault();
      event.stopPropagation();

      const files = event.dataTransfer.files;
      if (files.length === 0) {
        return;
      }
      const reader = new FileReader();
      reader.onload = (event) => {
        this.editor.setValue(event.target.result);
      };
      reader.readAsText(files[0], "UTF-8");
    });
  }

  getValue() {
    return this.editor.getValue();
  }

  setValue(value) {
    this.editor.setValue(value);
  }

  setSelection(range) {
    this.editor.setSelection(
      { ch: range.graphemeStartColumn - 1, line: range.startRow - 1 },
      { ch: range.graphemeEndColumn - 1, line: range.endRow - 1 },
      { scroll: false }
    );
  }

  markText(range) {
    return this.editor.markText(
      { ch: range.graphemeStartColumn - 1, line: range.startRow - 1 },
      { ch: range.graphemeEndColumn - 1, line: range.endRow - 1 },
      {
        className: "editor-marker",
        startStyle: "editor-marker-start",
        endStyle: "editor-marker-end",
      }
    );
  }

  clearMarks() {
    this.editor.getAllMarks().forEach((mark) => {
      mark.clear();
    });
  }

  charCoords(range, mode = "page") {
    return this.editor.charCoords(
      { ch: range.startColumn - 1, line: range.startRow - 1 },
      mode
    );
  }

  focus() {
    this.editor.focus();
  }

  refresh() {
    this.editor.refresh();
  }

  on(event, callback) {
    this.editor.on(event, callback);
  }
}


================================================
FILE: Public/js/icon.js
================================================
"use strict";

import { library, dom } from "@fortawesome/fontawesome-svg-core";
import {
  faPlay,
  faEraser,
  faAlignLeft,
  faCog,
  faQuestion,
  faCodeBranch,
  faCaretRight,
  faCaretDown,
  faSlashForward,
  faHeart,
} from "@fortawesome/pro-solid-svg-icons";
import {
  faCheck,
  faListTree,
  faTable,
  faCircleInfo,
  faQuestionCircle,
  faFileImport,
  faMessageSmile,
  faAt,
} from "@fortawesome/pro-regular-svg-icons";
import {
  faFileCode,
  faMonitorHeartRate,
} from "@fortawesome/pro-light-svg-icons";
import { faSpinnerThird } from "@fortawesome/pro-duotone-svg-icons";
import { faSwift, faGithub } from "@fortawesome/free-brands-svg-icons";

library.add(
  faPlay,
  faEraser,
  faAlignLeft,
  faCog,
  faQuestion,
  faCodeBranch,
  faCaretRight,
  faCaretDown,
  faSlashForward,
  faHeart,

  faCheck,
  faListTree,
  faTable,
  faCircleInfo,
  faQuestionCircle,
  faFileImport,
  faMessageSmile,
  faAt,

  faFileCode,
  faMonitorHeartRate,

  faSpinnerThird,

  faSwift,
  faGithub
);
dom.watch();


================================================
FILE: Public/js/lookup_view.js
================================================
"use strict";

import "../css/lookup.css";
import { Popover } from "./popover.js";

export class LookupView {
  set error(error) {
    this.container.innerHTML = `<div class="alert alert-danger m-3" role="alert">${error}</div>`;
  }

  constructor(container) {
    this.container = container;
    this.popover = new Popover();
  }

  update(syntaxHTML) {
    this.container.innerHTML = "";

    const contentView = document.createElement("div");
    contentView.innerHTML = syntaxHTML;

    this.container.appendChild(contentView);

    const popover = this.popover;

    const self = this;

    $(this.container)
      .find("span")
      .each(function () {
        $(this).mouseover(function (event) {
          event.stopPropagation();

          const contents = [];

          $(this)
            .parents("span")
            .each(function (index, element) {
              self.createDOMRectElement(element.getBoundingClientRect());
              contents.push({
                title: element.dataset.title,
                content: element.dataset.content,
                type: element.dataset.type,
                range: element.dataset.range,
              });
              if (index > 0) {
                return false;
              }
            });

          let element = event.target;
          element.style.backgroundColor = "rgba(81, 101, 255, 0.5)";

          contents.reverse();
          contents.push({
            title: element.dataset.title,
            content: element.dataset.content,
            type: element.dataset.type,
            range: element.dataset.range,
          });

          const list = contents
            .filter(
              (item, index, self) =>
                index ===
                self.findIndex(
                  (t) =>
                    t.title === item.title &&
                    t.content === item.content &&
                    t.range === item.range
                )
            )
            .map((item) => {
              const title = escapeHTML(item.title);
              const type = escapeHTML(item.type);
              const content = escapeHTML(item.content);
              if (item.range) {
                const range = JSON.parse(item.range);
                const sourceRange = `${range.startRow}:${range.startColumn} ... ${range.endRow}:${range.endColumn}`;
                return `<dt class="text-truncate" style="max-width: calc(40vw - 20px);">
  <span class="badge annotation" style="width: auto; text-align: start;">Text</span><span class="font-monospace">${title}</span>
</dt>
<dd><div><span class="badge annotation">Range</span>${sourceRange}</div><div><span class="badge annotation">${type}</span>${content}</div></dd>`;
              } else {
                return `<dt class="text-truncate" style="max-width: calc(40vw - 20px);">
  <span class="badge annotation" style="width: auto; text-align: start;">Text</span><span class="font-monospace">${title}</span>
</dt>
<dd><div><span class="badge annotation">${type}</span>${content}</div></dd>`;
              }
            })
            .join("");
          const dl = `<dl>${list}</dl>`;
          popover.setContent(dl);

          const tabContainer = document.querySelector(".tab-content");
          const containerRect = tabContainer.getBoundingClientRect();

          popover.show(element, {
            containerRect: containerRect,
            offset: { x: -16, y: -2 },
          });
        });

        $(this).mouseout(function (event) {
          event.stopPropagation();

          let element = event.target;
          element.style.backgroundColor = "";

          self.removeDOMRectElement();

          popover.hide();
        });
      });
  }

  createDOMRectElement(domRect) {
    const className = "dom-rect";
    let rectElements = this.container.getElementsByClassName(className);
    for (let i = 0, l = rectElements.length; l > i; i++) {
      rectElements[0].parentNode.removeChild(rectElements[0]);
    }

    let rectElement = document.createElement("div");
    rectElement.className = className;
    rectElement.style.left = domRect.x - 1 + "px";
    rectElement.style.top = domRect.y - 1 + "px";
    rectElement.style.width = domRect.width + 1 + "px";
    rectElement.style.height = domRect.height + 1 + "px";
    rectElement.style.pointerEvents = "none";
    rectElement.style.position = "absolute";
    rectElement.style.border = "1px solid rgb(81, 101, 255)";
    rectElement.style.backgroundColor = "rgba(81, 101, 255, 0.25)";
    this.container.appendChild(rectElement);
  }

  removeDOMRectElement() {
    let rectElements = this.container.getElementsByClassName("dom-rect");
    for (let i = 0, l = rectElements.length; l > i; i++) {
      rectElements[0].parentNode.removeChild(rectElements[0]);
    }
  }
}

function escapeHTML(text) {
  const div = document.createElement("div");
  div.appendChild(document.createTextNode(text));
  return div.innerHTML;
}


================================================
FILE: Public/js/popover.js
================================================
"use strict";

import "../css/popover.css";

export class Popover {
  constructor() {
    this.popover = document.createElement("div");
    this.popoverContent = document.createElement("div");
    this.arrow = document.createElement("div");

    this.onmouseover = () => {};
    this.onmouseout = () => {};

    this.init();
  }

  init() {
    this.popover.classList.add("popover", "d-none");
    this.popoverContent.classList.add("popover-content");
    this.arrow.classList.add("arrow");

    this.popover.appendChild(this.popoverContent);
    this.popover.appendChild(this.arrow);
    document.body.appendChild(this.popover);

    this.popover.addEventListener(
      "mouseenter",
      (event) => {
        event.stopPropagation();
        this.onmouseover(event);
      },
      { capture: false, once: false, passive: true }
    );
    this.popover.addEventListener(
      "mouseleave",
      (event) => {
        event.stopPropagation();
        this.onmouseout(event);
      },
      { capture: false, once: false, passive: true }
    );
  }

  setContent(content) {
    if (this.content === content) {
      return;
    }
    this.content = content;
    this.popoverContent.innerHTML = content;
  }

  show(target, options = {}) {
    const targetRect = target.getBoundingClientRect();
    const containerRect = options.containerRect || {
      left: 0,
      top: 0,
      width: 0,
      height: 0,
    };
    const offset = options.offset || { x: 0, y: 0 };

    this.popover.classList.remove("d-none");

    const popoverRect = this.popover.getBoundingClientRect();

    const left = `${targetRect.left - popoverRect.width + offset.x}px`;
    this.popover.style.left = left;

    const bottom = containerRect.top + containerRect.height;
    const top = targetRect.top - 6 + offset.y;
    if (top + popoverRect.height > bottom) {
      const popoverTop = bottom - popoverRect.height;
      this.popover.style.top = `${popoverTop}px`;
      this.arrow.style.top = `${targetRect.top - popoverTop + 10 + offset.y}px`;
    } else {
      this.popover.style.top = `${top}px`;
      this.arrow.style.top = "15px";
    }
  }

  hide() {
    this.popover.classList.add("d-none");
  }
}


================================================
FILE: Public/js/statistics_view.js
================================================
"use strict";

import DataTable from "datatables.net";
import "datatables.net-bs5/css/dataTables.bootstrap5.min.css";

import "../css/table.css";

export class StatisticsView {
  set error(error) {
    this.container.innerHTML = `<div class="alert alert-danger m-3" role="alert">${error}</div>`;
  }

  constructor(container) {
    this.container = container;

    this.onmouseover = () => {};
    this.onmouseout = () => {};
  }

  update(statistics) {
    this.container.innerHTML = `<table class="table table-borderless table-striped table-hover table-sm">
  <thead class="table-light">
    <tr>
      <th scope="col" style="width: 60%;">Syntax</th>
      <th scope="col">Count</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>
`;

    const body = this.container.querySelector(":scope > table > tbody");
    for (const row of statistics) {
      const tr = document.createElement("tr");
      tr.innerHTML = `<td style="font-family: Menlo, Consolas, 'DejaVu Sans Mono', 'Ubuntu Mono', monospace;">${row.text}</td><td><div>${row.ranges.length}</div></td>`;
      body.appendChild(tr);

      tr.addEventListener(
        "mouseover",
        (event) => {
          event.stopPropagation();
          this.onmouseover(event, tr, row.ranges);
        },
        { capture: false, once: false, passive: true }
      );
      tr.addEventListener(
        "mouseout",
        (event) => {
          event.stopPropagation();
          this.onmouseout(event, tr);
        },
        { capture: false, once: false, passive: true }
      );
    }

    if (this.dataTable) {
      this.dataTable.destroy();
    }
    this.dataTable = new DataTable(
      this.container.querySelector(":scope > table"),
      {
        autoWidth: false,
        info: false,
        paging: false,
        searching: false,
        columnDefs: [{ className: "statistics_count", targets: [1] }],
      }
    );
  }
}


================================================
FILE: Public/js/structure_view.js
================================================
"use strict";

import { TreeView } from "./tree_view.js";
import { Popover } from "./popover.js";

export class StructureView {
  set error(error) {
    this.container.innerHTML = `<div class="alert alert-danger m-3" role="alert">${error}</div>`;
  }

  constructor(container) {
    this.container = container;
    this.popover = new Popover();

    this.onmouseover = () => {};
    this.onmouseout = () => {};

    this.init();
  }

  init() {
    this.body = this.container.querySelector(":scope > table > tbody");
  }

  update(structureData) {
    this.container.innerHTML = "";
    const treeView = new TreeView(this.container, structureData);

    treeView.onmouseover = (event, target, data) => {
      this.onmouseover(event, target, data);
      if (!data.structure.length && !data.token) {
        return;
      }
      if (data.structure.length > 0) {
        this.popover.setContent(makeSyntaxPopoverContent(data));
      }
      if (data.token) {
        this.popover.setContent(makeTokenPopoverContent(data));
      }
      const tabContainer = document.querySelector(".tab-content");
      const containerRect = tabContainer.getBoundingClientRect();

      this.popover.show(target, {
        containerRect: containerRect,
        offset: { x: -10, y: 1 },
      });
    };

    treeView.onmouseout = (event, target, data) => {
      this.onmouseout(event, target, data);

      if (!event.relatedTarget) {
        return;
      }
      if (!event.relatedTarget.classList.contains("popover-content")) {
        this.popover.hide();
      }
    };

    this.popover.onmouseout = (event) => {
      this.popover.hide();
    };
  }
}

function makeSyntaxPopoverContent(data) {
  const container = document.createElement("div");

  const title = document.createElement("div");
  title.classList.add("title");
  title.innerText = `${data.text}Syntax`;
  title.appendChild(makeSyntaxTypeBadge(data.type));

  container.appendChild(title);

  const dl = document.createElement("dl");

  makeSourceRangePopoverContent(data, dl);

  for (const property of data.structure) {
    makePropertyPopoverContent(property, dl);
  }
  container.appendChild(dl);

  return container.innerHTML;
}

function makeTokenPopoverContent(data) {
  const container = document.createElement("div");

  const title = document.createElement("div");
  title.classList.add("title");
  title.innerText = "TokenSyntax";

  container.appendChild(title);

  const dl = document.createElement("dl");

  makeSourceRangePopoverContent(data, dl);

  makeDescriptionList("kind", data.token.kind, dl);
  makeDescriptionList("leadingTrivia", data.token.leadingTrivia, dl);
  makeDescriptionList("text", data.text, dl);
  makeDescriptionList("trailingTrivia", data.token.trailingTrivia, dl);

  container.appendChild(dl);

  return container.innerHTML;
}

function makeSourceRangePopoverContent(data, list) {
  const range = data.range;
  const details = `${range.startRow}:${range.startColumn} ... ${range.endRow}:${range.endColumn}`;
  makeDescriptionList("Source Range", details, list);
}

function makePropertyPopoverContent(property, list) {
  const details = (() => {
    const value = property.value;
    if (property.ref) {
      return `<span class="badge ref">${property.ref}</span>`;
    } else if (value && value.text && value.kind) {
      const text = value.text;
      const kind = value.kind;
      return `${text}<span class="badge rounded-pill">${kind}</span>`;
    } else if (value && value.text) {
      return value.text;
    }
  })();
  makeDescriptionList(property.name, details, list);
}

function makeDescriptionList(term, details, list) {
  const dt = document.createElement("dt");
  dt.innerHTML = term;

  const dd = document.createElement("dd");
  dd.innerHTML = details;

  list.appendChild(dt);
  list.appendChild(dd);
}

function makeSyntaxTypeBadge(type) {
  const badge = document.createElement("span");
  badge.classList.add("badge", "text-bg-light");
  switch (type) {
    case "decl": {
      badge.innerText = "DeclSyntax";
      break;
    }
    case "expr": {
      badge.innerText = "ExprSyntax";
      break;
    }
    case "pattern": {
      badge.innerText = "PatternSyntax";
      break;
    }
    case "type": {
      badge.innerText = "TypeSyntax";
      break;
    }
    case "collection": {
      badge.innerText = "SyntaxCollection";
      break;
    }
    default:
      break;
  }
  return badge;
}


================================================
FILE: Public/js/tree_view.js
================================================
"use strict";

import "../css/tree_view.css";

export class TreeView {
  constructor(container, tree) {
    this.container = container;
    this.tree = tree;

    this.treeView = document.createElement("div");

    this.state = {};

    this.onmouseover = () => {};
    this.onmouseout = () => {};

    this.init();
  }

  init() {
    this.treeView.classList.add("tree-view");

    const fragment = document.createDocumentFragment();
    this.renderTree(fragment, this.tree);
    this.treeView.appendChild(fragment);

    this.container.appendChild(this.treeView);
  }

  renderTree(container, tree) {
    tree
      .filter(function (node) {
        return node.parent === undefined;
      })
      .forEach((node) => {
        container.appendChild(this.renderNode(node));
      });
  }

  renderNode(node) {
    const ul = document.createElement("ul");
    const li = document.createElement("li");
    const content = document.createElement("div");

    if (!node.token) {
      content.classList.add("collapsible");
      content.addEventListener("click", (event) => {
        this.onclick(event, node, li);
      });

      const div = document.createElement("div");
      div.classList.add(`${node.type}-syntax`);
      div.innerHTML = node.text;

      content.appendChild(div);
      li.appendChild(content);

      const children = this.getChildren(node.id);
      for (const child of children) {
        li.classList.add("opened");
        li.appendChild(this.renderNode(child));
      }
    } else {
      content.classList.add("token");
      if (node.class) {
        content.classList.add(node.class);
      }
      content.innerHTML =
        node.text.length === 0 ? `<span class="badge">Empty</span>` : node.text;
      li.appendChild(content);
    }

    li.addEventListener(
      "mouseover",
      (event) => {
        event.stopPropagation();
        li.classList.add("hover");
        this.onmouseover(event, content, node);
      },
      { capture: false, once: false, passive: true }
    );
    li.addEventListener(
      "mouseout",
      (event) => {
        event.stopPropagation();
        li.classList.remove("hover");
        this.onmouseout(event, content, node);
      },
      { capture: false, once: false, passive: true }
    );

    ul.appendChild(li);
    return ul;
  }

  hasChildren(id) {
    return this.tree.some(function (node) {
      return node.parent === id;
    });
  }

  getChildren(id) {
    return this.tree.filter(function (node) {
      return node.parent === id;
    });
  }

  open(node, li) {
    li.classList.add("opened");
    li.classList.remove("collapsed");

    const children = this.state[node.id];
    if (children) {
      for (const child of children) {
        li.appendChild(child);
      }
    } else {
      const children = this.getChildren(node.id);
      for (const child of children) {
        li.classList.add("opened");
        li.appendChild(this.renderNode(child));
      }
    }
  }

  collapse(node, li) {
    li.classList.add("collapsed");
    li.classList.remove("opened");

    const children = li.querySelectorAll(":scope > ul");
    for (const child of children) {
      li.removeChild(child);
    }

    this.state[node.id] = children;
  }

  onclick(event, node, li) {
    event.preventDefault();
    event.stopPropagation();

    if (li.classList.contains("opened")) {
      this.collapse(node, li);
    } else {
      this.open(node, li);
    }
  }
}


================================================
FILE: Public/js/trivia_view.js
================================================
"use strict";

import "../css/trivia.css";
import { Popover } from "./popover.js";

export class TriviaView {
  set error(error) {
    this.container.innerHTML = `<div class="alert alert-danger m-3" role="alert">${error}</div>`;
  }

  constructor(container) {
    this.container = container;
    this.popover = new Popover();
  }

  update(syntaxHTML) {
    this.container.innerHTML = "";

    const contentView = document.createElement("div");
    contentView.innerHTML = syntaxHTML;

    const newlines = contentView.querySelectorAll("br");
    for (const newline of newlines) {
      const span = document.createElement("span");
      span.classList.add("br");
      span.textContent = "↲";
      span.appendChild(newline.cloneNode(true));
      const parent = newline.parentElement;
      parent.replaceChild(span, newline);
    }

    this.container.appendChild(contentView);

    this.container.querySelectorAll(".token").forEach((token) => {
      token.addEventListener("mouseover", (event) => {
        event.stopPropagation();

        this.createDOMRectElement(token.getBoundingClientRect());

        const parent = token.parentElement;
        let isLeadingTrivia = true;

        const leadingTrivias = [];
        const trailingTrivias = [];

        for (const child of Array.from(parent.childNodes)) {
          if (child === token) {
            isLeadingTrivia = false;
            continue;
          }

          if (child.nodeType === Node.TEXT_NODE) {
            const span = document.createElement("span");
            span.textContent = child.textContent;
            parent.replaceChild(span, child);

            if (isLeadingTrivia) {
              span.classList.add("leading-trivia");
              leadingTrivias.push(
                span.textContent
                  .replace(/\s/g, `<span style="color: #a3a3a3;">␣</span>`)
                  .replace(/\n/g, `<span style="color: #a3a3a3;">↲</span>`)
              );
            } else {
              span.classList.add("trailing-trivia");
              trailingTrivias.push(
                span.textContent
                  .replace(/\s/g, `<span style="color: #a3a3a3;">␣</span>`)
                  .replace(/\n/g, `<span style="color: #a3a3a3;">↲</span>`)
              );
            }
          } else if (child.nodeType === Node.ELEMENT_NODE) {
            if (isLeadingTrivia) {
              child.classList.add("leading-trivia");
              if (child.classList.contains("br")) {
                leadingTrivias.push(`<span style="color: #a3a3a3;">↲</span>`);
              } else {
                leadingTrivias.push(
                  child.textContent
                    .replace(/\s/g, `<span style="color: #a3a3a3;">␣</span>`)
                    .replace(/\n/g, `<span style="color: #a3a3a3;">↲</span>`)
                );
              }
            } else {
              child.classList.add("trailing-trivia");
              if (child.classList.contains("br")) {
                trailingTrivias.push(`<span style="color: #a3a3a3;">↲</span>`);
              } else {
                trailingTrivias.push(
                  child.textContent
                    .replace(/\s/g, `<span style="color: #a3a3a3;">␣</span>`)
                    .replace(/\n/g, `<span style="color: #a3a3a3;">↲</span>`)
                );
              }
            }
          }
        }

        const tabContainer = document.querySelector(".tab-content");

        const containerRect = tabContainer.getBoundingClientRect();
        const elementRect = token.getBoundingClientRect();
        const offset = {
          x: containerRect.left - elementRect.left - 16,
          y: -2,
        };

        const leadingTrivia = leadingTrivias.join("");
        const trailingTrivia = trailingTrivias.join("");
        this.popover.setContent(
          `<dl>
  <dt class="text-truncate" style="max-width: calc(40vw - 20px);"><span class="font-monospace">${token.dataset.title}</span></dt>
  <dt class="text-truncate" style="max-width: calc(40vw - 20px);"><span class="font-monospace">${token.dataset.content}</span></dt>
  <dt class="text-truncate" style="max-width: calc(40vw - 20px); margin-top: 8px;"><span class="badge annotation text-body" style="width: auto; text-align: start;"><svg width="12" height="10" xmlns="http://www.w3.org/2000/svg"><circle stroke="#c8e1c8" fill="#c8e1c8" cx="4" cy="4" r="3.5" fill-rule="evenodd"/></svg>Leading Trivia</span><div style="padding-left: 12px;"><span class="font-monospace">${leadingTrivia}</span></div></dt>
  <dt class="text-truncate" style="max-width: calc(40vw - 20px); margin-top: 8px;"><span class="badge annotation text-body" style="width: auto; text-align: start;"><svg width="12" height="10" xmlns="http://www.w3.org/2000/svg"><circle stroke="#ffd8a8" fill="#ffd8a8" cx="4" cy="4" r="3.5" fill-rule="evenodd"/></svg>Trailing Trivia</span><div style="padding-left: 12px;"><span class="font-monospace">${trailingTrivia}</span></div></dt>
  <dt class="text-truncate" style="max-width: calc(40vw - 20px); margin-top: 8px;"><span class="badge annotation" style="width: auto; text-align: start;"><span class="fa-regular fa-circle-info"></span><span class="mx-1">Trivia Attribution Rule</span></dt>
  <dt style="max-width: calc(40vw - 20px);"><ol style="font-weight: normal; margin-bottom: 4px;"><li>A token owns all of its trailing trivia up to, but not including, the next newline character.</li><li>Looking backward in the text, a token owns all of the leading trivia up to and including the first contiguous sequence of newlines characters.</li></ol></dt>
</dl>`
        );
        this.popover.show(token, {
          containerRect: containerRect,
          offset: offset,
        });
      });

      token.addEventListener("mouseout", (event) => {
        event.stopPropagation();

        this.removeDOMRectElement();

        const parent = token.parentElement;
        for (const child of Array.from(parent.childNodes)) {
          if (child.nodeType === Node.ELEMENT_NODE) {
            child.classList.remove("leading-trivia");
            child.classList.remove("trailing-trivia");
          }
        }

        this.popover.hide();
      });
    });
  }

  createDOMRectElement(domRect) {
    const className = "dom-rect";
    let rectElements = this.container.getElementsByClassName(className);
    for (let i = 0, l = rectElements.length; l > i; i++) {
      rectElements[0].parentNode.removeChild(rectElements[0]);
    }

    let rectElement = document.createElement("div");
    rectElement.className = className;
    rectElement.style.left = domRect.x + "px";
    rectElement.style.top = domRect.y + "px";
    rectElement.style.width = domRect.width + "px";
    rectElement.style.height = domRect.height + "px";
    rectElement.style.pointerEvents = "none";
    rectElement.style.position = "absolute";
    rectElement.style.border = "1px solid rgb(100, 149, 237)";
    this.container.appendChild(rectElement);
  }

  removeDOMRectElement() {
    let rectElements = this.container.getElementsByClassName("dom-rect");
    for (let i = 0, l = rectElements.length; l > i; i++) {
      rectElements[0].parentNode.removeChild(rectElements[0]);
    }
  }
}


================================================
FILE: Public/js/websocket.js
================================================
"use strict";

import ReconnectingWebSocket from "reconnecting-websocket";

export class WebSocketClient {
  constructor(endpoint) {
    this.connection = this.createConnection(endpoint);

    this.onconnect = () => {};
    this.onresponse = () => {};
  }

  get isReady() {
    return this.connection.readyState === 1;
  }

  send(params) {
    const encoder = new TextEncoder();
    this.connection.send(encoder.encode(JSON.stringify(params)));
  }

  createConnection(endpoint) {
    if (
      this.connection &&
      (this.connection.readyState === 0 || this.connection.readyState === 1)
    ) {
      return this.connection;
    }

    const connection = new ReconnectingWebSocket(endpoint, [], {
      maxReconnectionDelay: 10000,
      minReconnectionDelay: 1000,
      reconnectionDelayGrowFactor: 1.3,
      connectionTimeout: 10000,
      maxRetries: Infinity,
      debug: false,
    });
    connection.bufferType = "arraybuffer";

    connection.onopen = () => {
      this.onconnect();
    };

    connection.onerror = (event) => {
      connection.close();
    };

    connection.onmessage = (event) => {
      try {
        this.onresponse(JSON.parse(event.data));
      } catch (error) {}
    };

    return connection;
  }
}


================================================
FILE: Public/robots.txt
================================================


================================================
FILE: Public/scss/default.scss
================================================
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/variables-dark";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/utilities";

@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/containers";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/tables";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/transitions";
@import "bootstrap/scss/dropdown";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/badge";
@import "bootstrap/scss/alert";
@import "bootstrap/scss/close";
@import "bootstrap/scss/modal";
@import "bootstrap/scss/tooltip";

@import "bootstrap/scss/helpers";

@import "bootstrap/scss/utilities/api";


================================================
FILE: README.md
================================================
<p>
<img src="https://img.shields.io/badge/os-macOS/Linux-green.svg?style=flat" alt="macOS/Linux">
<a href="http://swift.org">
<img src="https://img.shields.io/badge/swift-5.8-orange.svg?style=flat" alt="Swift 5.8 Compatible">
</a>
<a href="https://github.com/kishikawakatsumi/swift-ast-explorer/blob/master/LICENSE">
<img src="https://img.shields.io/badge/license-Apache2-blue.svg?style=flat" alt="Apache 2">
</a>
</p>

# Swift AST Explorer

Swift AST Explorer is a tool for visualizing the Abstract Syntax Tree (AST) of Swift source code.  
Check it out at https://swift-ast-explorer.com/

<a href="https://swift-ast-explorer.com/"><img width="1024" alt="Screen Shot" src="https://github.com/SwiftFiddle/swift-ast-explorer/assets/40610/d41c6f6f-4493-4673-99a6-8dc05fcab30b"></a>

## Features

### Presents Swift syntax in a tree structure

<img width="600" alt="Screen Shot" src="https://github.com/SwiftFiddle/swift-ast-explorer/assets/40610/4815c8e3-5e62-455d-8954-656a24d3461d.png">

### Maps each token in the source code to the corresponding syntax

<img width="600" alt="Screen Shot" src="https://github.com/SwiftFiddle/swift-ast-explorer/assets/40610/2632bb58-2315-4488-bbc6-a8d2c86ae3ff.png">

### Provides an overview and inspection of syntax usage

<img width="600" alt="Screen Shot" src="https://github.com/SwiftFiddle/swift-ast-explorer/assets/40610/c36e5705-1029-4590-8719-1b939c9ab209.png">

## Author

[Kishikawa Katsumi](https://github.com/kishikawakatsumi)

## Supporters & Sponsors

Open source projects thrive on the generosity and support of people like you. If you find this project valuable, please consider extending your support. Contributing to the project not only sustains its growth, but also helps drive innovation and improve its features.

To support this project, you can become a sponsor through [GitHub Sponsors](https://github.com/sponsors/kishikawakatsumi). Your contribution will be greatly appreciated and will help keep the project alive and thriving. Thanks for your consideration! :heart:

## License

The project is released under the [Apache License 2.0](https://github.com/kishikawakatsumi/swift-ast-explorer/blob/main/LICENSE)


================================================
FILE: Resources/parsers/50800/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
   version = "1.0">
   <FileRef
      location = "self:">
   </FileRef>
</Workspace>


================================================
FILE: Resources/parsers/50800/Package.resolved
================================================
{
  "pins" : [
    {
      "identity" : "swift-syntax",
      "kind" : "remoteSourceControl",
      "location" : "https://github.com/apple/swift-syntax",
      "state" : {
        "revision" : "2c49d66d34dfd6f8130afdba889de77504b58ec0",
        "version" : "508.0.1"
      }
    }
  ],
  "version" : 2
}


================================================
FILE: Resources/parsers/50800/Package.swift
================================================
// swift-tools-version:5.8
import PackageDescription

let package = Package(
  name: "parser",
  platforms: [
    .macOS(.v13)
  ],
  dependencies: [
    .package(url: "https://github.com/apple/swift-syntax", from: "508.0.1"),
  ],
  targets: [
    .executableTarget(
      name: "parser",
      dependencies: [
        .product(name: "SwiftSyntax", package: "swift-syntax"),
        .product(name: "SwiftOperators", package: "swift-syntax"),
        .product(name: "SwiftParser", package: "swift-syntax"),
      ],
      swiftSettings: [
        .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release))
      ]
    ),
    .testTarget(
      name: "Tests",
      dependencies: [
        .target(name: "parser"),
      ],
      resources: [.process("Fixtures")]
    )
  ]
)


================================================
FILE: Resources/parsers/50800/Sources/parser/Main.swift
================================================
import Foundation

@main
struct Main {
  static func main() throws {
    do {
      let code = String(decoding: FileHandle.standardInput.availableData, as: UTF8.self)
      let options = Array(CommandLine.arguments.dropFirst(1))

      let response = try SyntaxParser.parse(code: code, options: options)

      let data = try JSONEncoder().encode(response)
      print(String(decoding: data, as: UTF8.self))
    } catch {
      var standardError = FileHandle.standardError
      print("\(error)", to:&standardError)
    }
  }
}

extension FileHandle: @retroactive TextOutputStream {
  public func write(_ string: String) {
    self.write(Data(string.utf8))
  }
}


================================================
FILE: Resources/parsers/50800/Sources/parser/SyntaxParser.swift
================================================
import Foundation
import SwiftSyntax
import SwiftOperators
import SwiftParser

struct SyntaxParser {
  static func parse(code: String, options: [String] = []) throws -> SyntaxResponse {
    let sourceFile = Parser.parse(source: code)

    let syntax: Syntax
    if options.contains("fold") {
      syntax = OperatorTable.standardOperators.foldAll(sourceFile, errorHandler: { _ in })
    } else {
      syntax = Syntax(sourceFile)
    }

    let visitor = TokenVisitor(
      locationConverter: SourceLocationConverter(file: "", tree: sourceFile),
      showMissingTokens: options.contains("showmissing")
    )
    _ = visitor.rewrite(syntax)

    let html = "\(visitor.list.joined())"

    let tree = visitor.tree
    let encoder = JSONEncoder()
    let json = String(decoding: try encoder.encode(tree), as: UTF8.self)

    return SyntaxResponse(syntaxHTML: html, syntaxJSON: json, swiftVersion: version)
  }
}


================================================
FILE: Resources/parsers/50800/Sources/parser/SyntaxResponse.swift
================================================
import Foundation

struct SyntaxResponse: Codable {
  let syntaxHTML: String
  let syntaxJSON: String
  let swiftVersion: String
}


================================================
FILE: Resources/parsers/50800/Sources/parser/TokenVisitor.swift
================================================
import Foundation
import SwiftSyntax

final class TokenVisitor: SyntaxRewriter {
  var list = [String]()
  var tree = [TreeNode]()

  private var current: TreeNode!
  private var index = 0

  private let locationConverter: SourceLocationConverter
  private let showMissingTokens: Bool

  init(locationConverter: SourceLocationConverter, showMissingTokens: Bool) {
    self.locationConverter = locationConverter
    self.showMissingTokens = showMissingTokens
  }

  func rewrite(_ node: Syntax) -> Syntax {
    visit(node)
  }

  override func visitPre(_ node: Syntax) {
    if let token = node.as(TokenSyntax.self), token.presence == .missing, !showMissingTokens {
      return
    }

    let syntaxNodeType = node.syntaxNodeType

    let className: String
    if "\(syntaxNodeType)".hasSuffix("Syntax") {
      className = String("\(syntaxNodeType)".dropLast(6))
    } else {
      className = "\(syntaxNodeType)"
    }

    let title: String
    let content: String
    let type: String
    if let token = node.as(TokenSyntax.self) {
      title = sourceAccurateText(token)
      content = "\(token.tokenKind)"
      type = "Token"
    } else {
      title = sourceAccurateText(node)
      content = "\(syntaxNodeType)"
      type = "Syntax"
    }

    let sourceRange = node.sourceRange(converter: locationConverter)
    let start = sourceRange.start
    let end = sourceRange.end
    let startRow = start.line ?? 1
    let startColumn = start.column ?? 1
    let endRow = end.line ?? 1
    let endColumn = end.column ?? 1

    let graphemeStartColumn: Int
    if let prefix = String(locationConverter.sourceLines[startRow - 1].utf8.prefix(startColumn - 1)) {
      graphemeStartColumn = prefix.utf16.count + 1
    } else {
      graphemeStartColumn = startColumn
    }
    let graphemeEndColumn: Int
    if let prefix = String(locationConverter.sourceLines[endRow - 1].utf8.prefix(endColumn - 1)) {
      graphemeEndColumn = prefix.utf16.count + 1
    } else {
      graphemeEndColumn = endColumn
    }

    list.append(
      "<span class='\(className)' " +
      "data-title='\(title.escapeHTML().replaceInvisiblesWithSymbols())' " +
      "data-content='\(content.escapeHTML().replaceInvisiblesWithHTML())' " +
      "data-type='\(type.escapeHTML())' " +
      #"data-range='{"startRow":\#(startRow),"startColumn":\#(startColumn),"endRow":\#(endRow),"endColumn":\#(endColumn)}'>"#
    )

    let syntaxType: SyntaxType
    switch node {
    case _ where node.is(DeclSyntax.self):
      syntaxType = .decl
    case _ where node.is(ExprSyntax.self):
      syntaxType = .expr
    case _ where node.is(PatternSyntax.self):
      syntaxType = .pattern
    case _ where node.is(TypeSyntax.self):
      syntaxType = .type
    default:
      syntaxType = .other
    }

    let treeNode = TreeNode(
      id: index,
      text: className,
      range: Range(
        startRow: startRow,
        startColumn: startColumn,
        graphemeStartColumn: graphemeStartColumn,
        endRow: endRow,
        endColumn: endColumn,
        graphemeEndColumn: graphemeEndColumn
      ),
      type: syntaxType
    )

    tree.append(treeNode)
    index += 1

    switch node.syntaxNodeType.structure {
    case .layout(let keyPaths):
      if let syntaxNode = node.as(node.syntaxNodeType) {
        for (index, keyPath) in keyPaths.enumerated() {
          let mirror = Mirror(reflecting: syntaxNode)
          if let label = mirror.children.map({ $0 })[index].label {
            let key = label
            switch syntaxNode[keyPath: keyPath] {
            case let value as TokenSyntax:
              treeNode.structure.append(
                StructureProperty(
                  name: key,
                  value: StructureValue(
                    text: value.text,
                    kind: "\(value.tokenKind)"
                  )
                )
              )
            case let value?:
              if let value = value as? SyntaxProtocol {
                let type = "\(value.syntaxNodeType)"
                treeNode.structure.append(StructureProperty(name: key, value: StructureValue(text: "\(type)"), ref: "\(type)"))
              } else {
                treeNode.structure.append(StructureProperty(name: key, value: StructureValue(text: "\(value)")))
              }
            case .none:
              treeNode.structure.append(StructureProperty(name: key))
            }
          }
        }
      }
    case .collection(let syntax):
      treeNode.type = .collection
      treeNode.structure.append(StructureProperty(name: "Element", value: StructureValue(text: "\(syntax)")))
      treeNode.structure.append(StructureProperty(name: "Count", value: StructureValue(text: "\(node.children(viewMode: .all).count)")))
      break
    case .choices:
      break
    }

    if let current {
      treeNode.parent = current.id
    }
    current = treeNode
  }

  override func visit(_ token: TokenSyntax) -> TokenSyntax {
    if token.presence == .missing && !showMissingTokens {
      return token
    }

    let text = sourceAccurateText(token)
    current.text = text
      .escapeHTML()
      .replaceInvisiblesWithHTML()
      .replaceHTMLWhitespacesWithSymbols()
    if token.presence == .missing {
      current.class = token.presence.rawValue.lowercased()
    }
    current.token = Token(kind: "\(token.tokenKind)", leadingTrivia: "", trailingTrivia: "")

    token.leadingTrivia.forEach { (piece) in
      let trivia = processTriviaPiece(piece)
      list.append(trivia)
      current.token?.leadingTrivia += trivia.replaceHTMLWhitespacesWithSymbols()
    }
    processToken(token)
    token.trailingTrivia.forEach { (piece) in
      let trivia = processTriviaPiece(piece)
      list.append(trivia)
      current.token?.trailingTrivia += trivia.replaceHTMLWhitespacesWithSymbols()
    }

    return token
  }

  override func visitPost(_ node: Syntax) {
    if let token = node.as(TokenSyntax.self), token.presence == .missing, !showMissingTokens {
      return
    }

    list.append("</span>")
    if let parent = current.parent {
      current = tree[parent]
    } else {
      current = nil
    }
  }

  private func processToken(_ token: TokenSyntax) {
    var kind = "\(token.tokenKind)"
    if let index = kind.firstIndex(of: "(") {
      kind = String(kind.prefix(upTo: index))
    }
    if kind.hasSuffix("Keyword") {
      kind = "keyword"
    }

    let sourceRange = token.sourceRange(converter: locationConverter)
    let start = sourceRange.start
    let end = sourceRange.end
    let startRow = start.line ?? 1
    let startColumn = start.column ?? 1
    let endRow = end.line ?? 1
    let endColumn = end.column ?? 1
    let text: String
    switch token.presence {
    case .present:
      text = sourceAccurateText(token)
    case .missing:
      if showMissingTokens {
        text = sourceAccurateText(token)
      } else {
        text = ""
      }
    }

    list.append(
      "<span class='token \(kind.escapeHTML()) \(token.presence.rawValue.lowercased())' " +
      "data-title='\(token.text.escapeHTML().replaceInvisiblesWithSymbols())' " +
      "data-content='\("\(token.tokenKind)".escapeHTML().replaceInvisiblesWithHTML())' " +
      "data-type='Token' " +
      #"data-range='{"startRow":\#(startRow),"startColumn":\#(startColumn),"endRow":\#(endRow),"endColumn":\#(endColumn)}'>"# +
      "\(text.escapeHTML().replaceInvisiblesWithHTML())</span>"
    )
  }

  private func processTriviaPiece(_ piece: TriviaPiece) -> String {
    func wrapWithSpanTag(class c: String, text: String) -> String {
      "<span class='\(c.escapeHTML())' " +
      "data-title='\("\(piece)".escapeHTML().replaceInvisiblesWithSymbols())' " +
      "data-content='\(c.escapeHTML().replaceInvisiblesWithHTML())' " +
      "data-type='Trivia'>\(text.escapeHTML().replaceInvisiblesWithHTML())</span>"
    }

    var trivia = ""
    switch piece {
    case .spaces(let count):
      trivia += String(repeating: "&nbsp;", count: count)
    case .tabs(let count):
      trivia += String(repeating: "&nbsp;", count: count * 2)
    case .verticalTabs, .formfeeds:
      break
    case .newlines(let count), .carriageReturns(let count), .carriageReturnLineFeeds(let count):
      trivia += String(repeating: "<br/>", count: count)
    case .lineComment(let text):
      trivia += wrapWithSpanTag(class: "lineComment", text: text)
    case .blockComment(let text):
      trivia += wrapWithSpanTag(class: "blockComment", text: text)
    case .docLineComment(let text):
      trivia += wrapWithSpanTag(class: "docLineComment", text: text)
    case .docBlockComment(let text):
      trivia += wrapWithSpanTag(class: "docBlockComment", text: text)
    case .unexpectedText(let text):
      trivia += wrapWithSpanTag(class: "unexpectedText", text: text)
    case .shebang(let text):
      trivia += wrapWithSpanTag(class: "shebang", text: text)
    }
    return trivia
  }
}

private func sourceAccurateText(_ syntax: Syntax) -> String {
  let text = "\(syntax.withoutTrivia())"
  let utf8Length = syntax.contentLength.utf8Length
  if text.utf8.count == utf8Length {
    return text
  } else {
    return String(decoding: syntax.syntaxTextBytes.prefix(utf8Length), as: UTF8.self)
  }
}

private func sourceAccurateText(_ token: TokenSyntax) -> String {
  let text = token.text
  let utf8Length = token.contentLength.utf8Length
  if text.utf8.count == utf8Length {
    return text
  } else {
    return String(decoding: token.syntaxTextBytes.prefix(utf8Length), as: UTF8.self)
  }
}

private extension String {
  func escapeHTML() -> String {
    var string = self
    let specialCharacters = [
      ("&", "&amp;"),
      ("<", "&lt;"),
      (">", "&gt;"),
      ("\"", "&quot;"),
      ("'", "&apos;"),
    ];
    for (unescaped, escaped) in specialCharacters {
      string = string.replacingOccurrences(of: unescaped, with: escaped, options: .literal, range: nil)
    }
    return string
  }

  func replaceInvisiblesWithHTML() -> String {
    self
      .replacingOccurrences(of: " ", with: "&nbsp;")
      .replacingOccurrences(of: "\n", with: "<br/>")
  }

  func replaceInvisiblesWithSymbols() -> String {
    self
      .replacingOccurrences(of: " ", with: "␣")
      .replacingOccurrences(of: "\n", with: "↲")
  }

  func replaceHTMLWhitespacesWithSymbols() -> String {
    self
      .replacingOccurrences(of: "&nbsp;", with: "<span class='whitespace'>␣</span>")
      .replacingOccurrences(of: "<br/>", with: "<span class='newline'>↲</span><br/>")
  }
}


================================================
FILE: Resources/parsers/50800/Sources/parser/TreeNode.swift
================================================
import Foundation

final class TreeNode: Codable {
  let id: Int
  var parent: Int?

  var text: String
  var range = Range(startRow: 0, startColumn: 0, graphemeStartColumn: 0, endRow: 0, endColumn: 0, graphemeEndColumn: 0)
  var structure = [StructureProperty]()
  var type: SyntaxType
  var token: Token?
  var `class`: String?

  init(id: Int, text: String, range: Range, type: SyntaxType) {
    self.id = id
    self.text = text.escapeHTML()
    self.range = range
    self.type = type
  }
}

extension TreeNode: Equatable {
  static func == (lhs: TreeNode, rhs: TreeNode) -> Bool {
    lhs.id == rhs.id &&
    lhs.parent == rhs.parent &&
    lhs.text == rhs.text &&
    lhs.range == rhs.range &&
    lhs.structure == rhs.structure &&
    lhs.type == rhs.type &&
    lhs.token == rhs.token
  }
}

extension TreeNode: CustomStringConvertible {
  var description: String {
    """
    {
      id: \(id)
      parent: \(String(describing: parent))
      text: \(text)
      range: \(range)
      structure: \(structure)
      type: \(type)
      token: \(String(describing: token))
    }
    """
  }
}

struct Range: Codable, Equatable {
  let startRow: Int
  let startColumn: Int
  let graphemeStartColumn: Int
  let endRow: Int
  let endColumn: Int
  let graphemeEndColumn: Int
}

extension Range: CustomStringConvertible {
  var description: String {
    """
    {
      startRow: \(startRow)
      startColumn: \(startColumn)
      endRow: \(endRow)
      endColumn: \(endColumn)
    }
    """
  }
}

struct StructureProperty: Codable, Equatable {
  let name: String
  let value: StructureValue?
  let ref: String?

  init(name: String, value: StructureValue? = nil, ref: String? = nil) {
    self.name = name.escapeHTML()
    self.value = value
    self.ref = ref?.escapeHTML()
  }
}

extension StructureProperty: CustomStringConvertible {
  var description: String {
    """
    {
      name: \(name)
      value: \(String(describing: value))
      ref: \(String(describing: ref))
    }
    """
  }
}

struct StructureValue: Codable, Equatable {
  let text: String
  let kind: String?

  init(text: String, kind: String? = nil) {
    self.text = text.escapeHTML().replaceHTMLWhitespacesToSymbols()
    self.kind = kind?.escapeHTML()
  }
}

extension StructureValue: CustomStringConvertible {
  var description: String {
    """
    {
      text: \(text)
      kind: \(String(describing: kind))
    }
    """
  }
}

enum SyntaxType: String, Codable {
  case decl
  case expr
  case pattern
  case type
  case collection
  case other
}

struct Token: Codable, Equatable {
  let kind: String
  var leadingTrivia: String
  var trailingTrivia: String

  init(kind: String, leadingTrivia: String, trailingTrivia: String) {
    self.kind = kind.escapeHTML()
    self.leadingTrivia = leadingTrivia
    self.trailingTrivia = trailingTrivia
  }
}

extension Token: CustomStringConvertible {
  var description: String {
    """
    {
      kind: \(kind)
      leadingTrivia: \(leadingTrivia)
      trailingTrivia: \(trailingTrivia)
    }
    """
  }
}

private extension String {
  func escapeHTML() -> String {
    var string = self
    let specialCharacters = [
      ("&", "&amp;"),
      ("<", "&lt;"),
      (">", "&gt;"),
      ("\"", "&quot;"),
      ("'", "&apos;"),
    ];
    for (unescaped, escaped) in specialCharacters {
      string = string.replacingOccurrences(of: unescaped, with: escaped, options: .literal, range: nil)
    }
    return string
      .replacingOccurrences(of: " ", with: "&nbsp;")
      .replacingOccurrences(of: "\n", with: "<br>")
  }

  func replaceHTMLWhitespacesToSymbols() -> String {
    self
      .replacingOccurrences(of: "&nbsp;", with: "<span class='whitespace'>␣</span>")
      .replacingOccurrences(of: "<br>", with: "<span class='newline'>↲</span>")
  }
}


================================================
FILE: Resources/parsers/50800/Sources/parser/Version.swift
================================================
import Foundation
let version = "5.8.1"


================================================
FILE: Resources/parsers/50800/Tests/Tests/Fixtures/test-1-1.html
================================================
<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
<span class='CodeBlockItemList' data-title='let␣number␣=␣0' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
<span class='CodeBlockItem' data-title='let␣number␣=␣0' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
<span class='VariableDecl' data-title='let␣number␣=␣0' data-content='VariableDeclSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":15}'>
<span class='Token' data-title='let' data-content='letKeyword' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
<span class='token keyword present' data-title='let' data-content='letKeyword' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
let
</span>
&nbsp;
</span>
<span class='PatternBindingList' data-title='number␣=␣0' data-content='PatternBindingListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
<span class='PatternBinding' data-title='number␣=␣0' data-content='PatternBindingSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":15}'>
<span class='IdentifierPattern' data-title='number' data-content='IdentifierPatternSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
<span class='Token' data-title='number' data-content='identifier(&quot;number&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
<span class='token identifier present' data-title='number' data-content='identifier(&quot;number&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":11}'>
number
</span>
&nbsp;
</span>
</span>
<span class='InitializerClause' data-title='=␣0' data-content='InitializerClauseSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":15}'>
<span class='Token' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":13}'>
<span class='token equal present' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":12,"endRow":1,"endColumn":13}'>
=
</span>
&nbsp;
</span>
<span class='IntegerLiteralExpr' data-title='0' data-content='IntegerLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":14,"endRow":1,"endColumn":15}'>
<span class='Token' data-title='0' data-content='integerLiteral(&quot;0&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":14,"endRow":1,"endColumn":15}'>
<span class='token integerLiteral present' data-title='0' data-content='integerLiteral(&quot;0&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":14,"endRow":1,"endColumn":15}'>
0
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title='' data-content='eof' data-type='Token' data-range='{"startRow":1,"startColumn":15,"endRow":1,"endColumn":15}'>
<span class='token eof present' data-title='' data-content='eof' data-type='Token' data-range='{"startRow":1,"startColumn":15,"endRow":1,"endColumn":15}'></span>
</span>
</span>


================================================
FILE: Resources/parsers/50800/Tests/Tests/Fixtures/test-1-1.json
================================================
[
  {
    "id": 0,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeStatements",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "statements",
        "ref": "CodeBlockItemListSyntax",
        "value": {
          "text": "CodeBlockItemListSyntax"
        }
      },
      {
        "name": "unexpectedBetweenStatementsAndEOFToken",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "eofToken",
        "value": {
          "kind": "eof",
          "text": ""
        }
      },
      {
        "name": "unexpectedAfterEOFToken",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "SourceFile",
    "type": "other"
  },
  {
    "id": 1,
    "parent": 0,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "CodeBlockItemSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "1"
        }
      }
    ],
    "text": "CodeBlockItemList",
    "type": "collection"
  },
  {
    "id": 2,
    "parent": 1,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeItem",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "item",
        "ref": "VariableDeclSyntax",
        "value": {
          "text": "VariableDeclSyntax"
        }
      },
      {
        "name": "unexpectedBetweenItemAndSemicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "semicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenSemicolonAndErrorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "errorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterErrorTokens",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "CodeBlockItem",
    "type": "other"
  },
  {
    "id": 3,
    "parent": 2,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeAttributes",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "attributes",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenAttributesAndModifiers",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "modifiers",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenModifiersAndLetOrVarKeyword",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "letOrVarKeyword",
        "value": {
          "kind": "letKeyword",
          "text": "let"
        }
      },
      {
        "name": "unexpectedBetweenLetOrVarKeywordAndBindings",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "bindings",
        "ref": "PatternBindingListSyntax",
        "value": {
          "text": "PatternBindingListSyntax"
        }
      },
      {
        "name": "unexpectedAfterBindings",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "VariableDecl",
    "type": "decl"
  },
  {
    "id": 4,
    "parent": 3,
    "range": {
      "endColumn": 4,
      "endRow": 1,
      "graphemeEndColumn": 4,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [],
    "text": "let",
    "token": {
      "kind": "letKeyword",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 5,
    "parent": 3,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "PatternBindingSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "1"
        }
      }
    ],
    "text": "PatternBindingList",
    "type": "collection"
  },
  {
    "id": 6,
    "parent": 5,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforePattern",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "pattern",
        "ref": "IdentifierPatternSyntax",
        "value": {
          "text": "IdentifierPatternSyntax"
        }
      },
      {
        "name": "unexpectedBetweenPatternAndTypeAnnotation",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "typeAnnotation",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenTypeAnnotationAndInitializer",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "initializer",
        "ref": "InitializerClauseSyntax",
        "value": {
          "text": "InitializerClauseSyntax"
        }
      },
      {
        "name": "unexpectedBetweenInitializerAndAccessor",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "accessor",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenAccessorAndTrailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "trailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterTrailingComma",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "PatternBinding",
    "type": "other"
  },
  {
    "id": 7,
    "parent": 6,
    "range": {
      "endColumn": 11,
      "endRow": 1,
      "graphemeEndColumn": 11,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeIdentifier",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "identifier",
        "value": {
          "kind": "identifier(&quot;number&quot;)",
          "text": "number"
        }
      },
      {
        "name": "unexpectedAfterIdentifier",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IdentifierPattern",
    "type": "pattern"
  },
  {
    "id": 8,
    "parent": 7,
    "range": {
      "endColumn": 11,
      "endRow": 1,
      "graphemeEndColumn": 11,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [],
    "text": "number",
    "token": {
      "kind": "identifier(&quot;number&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 9,
    "parent": 6,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 12,
      "startColumn": 12,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeEqual",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "equal",
        "value": {
          "kind": "equal",
          "text": "="
        }
      },
      {
        "name": "unexpectedBetweenEqualAndValue",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "value",
        "ref": "IntegerLiteralExprSyntax",
        "value": {
          "text": "IntegerLiteralExprSyntax"
        }
      },
      {
        "name": "unexpectedAfterValue",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "InitializerClause",
    "type": "other"
  },
  {
    "id": 10,
    "parent": 9,
    "range": {
      "endColumn": 13,
      "endRow": 1,
      "graphemeEndColumn": 13,
      "graphemeStartColumn": 12,
      "startColumn": 12,
      "startRow": 1
    },
    "structure": [],
    "text": "=",
    "token": {
      "kind": "equal",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 11,
    "parent": 9,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 14,
      "startColumn": 14,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeDigits",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "digits",
        "value": {
          "kind": "integerLiteral(&quot;0&quot;)",
          "text": "0"
        }
      },
      {
        "name": "unexpectedAfterDigits",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IntegerLiteralExpr",
    "type": "expr"
  },
  {
    "id": 12,
    "parent": 11,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 14,
      "startColumn": 14,
      "startRow": 1
    },
    "structure": [],
    "text": "0",
    "token": {
      "kind": "integerLiteral(&quot;0&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": ""
    },
    "type": "other"
  },
  {
    "id": 13,
    "parent": 0,
    "range": {
      "endColumn": 15,
      "endRow": 1,
      "graphemeEndColumn": 15,
      "graphemeStartColumn": 15,
      "startColumn": 15,
      "startRow": 1
    },
    "structure": [],
    "text": "",
    "token": {
      "kind": "eof",
      "leadingTrivia": "",
      "trailingTrivia": ""
    },
    "type": "other"
  }
]


================================================
FILE: Resources/parsers/50800/Tests/Tests/Fixtures/test-1-2.html
================================================
<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)↲}␣else␣if␣temperatureInFahrenheit␣&gt;=␣86␣{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}␣else␣{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}↲↲//␣Prints␣&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;' data-content='SourceFileSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":11,"endColumn":62}'>
<span class='CodeBlockItemList' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)↲}␣else␣if␣temperatureInFahrenheit␣&gt;=␣86␣{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}␣else␣{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":9,"endColumn":2}'>
<span class='CodeBlockItem' data-title='var␣temperatureInFahrenheit␣=␣90' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":33}'>
<span class='VariableDecl' data-title='var␣temperatureInFahrenheit␣=␣90' data-content='VariableDeclSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":33}'>
<span class='Token' data-title='var' data-content='varKeyword' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
<span class='token keyword present' data-title='var' data-content='varKeyword' data-type='Token' data-range='{"startRow":1,"startColumn":1,"endRow":1,"endColumn":4}'>
var
</span>
&nbsp;
</span>
<span class='PatternBindingList' data-title='temperatureInFahrenheit␣=␣90' data-content='PatternBindingListSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":33}'>
<span class='PatternBinding' data-title='temperatureInFahrenheit␣=␣90' data-content='PatternBindingSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":33}'>
<span class='IdentifierPattern' data-title='temperatureInFahrenheit' data-content='IdentifierPatternSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":28}'>
<span class='Token' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":28}'>
<span class='token identifier present' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":5,"endRow":1,"endColumn":28}'>
temperatureInFahrenheit
</span>
&nbsp;
</span>
</span>
<span class='InitializerClause' data-title='=␣90' data-content='InitializerClauseSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":29,"endRow":1,"endColumn":33}'>
<span class='Token' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":29,"endRow":1,"endColumn":30}'>
<span class='token equal present' data-title='=' data-content='equal' data-type='Token' data-range='{"startRow":1,"startColumn":29,"endRow":1,"endColumn":30}'>
=
</span>
&nbsp;
</span>
<span class='IntegerLiteralExpr' data-title='90' data-content='IntegerLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":1,"startColumn":31,"endRow":1,"endColumn":33}'>
<span class='Token' data-title='90' data-content='integerLiteral(&quot;90&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":31,"endRow":1,"endColumn":33}'>
<span class='token integerLiteral present' data-title='90' data-content='integerLiteral(&quot;90&quot;)' data-type='Token' data-range='{"startRow":1,"startColumn":31,"endRow":1,"endColumn":33}'>
90
</span>
</span>
</span>
</span>
</span>
</span>
</span>
</span>
<span class='CodeBlockItem' data-title='if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)↲}␣else␣if␣temperatureInFahrenheit␣&gt;=␣86␣{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}␣else␣{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":1,"endRow":9,"endColumn":2}'>
<span class='IfStmt' data-title='if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)↲}␣else␣if␣temperatureInFahrenheit␣&gt;=␣86␣{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}␣else␣{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}' data-content='IfStmtSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":1,"endRow":9,"endColumn":2}'>
<span class='Token' data-title='if' data-content='ifKeyword' data-type='Token' data-range='{"startRow":3,"startColumn":1,"endRow":3,"endColumn":3}'>
<br/>
<br/>
<span class='token keyword present' data-title='if' data-content='ifKeyword' data-type='Token' data-range='{"startRow":3,"startColumn":1,"endRow":3,"endColumn":3}'>
if
</span>
&nbsp;
</span>
<span class='ConditionElementList' data-title='temperatureInFahrenheit␣&lt;=␣32' data-content='ConditionElementListSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":33}'>
<span class='ConditionElement' data-title='temperatureInFahrenheit␣&lt;=␣32' data-content='ConditionElementSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":33}'>
<span class='SequenceExpr' data-title='temperatureInFahrenheit␣&lt;=␣32' data-content='SequenceExprSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":33}'>
<span class='ExprList' data-title='temperatureInFahrenheit␣&lt;=␣32' data-content='ExprListSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":33}'>
<span class='IdentifierExpr' data-title='temperatureInFahrenheit' data-content='IdentifierExprSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":27}'>
<span class='Token' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":27}'>
<span class='token identifier present' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":4,"endRow":3,"endColumn":27}'>
temperatureInFahrenheit
</span>
&nbsp;
</span>
</span>
<span class='BinaryOperatorExpr' data-title='&lt;=' data-content='BinaryOperatorExprSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":28,"endRow":3,"endColumn":30}'>
<span class='Token' data-title='&lt;=' data-content='spacedBinaryOperator(&quot;&lt;=&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":28,"endRow":3,"endColumn":30}'>
<span class='token spacedBinaryOperator present' data-title='&lt;=' data-content='spacedBinaryOperator(&quot;&lt;=&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":28,"endRow":3,"endColumn":30}'>
&lt;=
</span>
&nbsp;
</span>
</span>
<span class='IntegerLiteralExpr' data-title='32' data-content='IntegerLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":31,"endRow":3,"endColumn":33}'>
<span class='Token' data-title='32' data-content='integerLiteral(&quot;32&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":31,"endRow":3,"endColumn":33}'>
<span class='token integerLiteral present' data-title='32' data-content='integerLiteral(&quot;32&quot;)' data-type='Token' data-range='{"startRow":3,"startColumn":31,"endRow":3,"endColumn":33}'>
32
</span>
&nbsp;
</span>
</span>
</span>
</span>
</span>
</span>
<span class='CodeBlock' data-title='{↲␣␣print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)↲}' data-content='CodeBlockSyntax' data-type='Syntax' data-range='{"startRow":3,"startColumn":34,"endRow":5,"endColumn":2}'>
<span class='Token' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":3,"startColumn":34,"endRow":3,"endColumn":35}'>
<span class='token leftBrace present' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":3,"startColumn":34,"endRow":3,"endColumn":35}'>
{
</span>
</span>
<span class='CodeBlockItemList' data-title='print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":53}'>
<span class='CodeBlockItem' data-title='print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":53}'>
<span class='FunctionCallExpr' data-title='print(&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;)' data-content='FunctionCallExprSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":53}'>
<span class='IdentifierExpr' data-title='print' data-content='IdentifierExprSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":8}'>
<span class='Token' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":8}'>
<br/>
&nbsp;&nbsp;
<span class='token identifier present' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":4,"startColumn":3,"endRow":4,"endColumn":8}'>
print
</span>
</span>
</span>
<span class='Token' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":4,"startColumn":8,"endRow":4,"endColumn":9}'>
<span class='token leftParen present' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":4,"startColumn":8,"endRow":4,"endColumn":9}'>
(
</span>
</span>
<span class='TupleExprElementList' data-title='&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;' data-content='TupleExprElementListSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":9,"endRow":4,"endColumn":52}'>
<span class='TupleExprElement' data-title='&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;' data-content='TupleExprElementSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":9,"endRow":4,"endColumn":52}'>
<span class='StringLiteralExpr' data-title='&quot;It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.&quot;' data-content='StringLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":9,"endRow":4,"endColumn":52}'>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":4,"startColumn":9,"endRow":4,"endColumn":10}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":4,"startColumn":9,"endRow":4,"endColumn":10}'>
&quot;
</span>
</span>
<span class='StringLiteralSegments' data-title='It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.' data-content='StringLiteralSegmentsSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":10,"endRow":4,"endColumn":51}'>
<span class='StringSegment' data-title='It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.' data-content='StringSegmentSyntax' data-type='Syntax' data-range='{"startRow":4,"startColumn":10,"endRow":4,"endColumn":51}'>
<span class='Token' data-title='It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.' data-content='stringSegment(&quot;It\&apos;s&nbsp;very&nbsp;cold.&nbsp;Consider&nbsp;wearing&nbsp;a&nbsp;scarf.&quot;)' data-type='Token' data-range='{"startRow":4,"startColumn":10,"endRow":4,"endColumn":51}'>
<span class='token stringSegment present' data-title='It&apos;s␣very␣cold.␣Consider␣wearing␣a␣scarf.' data-content='stringSegment(&quot;It\&apos;s&nbsp;very&nbsp;cold.&nbsp;Consider&nbsp;wearing&nbsp;a&nbsp;scarf.&quot;)' data-type='Token' data-range='{"startRow":4,"startColumn":10,"endRow":4,"endColumn":51}'>
It&apos;s&nbsp;very&nbsp;cold.&nbsp;Consider&nbsp;wearing&nbsp;a&nbsp;scarf.
</span>
</span>
</span>
</span>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":4,"startColumn":51,"endRow":4,"endColumn":52}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":4,"startColumn":51,"endRow":4,"endColumn":52}'>
&quot;
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":4,"startColumn":52,"endRow":4,"endColumn":53}'>
<span class='token rightParen present' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":4,"startColumn":52,"endRow":4,"endColumn":53}'>
)
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":5,"startColumn":1,"endRow":5,"endColumn":2}'>
<br/>
<span class='token rightBrace present' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":5,"startColumn":1,"endRow":5,"endColumn":2}'>
}
</span>
&nbsp;
</span>
</span>
<span class='Token' data-title='else' data-content='elseKeyword' data-type='Token' data-range='{"startRow":5,"startColumn":3,"endRow":5,"endColumn":7}'>
<span class='token keyword present' data-title='else' data-content='elseKeyword' data-type='Token' data-range='{"startRow":5,"startColumn":3,"endRow":5,"endColumn":7}'>
else
</span>
&nbsp;
</span>
<span class='IfStmt' data-title='if␣temperatureInFahrenheit␣&gt;=␣86␣{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}␣else␣{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}' data-content='IfStmtSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":8,"endRow":9,"endColumn":2}'>
<span class='Token' data-title='if' data-content='ifKeyword' data-type='Token' data-range='{"startRow":5,"startColumn":8,"endRow":5,"endColumn":10}'>
<span class='token keyword present' data-title='if' data-content='ifKeyword' data-type='Token' data-range='{"startRow":5,"startColumn":8,"endRow":5,"endColumn":10}'>
if
</span>
&nbsp;
</span>
<span class='ConditionElementList' data-title='temperatureInFahrenheit␣&gt;=␣86' data-content='ConditionElementListSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":40}'>
<span class='ConditionElement' data-title='temperatureInFahrenheit␣&gt;=␣86' data-content='ConditionElementSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":40}'>
<span class='SequenceExpr' data-title='temperatureInFahrenheit␣&gt;=␣86' data-content='SequenceExprSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":40}'>
<span class='ExprList' data-title='temperatureInFahrenheit␣&gt;=␣86' data-content='ExprListSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":40}'>
<span class='IdentifierExpr' data-title='temperatureInFahrenheit' data-content='IdentifierExprSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":34}'>
<span class='Token' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":34}'>
<span class='token identifier present' data-title='temperatureInFahrenheit' data-content='identifier(&quot;temperatureInFahrenheit&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":11,"endRow":5,"endColumn":34}'>
temperatureInFahrenheit
</span>
&nbsp;
</span>
</span>
<span class='BinaryOperatorExpr' data-title='&gt;=' data-content='BinaryOperatorExprSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":35,"endRow":5,"endColumn":37}'>
<span class='Token' data-title='&gt;=' data-content='spacedBinaryOperator(&quot;&gt;=&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":35,"endRow":5,"endColumn":37}'>
<span class='token spacedBinaryOperator present' data-title='&gt;=' data-content='spacedBinaryOperator(&quot;&gt;=&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":35,"endRow":5,"endColumn":37}'>
&gt;=
</span>
&nbsp;
</span>
</span>
<span class='IntegerLiteralExpr' data-title='86' data-content='IntegerLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":38,"endRow":5,"endColumn":40}'>
<span class='Token' data-title='86' data-content='integerLiteral(&quot;86&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":38,"endRow":5,"endColumn":40}'>
<span class='token integerLiteral present' data-title='86' data-content='integerLiteral(&quot;86&quot;)' data-type='Token' data-range='{"startRow":5,"startColumn":38,"endRow":5,"endColumn":40}'>
86
</span>
&nbsp;
</span>
</span>
</span>
</span>
</span>
</span>
<span class='CodeBlock' data-title='{↲␣␣print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)↲}' data-content='CodeBlockSyntax' data-type='Syntax' data-range='{"startRow":5,"startColumn":41,"endRow":7,"endColumn":2}'>
<span class='Token' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":5,"startColumn":41,"endRow":5,"endColumn":42}'>
<span class='token leftBrace present' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":5,"startColumn":41,"endRow":5,"endColumn":42}'>
{
</span>
</span>
<span class='CodeBlockItemList' data-title='print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":61}'>
<span class='CodeBlockItem' data-title='print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":61}'>
<span class='FunctionCallExpr' data-title='print(&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;)' data-content='FunctionCallExprSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":61}'>
<span class='IdentifierExpr' data-title='print' data-content='IdentifierExprSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":8}'>
<span class='Token' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":8}'>
<br/>
&nbsp;&nbsp;
<span class='token identifier present' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":6,"startColumn":3,"endRow":6,"endColumn":8}'>
print
</span>
</span>
</span>
<span class='Token' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":6,"startColumn":8,"endRow":6,"endColumn":9}'>
<span class='token leftParen present' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":6,"startColumn":8,"endRow":6,"endColumn":9}'>
(
</span>
</span>
<span class='TupleExprElementList' data-title='&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;' data-content='TupleExprElementListSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":9,"endRow":6,"endColumn":60}'>
<span class='TupleExprElement' data-title='&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;' data-content='TupleExprElementSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":9,"endRow":6,"endColumn":60}'>
<span class='StringLiteralExpr' data-title='&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;' data-content='StringLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":9,"endRow":6,"endColumn":60}'>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":6,"startColumn":9,"endRow":6,"endColumn":10}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":6,"startColumn":9,"endRow":6,"endColumn":10}'>
&quot;
</span>
</span>
<span class='StringLiteralSegments' data-title='It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.' data-content='StringLiteralSegmentsSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":10,"endRow":6,"endColumn":59}'>
<span class='StringSegment' data-title='It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.' data-content='StringSegmentSyntax' data-type='Syntax' data-range='{"startRow":6,"startColumn":10,"endRow":6,"endColumn":59}'>
<span class='Token' data-title='It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.' data-content='stringSegment(&quot;It\&apos;s&nbsp;really&nbsp;warm.&nbsp;Don\&apos;t&nbsp;forget&nbsp;to&nbsp;wear&nbsp;sunscreen.&quot;)' data-type='Token' data-range='{"startRow":6,"startColumn":10,"endRow":6,"endColumn":59}'>
<span class='token stringSegment present' data-title='It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.' data-content='stringSegment(&quot;It\&apos;s&nbsp;really&nbsp;warm.&nbsp;Don\&apos;t&nbsp;forget&nbsp;to&nbsp;wear&nbsp;sunscreen.&quot;)' data-type='Token' data-range='{"startRow":6,"startColumn":10,"endRow":6,"endColumn":59}'>
It&apos;s&nbsp;really&nbsp;warm.&nbsp;Don&apos;t&nbsp;forget&nbsp;to&nbsp;wear&nbsp;sunscreen.
</span>
</span>
</span>
</span>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":6,"startColumn":59,"endRow":6,"endColumn":60}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":6,"startColumn":59,"endRow":6,"endColumn":60}'>
&quot;
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":6,"startColumn":60,"endRow":6,"endColumn":61}'>
<span class='token rightParen present' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":6,"startColumn":60,"endRow":6,"endColumn":61}'>
)
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":7,"startColumn":1,"endRow":7,"endColumn":2}'>
<br/>
<span class='token rightBrace present' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":7,"startColumn":1,"endRow":7,"endColumn":2}'>
}
</span>
&nbsp;
</span>
</span>
<span class='Token' data-title='else' data-content='elseKeyword' data-type='Token' data-range='{"startRow":7,"startColumn":3,"endRow":7,"endColumn":7}'>
<span class='token keyword present' data-title='else' data-content='elseKeyword' data-type='Token' data-range='{"startRow":7,"startColumn":3,"endRow":7,"endColumn":7}'>
else
</span>
&nbsp;
</span>
<span class='CodeBlock' data-title='{↲␣␣print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)↲}' data-content='CodeBlockSyntax' data-type='Syntax' data-range='{"startRow":7,"startColumn":8,"endRow":9,"endColumn":2}'>
<span class='Token' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":7,"startColumn":8,"endRow":7,"endColumn":9}'>
<span class='token leftBrace present' data-title='{' data-content='leftBrace' data-type='Token' data-range='{"startRow":7,"startColumn":8,"endRow":7,"endColumn":9}'>
{
</span>
</span>
<span class='CodeBlockItemList' data-title='print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)' data-content='CodeBlockItemListSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":47}'>
<span class='CodeBlockItem' data-title='print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)' data-content='CodeBlockItemSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":47}'>
<span class='FunctionCallExpr' data-title='print(&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;)' data-content='FunctionCallExprSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":47}'>
<span class='IdentifierExpr' data-title='print' data-content='IdentifierExprSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":8}'>
<span class='Token' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":8}'>
<br/>
&nbsp;&nbsp;
<span class='token identifier present' data-title='print' data-content='identifier(&quot;print&quot;)' data-type='Token' data-range='{"startRow":8,"startColumn":3,"endRow":8,"endColumn":8}'>
print
</span>
</span>
</span>
<span class='Token' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":8,"startColumn":8,"endRow":8,"endColumn":9}'>
<span class='token leftParen present' data-title='(' data-content='leftParen' data-type='Token' data-range='{"startRow":8,"startColumn":8,"endRow":8,"endColumn":9}'>
(
</span>
</span>
<span class='TupleExprElementList' data-title='&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;' data-content='TupleExprElementListSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":9,"endRow":8,"endColumn":46}'>
<span class='TupleExprElement' data-title='&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;' data-content='TupleExprElementSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":9,"endRow":8,"endColumn":46}'>
<span class='StringLiteralExpr' data-title='&quot;It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.&quot;' data-content='StringLiteralExprSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":9,"endRow":8,"endColumn":46}'>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":8,"startColumn":9,"endRow":8,"endColumn":10}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":8,"startColumn":9,"endRow":8,"endColumn":10}'>
&quot;
</span>
</span>
<span class='StringLiteralSegments' data-title='It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.' data-content='StringLiteralSegmentsSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":10,"endRow":8,"endColumn":45}'>
<span class='StringSegment' data-title='It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.' data-content='StringSegmentSyntax' data-type='Syntax' data-range='{"startRow":8,"startColumn":10,"endRow":8,"endColumn":45}'>
<span class='Token' data-title='It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.' data-content='stringSegment(&quot;It\&apos;s&nbsp;not&nbsp;that&nbsp;cold.&nbsp;Wear&nbsp;a&nbsp;t-shirt.&quot;)' data-type='Token' data-range='{"startRow":8,"startColumn":10,"endRow":8,"endColumn":45}'>
<span class='token stringSegment present' data-title='It&apos;s␣not␣that␣cold.␣Wear␣a␣t-shirt.' data-content='stringSegment(&quot;It\&apos;s&nbsp;not&nbsp;that&nbsp;cold.&nbsp;Wear&nbsp;a&nbsp;t-shirt.&quot;)' data-type='Token' data-range='{"startRow":8,"startColumn":10,"endRow":8,"endColumn":45}'>
It&apos;s&nbsp;not&nbsp;that&nbsp;cold.&nbsp;Wear&nbsp;a&nbsp;t-shirt.
</span>
</span>
</span>
</span>
<span class='Token' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":8,"startColumn":45,"endRow":8,"endColumn":46}'>
<span class='token stringQuote present' data-title='&quot;' data-content='stringQuote' data-type='Token' data-range='{"startRow":8,"startColumn":45,"endRow":8,"endColumn":46}'>
&quot;
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":8,"startColumn":46,"endRow":8,"endColumn":47}'>
<span class='token rightParen present' data-title=')' data-content='rightParen' data-type='Token' data-range='{"startRow":8,"startColumn":46,"endRow":8,"endColumn":47}'>
)
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":9,"startColumn":1,"endRow":9,"endColumn":2}'>
<br/>
<span class='token rightBrace present' data-title='}' data-content='rightBrace' data-type='Token' data-range='{"startRow":9,"startColumn":1,"endRow":9,"endColumn":2}'>
}
</span>
</span>
</span>
</span>
</span>
</span>
</span>
<span class='Token' data-title='' data-content='eof' data-type='Token' data-range='{"startRow":11,"startColumn":62,"endRow":11,"endColumn":62}'>
<br/>
<br/>
<span class='lineComment' data-title='//␣Prints␣&quot;It&apos;s␣really␣warm.␣Don&apos;t␣forget␣to␣wear␣sunscreen.&quot;' data-content='lineComment' data-type='Trivia'>
//&nbsp;Prints&nbsp;&quot;It&apos;s&nbsp;really&nbsp;warm.&nbsp;Don&apos;t&nbsp;forget&nbsp;to&nbsp;wear&nbsp;sunscreen.&quot;
</span>
<span class='token eof present' data-title='' data-content='eof' data-type='Token' data-range='{"startRow":11,"startColumn":62,"endRow":11,"endColumn":62}'></span>
</span>
</span>


================================================
FILE: Resources/parsers/50800/Tests/Tests/Fixtures/test-1-2.json
================================================
[
  {
    "id": 0,
    "range": {
      "endColumn": 62,
      "endRow": 11,
      "graphemeEndColumn": 62,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeStatements",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "statements",
        "ref": "CodeBlockItemListSyntax",
        "value": {
          "text": "CodeBlockItemListSyntax"
        }
      },
      {
        "name": "unexpectedBetweenStatementsAndEOFToken",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "eofToken",
        "value": {
          "kind": "eof",
          "text": ""
        }
      },
      {
        "name": "unexpectedAfterEOFToken",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "SourceFile",
    "type": "other"
  },
  {
    "id": 1,
    "parent": 0,
    "range": {
      "endColumn": 2,
      "endRow": 9,
      "graphemeEndColumn": 2,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "CodeBlockItemSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "2"
        }
      }
    ],
    "text": "CodeBlockItemList",
    "type": "collection"
  },
  {
    "id": 2,
    "parent": 1,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeItem",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "item",
        "ref": "VariableDeclSyntax",
        "value": {
          "text": "VariableDeclSyntax"
        }
      },
      {
        "name": "unexpectedBetweenItemAndSemicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "semicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenSemicolonAndErrorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "errorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterErrorTokens",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "CodeBlockItem",
    "type": "other"
  },
  {
    "id": 3,
    "parent": 2,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeAttributes",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "attributes",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenAttributesAndModifiers",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "modifiers",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenModifiersAndLetOrVarKeyword",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "letOrVarKeyword",
        "value": {
          "kind": "varKeyword",
          "text": "var"
        }
      },
      {
        "name": "unexpectedBetweenLetOrVarKeywordAndBindings",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "bindings",
        "ref": "PatternBindingListSyntax",
        "value": {
          "text": "PatternBindingListSyntax"
        }
      },
      {
        "name": "unexpectedAfterBindings",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "VariableDecl",
    "type": "decl"
  },
  {
    "id": 4,
    "parent": 3,
    "range": {
      "endColumn": 4,
      "endRow": 1,
      "graphemeEndColumn": 4,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 1
    },
    "structure": [],
    "text": "var",
    "token": {
      "kind": "varKeyword",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 5,
    "parent": 3,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "PatternBindingSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "1"
        }
      }
    ],
    "text": "PatternBindingList",
    "type": "collection"
  },
  {
    "id": 6,
    "parent": 5,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforePattern",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "pattern",
        "ref": "IdentifierPatternSyntax",
        "value": {
          "text": "IdentifierPatternSyntax"
        }
      },
      {
        "name": "unexpectedBetweenPatternAndTypeAnnotation",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "typeAnnotation",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenTypeAnnotationAndInitializer",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "initializer",
        "ref": "InitializerClauseSyntax",
        "value": {
          "text": "InitializerClauseSyntax"
        }
      },
      {
        "name": "unexpectedBetweenInitializerAndAccessor",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "accessor",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenAccessorAndTrailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "trailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterTrailingComma",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "PatternBinding",
    "type": "other"
  },
  {
    "id": 7,
    "parent": 6,
    "range": {
      "endColumn": 28,
      "endRow": 1,
      "graphemeEndColumn": 28,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeIdentifier",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "identifier",
        "value": {
          "kind": "identifier(&quot;temperatureInFahrenheit&quot;)",
          "text": "temperatureInFahrenheit"
        }
      },
      {
        "name": "unexpectedAfterIdentifier",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IdentifierPattern",
    "type": "pattern"
  },
  {
    "id": 8,
    "parent": 7,
    "range": {
      "endColumn": 28,
      "endRow": 1,
      "graphemeEndColumn": 28,
      "graphemeStartColumn": 5,
      "startColumn": 5,
      "startRow": 1
    },
    "structure": [],
    "text": "temperatureInFahrenheit",
    "token": {
      "kind": "identifier(&quot;temperatureInFahrenheit&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 9,
    "parent": 6,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 29,
      "startColumn": 29,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeEqual",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "equal",
        "value": {
          "kind": "equal",
          "text": "="
        }
      },
      {
        "name": "unexpectedBetweenEqualAndValue",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "value",
        "ref": "IntegerLiteralExprSyntax",
        "value": {
          "text": "IntegerLiteralExprSyntax"
        }
      },
      {
        "name": "unexpectedAfterValue",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "InitializerClause",
    "type": "other"
  },
  {
    "id": 10,
    "parent": 9,
    "range": {
      "endColumn": 30,
      "endRow": 1,
      "graphemeEndColumn": 30,
      "graphemeStartColumn": 29,
      "startColumn": 29,
      "startRow": 1
    },
    "structure": [],
    "text": "=",
    "token": {
      "kind": "equal",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 11,
    "parent": 9,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 31,
      "startColumn": 31,
      "startRow": 1
    },
    "structure": [
      {
        "name": "unexpectedBeforeDigits",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "digits",
        "value": {
          "kind": "integerLiteral(&quot;90&quot;)",
          "text": "90"
        }
      },
      {
        "name": "unexpectedAfterDigits",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IntegerLiteralExpr",
    "type": "expr"
  },
  {
    "id": 12,
    "parent": 11,
    "range": {
      "endColumn": 33,
      "endRow": 1,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 31,
      "startColumn": 31,
      "startRow": 1
    },
    "structure": [],
    "text": "90",
    "token": {
      "kind": "integerLiteral(&quot;90&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": ""
    },
    "type": "other"
  },
  {
    "id": 13,
    "parent": 1,
    "range": {
      "endColumn": 2,
      "endRow": 9,
      "graphemeEndColumn": 2,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeItem",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "item",
        "ref": "IfStmtSyntax",
        "value": {
          "text": "IfStmtSyntax"
        }
      },
      {
        "name": "unexpectedBetweenItemAndSemicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "semicolon",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedBetweenSemicolonAndErrorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "errorTokens",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterErrorTokens",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "CodeBlockItem",
    "type": "other"
  },
  {
    "id": 14,
    "parent": 13,
    "range": {
      "endColumn": 2,
      "endRow": 9,
      "graphemeEndColumn": 2,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeIfKeyword",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "ifKeyword",
        "value": {
          "kind": "ifKeyword",
          "text": "if"
        }
      },
      {
        "name": "unexpectedBetweenIfKeywordAndConditions",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "conditions",
        "ref": "ConditionElementListSyntax",
        "value": {
          "text": "ConditionElementListSyntax"
        }
      },
      {
        "name": "unexpectedBetweenConditionsAndBody",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "body",
        "ref": "CodeBlockSyntax",
        "value": {
          "text": "CodeBlockSyntax"
        }
      },
      {
        "name": "unexpectedBetweenBodyAndElseKeyword",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "elseKeyword",
        "value": {
          "kind": "elseKeyword",
          "text": "else"
        }
      },
      {
        "name": "unexpectedBetweenElseKeywordAndElseBody",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "elseBody",
        "ref": "IfStmtSyntax",
        "value": {
          "text": "IfStmtSyntax"
        }
      },
      {
        "name": "unexpectedAfterElseBody",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IfStmt",
    "type": "other"
  },
  {
    "id": 15,
    "parent": 14,
    "range": {
      "endColumn": 3,
      "endRow": 3,
      "graphemeEndColumn": 3,
      "graphemeStartColumn": 1,
      "startColumn": 1,
      "startRow": 3
    },
    "structure": [],
    "text": "if",
    "token": {
      "kind": "ifKeyword",
      "leadingTrivia": "<span class='newline'>↲</span><br/><span class='newline'>↲</span><br/>",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 16,
    "parent": 14,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "ConditionElementSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "1"
        }
      }
    ],
    "text": "ConditionElementList",
    "type": "collection"
  },
  {
    "id": 17,
    "parent": 16,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeCondition",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "condition",
        "ref": "SequenceExprSyntax",
        "value": {
          "text": "SequenceExprSyntax"
        }
      },
      {
        "name": "unexpectedBetweenConditionAndTrailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "trailingComma",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterTrailingComma",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "ConditionElement",
    "type": "other"
  },
  {
    "id": 18,
    "parent": 17,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeElements",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "elements",
        "ref": "ExprListSyntax",
        "value": {
          "text": "ExprListSyntax"
        }
      },
      {
        "name": "unexpectedAfterElements",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "SequenceExpr",
    "type": "expr"
  },
  {
    "id": 19,
    "parent": 18,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [
      {
        "name": "Element",
        "value": {
          "text": "ExprSyntax"
        }
      },
      {
        "name": "Count",
        "value": {
          "text": "3"
        }
      }
    ],
    "text": "ExprList",
    "type": "collection"
  },
  {
    "id": 20,
    "parent": 19,
    "range": {
      "endColumn": 27,
      "endRow": 3,
      "graphemeEndColumn": 27,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeIdentifier",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "identifier",
        "value": {
          "kind": "identifier(&quot;temperatureInFahrenheit&quot;)",
          "text": "temperatureInFahrenheit"
        }
      },
      {
        "name": "unexpectedBetweenIdentifierAndDeclNameArguments",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "declNameArguments",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "unexpectedAfterDeclNameArguments",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IdentifierExpr",
    "type": "expr"
  },
  {
    "id": 21,
    "parent": 20,
    "range": {
      "endColumn": 27,
      "endRow": 3,
      "graphemeEndColumn": 27,
      "graphemeStartColumn": 4,
      "startColumn": 4,
      "startRow": 3
    },
    "structure": [],
    "text": "temperatureInFahrenheit",
    "token": {
      "kind": "identifier(&quot;temperatureInFahrenheit&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 22,
    "parent": 19,
    "range": {
      "endColumn": 30,
      "endRow": 3,
      "graphemeEndColumn": 30,
      "graphemeStartColumn": 28,
      "startColumn": 28,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeOperatorToken",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "operatorToken",
        "value": {
          "kind": "spacedBinaryOperator(&quot;&lt;=&quot;)",
          "text": "&lt;="
        }
      },
      {
        "name": "unexpectedAfterOperatorToken",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "BinaryOperatorExpr",
    "type": "expr"
  },
  {
    "id": 23,
    "parent": 22,
    "range": {
      "endColumn": 30,
      "endRow": 3,
      "graphemeEndColumn": 30,
      "graphemeStartColumn": 28,
      "startColumn": 28,
      "startRow": 3
    },
    "structure": [],
    "text": "&lt;=",
    "token": {
      "kind": "spacedBinaryOperator(&quot;&lt;=&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 24,
    "parent": 19,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 31,
      "startColumn": 31,
      "startRow": 3
    },
    "structure": [
      {
        "name": "unexpectedBeforeDigits",
        "value": {
          "text": "nil"
        }
      },
      {
        "name": "digits",
        "value": {
          "kind": "integerLiteral(&quot;32&quot;)",
          "text": "32"
        }
      },
      {
        "name": "unexpectedAfterDigits",
        "value": {
          "text": "nil"
        }
      }
    ],
    "text": "IntegerLiteralExpr",
    "type": "expr"
  },
  {
    "id": 25,
    "parent": 24,
    "range": {
      "endColumn": 33,
      "endRow": 3,
      "graphemeEndColumn": 33,
      "graphemeStartColumn": 31,
      "startColumn": 31,
      "startRow": 3
    },
    "structure": [],
    "text": "32",
    "token": {
      "kind": "integerLiteral(&quot;32&quot;)",
      "leadingTrivia": "",
      "trailingTrivia": "<span class='whitespace'>␣</span>"
    },
    "type": "other"
  },
  {
    "id": 26,
    "parent": 14,
    "range": {
      "endColumn": 2,
      "endRow": 5,
      "graphemeEndColumn": 2,
      "graphemeStartColumn": 34,
      "startColumn
Download .txt
gitextract_tk66xfku/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── renovate.json
│   └── workflows/
│       ├── spm.yml
│       └── test.yml
├── .gitignore
├── .swiftpm/
│   └── xcode/
│       └── package.xcworkspace/
│           └── contents.xcworkspacedata
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CODE_OF_CONDUCT.md
├── DEPLOYMENT.md
├── Dockerfile
├── LICENSE
├── Package.resolved
├── Package.swift
├── Public/
│   ├── css/
│   │   ├── balloon.css
│   │   ├── common.css
│   │   ├── editor.css
│   │   ├── lookup.css
│   │   ├── popover.css
│   │   ├── table.css
│   │   ├── tree_view.css
│   │   └── trivia.css
│   ├── error.html
│   ├── favicons/
│   │   ├── browserconfig.xml
│   │   └── site.webmanifest
│   ├── index.html
│   ├── index.js
│   ├── js/
│   │   ├── app.js
│   │   ├── balloon.js
│   │   ├── debounce.js
│   │   ├── editor.js
│   │   ├── icon.js
│   │   ├── lookup_view.js
│   │   ├── popover.js
│   │   ├── statistics_view.js
│   │   ├── structure_view.js
│   │   ├── tree_view.js
│   │   ├── trivia_view.js
│   │   └── websocket.js
│   ├── robots.txt
│   └── scss/
│       └── default.scss
├── README.md
├── Resources/
│   └── parsers/
│       ├── 50800/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       ├── Main.swift
│       │   │       ├── SyntaxParser.swift
│       │   │       ├── SyntaxResponse.swift
│       │   │       ├── TokenVisitor.swift
│       │   │       ├── TreeNode.swift
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           ├── Fixtures/
│       │           │   ├── test-1-1.html
│       │           │   ├── test-1-1.json
│       │           │   ├── test-1-2.html
│       │           │   ├── test-1-2.json
│       │           │   ├── test-1-3.html
│       │           │   ├── test-1-3.json
│       │           │   ├── test-1-4.html
│       │           │   ├── test-1-4.json
│       │           │   ├── test-1-5.html
│       │           │   ├── test-1-5.json
│       │           │   ├── test-1-6.html
│       │           │   ├── test-1-6.json
│       │           │   ├── test-2-1.html
│       │           │   ├── test-2-1.json
│       │           │   ├── test-2-2.html
│       │           │   ├── test-2-2.json
│       │           │   ├── test-2-3.html
│       │           │   ├── test-2-3.json
│       │           │   ├── test-2-4.html
│       │           │   ├── test-2-4.json
│       │           │   ├── test-2-5.html
│       │           │   ├── test-2-5.json
│       │           │   ├── test-2-6.html
│       │           │   └── test-2-6.json
│       │           └── Tests.swift
│       ├── 50900/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       ├── SyntaxParser.swift
│       │   │       ├── TokenVisitor.swift
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 51000/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60000/
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60100/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60200/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       ├── 60300/
│       │   ├── .swiftpm/
│       │   │   └── xcode/
│       │   │       └── package.xcworkspace/
│       │   │           └── contents.xcworkspacedata
│       │   ├── Package.resolved
│       │   ├── Package.swift
│       │   ├── Sources/
│       │   │   └── parser/
│       │   │       └── Version.swift
│       │   └── Tests/
│       │       └── Tests/
│       │           └── Fixtures/
│       │               ├── test-1-1.html
│       │               ├── test-1-1.json
│       │               ├── test-1-2.html
│       │               ├── test-1-2.json
│       │               ├── test-1-3.html
│       │               ├── test-1-3.json
│       │               ├── test-1-4.html
│       │               ├── test-1-4.json
│       │               ├── test-1-5.html
│       │               ├── test-1-5.json
│       │               ├── test-1-6.html
│       │               ├── test-1-6.json
│       │               ├── test-2-1.html
│       │               ├── test-2-1.json
│       │               ├── test-2-2.html
│       │               ├── test-2-2.json
│       │               ├── test-2-3.html
│       │               ├── test-2-3.json
│       │               ├── test-2-4.html
│       │               ├── test-2-4.json
│       │               ├── test-2-5.html
│       │               ├── test-2-5.json
│       │               ├── test-2-6.html
│       │               └── test-2-6.json
│       └── trunk/
│           ├── .swiftpm/
│           │   └── xcode/
│           │       └── package.xcworkspace/
│           │           └── contents.xcworkspacedata
│           ├── Package.resolved
│           ├── Package.swift
│           ├── Sources/
│           │   └── parser/
│           │       └── Version.swift
│           └── Tests/
│               └── Tests/
│                   └── Fixtures/
│                       ├── test-1-1.html
│                       ├── test-1-1.json
│                       ├── test-1-2.html
│                       ├── test-1-2.json
│                       ├── test-1-3.html
│                       ├── test-1-3.json
│                       ├── test-1-4.html
│                       ├── test-1-4.json
│                       ├── test-1-5.html
│                       ├── test-1-5.json
│                       ├── test-1-6.html
│                       ├── test-1-6.json
│                       ├── test-2-1.html
│                       ├── test-2-1.json
│                       ├── test-2-2.html
│                       ├── test-2-2.json
│                       ├── test-2-3.html
│                       ├── test-2-3.json
│                       ├── test-2-4.html
│                       ├── test-2-4.json
│                       ├── test-2-5.html
│                       ├── test-2-5.json
│                       ├── test-2-6.html
│                       └── test-2-6.json
├── SECURITY.md
├── Sources/
│   └── App/
│       ├── Middlewares/
│       │   ├── CommonErrorMiddleware.swift
│       │   └── CustomHeaderMiddleware.swift
│       ├── configure.swift
│       ├── entrypoint.swift
│       └── routes.swift
├── Tests/
│   └── AppTests/
│       └── AppTests.swift
├── build_pasers.sh
├── deploy/
│   └── Dockerfile
├── dev/
│   ├── .gitignore
│   ├── index.js
│   ├── package.json
│   └── xml-formatter/
│       ├── .eslintignore
│       ├── .eslintrc.json
│       ├── .gitignore
│       ├── .npmignore
│       ├── LICENSE
│       ├── README.md
│       ├── package.json
│       ├── publish.sh
│       ├── src/
│       │   ├── index.d.ts
│       │   └── index.ts
│       ├── test/
│       │   ├── .eslintrc.json
│       │   ├── browser/
│       │   │   ├── README.md
│       │   │   └── index.html
│       │   ├── data1/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   ├── data10/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data11/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   └── xml2-output.xml
│       │   ├── data12/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data13/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data14/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data2/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   ├── data3/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   ├── xml4-output.xml
│       │   │   ├── xml5-input.xml
│       │   │   ├── xml5-output.xml
│       │   │   ├── xml6-input.xml
│       │   │   ├── xml6-output.xml
│       │   │   ├── xml7-input.xml
│       │   │   └── xml7-output.xml
│       │   ├── data4/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   ├── xml4-output.xml
│       │   │   ├── xml5-input.xml
│       │   │   └── xml5-output.xml
│       │   ├── data5/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data6/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   └── xml2-output.xml
│       │   ├── data7/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data8/
│       │   │   ├── xml1-input.xml
│       │   │   └── xml1-output.xml
│       │   ├── data9/
│       │   │   ├── xml1-input.xml
│       │   │   ├── xml1-output.xml
│       │   │   ├── xml2-input.xml
│       │   │   ├── xml2-output.xml
│       │   │   ├── xml3-input.xml
│       │   │   ├── xml3-output.xml
│       │   │   ├── xml4-input.xml
│       │   │   └── xml4-output.xml
│       │   └── index.ts
│       └── tsconfig.json
├── package.json
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
Download .txt
SYMBOL INDEX (100 symbols across 14 files)

FILE: Public/js/app.js
  class App (line 13) | class App {
    method contentViewHeight (line 14) | get contentViewHeight() {
    method constructor (line 21) | constructor() {
    method init (line 41) | init() {
    method update (line 111) | update() {
    method updateStructure (line 153) | updateStructure() {
    method updateLookup (line 191) | updateLookup() {
    method updateTrivia (line 199) | updateTrivia() {
    method updateStatistics (line 207) | updateStatistics() {
    method onresize (line 279) | onresize() {
  function branchOptions (line 294) | function branchOptions() {
  function parserOptions (line 306) | function parserOptions() {
  function showLoading (line 318) | function showLoading() {
  function hideLoading (line 324) | function hideLoading() {
  function formatRange (line 330) | function formatRange(range) {

FILE: Public/js/balloon.js
  class Balloon (line 5) | class Balloon {
    method constructor (line 6) | constructor() {
    method init (line 11) | init() {
    method setContent (line 16) | setContent(content) {
    method show (line 21) | show(rect, options = {}) {
    method hide (line 91) | hide() {

FILE: Public/js/debounce.js
  function debounce (line 3) | function debounce(cb, delay = 250) {

FILE: Public/js/editor.js
  class Editor (line 11) | class Editor {
    method constructor (line 12) | constructor(container) {
    method init (line 17) | init() {
    method getValue (line 45) | getValue() {
    method setValue (line 49) | setValue(value) {
    method setSelection (line 53) | setSelection(range) {
    method markText (line 61) | markText(range) {
    method clearMarks (line 73) | clearMarks() {
    method charCoords (line 79) | charCoords(range, mode = "page") {
    method focus (line 86) | focus() {
    method refresh (line 90) | refresh() {
    method on (line 94) | on(event, callback) {

FILE: Public/js/lookup_view.js
  class LookupView (line 6) | class LookupView {
    method error (line 7) | set error(error) {
    method constructor (line 11) | constructor(container) {
    method update (line 16) | update(syntaxHTML) {
    method createDOMRectElement (line 117) | createDOMRectElement(domRect) {
    method removeDOMRectElement (line 137) | removeDOMRectElement() {
  function escapeHTML (line 145) | function escapeHTML(text) {

FILE: Public/js/popover.js
  class Popover (line 5) | class Popover {
    method constructor (line 6) | constructor() {
    method init (line 17) | init() {
    method setContent (line 44) | setContent(content) {
    method show (line 52) | show(target, options = {}) {
    method hide (line 81) | hide() {

FILE: Public/js/statistics_view.js
  class StatisticsView (line 8) | class StatisticsView {
    method error (line 9) | set error(error) {
    method constructor (line 13) | constructor(container) {
    method update (line 20) | update(statistics) {

FILE: Public/js/structure_view.js
  class StructureView (line 6) | class StructureView {
    method error (line 7) | set error(error) {
    method constructor (line 11) | constructor(container) {
    method init (line 21) | init() {
    method update (line 25) | update(structureData) {
  function makeSyntaxPopoverContent (line 66) | function makeSyntaxPopoverContent(data) {
  function makeTokenPopoverContent (line 88) | function makeTokenPopoverContent(data) {
  function makeSourceRangePopoverContent (line 111) | function makeSourceRangePopoverContent(data, list) {
  function makePropertyPopoverContent (line 117) | function makePropertyPopoverContent(property, list) {
  function makeDescriptionList (line 133) | function makeDescriptionList(term, details, list) {
  function makeSyntaxTypeBadge (line 144) | function makeSyntaxTypeBadge(type) {

FILE: Public/js/tree_view.js
  class TreeView (line 5) | class TreeView {
    method constructor (line 6) | constructor(container, tree) {
    method init (line 20) | init() {
    method renderTree (line 30) | renderTree(container, tree) {
    method renderNode (line 40) | renderNode(node) {
    method hasChildren (line 96) | hasChildren(id) {
    method getChildren (line 102) | getChildren(id) {
    method open (line 108) | open(node, li) {
    method collapse (line 126) | collapse(node, li) {
    method onclick (line 138) | onclick(event, node, li) {

FILE: Public/js/trivia_view.js
  class TriviaView (line 6) | class TriviaView {
    method error (line 7) | set error(error) {
    method constructor (line 11) | constructor(container) {
    method update (line 16) | update(syntaxHTML) {
    method createDOMRectElement (line 144) | createDOMRectElement(domRect) {
    method removeDOMRectElement (line 163) | removeDOMRectElement() {

FILE: Public/js/websocket.js
  class WebSocketClient (line 5) | class WebSocketClient {
    method constructor (line 6) | constructor(endpoint) {
    method isReady (line 13) | get isReady() {
    method send (line 17) | send(params) {
    method createConnection (line 22) | createConnection(endpoint) {

FILE: dev/xml-formatter/src/index.d.ts
  type FormatOptions (line 1) | type FormatOptions = {

FILE: dev/xml-formatter/src/index.ts
  type XMLFormatterOptions (line 9) | type XMLFormatterOptions = {
  type XMLFormatterMinifyOptions (line 61) | type XMLFormatterMinifyOptions = Omit<XMLFormatterOptions, 'lineSeparato...
  type XMLFormatterState (line 63) | type XMLFormatterState = {
  function newLine (line 70) | function newLine(state: XMLFormatterState): void {
  function indent (line 79) | function indent(state: XMLFormatterState): void {
  function appendContent (line 87) | function appendContent(state: XMLFormatterState, content: string): void {
  function processNode (line 91) | function processNode(node: XmlParserNode, state: XMLFormatterState, pres...
  function processContent (line 103) | function processContent(content: string, state: XMLFormatterState, prese...
  function isPathMatchingIgnoredPaths (line 120) | function isPathMatchingIgnoredPaths(path: string[], ignoredPaths: string...
  function processElementNode (line 126) | function processElementNode(node: XmlParserElementNode, state: XMLFormat...
  function processAttributes (line 208) | function processAttributes(state: XMLFormatterState, attributes: Record<...
  function processProcessingIntruction (line 214) | function processProcessingIntruction(node: XmlParserProcessingInstructio...
  function formatXml (line 227) | function formatXml(xml: string, options: XMLFormatterOptions = {}): stri...

FILE: dev/xml-formatter/test/index.ts
  function assertFormatError (line 9) | function assertFormatError(src: string, formatterOptions: XMLFormatterOp...
  function assertFormat (line 32) | function assertFormat(src: string, formatterOptions: XMLFormatterOptions...
  function assertMinifyFormat (line 54) | function assertMinifyFormat(src: string, formatterOptions: XMLFormatterM...
Copy disabled (too large) Download .json
Condensed preview — 375 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (13,508K chars).
[
  {
    "path": ".dockerignore",
    "chars": 18,
    "preview": ".build/\n.swiftpm/\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 25,
    "preview": "github: kishikawakatsumi\n"
  },
  {
    "path": ".github/renovate.json",
    "chars": 212,
    "preview": "{\n  \"extends\": [\n    \"config:recommended\"\n  ],\n  \"packageRules\": [\n    {\n      \"matchUpdateTypes\": [\n        \"minor\",\n  "
  },
  {
    "path": ".github/workflows/spm.yml",
    "chars": 1308,
    "preview": "name: Update Swift Package\n\non:\n  schedule:\n    - cron: \"30 22 * * *\"\n  workflow_dispatch:\n\njobs:\n  update:\n    runs-on:"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 1301,
    "preview": "name: Test\non:\n  pull_request:\n    branches: [master]\n  workflow_dispatch:\n\nenv:\n  FONTAWESOME_TOKEN: ${{ secrets.FONTAW"
  },
  {
    "path": ".gitignore",
    "chars": 4741,
    "preview": "### https://raw.github.com/github/gitignore/991e760c1c6d50fdda246e0178b9c58b06770b90/Global/macOS.gitignore\n\n# General\n."
  },
  {
    "path": ".swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 677,
    "preview": "{\n  \"configurations\": [\n    {\n      \"type\": \"swift\",\n      \"request\": \"launch\",\n      \"sourceLanguages\": [\"swift\"],\n    "
  },
  {
    "path": ".vscode/settings.json",
    "chars": 144,
    "preview": "{\n  \"lldb.library\": \"/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB\",\n  \"lldb.launch.e"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 5257,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": "DEPLOYMENT.md",
    "chars": 1024,
    "preview": "# Deployment Instructions\n\n## Prerequisites\n\nBefore deploying, make sure you have the following software installed on yo"
  },
  {
    "path": "Dockerfile",
    "chars": 2360,
    "preview": "FROM node:lts-slim as node\n\nWORKDIR /build\n\nARG FONTAWESOME_TOKEN\nCOPY package*.json ./\nRUN echo \"@fortawesome:registry="
  },
  {
    "path": "LICENSE",
    "chars": 11357,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "Package.resolved",
    "chars": 8877,
    "preview": "{\n  \"pins\" : [\n    {\n      \"identity\" : \"async-http-client\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"h"
  },
  {
    "path": "Package.swift",
    "chars": 952,
    "preview": "// swift-tools-version:5.8\nimport PackageDescription\n\nlet package = Package(\n  name: \"swift-ast-explorer\",\n  platforms: "
  },
  {
    "path": "Public/css/balloon.css",
    "chars": 1532,
    "preview": ".balloon {\n  font-size: 80%;\n  white-space: nowrap;\n  border-radius: 4px;\n  background-color: rgba(85, 85, 85, 0.9);\n  c"
  },
  {
    "path": "Public/css/common.css",
    "chars": 827,
    "preview": ".svg-inline--fa.fa-fw {\n  width: 1em;\n}\n\n.nav-tabs {\n  border-bottom: none;\n}\n\n.dropdown-menu {\n  min-width: 260px;\n  li"
  },
  {
    "path": "Public/css/editor.css",
    "chars": 568,
    "preview": ".CodeMirror {\n  font-family: Menlo, Consolas, \"DejaVu Sans Mono\", \"Ubuntu Mono\", monospace;\n  font-size: 11pt;\n  line-he"
  },
  {
    "path": "Public/css/lookup.css",
    "chars": 450,
    "preview": ".keyword,\n.atSign {\n  color: #c800a4;\n}\n\n.importKeyword {\n  color: #1c00cf;\n}\n\n.stringLiteral {\n  color: #df0002;\n}\n\n.St"
  },
  {
    "path": "Public/css/popover.css",
    "chars": 1817,
    "preview": ".popover {\n  position: absolute;\n  z-index: 1070;\n  font-size: 10pt;\n  box-shadow: 0 8px 24px rgba(140, 149, 159, 0.2);\n"
  },
  {
    "path": "Public/css/table.css",
    "chars": 107,
    "preview": "table.dataTable {\n  margin-top: 0 !important;\n}\n\nth.statistics_count {\n  text-align: initial !important;\n}\n"
  },
  {
    "path": "Public/css/tree_view.css",
    "chars": 2061,
    "preview": ".tree-view {\n  font-family: Menlo, Consolas, \"DejaVu Sans Mono\", \"Ubuntu Mono\", monospace;\n  font-size: 11pt;\n}\n\n.tree-v"
  },
  {
    "path": "Public/css/trivia.css",
    "chars": 189,
    "preview": "#trivia-container span.leading-trivia {\n  background-color: #c8e1c8;\n}\n\n#trivia-container span.trailing-trivia {\n  backg"
  },
  {
    "path": "Public/error.html",
    "chars": 6664,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n  <!-- Simple HttpErrorPages | MIT License | https://github.com/AndiDittrich/Ht"
  },
  {
    "path": "Public/favicons/browserconfig.xml",
    "chars": 255,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n    <msapplication>\n        <tile>\n            <square150x150logo"
  },
  {
    "path": "Public/favicons/site.webmanifest",
    "chars": 444,
    "preview": "{\n    \"name\": \"\",\n    \"short_name\": \"\",\n    \"icons\": [\n        {\n            \"src\": \"/favicons/android-chrome-192x192.pn"
  },
  {
    "path": "Public/index.html",
    "chars": 14929,
    "preview": "<!doctype html>\n<html lang=\"en\">\n\n<head>\n  <meta charset=\"utf-8\">\n\n  <meta name=\"twitter:card\" content=\"summary\" />\n  <m"
  },
  {
    "path": "Public/index.js",
    "chars": 143,
    "preview": "\"use strict\";\n\nimport \"./scss/default.scss\";\nimport \"./css/common.css\";\n\nimport \"./js/icon.js\";\n\nimport { App } from \"./"
  },
  {
    "path": "Public/js/app.js",
    "chars": 9693,
    "preview": "\"use strict\";\n\nimport { Tooltip } from \"bootstrap\";\nimport { Editor } from \"./editor.js\";\nimport { Balloon } from \"./bal"
  },
  {
    "path": "Public/js/balloon.js",
    "chars": 2407,
    "preview": "\"use strict\";\n\nimport \"../css/balloon.css\";\n\nexport class Balloon {\n  constructor() {\n    this.balloon = document.create"
  },
  {
    "path": "Public/js/debounce.js",
    "chars": 199,
    "preview": "\"use strict\";\n\nexport function debounce(cb, delay = 250) {\n  let timeout;\n  return (...args) => {\n    clearTimeout(timeo"
  },
  {
    "path": "Public/js/editor.js",
    "chars": 2165,
    "preview": "\"use strict\";\n\nimport \"codemirror/lib/codemirror.css\";\nimport \"../css/editor.css\";\n\nimport CodeMirror from \"codemirror\";"
  },
  {
    "path": "Public/js/icon.js",
    "chars": 1026,
    "preview": "\"use strict\";\n\nimport { library, dom } from \"@fortawesome/fontawesome-svg-core\";\nimport {\n  faPlay,\n  faEraser,\n  faAlig"
  },
  {
    "path": "Public/js/lookup_view.js",
    "chars": 4951,
    "preview": "\"use strict\";\n\nimport \"../css/lookup.css\";\nimport { Popover } from \"./popover.js\";\n\nexport class LookupView {\n  set erro"
  },
  {
    "path": "Public/js/popover.js",
    "chars": 2192,
    "preview": "\"use strict\";\n\nimport \"../css/popover.css\";\n\nexport class Popover {\n  constructor() {\n    this.popover = document.create"
  },
  {
    "path": "Public/js/statistics_view.js",
    "chars": 1898,
    "preview": "\"use strict\";\n\nimport DataTable from \"datatables.net\";\nimport \"datatables.net-bs5/css/dataTables.bootstrap5.min.css\";\n\ni"
  },
  {
    "path": "Public/js/structure_view.js",
    "chars": 4421,
    "preview": "\"use strict\";\n\nimport { TreeView } from \"./tree_view.js\";\nimport { Popover } from \"./popover.js\";\n\nexport class Structur"
  },
  {
    "path": "Public/js/tree_view.js",
    "chars": 3444,
    "preview": "\"use strict\";\n\nimport \"../css/tree_view.css\";\n\nexport class TreeView {\n  constructor(container, tree) {\n    this.contain"
  },
  {
    "path": "Public/js/trivia_view.js",
    "chars": 7208,
    "preview": "\"use strict\";\n\nimport \"../css/trivia.css\";\nimport { Popover } from \"./popover.js\";\n\nexport class TriviaView {\n  set erro"
  },
  {
    "path": "Public/js/websocket.js",
    "chars": 1244,
    "preview": "\"use strict\";\n\nimport ReconnectingWebSocket from \"reconnecting-websocket\";\n\nexport class WebSocketClient {\n  constructor"
  },
  {
    "path": "Public/robots.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "Public/scss/default.scss",
    "chars": 785,
    "preview": "@import \"bootstrap/scss/functions\";\n@import \"bootstrap/scss/variables\";\n@import \"bootstrap/scss/variables-dark\";\n@import"
  },
  {
    "path": "README.md",
    "chars": 2174,
    "preview": "<p>\n<img src=\"https://img.shields.io/badge/os-macOS/Linux-green.svg?style=flat\" alt=\"macOS/Linux\">\n<a href=\"http://swift"
  },
  {
    "path": "Resources/parsers/50800/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Resources/parsers/50800/Package.resolved",
    "chars": 304,
    "preview": "{\n  \"pins\" : [\n    {\n      \"identity\" : \"swift-syntax\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"https:"
  },
  {
    "path": "Resources/parsers/50800/Package.swift",
    "chars": 793,
    "preview": "// swift-tools-version:5.8\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macOS"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/Main.swift",
    "chars": 663,
    "preview": "import Foundation\n\n@main\nstruct Main {\n  static func main() throws {\n    do {\n      let code = String(decoding: FileHand"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/SyntaxParser.swift",
    "chars": 911,
    "preview": "import Foundation\nimport SwiftSyntax\nimport SwiftOperators\nimport SwiftParser\n\nstruct SyntaxParser {\n  static func parse"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/SyntaxResponse.swift",
    "chars": 131,
    "preview": "import Foundation\n\nstruct SyntaxResponse: Codable {\n  let syntaxHTML: String\n  let syntaxJSON: String\n  let swiftVersion"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/TokenVisitor.swift",
    "chars": 10484,
    "preview": "import Foundation\nimport SwiftSyntax\n\nfinal class TokenVisitor: SyntaxRewriter {\n  var list = [String]()\n  var tree = [T"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/TreeNode.swift",
    "chars": 3801,
    "preview": "import Foundation\n\nfinal class TreeNode: Codable {\n  let id: Int\n  var parent: Int?\n\n  var text: String\n  var range = Ra"
  },
  {
    "path": "Resources/parsers/50800/Sources/parser/Version.swift",
    "chars": 40,
    "preview": "import Foundation\nlet version = \"5.8.1\"\n"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3470,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 10334,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 29452,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 72690,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 137193,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 340654,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-4.html",
    "chars": 11454,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-4.json",
    "chars": 33604,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-5.html",
    "chars": 6780,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-5.json",
    "chars": 18625,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-6.html",
    "chars": 6780,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-1-6.json",
    "chars": 18625,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-1.html",
    "chars": 3470,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-1.json",
    "chars": 10334,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-2.html",
    "chars": 29077,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-2.json",
    "chars": 73012,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-3.html",
    "chars": 136792,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-3.json",
    "chars": 340966,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-4.html",
    "chars": 11454,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-4.json",
    "chars": 33604,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-5.html",
    "chars": 6804,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-5.json",
    "chars": 20068,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-6.html",
    "chars": 6803,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Fixtures/test-2-6.json",
    "chars": 20063,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50800/Tests/Tests/Tests.swift",
    "chars": 13470,
    "preview": "@testable import parser\nimport XCTest\n\nfinal class Tests: XCTestCase {\n  func testParser1() throws {\n    let response = "
  },
  {
    "path": "Resources/parsers/50900/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Resources/parsers/50900/Package.resolved",
    "chars": 304,
    "preview": "{\n  \"pins\" : [\n    {\n      \"identity\" : \"swift-syntax\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"https:"
  },
  {
    "path": "Resources/parsers/50900/Package.swift",
    "chars": 793,
    "preview": "// swift-tools-version:5.9\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macOS"
  },
  {
    "path": "Resources/parsers/50900/Sources/parser/SyntaxParser.swift",
    "chars": 915,
    "preview": "import Foundation\nimport SwiftSyntax\nimport SwiftOperators\nimport SwiftParser\n\nstruct SyntaxParser {\n  static func parse"
  },
  {
    "path": "Resources/parsers/50900/Sources/parser/TokenVisitor.swift",
    "chars": 9757,
    "preview": "import Foundation\n@_spi(RawSyntax) import SwiftSyntax\n\nfinal class TokenVisitor: SyntaxRewriter {\n  var list = [String]("
  },
  {
    "path": "Resources/parsers/50900/Sources/parser/Version.swift",
    "chars": 40,
    "preview": "import Foundation\nlet version = \"5.9.0\"\n"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 31125,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 75537,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 147678,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 368098,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-5.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-5.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-6.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-1-6.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-2.html",
    "chars": 30750,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-2.json",
    "chars": 75828,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-3.html",
    "chars": 147277,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-3.json",
    "chars": 368380,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-5.html",
    "chars": 7093,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-5.json",
    "chars": 20488,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-6.html",
    "chars": 7092,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/50900/Tests/Tests/Fixtures/test-2-6.json",
    "chars": 20484,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Resources/parsers/51000/Package.resolved",
    "chars": 304,
    "preview": "{\n  \"pins\" : [\n    {\n      \"identity\" : \"swift-syntax\",\n      \"kind\" : \"remoteSourceControl\",\n      \"location\" : \"https:"
  },
  {
    "path": "Resources/parsers/51000/Package.swift",
    "chars": 794,
    "preview": "// swift-tools-version:5.10\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macO"
  },
  {
    "path": "Resources/parsers/51000/Sources/parser/Version.swift",
    "chars": 41,
    "preview": "import Foundation\nlet version = \"5.10.0\"\n"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 31125,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 75537,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 147678,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 368098,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-5.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-5.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-6.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-1-6.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-2.html",
    "chars": 30750,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-2.json",
    "chars": 75828,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-3.html",
    "chars": 147277,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-3.json",
    "chars": 368380,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-5.html",
    "chars": 7093,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-5.json",
    "chars": 20488,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-6.html",
    "chars": 7092,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/51000/Tests/Tests/Fixtures/test-2-6.json",
    "chars": 20484,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Package.resolved",
    "chars": 389,
    "preview": "{\n  \"originHash\" : \"8515d5150b83025ad58574845ed771a96d911ed4b25e0cab591227cc70c2eab4\",\n  \"pins\" : [\n    {\n      \"identit"
  },
  {
    "path": "Resources/parsers/60000/Package.swift",
    "chars": 794,
    "preview": "// swift-tools-version:5.10\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macO"
  },
  {
    "path": "Resources/parsers/60000/Sources/parser/Version.swift",
    "chars": 41,
    "preview": "import Foundation\nlet version = \"6.00.0\"\n"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 31125,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 75537,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 147678,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 368098,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-5.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-5.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-6.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-1-6.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-2.html",
    "chars": 30750,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-2.json",
    "chars": 75828,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-3.html",
    "chars": 147277,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-3.json",
    "chars": 368380,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-5.html",
    "chars": 7093,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-5.json",
    "chars": 20488,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-6.html",
    "chars": 7092,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60000/Tests/Tests/Fixtures/test-2-6.json",
    "chars": 20484,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Resources/parsers/60100/Package.resolved",
    "chars": 389,
    "preview": "{\n  \"originHash\" : \"9c1380812b25a7a61cbbf113c12ca68af64c132e23b44e1f060ec564652daef2\",\n  \"pins\" : [\n    {\n      \"identit"
  },
  {
    "path": "Resources/parsers/60100/Package.swift",
    "chars": 794,
    "preview": "// swift-tools-version:5.10\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macO"
  },
  {
    "path": "Resources/parsers/60100/Sources/parser/Version.swift",
    "chars": 41,
    "preview": "import Foundation\nlet version = \"6.01.0\"\n"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 31125,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 75537,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 147678,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 368098,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-5.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-5.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-6.html",
    "chars": 7069,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-1-6.json",
    "chars": 19070,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-2.html",
    "chars": 30750,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-2.json",
    "chars": 75828,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-3.html",
    "chars": 147277,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-3.json",
    "chars": 368380,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-4.html",
    "chars": 12647,
    "preview": "<span class='SourceFile' data-title='struct␣Result&lt;␣{{↲␣␣let␣text:␣String↲␣␣let␣someOtherThing:␣String↲}' data-conten"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-4.json",
    "chars": 36273,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 4,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-5.html",
    "chars": 7093,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣*␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-5.json",
    "chars": 20488,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-6.html",
    "chars": 7092,
    "preview": "<span class='SourceFile' data-title='if␣a␣+␣b␣×␣c␣{↲␣␣return↲}' data-content='SourceFileSyntax' data-type='Syntax' data-"
  },
  {
    "path": "Resources/parsers/60100/Tests/Tests/Fixtures/test-2-6.json",
    "chars": 20484,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 2,\n      \"endRow\": 3,\n      \"graphemeEndColumn\": 2,\n      \"grapheme"
  },
  {
    "path": "Resources/parsers/60200/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "Resources/parsers/60200/Package.resolved",
    "chars": 389,
    "preview": "{\n  \"originHash\" : \"ea0acfa5036e50d9e86176f9c8bdc2453fc3789f6df5f40e20fe5d5ce712a71e\",\n  \"pins\" : [\n    {\n      \"identit"
  },
  {
    "path": "Resources/parsers/60200/Package.swift",
    "chars": 794,
    "preview": "// swift-tools-version:5.10\nimport PackageDescription\n\nlet package = Package(\n  name: \"parser\",\n  platforms: [\n    .macO"
  },
  {
    "path": "Resources/parsers/60200/Sources/parser/Version.swift",
    "chars": 41,
    "preview": "import Foundation\nlet version = \"6.02.0\"\n"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-1.html",
    "chars": 3884,
    "preview": "<span class='SourceFile' data-title='let␣number␣=␣0' data-content='SourceFileSyntax' data-type='Syntax' data-range='{\"st"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-1.json",
    "chars": 11511,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 15,\n      \"endRow\": 1,\n      \"graphemeEndColumn\": 15,\n      \"graphe"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-2.html",
    "chars": 31125,
    "preview": "<span class='SourceFile' data-title='var␣temperatureInFahrenheit␣=␣90↲↲if␣temperatureInFahrenheit␣&lt;=␣32␣{↲␣␣print(&qu"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-2.json",
    "chars": 75537,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 62,\n      \"endRow\": 11,\n      \"graphemeEndColumn\": 62,\n      \"graph"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-3.html",
    "chars": 147678,
    "preview": "<span class='SourceFile' data-title='import␣Foundation↲↲struct␣BlackjackCard␣{↲␣␣//␣nested␣Suit␣enumeration↲␣␣enum␣Suit:"
  },
  {
    "path": "Resources/parsers/60200/Tests/Tests/Fixtures/test-1-3.json",
    "chars": 368098,
    "preview": "[\n  {\n    \"id\": 0,\n    \"range\": {\n      \"endColumn\": 1,\n      \"endRow\": 45,\n      \"graphemeEndColumn\": 1,\n      \"graphem"
  }
]

// ... and 175 more files (download for full content)

About this extraction

This page contains the full source code of the kishikawakatsumi/swift-ast-explorer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 375 files (11.4 MB), approximately 3.0M tokens, and a symbol index with 100 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!