Full Code of voloko/sdoc for AI

main ee479f9c1ba3 cached
45 files
300.6 KB
78.4k tokens
776 symbols
1 requests
Download .txt
Showing preview only (316K chars total). Download the full file or copy to clipboard to get everything.
Repository: voloko/sdoc
Branch: main
Commit: ee479f9c1ba3
Files: 45
Total size: 300.6 KB

Directory structure:
gitextract_kxlx5hx4/

├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   └── workflows/
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│   └── sdoc
├── config.ru
├── lib/
│   ├── rdoc/
│   │   ├── discover.rb
│   │   └── generator/
│   │       └── template/
│   │           └── rails/
│   │               ├── _context.rhtml
│   │               ├── _file_nav.rhtml
│   │               ├── _head.rhtml
│   │               ├── _index_nav.rhtml
│   │               ├── _module_nav.rhtml
│   │               ├── _panel.rhtml
│   │               ├── class.rhtml
│   │               ├── file.rhtml
│   │               ├── index.rhtml
│   │               └── resources/
│   │                   ├── css/
│   │                   │   ├── highlight.css
│   │                   │   └── main.css
│   │                   └── js/
│   │                       ├── .gitattributes
│   │                       ├── @hotwired--turbo.js
│   │                       ├── main.js
│   │                       └── search.js
│   ├── sdoc/
│   │   ├── generator.rb
│   │   ├── helpers/
│   │   │   └── git.rb
│   │   ├── helpers.rb
│   │   ├── name_list.rb
│   │   ├── postprocessor.rb
│   │   ├── rdoc_monkey_patches.rb
│   │   ├── renderer.rb
│   │   ├── search_index.rb
│   │   └── version.rb
│   └── sdoc.rb
├── netlify.toml
├── sdoc.gemspec
└── spec/
    ├── helpers_spec.rb
    ├── postprocessor_spec.rb
    ├── rdoc_generator_spec.rb
    ├── rdoc_monkey_patches_spec.rb
    ├── renderer_spec.rb
    ├── search_index_spec.rb
    └── spec_helper.rb

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

================================================
FILE: .devcontainer/devcontainer.json
================================================
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/ruby
{
	"name": "sdoc",
	// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
	"image": "ghcr.io/rails/devcontainer/images/ruby:3.4.5",
	"features": {
		"ghcr.io/devcontainers/features/github-cli:1": {}
	}

	// Features to add to the dev container. More info: https://containers.dev/features.
	// "features": {},

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Use 'postCreateCommand' to run commands after the container is created.
	// "postCreateCommand": "ruby --version",

	// Configure tool-specific properties.
	// "customizations": {},

	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
	// "remoteUser": "root"
}


================================================
FILE: .github/workflows/test.yml
================================================
name: Tests

on:
  push:
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 0 * * *'

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        ruby:
          - '2.7'
          - '3.0'
          - '3.1'
          - '3.2'
          - '3.3'
          - '3.4'
          - 'ruby-head'

    steps:
      - uses: actions/checkout@v4

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true

      - name: Test
        run: |
          bundle exec rake
        continue-on-error: true


================================================
FILE: .gitignore
================================================
*.gem
.bundle
pkg
doc
/test.rb
Gemfile.lock
/.rake_tasks~
/*.gem
/rails/
/ruby/


================================================
FILE: CHANGELOG.md
================================================
Main (3.0.0.alpha)
==================

* [#198](https://github.com/rails/sdoc/pull/198) Bump version to 3.0.0.alpha [@zzak](https://github.com/zzak)
* [#197](https://github.com/rails/sdoc/pull/197) Remove sdoc-merge and sdoc template [@zzak](https://github.com/zzak)
* [#195](https://github.com/rails/sdoc/pull/195) Replace turbolinks with turbo v7.3.0 [@zzak](https://github.com/zzak)
* [#200](https://github.com/rails/sdoc/pull/200) Add canonical url link to all pages [@zzak](https://github.com/zzak)
* [#222](https://github.com/rails/sdoc/pull/222) Add NameList for building a static file of classes and methods [@zzak](https://github.com/zzak)
* [#206](https://github.com/rails/sdoc/pull/206) Move file links to the footer [@p8](https://github.com/p8)
* [#237](https://github.com/rails/sdoc/pull/237) Hide scrollbar for unscrollable code snippets [@jonathanhefner](https://github.com/jonathanhefner)
* [#239](https://github.com/rails/sdoc/pull/239) Replace highlight.js with Rouge gem [@jonathanhefner](https://github.com/jonathanhefner)
* [#242](https://github.com/rails/sdoc/pull/242) Use Rouge to highlight method source code [@jonathanhefner](https://github.com/jonathanhefner)
* [#243](https://github.com/rails/sdoc/pull/243) Enable horizontal scrollbar for method source code [@jonathanhefner](https://github.com/jonathanhefner)
* [#251](https://github.com/rails/sdoc/pull/251) Move alias listing closer to method name [@jonathanhefner](https://github.com/jonathanhefner)
* [#252](https://github.com/rails/sdoc/pull/252) Replace source code toggler JavaScript with `<details>` [@jonathanhefner](https://github.com/jonathanhefner)
* [#253](https://github.com/rails/sdoc/pull/253) Version links to Rails guides [@jonathanhefner](https://github.com/jonathanhefner)
* [#254](https://github.com/rails/sdoc/pull/254) Unlink unintentional autolinked code ref links [@jonathanhefner](https://github.com/jonathanhefner)
* [#255](https://github.com/rails/sdoc/pull/255) Style unstyled code ref links [@jonathanhefner](https://github.com/jonathanhefner)
* [#260](https://github.com/rails/sdoc/pull/260) Include site title in page titles [@jonathanhefner](https://github.com/jonathanhefner)
* [#261](https://github.com/rails/sdoc/pull/261) Include project name and version in `og:title` [@jonathanhefner](https://github.com/jonathanhefner)
* [#262](https://github.com/rails/sdoc/pull/262) Refine meta description [@jonathanhefner](https://github.com/jonathanhefner)
* [#265](https://github.com/rails/sdoc/pull/265) Add required Open Graph meta tags [@jonathanhefner](https://github.com/jonathanhefner)
* [#266](https://github.com/rails/sdoc/pull/266) Add `article:modified_time` meta tag [@jonathanhefner](https://github.com/jonathanhefner)
* [#268](https://github.com/rails/sdoc/pull/268) Add initial dark mode support [@p8](https://github.com/p8)
* [#279](https://github.com/rails/sdoc/pull/279) Redesign "Appears in" file list [@jonathanhefner](https://github.com/jonathanhefner)
* [#280](https://github.com/rails/sdoc/pull/280) Redesign banner and mobile menu bar [@jonathanhefner](https://github.com/jonathanhefner)
* [#283](https://github.com/rails/sdoc/pull/283), [#336](https://github.com/rails/sdoc/pull/336) Rework typography [@jonathanhefner](https://github.com/jonathanhefner)
* [#286](https://github.com/rails/sdoc/pull/286) Render breadcrumb links for module's parents [@jonathanhefner](https://github.com/jonathanhefner)
* [#287](https://github.com/rails/sdoc/pull/287) Generate uniform `<h1>` headings for all modules [@jonathanhefner](https://github.com/jonathanhefner)
* [#291](https://github.com/rails/sdoc/pull/291) Remove keyboard shortcuts that use meta keys [@jonathanhefner](https://github.com/jonathanhefner)
* [#294](https://github.com/rails/sdoc/pull/294) Remove version badge [@jonathanhefner](https://github.com/jonathanhefner)
* [#298](https://github.com/rails/sdoc/pull/298) Rewrite search [@jonathanhefner](https://github.com/jonathanhefner)
* [#315](https://github.com/rails/sdoc/pull/315) Replace navigation tree [@jonathanhefner](https://github.com/jonathanhefner)
* [#319](https://github.com/rails/sdoc/pull/319) Rework method spotlight effect [@jonathanhefner](https://github.com/jonathanhefner)
* [#320](https://github.com/rails/sdoc/pull/320) Remove jQuery [@jonathanhefner](https://github.com/jonathanhefner)
* [#322](https://github.com/rails/sdoc/pull/322) Use `type="search"` for search input [@jonathanhefner](https://github.com/jonathanhefner)
* [#323](https://github.com/rails/sdoc/pull/323) Update favicon [@jonathanhefner](https://github.com/jonathanhefner)
* [#345](https://github.com/rails/sdoc/pull/345) Version explicit links to `api.rubyonrails.org` [@jonathanhefner](https://github.com/jonathanhefner)
* [#356](https://github.com/rails/sdoc/pull/356) Redesign "Constants" section [@jonathanhefner](https://github.com/jonathanhefner)
* [#357](https://github.com/rails/sdoc/pull/357) Support permalinking constants [@jonathanhefner](https://github.com/jonathanhefner)
* [#358](https://github.com/rails/sdoc/pull/358) Add constants to search index [@jonathanhefner](https://github.com/jonathanhefner)
* [#370](https://github.com/rails/sdoc/pull/370) Add attributes to search index [@earlopain](https://github.com/earlopain)

2.6.1
=====

* [#194](https://github.com/rails/sdoc/pull/194) Remove `text-align: justify` on paragraphs [@zzak](https://github.com/zzak)

2.6.0
=====

* #193 Add support for Ruby 3.2 as File.exists? has been removed [@sato11](https://github.com/sato11)

2.5.0
=====

* #192 Add padding and rounded borders to code examples [@p8](https://github.com/p8)
* #191 Add css class for constant [@p8](https://github.com/p8)
* #189 `index_path` should handle a nil `main_page` [@ghiculescu](https://github.com/ghiculescu)

2.4.0
=====

* #187 Allow setting CSS based version badge [@p8](https://github.com/p8)

2.3.2
=====

* #184 Add support for rdoc 6.4.0 [@p8](https://github.com/p8)

2.3.1
=====

* #183 Remove unsupported browser detection  [@p8](https://github.com/p8)
* #182 Use window.location instead of Turbolinks.visit if protocol is 'file:' [@p8](https://github.com/p8)

2.3.0
=====

* #178 Don't use rdoc 6.4.0 for now [@p8](https://github.com/p8)
* #177 Remove rake version constraint for ruby head [@p8](https://github.com/p8)
* #176 Make sidepanel work with relative paths/URLs [@p8](https://github.com/p8)
* #175 Avoid displaying source toggler for ghost methods [Robin Dupret](https://github.com/robin850)
* #174 Suppress unused variable warnings [Masataka Pocke Kuwabara](https://github.com/pocke)

2.2.0
=====

* #161 Add 'skip to content' link and improve shortcut keys [@MikeRogers0](https://github.com/MikeRogers0)
* #170 Fix link hovers in headings [@tlatsas](https://github.com/tlatsas)
* #169 Fix clearing search results [@mikdiet](https://github.com/mikdiet)
* #167 Update Merge script to work with sdoc v2 [@mikdiet](https://github.com/mikdiet)
* #160 Remove outline from reset stylesheet [@p8](https://github.com/p8)
* #159 Remove TAB override in panel [@p8](https://github.com/p8)
* #157 Move to GitHub action for tests [@MikeRogers0](https://github.com/MikeRogers0)
* #155 Fix Ctrl+C copying [Jan Schär](https://github.com/jscissr)

2.1.0
=====

* #154 Make panel responsive for mobile [@MikeRogers0](https://github.com/MikeRogers0) and [@p8](https://github.com/p8)
* #153 Add viewport metatag to views for improved Lighthouse score. [@MikeRogers0](https://github.com/MikeRogers0)
* #150 Use semantic headers for better SEO [@p8](https://github.com/p8)

2.0.4
=====

* #149 Using HTML5 doctype across all HTML files. [@MikeRogers0](https://github.com/MikeRogers0)
* #148 Fix overflow CSS property of panel elements. [@cveneziani](https://github.com/cveneziani)

2.0.3
=====

* #147 Use @options.title for the index [@p8](https://github.com/p8)

2.0.2
=====

* Remove accidental rack inclusion in gemspec

2.0.1
=====

* #142 Fix arrow icons for selected panel items [@p8](https://github.com/p8)
* #141 Always use only one metatag for keywords [@p8](https://github.com/p8)
* #140 Use h2 instead of h1 for banner header [@p8](https://github.com/p8)

2.0.0
=====

* #137 Replace frames based implementation with a css [@p8](https://github.com/p8)
* #132 Deprecate safe_level of ERB.new in Ruby 2.6

1.1.0
=====

* #138 - Fix panel header overflow on Chrome
* 39e6cae9 - Display version using `-v` or `--version` flags

1.0.0
=====

* #110 - Strip out HTML tags from search results description
* #109 - Add basic SEO tags
* #108 - Tiny refresh of the Rails theme
* e6f02b91 - Remove the jQuery effect library
* 73ace366 - Remove the `--without-search` option
* b1d429f2 - Produce HTML 5 output
* 38d06095 - Support only RDoc 5 and up
* #96 - Require at least Ruby 1.9.3

0.4.2
=====

[Compare v0.4.1...v0.4.2](https://github.com/voloko/sdoc/compare/v0.4.1...v0.4.2)

0.4.1
=====

[Compare v0.4.0...v0.4.1](https://github.com/voloko/sdoc/compare/v0.4.0...v0.4.1)

Breaking Changes
----------------

None.

Enhancements
------------

- 65e46cb2 Unordered lists inside ordered ones render ordered
- SDoc::VERSION
  - 2fe1a7b8 Move version to separate file, remove require_relative from gemspec
  - 97e1eda8 Push ./lib to $LOAD_PATH for require SDoc::VERSION
  - ad0a7e1e Initialize SDoc namespace in main file

Bug Fixes
---------

- 926ff732 Remove redundancy < 5.0 from rdoc dependency specification
- db99e402 Remove code tags styling under pre elements
- a1d7e211 Follow up of #68
- bffc93ef Relax JSON dependency to ~> 1.7, >= 1.7.7
- 404dceb9 GH-72: Extra `<p>` tags appear in results snippet

0.4.0
=====

[Compare v0.3.20...v0.4.0](https://github.com/voloko/sdoc/compare/v0.3.20...v0.4.0)

No friendly log for this version yet, but PRs are welcome!


================================================
FILE: Gemfile
================================================
source "https://rubygems.org"

gemspec

gem "rack", "~> 3.0"
gem "rake"
gem "hoe"
gem "minitest"
gem "puma"

if ENV["rdoc"] == "master"
  gem "rdoc", :github => "ruby/rdoc"
end

gem "importmap-rails"
gem "railties"


================================================
FILE: LICENSE
================================================
Copyright (c) 2014 Vladimir Kolesnikov, and Nathan Broadbent
Copyright (c) 2014-2017 Zachary Scott

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



Darkfish RDoc HTML Generator

Copyright (c) 2007, 2008, Michael Granger. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the author/s, nor the names of the project's
  contributors may be used to endorse or promote products derived from this
  software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


RDoc is copyrighted free software.

You can redistribute it and/or modify it under either the terms of the GPL
version 2 (see the file GPL), or the conditions below:

  1. You may make and give away verbatim copies of the source form of the
     software without restriction, provided that you duplicate all of the
     original copyright notices and associated disclaimers.

  2. You may modify your copy of the software in any way, provided that
     you do at least ONE of the following:

       a) place your modifications in the Public Domain or otherwise
          make them Freely Available, such as by posting said
          modifications to Usenet or an equivalent medium, or by allowing
          the author to include your modifications in the software.

       b) use the modified software only within your corporation or
          organization.

       c) give non-standard binaries non-standard names, with
          instructions on where to get the original software distribution.

       d) make other distribution arrangements with the author.

  3. You may distribute the software in object code or binary form,
     provided that you do at least ONE of the following:

       a) distribute the binaries and library files of the software,
          together with instructions (in the manual page or equivalent)
          on where to get the original distribution.

       b) accompany the distribution with the machine-readable source of
          the software.

       c) give non-standard binaries non-standard names, with
          instructions on where to get the original software distribution.

       d) make other distribution arrangements with the author.

  4. You may modify and include the part of the software into any other
     software (possibly commercial).  But some files in the distribution
     are not written by the author, so that they are not under these terms.

     For the list of those files and their copying conditions, see the
     file LEGAL.

  5. The scripts and library files supplied as input to or produced as
     output from the software do not automatically fall under the
     copyright of the software, but belong to whomever generated them,
     and may be sold commercially, and may be aggregated with this
     software.

  6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
     IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     PURPOSE.


================================================
FILE: README.md
================================================
# SDoc

[![Tests](https://github.com/rails/sdoc/actions/workflows/test.yml/badge.svg)](https://github.com/rails/sdoc/actions/workflows/test.yml)

**Powering http://api.rubyonrails.org/**

### What is sdoc?

SDoc is an HTML template built on top of the RDoc documentation generator for Ruby code.

### Getting Started

```bash
# Install the gem
gem install sdoc

# Generate documentation for 'projectdir'
sdoc projectdir
```

### sdoc

`sdoc` is simply a wrapper for the `rdoc` command line tool. See `sdoc --help` for more details.

When using the `sdoc` command, `--fmt` is set to `shtml` by default. The default template (or `-T` option) is set to `shtml`, but you can also use the `direct` template when generating documentation.

Example:

```bash
sdoc -o doc/rails -T direct rails
```

### Rake Task

If you want, you can setup a task in your `Rakefile` for generating your project's documentation via the `rake rdoc` command.

```ruby
# Rakefile
require 'sdoc' # and use your RDoc task the same way you used it before
require 'rdoc/task' # ensure this file is also required in order to use `RDoc::Task`

RDoc::Task.new do |rdoc|
  rdoc.rdoc_dir = 'doc/rdoc'      # name of output directory
  rdoc.options << '--format=sdoc' # explicitly set the sdoc generator
  rdoc.template = 'rails'         # template used on api.rubyonrails.org
end
```

NOTE: If you don't set `template` the default "sdoc" template is chosen, with a lighter color scheme.

Now you can execute this command with `rake rdoc`, to compile the documentation for the current project directory.

Alternatively you can pass this command a path to the project you wish to compile: `rake rdoc path/to/project`.

### RDoc

As mentioned before, SDoc is built on top of the RDoc project.

If you notice any bugs in the output of your documentation, it may be RDoc's fault and should be [reported upstream](https://github.com/ruby/rdoc/issues/new).

An example of an SDoc bug would be:

* Error or warning in JavaScript or HTML found in your browser
* Generation fails with some exception (likely due to incompatibility with RDoc)

Please feel free to still report issues here for both projects, especially if you aren't sure. We will try to redirect to the proper place if necessary.

## Contributing

If you'd like to contribute you can generate the Rails main branch documentation by running:

```bash
bundle exec rake test:rails
```

You can generate the Ruby default branch documentation by running:

```bash
bundle exec rake test:ruby
```

The generated documentation will be put into `doc/public` directory.
To view the just generated documentation start up a rack application by running:

```bash
bundle exec rackup config.ru
```

Then open http://localhost:9292 in the browser to view the documentation.

### Who?

* Vladimir Kolesnikov ([voloko](https://github.com/voloko))
* Nathan Broadbent ([ndbroadbent](https://github.com/ndbroadbent))
* Petrik de Heus ([p8](https://github.com/p8))
* ([zzak](https://github.com/zzak))


================================================
FILE: Rakefile
================================================
require 'bundler'
Bundler::GemHelper.install_tasks

require 'rake/testtask'

Rake::TestTask.new do |t|
  t.pattern = "spec/*_spec.rb"
  t.libs << "spec"
end

task :default => :test
task :spec => :test

require 'sdoc'
require 'rdoc/task'
require 'rails/api/task'

rails = File.expand_path "rails"
ruby = File.expand_path "ruby"

directory rails do
  sh "git clone --depth=1 https://github.com/rails/rails"
end

directory ruby do
  sh "git clone --depth=1 https://github.com/ruby/ruby"
end

class RailsTask < Rails::API::EdgeTask
  def configure_sdoc
    options << "--root" << "rails"
    super
    self.title = nil # Use default title for local testing.
  end

  def rails_version
    Dir.chdir "rails" do
      super
    end
  end

  def api_dir
    "doc/rails"
  end

  def component_root_dir(component)
    File.join("rails", component)
  end

  def setup_horo_variables
    super

    ENV["HORO_BADGE_VERSION"] ||= "edge" if ENV["HORO_PROJECT_VERSION"]&.include?("@")

    if ENV['NETLIFY']
      ENV['HORO_CANONICAL_URL'] = ENV.fetch('DEPLOY_PRIME_URL', 'https://edgeapi.rubyonrails.org')
    end
  end
end

namespace :test do
  desc 'Deletes all generated test documentation'
  task :reset_docs do
    FileUtils.remove_dir(File.expand_path('doc'), force: true)
  end

  desc 'Generates test rails documentation'
  task :rails => [rails, :generate_rails] do
    FileUtils.mv(
      File.expand_path('rails/doc/rails'),
      File.expand_path('doc/public')
    )
  end

  RailsTask.new(:generate_rails)

  desc 'Generates test ruby documentation'
  task :ruby => [ruby, :generate_ruby] do
    FileUtils.mv(
      File.expand_path('doc/ruby'),
      File.expand_path('doc/public')
    )
  end

  RDoc::Task.new(:generate_ruby) do |rdoc|
    rdoc.rdoc_dir = 'doc/ruby'
    rdoc.generator = 'sdoc'
    rdoc.template = 'rails'
    rdoc.title = 'Ruby'
    rdoc.main = 'ruby/README.md'

    rdoc.rdoc_files.include("ruby/")
  end
end

ASSETS_PATH = "lib/rdoc/generator/template/rails/resources"

desc "Download and vendor JavaScript assets"
task :vendor_javascript do
  module Importmap; end
  require "importmap/packager"

  packager = Importmap::Packager.new(vendor_path: "#{ASSETS_PATH}/js")
  imports = packager.import("@hotwired/turbo", from: "unpkg")
  imports.each do |package, url|
    puts %(Vendoring "#{package}" to #{packager.vendor_path}/#{package}.js via download from #{url})
    packager.download(package, url)
  end
end


================================================
FILE: bin/sdoc
================================================
#!/usr/bin/env ruby
require 'sdoc'

begin
  ARGV.unshift('--format=sdoc') if ARGV.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty?
  r = RDoc::RDoc.new
  r.document ARGV
rescue SystemExit
  raise
rescue Exception => e
  if $DEBUG_RDOC then
    $stderr.puts e.message
    $stderr.puts "#{e.backtrace.join "\n\t"}"
    $stderr.puts
  elsif Interrupt === e then
    $stderr.puts
    $stderr.puts 'Interrupted'
  else
    $stderr.puts "uh-oh! RDoc had a problem:"
    $stderr.puts e.message
    $stderr.puts
    $stderr.puts "run with --debug for full backtrace"
  end

  exit 1
end


================================================
FILE: config.ru
================================================
# Rack application for serving the documentation locally.
# After generating the documentation run:
#
#   bundle exec rackup config.ru
#
require 'bundler/setup'

root = "doc/public"
unless Dir.exist?(root)
  puts <<~MESSAGE
    Could not find any docs in #{root}.
    Run the following command to generate sample documentation:
      bundle exec rake test:rails
  MESSAGE
  exit
end

require "rack/static"
use Rack::Static,
  :urls => ["/files", "/images", "/js", "/css", "/panel", "/i", "/fonts", "/classes", "/ruby", "/rails"],
  :root => root
run lambda { |env|
  [
    200,
    {
      'content-type'  => 'text/html',
      'cache-control' => 'public, max-age=86400'
    },
    File.open("#{root}/index.html", File::RDONLY)
  ]
}


================================================
FILE: lib/rdoc/discover.rb
================================================
begin
  gem 'rdoc', '>= 5.0'
  require_relative "../sdoc" unless defined?(SDoc)
rescue Gem::LoadError
end


================================================
FILE: lib/rdoc/generator/template/rails/_context.rhtml
================================================
<div id="context">
  <% unless (description = @context.description).empty? %>
    <div class="description">
      <%= description %>
    </div>
  <% end %>


  <%# File only: requires %>
  <% unless @context.requires.empty? %>
    <h2 class="content__divider">Required Files</h2>
    <ul>
      <% @context.requires.each do |req| %>
        <li><%= full_name_for req.name %></li>
      <% end %>
    </ul>
  <% end %>


  <%# Module only: ancestors %>
  <% unless @context.is_a?(RDoc::TopLevel) || (ancestors = module_ancestors(@context)).empty? %>
    <h2 class="content__divider">Inherits From</h2>
    <ul>
      <% ancestors.each do |kind, ancestor| %>
        <li>
          <span class="kind"><%= kind %></span>
          <%= ancestor.is_a?(String) ? full_name_for(ancestor) : link_to(ancestor) %>
        </li>
      <% end %>
    </ul>
  <% end %>


  <% sections = @context.sections.select { |s| s.title }.sort_by{ |s| s.title.to_s } %>
  <% unless sections.empty? then %>
    <!-- Sections -->
    <h2 class="content__divider">Sections</h2>
    <ul>
      <% sections.each do |section| %>
        <li><%= link_to h(section.title), "##{section.aref}" %></li>
      <% end %>
    </ul>
  <% end %>



  <% @context.each_section do |section, constants, attributes| %>

    <% if section.title then %>
      <div class="content__section-title" id="<%= h section.aref %>">
        <%= h section.title %>
      </div>
    <% end %>

    <%= description_for section %>

    <!-- Constants -->
    <% unless constants.empty? %>
      <h2 class="content__divider">Constants</h2>
      <% constants.each do |constant| %>
        <div class="constant" id="<%= constant.aref %>">
          <div class="constant__name permalink-container">
            <h3><%= short_name_for constant %></h3>
            <%= link_to %(<img src="/i/link.svg" alt="Permalink">), constant,
                  class: "permalink", title: "Permalink" %>
          </div>
          <%= description_for constant %>
          <div class="constant__source">
            <pre class="source-code"><code class="ruby"><%= h constant.value %></code></pre>
          </div>
        </div>
      <% end %>
    <% end %>

    <% unless attributes.empty? %>
      <!-- Section attributes -->
      <h2 class="content__divider">Attributes</h2>
      <table border='0' cellpadding='5'>
        <% attributes.each do |attrib| %>
          <tr valign='top' id='<%= attrib.aref %>'>
            <td class='attr-rw'>
              [<%= attrib.rw %>]
            </td>
            <td class='attr-name'><%= short_name_for attrib %></td>
            <td class='attr-desc'><%= attrib.description.strip %></td>
          </tr>
        <% end %>
      </table>
    <% end %>

    <!-- Methods -->
    <%
      @context.methods_by_type(section).each do |type, visibilities|
        next if visibilities.empty?

        visibilities.each do |visibility, methods|
          next if methods.empty?
    %>
      <h2 class="content__divider"><%= visibility.to_s.capitalize %> <%= type %> methods</h2>
      <% methods.each do |method| %>
        <div class="method" id="<%= method.aref %>">
          <div class="method__signature permalink-container">
            <h3><%= method_signature method %></h3>
            <%= link_to %(<img src="/i/link.svg" alt="Permalink">), method,
                  class: "permalink", title: "Permalink" %>
          </div>

          <% unless method.aliases.empty? %>
            <p class="method__aka">
              Also aliased as:
              <%# Sometimes a parent cannot be determined. See ruby/rdoc@85ebfe13dc. %>
              <%= method.aliases.map { |aka| link_to_if aka.parent, short_name_for(aka), aka }.join(", ") %>.
            </p>
          <% end %>

          <% if alias_for = method.is_alias_for then %>
            <p class="method__aka">
              Alias for:
              <%= link_to short_name_for(alias_for), alias_for %>.
            </p>
          <% end %>

          <%= description_for method %>

          <% source_code, source_url = method_source_code_and_url(method) %>
          <% if source_code %>
            <details class="method__source">
              <summary>
                <span class="label">Source code</span>
                <% if source_url %>
                  <%= link_to_external "GitHub", source_url %>
                <% end %>
              </summary>

              <pre class="source-code"><code class="ruby"><%= source_code %></code></pre>
            </details>
          <% elsif source_url %>
            <p class="method__source"><%= link_to_external "GitHub", source_url %></p>
          <% end %>
        </div>
      <% end %><%# methods.each %>
    <% end %><%# visibilities.each %>
    <% end %><%# context.methods_by_type %>
  <% end %><%# context.each_section %>

  <% unless @context.classes_and_modules.empty? %>
    <!-- Namespace -->
    <h2 id="namespace" class="content__divider">Namespace</h2>
    <ul>
      <% @context.classes_and_modules.sort.each do |mod| %>
        <li><%= link_to mod %></li>
      <% end %>
    </ul>
  <% end %>
</div>


================================================
FILE: lib/rdoc/generator/template/rails/_file_nav.rhtml
================================================
<% if @context.text? %>
  <div class="nav__heading">Outline</div>
  <div class="nav__outline">
    <%= outline(@context) %>
  </div>
<% else %>
  <% @context.each_classmodule do |rdoc_module| %>
    <%= button_to_search rdoc_module %>
  <% end %>
<% end %>


================================================
FILE: lib/rdoc/generator/template/rails/_head.rhtml
================================================
<%= base_tag_for_context(@context) %>

<link rel="preload" href="/fonts/Bitter-Roman.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/Bitter-Italic.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/Jost-Roman.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/Jost-Italic.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/RobotoMono-Roman.woff2" as="font" type="font/woff2" crossorigin>

<link rel="modulepreload" href="/js/search-index.js">
<link rel="modulepreload" href="/js/search.js">

<link rel="stylesheet" href="/css/main.css" type="text/css" media="screen" />
<link rel="stylesheet" href="/css/highlight.css" type="text/css" media="screen" />

<script src="/js/main.js" type="module"></script>
<script src="/js/@hotwired--turbo.js" type="module"></script>

<% if canonical = canonical_url(@context) %>
<link rel="canonical" href="<%= canonical %>" />
<meta property="og:url" content="<%= canonical %>">
<meta property="og:image" content="<%= canonical_url("/i/logo.svg") %>">
<% end %>
<meta property="og:type" content="article">
<meta property="article:modified_time" content="<%= og_modified_time %>">
<% if description = page_description(@context.description) %>
<meta name="description" property="og:description" content="<%= description %>">
<% end %>


================================================
FILE: lib/rdoc/generator/template/rails/_index_nav.rhtml
================================================
<div class="nav__heading">Outline</div>
<div class="nav__outline">
  <%= outline(@context) %>
</div>

<% unless (modules = top_modules(@context.store)).empty? %>
  <div class="nav__heading">Modules</div>
  <ul class="nav__list">
    <% modules.each do |rdoc_module| %>
      <li><%= link_to rdoc_module %></li>
    <% end %>
  </ul>
<% end %>

<% unless (extensions = core_extensions(@context.store)).empty? %>
  <div class="nav__heading">Core Extensions</div>
  <ul class="nav__list">
    <% extensions.each do |rdoc_module| %>
      <li><%= link_to rdoc_module %></li>
    <% end %>
  </ul>
<% end %>


================================================
FILE: lib/rdoc/generator/template/rails/_module_nav.rhtml
================================================
<% unless @context.classes_and_modules.empty? %>
  <a href="#namespace" class="namespace-link"><%= short_name_for(@context) %> namespace</a>
<% end %>
<%= button_to_search @context, display_name: short_name_for(@context) %>

<% if outline = outline(@context) %>
  <div class="nav__heading">Outline</div>
  <div class="nav__outline">
    <%= outline %>
  </div>
<% end %>

<% unless (constants = @context.constants).empty? %>
  <div class="nav__heading">Constants</div>
  <ul class="nav__list">
    <% constants.sort.each do |rdoc_constant| %>
      <li><%= link_to short_name_for(rdoc_constant), rdoc_constant %></li>
    <% end %>
  </ul>
<% end %>

<% unless (methods = module_methods(@context)).empty? %>
  <div class="nav__heading">Methods</div>
  <ul class="nav__list">
    <% methods.each do |rdoc_method| %>
      <li><%= link_to short_name_for(rdoc_method), rdoc_method,
                class: "ref-link nav__method-link#{"--singleton" if rdoc_method.singleton}" %></li>
    <% end %>
  </ul>
<% end %>


================================================
FILE: lib/rdoc/generator/template/rails/_panel.rhtml
================================================
<nav id="panel" class="panel">
  <div class="banner">
    <div class="banner__segment">
      <label class="banner__menu-button" for="panel__state"></label>
    </div>
    <div class="banner__segment">
      <a class="banner__logo" href="/"><img src="/i/logo.svg" alt="<%= project_name %>"></a>
      <span class="banner__version" title="<%= project_git_head %>"><%= project_version %></span>
    </div>
  </div>

  <input id="panel__state" type="checkbox">

  <div class="panel__tray">
    <input id="search" class="panel__search" type="search"
      tabindex="-1" autocomplete="off" autosave="searchdoc"
      placeholder="Search (/) for a class, method, ..."
      data-turbo-permanent>

    <div id="results" class="panel__results" data-turbo-permanent></div>

    <div class="panel__nav content">
      <% yield if block_given? %>
    </div>
  </div>
</nav>


================================================
FILE: lib/rdoc/generator/template/rails/class.rhtml
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="<%= @options.charset %>">
    <title><%= page_title @context.full_name %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <% inline "_head.rhtml" %>

    <meta property="og:title" value="<%= og_title @context.full_name %>">
</head>

<body>
    <a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
    <a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

    <% inline("_panel.rhtml") { inline("_module_nav.rhtml") } %>

    <main id="content" class="content">
        <hgroup class="content__title">
          <h1><span class="kind"><%= @context.type %></span> <%= module_breadcrumbs @context %></h1>
        </hgroup>

        <% inline "_context.rhtml" %>

        <h2 class="content__divider">Definition files</h2>
        <%= more_less_ul @context.in_files.map { |file| link_to file }, 5..9 %>
    </main>
  </body>
</html>


================================================
FILE: lib/rdoc/generator/template/rails/file.rhtml
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="<%= @options.charset %>">
    <title><%= page_title @context.name %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <% inline "_head.rhtml" %>

    <meta property="og:title" value="<%= og_title @context.name %>">
</head>

<body>
    <a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
    <a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

    <% inline("_panel.rhtml") { inline("_file_nav.rhtml") } %>

    <main id="content" class="content">
        <div class="content__title">
          <%= "<h1>" if @context.comment.empty? %>
            <%= full_name_for @context %>
          <%= "</h1>" if @context.comment.empty? %>
        </div>

        <% if source_url = github_url(@context.relative_name) %>
          <p class="content__source-link"><%= link_to_external "View on GitHub", source_url %></p>
        <% end %>

        <% inline "_context.rhtml" %>
    </main>
  </body>
</html>


================================================
FILE: lib/rdoc/generator/template/rails/index.rhtml
================================================
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="<%= @options.charset %>">
    <title><%= page_title %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <% inline "_head.rhtml" %>
</head>

<body>
    <a class="sr-only sr-only-focusable" href="#context" data-turbo="false">Skip to Content</a>
    <a class="sr-only sr-only-focusable" href="#search" data-turbo="false">Skip to Search</a>

    <% inline("_panel.rhtml") { inline("_index_nav.rhtml") } %>

    <main id="content" class="content">
        <% inline "_context.rhtml" %>
    </main>
  </body>
</html>


================================================
FILE: lib/rdoc/generator/template/rails/resources/css/highlight.css
================================================
/* From https://github.com/rails/rails/blob/a3b26873ebf80da6e218cf58b2c9c6669f2d2f1e/guides/assets/stylesheets/highlight.css */

.highlight table td { padding: 5px; }
.highlight table pre { margin: 0; }
.highlight .cm {
  color: #6c6c65;
  font-style: italic;
}
.highlight .cp {
  color: #6c6c6c;
  font-weight: bold;
}
.highlight .c1 {
  color: #6c6c65;
  font-style: italic;
}
.highlight .cs {
  color: #6c6c6c;
  font-weight: bold;
  font-style: italic;
}
.highlight .c, .highlight .ch, .highlight .cd, .highlight .cpf {
  color: #6c6c65;
  font-style: italic;
}
.highlight .err {
  color: #a61717;
  background-color: #e3d2d2;
}
.highlight .gd {
  color: #000000;
  background-color: #ffdddd;
}
.highlight .ge {
  color: #000000;
  font-style: italic;
}
.highlight .gr {
  color: #aa0000;
}
.highlight .gh {
  color: #6c6c6c;
}
.highlight .gi {
  color: #000000;
  background-color: #ddffdd;
}
.highlight .go {
  color: #6c6c6c;
}
.highlight .gp {
  color: #555555;
}
.highlight .gs {
  font-weight: bold;
}
.highlight .gu {
  color: #6c6c6c;
}
.highlight .gt {
  color: #aa0000;
}
.highlight .kc {
  color: #000000;
  font-weight: bold;
}
.highlight .kd {
  color: #000000;
  font-weight: bold;
}
.highlight .kn {
  color: #000000;
  font-weight: bold;
}
.highlight .kp {
  color: #000000;
  font-weight: bold;
}
.highlight .kr {
  color: #000000;
  font-weight: bold;
}
.highlight .kt {
  color: #445588;
  font-weight: bold;
}
.highlight .k, .highlight .kv {
  color: #0073a6;
}
.highlight .mf {
  color: #007979;
}
.highlight .mh {
  color: #007979;
}
.highlight .il {
  color: #007979;
}
.highlight .mi {
  color: #007979;
}
.highlight .mo {
  color: #007979;
}
.highlight .m, .highlight .mb, .highlight .mx {
  color: #007979;
}
.highlight .sb {
  color: #d51144;
}
.highlight .sc {
  color: #d51144;
}
.highlight .sd {
  color: #d51144;
}
.highlight .s2 {
  color: #d51144;
}
.highlight .se {
  color: #d51144;
}
.highlight .sh {
  color: #d51144;
}
.highlight .si {
  color: #d51144;
}
.highlight .sx {
  color: #d51144;
}
.highlight .sr {
  color: #007e26;
}
.highlight .s1 {
  color: #d51144;
}
.highlight .ss {
  color: #990073;
}
.highlight .s, .highlight .sa, .highlight .dl {
  color: #d51144;
}
.highlight .na {
  color: #007979;
}
.highlight .bp {
  color: #6c6c6c;
}
.highlight .nb {
  color: #0074a1;
}
.highlight .nc {
  color: #445588;
  font-weight: bold;
}
.highlight .no {
  color: #007979;
}
.highlight .nd {
  color: #3c5d5d;
  font-weight: bold;
}
.highlight .ni {
  color: #800080;
}
.highlight .ne {
  color: #990000;
  font-weight: bold;
}
.highlight .nf, .highlight .fm {
  color: #990000;
  font-weight: bold;
}
.highlight .nl {
  color: #990000;
  font-weight: bold;
}
.highlight .nn {
  color: #555555;
}
.highlight .nt {
  color: #000080;
}
.highlight .vc {
  color: #007979;
}
.highlight .vg {
  color: #007979;
}
.highlight .vi {
  color: #005cc5;
}
.highlight .nv, .highlight .vm {
  color: #007979;
}
.highlight .ow {
  color: #000000;
  font-weight: bold;
}
.highlight .o {
  color: #000000;
  font-weight: bold;
}
.highlight .w {
  color: #6c6c6c;
}
.highlight {
  background-color: transparent;
}

@media (prefers-color-scheme: dark) {
  .highlight pre { background-color: #272822; }
  .highlight .hll { background-color: #272822; }
  .highlight .c { color: #75715e } /* Comment */
  .highlight .err { color: #960050; background-color: #1e0010 } /* Error */
  .highlight .k { color: #66d9ef } /* Keyword */
  .highlight .l { color: #ae81ff } /* Literal */
  .highlight .n { color: #f8f8f2 } /* Name */
  .highlight .o { color: #f92672 } /* Operator */
  .highlight .p { color: #f8f8f2 } /* Punctuation */
  .highlight .cm { color: #75715e } /* Comment.Multiline */
  .highlight .cp { color: #75715e } /* Comment.Preproc */
  .highlight .c1 { color: #75715e } /* Comment.Single */
  .highlight .cs { color: #75715e } /* Comment.Special */
  .highlight .ge { font-style: italic } /* Generic.Emph */
  .highlight .gs { font-weight: bold } /* Generic.Strong */
  .highlight .kc { color: #66d9ef } /* Keyword.Constant */
  .highlight .kd { color: #66d9ef } /* Keyword.Declaration */
  .highlight .kn { color: #f92672 } /* Keyword.Namespace */
  .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */
  .highlight .kr { color: #66d9ef } /* Keyword.Reserved */
  .highlight .kt { color: #66d9ef } /* Keyword.Type */
  .highlight .ld { color: #e6db74 } /* Literal.Date */
  .highlight .m { color: #ae81ff } /* Literal.Number */
  .highlight .s { color: #e6db74 } /* Literal.String */
  .highlight .na { color: #a6e22e } /* Name.Attribute */
  .highlight .nb { color: #f8f8f2 } /* Name.Builtin */
  .highlight .nc { color: #a6e22e } /* Name.Class */
  .highlight .no { color: #66d9ef } /* Name.Constant */
  .highlight .nd { color: #a6e22e } /* Name.Decorator */
  .highlight .ni { color: #f8f8f2 } /* Name.Entity */
  .highlight .ne { color: #a6e22e } /* Name.Exception */
  .highlight .nf { color: #a6e22e } /* Name.Function */
  .highlight .nl { color: #f8f8f2 } /* Name.Label */
  .highlight .nn { color: #f8f8f2 } /* Name.Namespace */
  .highlight .nx { color: #a6e22e } /* Name.Other */
  .highlight .py { color: #f8f8f2 } /* Name.Property */
  .highlight .nt { color: #f92672 } /* Name.Tag */
  .highlight .nv { color: #f8f8f2 } /* Name.Variable */
  .highlight .ow { color: #f92672 } /* Operator.Word */
  .highlight .w { color: #f8f8f2 } /* Text.Whitespace */
  .highlight .mf { color: #ae81ff } /* Literal.Number.Float */
  .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */
  .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */
  .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */
  .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */
  .highlight .sc { color: #e6db74 } /* Literal.String.Char */
  .highlight .sd { color: #e6db74 } /* Literal.String.Doc */
  .highlight .s2 { color: #e6db74 } /* Literal.String.Double */
  .highlight .se { color: #ae81ff } /* Literal.String.Escape */
  .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */
  .highlight .si { color: #e6db74 } /* Literal.String.Interpol */
  .highlight .sx { color: #e6db74 } /* Literal.String.Other */
  .highlight .sr { color: #e6db74 } /* Literal.String.Regex */
  .highlight .s1 { color: #e6db74 } /* Literal.String.Single */
  .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */
  .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */
  .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */
  .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */
  .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */
  .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */

  .highlight .gh { } /* Generic Heading & Diff Header */
  .highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
  .highlight .gd { color: #f92672; background-color: unset; } /* Generic.Deleted & Diff Deleted */
  .highlight .gi { color: #a6e22e; background-color: unset; } /* Generic.Inserted & Diff Inserted */
}


================================================
FILE: lib/rdoc/generator/template/rails/resources/css/main.css
================================================
@font-face {
  font-family: "Bitter";
  src: url("../fonts/Bitter-Roman.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Bitter";
  src: url("../fonts/Bitter-Italic.woff2") format("woff2");
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost-Roman.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("../fonts/Jost-Italic.woff2") format("woff2");
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "RobotoMono";
  src: url("../fonts/RobotoMono-Roman.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  min-height: 100dvh;
}

:root {
  font-size: 18px;

  --line-height: 1.5;
  --space: 1.25rem;
  --space-xs: calc(var(--space) * 0.25);
  --space-sm: calc(var(--space) * 0.5);
  --space-lg: calc(var(--space) * 1.75);
  --space-xl: calc(var(--space) * 3);

  --body-font: "Bitter", serif;
  --heading-font: "Jost", sans-serif;
  --monospace-font: "RobotoMono", monospace;

  --brand-color: #b61d1d;

  --text-color: #3b3b3b;
  --link-color: var(--brand-color);
  --link-hover-color: var(--text-color);
  --icon-color: #777777;

  --body-bg: #ffffff;
  --code-bg: #f1f1f1;
  --source-code-bg: #f1f1e1;
}

@media (min-width: 600px) {
  :root {
    font-size: 20px;
  }
}

@media (prefers-color-scheme: dark) {
  :root {
    --text-color: #dddddd;
    --link-color: #ee3f3f;

    --body-bg: #0c0c0c;
    --code-bg: #1b1b1b;
    --source-code-bg: #000000;
  }
}

body {
  font-family: var(--body-font);
  line-height: var(--line-height);

  background: var(--body-bg);
  color: var(--text-color);
}

pre, code, .kind {
  font-family: var(--monospace-font);
  font-size: 0.95em;
}

:where(pre, code, .kind) > :is(pre, code, .kind) {
  font-size: unset;
}

.kind::after {
  content: " "; /* Ensure trailing space has width of 1 monospace char */
}

a {
  color: var(--link-color);
}

@media (hover: hover) {
  a:hover {
    color: var(--link-hover-color);
  }
}

.external-link {
  padding-left: 1.3em;
  background: url('../i/external-link.svg') no-repeat;
  background-size: 1.1em;
}

.ref-link {
  text-decoration: none;
}

.query-button {
  border: none;
  text-align: left;
  font-family: inherit;
  font-size: 1em;
  color: var(--link-color);
}

@media (hover: hover) {
  .query-button:hover {
    color: var(--link-hover-color);
  }
}

blockquote {
  padding: var(--space-xs) 0 var(--space-xs) var(--space);
  border-left: var(--space-sm) solid color-mix(in srgb, currentColor 15%, transparent);
}

table {
  border-collapse: collapse;
}

td, th
{
    padding: 0 0.7em 0.3em 0;
}

th
{
    font-weight: bold;
}

.attr-rw {
  padding-right: 1em;
  text-align: center;
  color: #055;
}

.attr-name {
  font-weight: bold;
  padding-right: 1em;
}

.attr-desc {
}

.attr-value {
  font-family: monospace;
  padding-left: 1em;
  font-size: 1.15em;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  border: 0;
}
.sr-only-focusable:active,
.sr-only-focusable:focus {
  position: fixed;
  top: 10%;
  width: auto;
  height: auto;
  overflow: visible;
  clip: auto;
  white-space: normal;
  padding: 2rem;
  border: 4px solid #990000;
  border-radius: 1rem;
  box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 15%) !important;
  left: 40%;
  z-index: 100;
  background: #fff;
  font-size: 2rem;
}


/*
 * Generic content
 */

:where(.content) *,
:where(.content) :is(br, wbr) {
  margin: 0;
}

:where(.content) * + * {
  margin-top: var(--space);
}

:where(.content) :is(ol, ul, dd) {
  padding: 0 0 0 1.25em;
}

:where(.content) * + :is(li, dd) {
  margin-top: var(--space-sm);
}

/* Increase top margin for list items when any item has more than one paragraph */
:where(.content :is(ol, ul):has(> li > p:not(:only-child))) * + li {
  margin-top: var(--space);
}

:where(.content) :is(hgroup, h1, h2, h3, h4, h5, h6) {
  font-family: var(--heading-font);
  font-weight: bold;
  line-height: 1.125;
}

:where(.content :is(hgroup, h1, h2, h3, h4, h5, h6)) :is(code, .kind) {
  font-size: 0.85em;
  font-weight: normal;
}

:where(.content) code {
  font-style: normal;
}


/*
 * Description section
 */

 .description * + :is(h1, h2) {
  margin-top: var(--space-xl);
}

.description * + :is(h3, h4, h5, h6) {
  margin-top: var(--space-lg);
}

.description h1 {
  font-size: 2em;
}

.description h2 {
  font-size: 1.6em;
}

.description h3 {
  font-size: 1.3em;
}

.description h4 {
  font-size: 1.2em;
  font-style: italic;
}

.description h5 {
  font-size: 1.1em;
}

.description h6 {
  font-size: 1em;
  font-style: italic;
}

.description pre, pre.source-code {
  padding: 0.5ch 1ch;
  border-radius: 6px;
  overflow-x: auto;
}

:is(.description p, p.description) code {
  padding: 0 0.15em;
  border-radius: 3px;
}

.description pre, :is(.description p, p.description) code {
  background: var(--code-bg);
}

pre.source-code {
  background: var(--source-code-bg);
}

@media (hover: hover) {
  .description a:hover code {
    box-shadow: 0 0 0 1px;
  }
}

.description dt {
  font-weight: bold;
}


/*
 * Navigation panel
 */

html {
  --panel-width: 100dvw;
  --banner-height: 3.25rem;
  --search-height: var(--space-lg);
  scroll-padding-top: calc(var(--banner-height) + 1rem);
}

#panel {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 90;
  width: var(--panel-width);
}

#panel__state {
  display: none;
}


/*
 * Navigation panel - Banner
 */

.banner {
  height: var(--banner-height);
  background-color: var(--brand-color);
  box-shadow: 1px 0px var(--brand-color); /* Match .panel_tray width on desktop */
}

.banner__segment {
  display: inline-block;
  height: 100%;
  padding: calc(0.15 * var(--banner-height));
  filter: brightness(0) invert(1);
}

.banner__segment:first-child {
  border-right: 1px solid;
}

.banner__menu-button {
  display: inline-block;
  height: 100%;
  aspect-ratio : 1 / 1;
  background: url('../i/menu.svg') no-repeat center;
  background-size: 100%;
}

#panel:has(#panel__state:checked) .banner__menu-button {
  background-image: url('../i/close.svg');
}

.banner__logo img {
  height: 100%;
}

.banner__version {
  font-size: 1.25rem;
  font-style: italic;

  position: relative;
  bottom: 0.1em;
}


/*
 * Navigation panel - Tray
 */

.panel__tray {
  background: var(--body-bg);
  position: absolute;

  overflow-y: hidden;
  transition: height 0.2s ease-in-out;
  height: 0;
}

#panel__state:checked ~ .panel__tray {
  height: 100dvh;
}

.panel__results, .panel__nav {
  position: relative;
  height: calc(100dvh - var(--banner-height) - var(--search-height));
  width: var(--panel-width);
  transition: opacity 0.15s ease-in-out;

  overflow-y: auto;
  overscroll-behavior: contain;
}

/* Force scrolling in order to always contain scroll events (on mobile) */
:is(.panel__results, .panel__nav)::after {
  content: "";
  height: 1px;
  width: 1px;
  position: absolute;
  bottom: -1px;
  z-index: -1;
}

.panel__results:not(.active),
.panel__search:placeholder-shown ~ .panel__results,
.panel__search:not(:placeholder-shown) ~ .panel__results.active ~ .panel__nav {
  /* `display: none` disables animations, so simulate it instead */
  max-height: 0;
  max-width: 0;
  padding: 0;

  opacity: 0;
}


/*
 * Navigation panel - Search input
 */

.panel__search {
  height: var(--search-height);
  width: 100%;

  background: url('../i/search.svg') no-repeat;
  background-size: 1.3em;
  background-position: 0.5em center;
  padding-left: calc(0.5em + 1.3em + 0.5em);

  color: inherit;

  border: 0;
  box-shadow: 1px 1px 4px color-mix(in srgb, currentColor 50%, transparent) inset;
}

/* Hide native magnifying glass icon in Webkit-based browsers (in favor of our icon) */
.panel__search::-webkit-search-results-button {
  -webkit-appearance: none;
}

/* Display "clear search" button consistently across (Webkit-based) browsers */
.panel__search::-webkit-search-cancel-button {
  -webkit-appearance: none;

  margin-right: 0.5em;
  height: 1.3em;
  width: 1.3em;
  background: url('../i/close.svg') no-repeat;
  background-size: contain;
}

.panel__search:not(:focus)::-webkit-search-cancel-button {
  display: none;
}


/*
 * Navigation panel - Search results
 */

.panel__results {
  padding: var(--space-sm) var(--space-xs);
  scroll-padding: var(--space-sm) 0;
}


.panel__results::before {
  display: block;
  text-align: center;
  text-wrap: balance;
  padding-bottom: var(--space-sm);

  font-size: 0.85em;
  font-style: italic;
  color: color-mix(in srgb, currentColor 70%, transparent);
}

.panel__results.active::before {
  content: "TIP: Prefix query with \"#\" or \".\" to search for methods.";
}

/* Hide TIP when one of the first three search results is a method. */
.panel__results:has(.results__result:nth-child(n+1):nth-child(-n+3) .result__member:not(:empty))::before {
  display: none;
}

.panel__results:empty::before {
  content: "No results.";
}


.results__result:not(:first-child) {
  margin-top: var(--space);
}

.results__result {
  border-left: 0.5ch solid color-mix(in srgb, currentColor 10%, transparent);
  border-radius: 0.5ch;
  padding-left: var(--space-xs);
}

/* Assume physical keyboard exists when not `pointer: coarse` */
@media not (pointer: coarse) {
  .results__result.cursor {
    border-color: var(--link-color);
  }
}

@media (hover: hover) {
  .results__result:has(.result__link:hover) {
    border-color: var(--link-hover-color);
  }
}


.result__link {
  display: flex;
  flex-direction: column;
}

.result__member {
  display: flex;
}

.result__member::before {
  content: "\221F";
  font-size: 1.25em;
  margin: -0.3em 0.2em;
  color: var(--text-color);
}

.result__summary {
  margin: var(--space-xs) 0 0 0;
}

:is(.result__member, .result__summary):empty {
  display: none;
}


/*
 * Navigation panel - Page nav
 */

.panel__nav {
  padding: var(--space);
  padding-right: var(--space-xs);
}

:where(.panel__nav) * + :is(ul, ol, li) {
  margin-top: var(--space-xs);
}


.panel__nav :is(.namespace-link, .query-button) {
  display: block;
  word-break: break-word;
}

.panel__nav * + :is(.namespace-link, .query-button) {
  margin-top: var(--space-sm);
}

.panel__nav .namespace-link {
  background: url('../i/list.svg') no-repeat;
  background-position-y: 3px;
  background-size: 1.1em;
  padding: 0 0 0 1.3em;

  text-decoration: none;
}

.panel__nav .query-button {
  background: url('../i/filter.svg') no-repeat;
  background-position-y: 2px;
  background-size: 1.1em;
  padding: 0 0 0 1.3em;
}


.nav__heading {
  font-family: var(--heading-font);
  font-weight: bold;
  font-size: 1.6em;
  line-height: 1;
}

* + .nav__heading {
  margin-top: var(--space-lg);
}

.nav__heading + * {
  margin-top: var(--space-sm);
}


.nav__outline ul {
  padding-left: 1em;
}

.nav__outline ul ul ul {
  display: none; /* Only show two levels deep */
}

.nav__outline li {
  word-break: break-word;
}


.nav__list {
  padding: 0;
  list-style: none;
}

.nav__list li {
  overflow: hidden;
  text-overflow: ellipsis;
}


.nav__method-link code::before {
  content: "#";
}

.nav__method-link--singleton code::before {
  content: "::";
}


/*
 * Navigation panel on desktop
 */

@media (min-width: 600px) {
  html {
    --panel-width: 300px;
    scroll-padding-top: 1rem;
  }

  .banner__segment:first-child {
    display: none;
  }

  .panel__tray {
    height: unset;
    box-shadow: 1px 0 color-mix(in srgb, currentColor 25%, transparent);
  }

  .panel__results.active {
    width: 60ch;
  }

  :is(.panel__results, .panel__nav) {
    font-size: 0.85em;
  }

  :is(.panel__results, .panel__nav)::after {
    display: none;
  }
}


/*
 * Main content
 */

#content {
  padding: 1em;
  overflow-x: auto;
}

@media (min-width: 600px) {
  #content {
    margin-top: calc(-1 * var(--banner-height));
    margin-left: var(--panel-width);
    padding: var(--space) var(--space-lg);
    max-width: calc(75ch + 2 * var(--space-lg));
  }
}

.content__title h1 {
  font-size: 1.75em;

  margin-left: 1em;
  text-indent: -1em;
}

.content__title p {
  font-size: 2em;
  font-style: italic;

  margin-top: 0;
}

.content__title ~ #context > .description {
  margin-top: var(--space-lg);
}

.content__source-link {
  margin-top: var(--space-xs);
}

.content__section-title {
  margin: var(--space-xl) 0 0 0;

  font-size: 1.8em;
  font-weight: bold;
}

.content__divider {
  margin: var(--space-xl) 0 0 0;

  font-size: 1.6em;
  font-weight: bold;
  text-transform: capitalize;

  border-bottom: 1px solid;
}

.content__section-title + .content__divider,
.content__divider + :is(*, div /* increase selector specificity */) {
  margin-top: var(--space);
}


/*
 * Constant
 */

.constant {
  margin-top: var(--space-lg);
}

.constant__name {
  padding-bottom: var(--space-xs);
  border-bottom: 2px solid var(--code-bg);

  display: flex;
  align-items: baseline;
  gap: 0.5em;
}

.constant__name > * {
  margin-top: 0;
}

.constant__name code {
  font-size: 1rem;
  font-weight: bold;
}

.constant__name + *, .constant__source {
  margin-top: var(--space-sm);
}


/*
 * Method
 */

.method {
  margin-top: var(--space-xl);
}


.method__signature {
  padding-bottom: var(--space-xs);
  border-bottom: 2px solid var(--code-bg);

  display: flex;
  align-items: baseline;
  gap: 0.5em;
}

.method__signature > * {
  margin-top: 0;
}

.method__signature code {
  font-size: 1rem;
  white-space: pre-wrap;
}

.method__signature code .returns {
  font-family: var(--body-font);
  font-size: 1.1em;
}

.method__signature + * {
  margin-top: var(--space-sm);
}

.method__aka {
  font-style: italic;
}


.method__source {
  width: fit-content; /* Reduce clickable area when collapsed */
}

.method__source[open] {
  width: auto;
}

.method__source summary {
  cursor: pointer;
}

.method__source summary::marker {
  color: var(--icon-color);
}

.method__source summary .label {
  margin-left: -0.2em;
  color: var(--link-color);
}

@media (hover: hover) {
  .method__source summary .label:hover {
    color: var(--link-hover-color);
  }
}

.method__source summary .external-link {
  margin-left: 1em;
}

.method__source pre {
  margin-top: var(--space-xs);
}


/*
 * Permalink
 */

.permalink img {
  height: 1.05em;
  vertical-align: middle;
}

@media (hover: hover) {
  .permalink:hover img {
    filter: brightness(0) invert(1);
    mix-blend-mode: difference;
  }
}

.permalink-container {
  position: relative;
}

:is(.target .permalink-container, .target.permalink-container)::before {
  content: " ";
  white-space: pre;

  position: absolute;
  left: calc(-0.5ch - var(--space-sm));
  border-left: 0.5ch solid var(--link-color);
  border-radius: 0.5ch;
  height: 100%;
}


/*
 * More-Less widget
 */

details.more-less {
  margin-top: 0;
  padding-bottom: calc(var(--line-height) * 1em + var(--space-sm));
  position: relative;
}

details.more-less > ul {
  margin-top: var(--space-sm);
}

details.more-less summary {
  position: absolute;
  bottom: 0;

  font-weight: bold;
  color: var(--icon-color);
  padding-left: 0.25em;
}

@media (hover: hover) {
  details.more-less summary:hover {
    cursor: pointer;
    color: inherit;
  }
}

details.more-less summary {
  list-style-type: none;
}
details.more-less summary::-webkit-details-marker {
  display: none;
}

details.more-less summary::before {
  content: "+";
}

details.more-less[open] summary::before {
  content: "-";
}

details.more-less:not([open]) .more-less__less,
details.more-less[open] .more-less__more {
  display: none;
}


================================================
FILE: lib/rdoc/generator/template/rails/resources/js/.gitattributes
================================================
@hotwired--turbo.js binary


================================================
FILE: lib/rdoc/generator/template/rails/resources/js/@hotwired--turbo.js
================================================
/*
Turbo 7.3.0
Copyright © 2023 37signals LLC
 */
(function () {
    if (window.Reflect === undefined ||
        window.customElements === undefined ||
        window.customElements.polyfillWrapFlushCallback) {
        return;
    }
    const BuiltInHTMLElement = HTMLElement;
    const wrapperForTheName = {
        HTMLElement: function HTMLElement() {
            return Reflect.construct(BuiltInHTMLElement, [], this.constructor);
        },
    };
    window.HTMLElement = wrapperForTheName["HTMLElement"];
    HTMLElement.prototype = BuiltInHTMLElement.prototype;
    HTMLElement.prototype.constructor = HTMLElement;
    Object.setPrototypeOf(HTMLElement, BuiltInHTMLElement);
})();

/**
 * The MIT License (MIT)
 * 
 * Copyright (c) 2019 Javan Makhmali
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

(function(prototype) {
  if (typeof prototype.requestSubmit == "function") return

  prototype.requestSubmit = function(submitter) {
    if (submitter) {
      validateSubmitter(submitter, this);
      submitter.click();
    } else {
      submitter = document.createElement("input");
      submitter.type = "submit";
      submitter.hidden = true;
      this.appendChild(submitter);
      submitter.click();
      this.removeChild(submitter);
    }
  };

  function validateSubmitter(submitter, form) {
    submitter instanceof HTMLElement || raise(TypeError, "parameter 1 is not of type 'HTMLElement'");
    submitter.type == "submit" || raise(TypeError, "The specified element is not a submit button");
    submitter.form == form || raise(DOMException, "The specified element is not owned by this form element", "NotFoundError");
  }

  function raise(errorConstructor, message, name) {
    throw new errorConstructor("Failed to execute 'requestSubmit' on 'HTMLFormElement': " + message + ".", name)
  }
})(HTMLFormElement.prototype);

const submittersByForm = new WeakMap();
function findSubmitterFromClickTarget(target) {
    const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
    const candidate = element ? element.closest("input, button") : null;
    return (candidate === null || candidate === void 0 ? void 0 : candidate.type) == "submit" ? candidate : null;
}
function clickCaptured(event) {
    const submitter = findSubmitterFromClickTarget(event.target);
    if (submitter && submitter.form) {
        submittersByForm.set(submitter.form, submitter);
    }
}
(function () {
    if ("submitter" in Event.prototype)
        return;
    let prototype = window.Event.prototype;
    if ("SubmitEvent" in window && /Apple Computer/.test(navigator.vendor)) {
        prototype = window.SubmitEvent.prototype;
    }
    else if ("SubmitEvent" in window) {
        return;
    }
    addEventListener("click", clickCaptured, true);
    Object.defineProperty(prototype, "submitter", {
        get() {
            if (this.type == "submit" && this.target instanceof HTMLFormElement) {
                return submittersByForm.get(this.target);
            }
        },
    });
})();

var FrameLoadingStyle;
(function (FrameLoadingStyle) {
    FrameLoadingStyle["eager"] = "eager";
    FrameLoadingStyle["lazy"] = "lazy";
})(FrameLoadingStyle || (FrameLoadingStyle = {}));
class FrameElement extends HTMLElement {
    static get observedAttributes() {
        return ["disabled", "complete", "loading", "src"];
    }
    constructor() {
        super();
        this.loaded = Promise.resolve();
        this.delegate = new FrameElement.delegateConstructor(this);
    }
    connectedCallback() {
        this.delegate.connect();
    }
    disconnectedCallback() {
        this.delegate.disconnect();
    }
    reload() {
        return this.delegate.sourceURLReloaded();
    }
    attributeChangedCallback(name) {
        if (name == "loading") {
            this.delegate.loadingStyleChanged();
        }
        else if (name == "complete") {
            this.delegate.completeChanged();
        }
        else if (name == "src") {
            this.delegate.sourceURLChanged();
        }
        else {
            this.delegate.disabledChanged();
        }
    }
    get src() {
        return this.getAttribute("src");
    }
    set src(value) {
        if (value) {
            this.setAttribute("src", value);
        }
        else {
            this.removeAttribute("src");
        }
    }
    get loading() {
        return frameLoadingStyleFromString(this.getAttribute("loading") || "");
    }
    set loading(value) {
        if (value) {
            this.setAttribute("loading", value);
        }
        else {
            this.removeAttribute("loading");
        }
    }
    get disabled() {
        return this.hasAttribute("disabled");
    }
    set disabled(value) {
        if (value) {
            this.setAttribute("disabled", "");
        }
        else {
            this.removeAttribute("disabled");
        }
    }
    get autoscroll() {
        return this.hasAttribute("autoscroll");
    }
    set autoscroll(value) {
        if (value) {
            this.setAttribute("autoscroll", "");
        }
        else {
            this.removeAttribute("autoscroll");
        }
    }
    get complete() {
        return !this.delegate.isLoading;
    }
    get isActive() {
        return this.ownerDocument === document && !this.isPreview;
    }
    get isPreview() {
        var _a, _b;
        return (_b = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.documentElement) === null || _b === void 0 ? void 0 : _b.hasAttribute("data-turbo-preview");
    }
}
function frameLoadingStyleFromString(style) {
    switch (style.toLowerCase()) {
        case "lazy":
            return FrameLoadingStyle.lazy;
        default:
            return FrameLoadingStyle.eager;
    }
}

function expandURL(locatable) {
    return new URL(locatable.toString(), document.baseURI);
}
function getAnchor(url) {
    let anchorMatch;
    if (url.hash) {
        return url.hash.slice(1);
    }
    else if ((anchorMatch = url.href.match(/#(.*)$/))) {
        return anchorMatch[1];
    }
}
function getAction(form, submitter) {
    const action = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formaction")) || form.getAttribute("action") || form.action;
    return expandURL(action);
}
function getExtension(url) {
    return (getLastPathComponent(url).match(/\.[^.]*$/) || [])[0] || "";
}
function isHTML(url) {
    return !!getExtension(url).match(/^(?:|\.(?:htm|html|xhtml|php))$/);
}
function isPrefixedBy(baseURL, url) {
    const prefix = getPrefix(url);
    return baseURL.href === expandURL(prefix).href || baseURL.href.startsWith(prefix);
}
function locationIsVisitable(location, rootLocation) {
    return isPrefixedBy(location, rootLocation) && isHTML(location);
}
function getRequestURL(url) {
    const anchor = getAnchor(url);
    return anchor != null ? url.href.slice(0, -(anchor.length + 1)) : url.href;
}
function toCacheKey(url) {
    return getRequestURL(url);
}
function urlsAreEqual(left, right) {
    return expandURL(left).href == expandURL(right).href;
}
function getPathComponents(url) {
    return url.pathname.split("/").slice(1);
}
function getLastPathComponent(url) {
    return getPathComponents(url).slice(-1)[0];
}
function getPrefix(url) {
    return addTrailingSlash(url.origin + url.pathname);
}
function addTrailingSlash(value) {
    return value.endsWith("/") ? value : value + "/";
}

class FetchResponse {
    constructor(response) {
        this.response = response;
    }
    get succeeded() {
        return this.response.ok;
    }
    get failed() {
        return !this.succeeded;
    }
    get clientError() {
        return this.statusCode >= 400 && this.statusCode <= 499;
    }
    get serverError() {
        return this.statusCode >= 500 && this.statusCode <= 599;
    }
    get redirected() {
        return this.response.redirected;
    }
    get location() {
        return expandURL(this.response.url);
    }
    get isHTML() {
        return this.contentType && this.contentType.match(/^(?:text\/([^\s;,]+\b)?html|application\/xhtml\+xml)\b/);
    }
    get statusCode() {
        return this.response.status;
    }
    get contentType() {
        return this.header("Content-Type");
    }
    get responseText() {
        return this.response.clone().text();
    }
    get responseHTML() {
        if (this.isHTML) {
            return this.response.clone().text();
        }
        else {
            return Promise.resolve(undefined);
        }
    }
    header(name) {
        return this.response.headers.get(name);
    }
}

function activateScriptElement(element) {
    if (element.getAttribute("data-turbo-eval") == "false") {
        return element;
    }
    else {
        const createdScriptElement = document.createElement("script");
        const cspNonce = getMetaContent("csp-nonce");
        if (cspNonce) {
            createdScriptElement.nonce = cspNonce;
        }
        createdScriptElement.textContent = element.textContent;
        createdScriptElement.async = false;
        copyElementAttributes(createdScriptElement, element);
        return createdScriptElement;
    }
}
function copyElementAttributes(destinationElement, sourceElement) {
    for (const { name, value } of sourceElement.attributes) {
        destinationElement.setAttribute(name, value);
    }
}
function createDocumentFragment(html) {
    const template = document.createElement("template");
    template.innerHTML = html;
    return template.content;
}
function dispatch(eventName, { target, cancelable, detail } = {}) {
    const event = new CustomEvent(eventName, {
        cancelable,
        bubbles: true,
        composed: true,
        detail,
    });
    if (target && target.isConnected) {
        target.dispatchEvent(event);
    }
    else {
        document.documentElement.dispatchEvent(event);
    }
    return event;
}
function nextAnimationFrame() {
    return new Promise((resolve) => requestAnimationFrame(() => resolve()));
}
function nextEventLoopTick() {
    return new Promise((resolve) => setTimeout(() => resolve(), 0));
}
function nextMicrotask() {
    return Promise.resolve();
}
function parseHTMLDocument(html = "") {
    return new DOMParser().parseFromString(html, "text/html");
}
function unindent(strings, ...values) {
    const lines = interpolate(strings, values).replace(/^\n/, "").split("\n");
    const match = lines[0].match(/^\s+/);
    const indent = match ? match[0].length : 0;
    return lines.map((line) => line.slice(indent)).join("\n");
}
function interpolate(strings, values) {
    return strings.reduce((result, string, i) => {
        const value = values[i] == undefined ? "" : values[i];
        return result + string + value;
    }, "");
}
function uuid() {
    return Array.from({ length: 36 })
        .map((_, i) => {
        if (i == 8 || i == 13 || i == 18 || i == 23) {
            return "-";
        }
        else if (i == 14) {
            return "4";
        }
        else if (i == 19) {
            return (Math.floor(Math.random() * 4) + 8).toString(16);
        }
        else {
            return Math.floor(Math.random() * 15).toString(16);
        }
    })
        .join("");
}
function getAttribute(attributeName, ...elements) {
    for (const value of elements.map((element) => element === null || element === void 0 ? void 0 : element.getAttribute(attributeName))) {
        if (typeof value == "string")
            return value;
    }
    return null;
}
function hasAttribute(attributeName, ...elements) {
    return elements.some((element) => element && element.hasAttribute(attributeName));
}
function markAsBusy(...elements) {
    for (const element of elements) {
        if (element.localName == "turbo-frame") {
            element.setAttribute("busy", "");
        }
        element.setAttribute("aria-busy", "true");
    }
}
function clearBusyState(...elements) {
    for (const element of elements) {
        if (element.localName == "turbo-frame") {
            element.removeAttribute("busy");
        }
        element.removeAttribute("aria-busy");
    }
}
function waitForLoad(element, timeoutInMilliseconds = 2000) {
    return new Promise((resolve) => {
        const onComplete = () => {
            element.removeEventListener("error", onComplete);
            element.removeEventListener("load", onComplete);
            resolve();
        };
        element.addEventListener("load", onComplete, { once: true });
        element.addEventListener("error", onComplete, { once: true });
        setTimeout(resolve, timeoutInMilliseconds);
    });
}
function getHistoryMethodForAction(action) {
    switch (action) {
        case "replace":
            return history.replaceState;
        case "advance":
        case "restore":
            return history.pushState;
    }
}
function isAction(action) {
    return action == "advance" || action == "replace" || action == "restore";
}
function getVisitAction(...elements) {
    const action = getAttribute("data-turbo-action", ...elements);
    return isAction(action) ? action : null;
}
function getMetaElement(name) {
    return document.querySelector(`meta[name="${name}"]`);
}
function getMetaContent(name) {
    const element = getMetaElement(name);
    return element && element.content;
}
function setMetaContent(name, content) {
    let element = getMetaElement(name);
    if (!element) {
        element = document.createElement("meta");
        element.setAttribute("name", name);
        document.head.appendChild(element);
    }
    element.setAttribute("content", content);
    return element;
}
function findClosestRecursively(element, selector) {
    var _a;
    if (element instanceof Element) {
        return (element.closest(selector) ||
            findClosestRecursively(element.assignedSlot || ((_a = element.getRootNode()) === null || _a === void 0 ? void 0 : _a.host), selector));
    }
}

var FetchMethod;
(function (FetchMethod) {
    FetchMethod[FetchMethod["get"] = 0] = "get";
    FetchMethod[FetchMethod["post"] = 1] = "post";
    FetchMethod[FetchMethod["put"] = 2] = "put";
    FetchMethod[FetchMethod["patch"] = 3] = "patch";
    FetchMethod[FetchMethod["delete"] = 4] = "delete";
})(FetchMethod || (FetchMethod = {}));
function fetchMethodFromString(method) {
    switch (method.toLowerCase()) {
        case "get":
            return FetchMethod.get;
        case "post":
            return FetchMethod.post;
        case "put":
            return FetchMethod.put;
        case "patch":
            return FetchMethod.patch;
        case "delete":
            return FetchMethod.delete;
    }
}
class FetchRequest {
    constructor(delegate, method, location, body = new URLSearchParams(), target = null) {
        this.abortController = new AbortController();
        this.resolveRequestPromise = (_value) => { };
        this.delegate = delegate;
        this.method = method;
        this.headers = this.defaultHeaders;
        this.body = body;
        this.url = location;
        this.target = target;
    }
    get location() {
        return this.url;
    }
    get params() {
        return this.url.searchParams;
    }
    get entries() {
        return this.body ? Array.from(this.body.entries()) : [];
    }
    cancel() {
        this.abortController.abort();
    }
    async perform() {
        const { fetchOptions } = this;
        this.delegate.prepareRequest(this);
        await this.allowRequestToBeIntercepted(fetchOptions);
        try {
            this.delegate.requestStarted(this);
            const response = await fetch(this.url.href, fetchOptions);
            return await this.receive(response);
        }
        catch (error) {
            if (error.name !== "AbortError") {
                if (this.willDelegateErrorHandling(error)) {
                    this.delegate.requestErrored(this, error);
                }
                throw error;
            }
        }
        finally {
            this.delegate.requestFinished(this);
        }
    }
    async receive(response) {
        const fetchResponse = new FetchResponse(response);
        const event = dispatch("turbo:before-fetch-response", {
            cancelable: true,
            detail: { fetchResponse },
            target: this.target,
        });
        if (event.defaultPrevented) {
            this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
        }
        else if (fetchResponse.succeeded) {
            this.delegate.requestSucceededWithResponse(this, fetchResponse);
        }
        else {
            this.delegate.requestFailedWithResponse(this, fetchResponse);
        }
        return fetchResponse;
    }
    get fetchOptions() {
        var _a;
        return {
            method: FetchMethod[this.method].toUpperCase(),
            credentials: "same-origin",
            headers: this.headers,
            redirect: "follow",
            body: this.isSafe ? null : this.body,
            signal: this.abortSignal,
            referrer: (_a = this.delegate.referrer) === null || _a === void 0 ? void 0 : _a.href,
        };
    }
    get defaultHeaders() {
        return {
            Accept: "text/html, application/xhtml+xml",
        };
    }
    get isSafe() {
        return this.method === FetchMethod.get;
    }
    get abortSignal() {
        return this.abortController.signal;
    }
    acceptResponseType(mimeType) {
        this.headers["Accept"] = [mimeType, this.headers["Accept"]].join(", ");
    }
    async allowRequestToBeIntercepted(fetchOptions) {
        const requestInterception = new Promise((resolve) => (this.resolveRequestPromise = resolve));
        const event = dispatch("turbo:before-fetch-request", {
            cancelable: true,
            detail: {
                fetchOptions,
                url: this.url,
                resume: this.resolveRequestPromise,
            },
            target: this.target,
        });
        if (event.defaultPrevented)
            await requestInterception;
    }
    willDelegateErrorHandling(error) {
        const event = dispatch("turbo:fetch-request-error", {
            target: this.target,
            cancelable: true,
            detail: { request: this, error: error },
        });
        return !event.defaultPrevented;
    }
}

class AppearanceObserver {
    constructor(delegate, element) {
        this.started = false;
        this.intersect = (entries) => {
            const lastEntry = entries.slice(-1)[0];
            if (lastEntry === null || lastEntry === void 0 ? void 0 : lastEntry.isIntersecting) {
                this.delegate.elementAppearedInViewport(this.element);
            }
        };
        this.delegate = delegate;
        this.element = element;
        this.intersectionObserver = new IntersectionObserver(this.intersect);
    }
    start() {
        if (!this.started) {
            this.started = true;
            this.intersectionObserver.observe(this.element);
        }
    }
    stop() {
        if (this.started) {
            this.started = false;
            this.intersectionObserver.unobserve(this.element);
        }
    }
}

class StreamMessage {
    static wrap(message) {
        if (typeof message == "string") {
            return new this(createDocumentFragment(message));
        }
        else {
            return message;
        }
    }
    constructor(fragment) {
        this.fragment = importStreamElements(fragment);
    }
}
StreamMessage.contentType = "text/vnd.turbo-stream.html";
function importStreamElements(fragment) {
    for (const element of fragment.querySelectorAll("turbo-stream")) {
        const streamElement = document.importNode(element, true);
        for (const inertScriptElement of streamElement.templateElement.content.querySelectorAll("script")) {
            inertScriptElement.replaceWith(activateScriptElement(inertScriptElement));
        }
        element.replaceWith(streamElement);
    }
    return fragment;
}

var FormSubmissionState;
(function (FormSubmissionState) {
    FormSubmissionState[FormSubmissionState["initialized"] = 0] = "initialized";
    FormSubmissionState[FormSubmissionState["requesting"] = 1] = "requesting";
    FormSubmissionState[FormSubmissionState["waiting"] = 2] = "waiting";
    FormSubmissionState[FormSubmissionState["receiving"] = 3] = "receiving";
    FormSubmissionState[FormSubmissionState["stopping"] = 4] = "stopping";
    FormSubmissionState[FormSubmissionState["stopped"] = 5] = "stopped";
})(FormSubmissionState || (FormSubmissionState = {}));
var FormEnctype;
(function (FormEnctype) {
    FormEnctype["urlEncoded"] = "application/x-www-form-urlencoded";
    FormEnctype["multipart"] = "multipart/form-data";
    FormEnctype["plain"] = "text/plain";
})(FormEnctype || (FormEnctype = {}));
function formEnctypeFromString(encoding) {
    switch (encoding.toLowerCase()) {
        case FormEnctype.multipart:
            return FormEnctype.multipart;
        case FormEnctype.plain:
            return FormEnctype.plain;
        default:
            return FormEnctype.urlEncoded;
    }
}
class FormSubmission {
    static confirmMethod(message, _element, _submitter) {
        return Promise.resolve(confirm(message));
    }
    constructor(delegate, formElement, submitter, mustRedirect = false) {
        this.state = FormSubmissionState.initialized;
        this.delegate = delegate;
        this.formElement = formElement;
        this.submitter = submitter;
        this.formData = buildFormData(formElement, submitter);
        this.location = expandURL(this.action);
        if (this.method == FetchMethod.get) {
            mergeFormDataEntries(this.location, [...this.body.entries()]);
        }
        this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
        this.mustRedirect = mustRedirect;
    }
    get method() {
        var _a;
        const method = ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formmethod")) || this.formElement.getAttribute("method") || "";
        return fetchMethodFromString(method.toLowerCase()) || FetchMethod.get;
    }
    get action() {
        var _a;
        const formElementAction = typeof this.formElement.action === "string" ? this.formElement.action : null;
        if ((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.hasAttribute("formaction")) {
            return this.submitter.getAttribute("formaction") || "";
        }
        else {
            return this.formElement.getAttribute("action") || formElementAction || "";
        }
    }
    get body() {
        if (this.enctype == FormEnctype.urlEncoded || this.method == FetchMethod.get) {
            return new URLSearchParams(this.stringFormData);
        }
        else {
            return this.formData;
        }
    }
    get enctype() {
        var _a;
        return formEnctypeFromString(((_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("formenctype")) || this.formElement.enctype);
    }
    get isSafe() {
        return this.fetchRequest.isSafe;
    }
    get stringFormData() {
        return [...this.formData].reduce((entries, [name, value]) => {
            return entries.concat(typeof value == "string" ? [[name, value]] : []);
        }, []);
    }
    async start() {
        const { initialized, requesting } = FormSubmissionState;
        const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement);
        if (typeof confirmationMessage === "string") {
            const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter);
            if (!answer) {
                return;
            }
        }
        if (this.state == initialized) {
            this.state = requesting;
            return this.fetchRequest.perform();
        }
    }
    stop() {
        const { stopping, stopped } = FormSubmissionState;
        if (this.state != stopping && this.state != stopped) {
            this.state = stopping;
            this.fetchRequest.cancel();
            return true;
        }
    }
    prepareRequest(request) {
        if (!request.isSafe) {
            const token = getCookieValue(getMetaContent("csrf-param")) || getMetaContent("csrf-token");
            if (token) {
                request.headers["X-CSRF-Token"] = token;
            }
        }
        if (this.requestAcceptsTurboStreamResponse(request)) {
            request.acceptResponseType(StreamMessage.contentType);
        }
    }
    requestStarted(_request) {
        var _a;
        this.state = FormSubmissionState.waiting;
        (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.setAttribute("disabled", "");
        this.setSubmitsWith();
        dispatch("turbo:submit-start", {
            target: this.formElement,
            detail: { formSubmission: this },
        });
        this.delegate.formSubmissionStarted(this);
    }
    requestPreventedHandlingResponse(request, response) {
        this.result = { success: response.succeeded, fetchResponse: response };
    }
    requestSucceededWithResponse(request, response) {
        if (response.clientError || response.serverError) {
            this.delegate.formSubmissionFailedWithResponse(this, response);
        }
        else if (this.requestMustRedirect(request) && responseSucceededWithoutRedirect(response)) {
            const error = new Error("Form responses must redirect to another location");
            this.delegate.formSubmissionErrored(this, error);
        }
        else {
            this.state = FormSubmissionState.receiving;
            this.result = { success: true, fetchResponse: response };
            this.delegate.formSubmissionSucceededWithResponse(this, response);
        }
    }
    requestFailedWithResponse(request, response) {
        this.result = { success: false, fetchResponse: response };
        this.delegate.formSubmissionFailedWithResponse(this, response);
    }
    requestErrored(request, error) {
        this.result = { success: false, error };
        this.delegate.formSubmissionErrored(this, error);
    }
    requestFinished(_request) {
        var _a;
        this.state = FormSubmissionState.stopped;
        (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.removeAttribute("disabled");
        this.resetSubmitterText();
        dispatch("turbo:submit-end", {
            target: this.formElement,
            detail: Object.assign({ formSubmission: this }, this.result),
        });
        this.delegate.formSubmissionFinished(this);
    }
    setSubmitsWith() {
        if (!this.submitter || !this.submitsWith)
            return;
        if (this.submitter.matches("button")) {
            this.originalSubmitText = this.submitter.innerHTML;
            this.submitter.innerHTML = this.submitsWith;
        }
        else if (this.submitter.matches("input")) {
            const input = this.submitter;
            this.originalSubmitText = input.value;
            input.value = this.submitsWith;
        }
    }
    resetSubmitterText() {
        if (!this.submitter || !this.originalSubmitText)
            return;
        if (this.submitter.matches("button")) {
            this.submitter.innerHTML = this.originalSubmitText;
        }
        else if (this.submitter.matches("input")) {
            const input = this.submitter;
            input.value = this.originalSubmitText;
        }
    }
    requestMustRedirect(request) {
        return !request.isSafe && this.mustRedirect;
    }
    requestAcceptsTurboStreamResponse(request) {
        return !request.isSafe || hasAttribute("data-turbo-stream", this.submitter, this.formElement);
    }
    get submitsWith() {
        var _a;
        return (_a = this.submitter) === null || _a === void 0 ? void 0 : _a.getAttribute("data-turbo-submits-with");
    }
}
function buildFormData(formElement, submitter) {
    const formData = new FormData(formElement);
    const name = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("name");
    const value = submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("value");
    if (name) {
        formData.append(name, value || "");
    }
    return formData;
}
function getCookieValue(cookieName) {
    if (cookieName != null) {
        const cookies = document.cookie ? document.cookie.split("; ") : [];
        const cookie = cookies.find((cookie) => cookie.startsWith(cookieName));
        if (cookie) {
            const value = cookie.split("=").slice(1).join("=");
            return value ? decodeURIComponent(value) : undefined;
        }
    }
}
function responseSucceededWithoutRedirect(response) {
    return response.statusCode == 200 && !response.redirected;
}
function mergeFormDataEntries(url, entries) {
    const searchParams = new URLSearchParams();
    for (const [name, value] of entries) {
        if (value instanceof File)
            continue;
        searchParams.append(name, value);
    }
    url.search = searchParams.toString();
    return url;
}

class Snapshot {
    constructor(element) {
        this.element = element;
    }
    get activeElement() {
        return this.element.ownerDocument.activeElement;
    }
    get children() {
        return [...this.element.children];
    }
    hasAnchor(anchor) {
        return this.getElementForAnchor(anchor) != null;
    }
    getElementForAnchor(anchor) {
        return anchor ? this.element.querySelector(`[id='${anchor}'], a[name='${anchor}']`) : null;
    }
    get isConnected() {
        return this.element.isConnected;
    }
    get firstAutofocusableElement() {
        const inertDisabledOrHidden = "[inert], :disabled, [hidden], details:not([open]), dialog:not([open])";
        for (const element of this.element.querySelectorAll("[autofocus]")) {
            if (element.closest(inertDisabledOrHidden) == null)
                return element;
            else
                continue;
        }
        return null;
    }
    get permanentElements() {
        return queryPermanentElementsAll(this.element);
    }
    getPermanentElementById(id) {
        return getPermanentElementById(this.element, id);
    }
    getPermanentElementMapForSnapshot(snapshot) {
        const permanentElementMap = {};
        for (const currentPermanentElement of this.permanentElements) {
            const { id } = currentPermanentElement;
            const newPermanentElement = snapshot.getPermanentElementById(id);
            if (newPermanentElement) {
                permanentElementMap[id] = [currentPermanentElement, newPermanentElement];
            }
        }
        return permanentElementMap;
    }
}
function getPermanentElementById(node, id) {
    return node.querySelector(`#${id}[data-turbo-permanent]`);
}
function queryPermanentElementsAll(node) {
    return node.querySelectorAll("[id][data-turbo-permanent]");
}

class FormSubmitObserver {
    constructor(delegate, eventTarget) {
        this.started = false;
        this.submitCaptured = () => {
            this.eventTarget.removeEventListener("submit", this.submitBubbled, false);
            this.eventTarget.addEventListener("submit", this.submitBubbled, false);
        };
        this.submitBubbled = ((event) => {
            if (!event.defaultPrevented) {
                const form = event.target instanceof HTMLFormElement ? event.target : undefined;
                const submitter = event.submitter || undefined;
                if (form &&
                    submissionDoesNotDismissDialog(form, submitter) &&
                    submissionDoesNotTargetIFrame(form, submitter) &&
                    this.delegate.willSubmitForm(form, submitter)) {
                    event.preventDefault();
                    event.stopImmediatePropagation();
                    this.delegate.formSubmitted(form, submitter);
                }
            }
        });
        this.delegate = delegate;
        this.eventTarget = eventTarget;
    }
    start() {
        if (!this.started) {
            this.eventTarget.addEventListener("submit", this.submitCaptured, true);
            this.started = true;
        }
    }
    stop() {
        if (this.started) {
            this.eventTarget.removeEventListener("submit", this.submitCaptured, true);
            this.started = false;
        }
    }
}
function submissionDoesNotDismissDialog(form, submitter) {
    const method = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formmethod")) || form.getAttribute("method");
    return method != "dialog";
}
function submissionDoesNotTargetIFrame(form, submitter) {
    if ((submitter === null || submitter === void 0 ? void 0 : submitter.hasAttribute("formtarget")) || form.hasAttribute("target")) {
        const target = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("formtarget")) || form.target;
        for (const element of document.getElementsByName(target)) {
            if (element instanceof HTMLIFrameElement)
                return false;
        }
        return true;
    }
    else {
        return true;
    }
}

class View {
    constructor(delegate, element) {
        this.resolveRenderPromise = (_value) => { };
        this.resolveInterceptionPromise = (_value) => { };
        this.delegate = delegate;
        this.element = element;
    }
    scrollToAnchor(anchor) {
        const element = this.snapshot.getElementForAnchor(anchor);
        if (element) {
            this.scrollToElement(element);
            this.focusElement(element);
        }
        else {
            this.scrollToPosition({ x: 0, y: 0 });
        }
    }
    scrollToAnchorFromLocation(location) {
        this.scrollToAnchor(getAnchor(location));
    }
    scrollToElement(element) {
        element.scrollIntoView();
    }
    focusElement(element) {
        if (element instanceof HTMLElement) {
            if (element.hasAttribute("tabindex")) {
                element.focus();
            }
            else {
                element.setAttribute("tabindex", "-1");
                element.focus();
                element.removeAttribute("tabindex");
            }
        }
    }
    scrollToPosition({ x, y }) {
        this.scrollRoot.scrollTo(x, y);
    }
    scrollToTop() {
        this.scrollToPosition({ x: 0, y: 0 });
    }
    get scrollRoot() {
        return window;
    }
    async render(renderer) {
        const { isPreview, shouldRender, newSnapshot: snapshot } = renderer;
        if (shouldRender) {
            try {
                this.renderPromise = new Promise((resolve) => (this.resolveRenderPromise = resolve));
                this.renderer = renderer;
                await this.prepareToRenderSnapshot(renderer);
                const renderInterception = new Promise((resolve) => (this.resolveInterceptionPromise = resolve));
                const options = { resume: this.resolveInterceptionPromise, render: this.renderer.renderElement };
                const immediateRender = this.delegate.allowsImmediateRender(snapshot, options);
                if (!immediateRender)
                    await renderInterception;
                await this.renderSnapshot(renderer);
                this.delegate.viewRenderedSnapshot(snapshot, isPreview);
                this.delegate.preloadOnLoadLinksForView(this.element);
                this.finishRenderingSnapshot(renderer);
            }
            finally {
                delete this.renderer;
                this.resolveRenderPromise(undefined);
                delete this.renderPromise;
            }
        }
        else {
            this.invalidate(renderer.reloadReason);
        }
    }
    invalidate(reason) {
        this.delegate.viewInvalidated(reason);
    }
    async prepareToRenderSnapshot(renderer) {
        this.markAsPreview(renderer.isPreview);
        await renderer.prepareToRender();
    }
    markAsPreview(isPreview) {
        if (isPreview) {
            this.element.setAttribute("data-turbo-preview", "");
        }
        else {
            this.element.removeAttribute("data-turbo-preview");
        }
    }
    async renderSnapshot(renderer) {
        await renderer.render();
    }
    finishRenderingSnapshot(renderer) {
        renderer.finishRendering();
    }
}

class FrameView extends View {
    missing() {
        this.element.innerHTML = `<strong class="turbo-frame-error">Content missing</strong>`;
    }
    get snapshot() {
        return new Snapshot(this.element);
    }
}

class LinkInterceptor {
    constructor(delegate, element) {
        this.clickBubbled = (event) => {
            if (this.respondsToEventTarget(event.target)) {
                this.clickEvent = event;
            }
            else {
                delete this.clickEvent;
            }
        };
        this.linkClicked = ((event) => {
            if (this.clickEvent && this.respondsToEventTarget(event.target) && event.target instanceof Element) {
                if (this.delegate.shouldInterceptLinkClick(event.target, event.detail.url, event.detail.originalEvent)) {
                    this.clickEvent.preventDefault();
                    event.preventDefault();
                    this.delegate.linkClickIntercepted(event.target, event.detail.url, event.detail.originalEvent);
                }
            }
            delete this.clickEvent;
        });
        this.willVisit = ((_event) => {
            delete this.clickEvent;
        });
        this.delegate = delegate;
        this.element = element;
    }
    start() {
        this.element.addEventListener("click", this.clickBubbled);
        document.addEventListener("turbo:click", this.linkClicked);
        document.addEventListener("turbo:before-visit", this.willVisit);
    }
    stop() {
        this.element.removeEventListener("click", this.clickBubbled);
        document.removeEventListener("turbo:click", this.linkClicked);
        document.removeEventListener("turbo:before-visit", this.willVisit);
    }
    respondsToEventTarget(target) {
        const element = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
        return element && element.closest("turbo-frame, html") == this.element;
    }
}

class LinkClickObserver {
    constructor(delegate, eventTarget) {
        this.started = false;
        this.clickCaptured = () => {
            this.eventTarget.removeEventListener("click", this.clickBubbled, false);
            this.eventTarget.addEventListener("click", this.clickBubbled, false);
        };
        this.clickBubbled = (event) => {
            if (event instanceof MouseEvent && this.clickEventIsSignificant(event)) {
                const target = (event.composedPath && event.composedPath()[0]) || event.target;
                const link = this.findLinkFromClickTarget(target);
                if (link && doesNotTargetIFrame(link)) {
                    const location = this.getLocationForLink(link);
                    if (this.delegate.willFollowLinkToLocation(link, location, event)) {
                        event.preventDefault();
                        this.delegate.followedLinkToLocation(link, location);
                    }
                }
            }
        };
        this.delegate = delegate;
        this.eventTarget = eventTarget;
    }
    start() {
        if (!this.started) {
            this.eventTarget.addEventListener("click", this.clickCaptured, true);
            this.started = true;
        }
    }
    stop() {
        if (this.started) {
            this.eventTarget.removeEventListener("click", this.clickCaptured, true);
            this.started = false;
        }
    }
    clickEventIsSignificant(event) {
        return !((event.target && event.target.isContentEditable) ||
            event.defaultPrevented ||
            event.which > 1 ||
            event.altKey ||
            event.ctrlKey ||
            event.metaKey ||
            event.shiftKey);
    }
    findLinkFromClickTarget(target) {
        return findClosestRecursively(target, "a[href]:not([target^=_]):not([download])");
    }
    getLocationForLink(link) {
        return expandURL(link.getAttribute("href") || "");
    }
}
function doesNotTargetIFrame(anchor) {
    if (anchor.hasAttribute("target")) {
        for (const element of document.getElementsByName(anchor.target)) {
            if (element instanceof HTMLIFrameElement)
                return false;
        }
        return true;
    }
    else {
        return true;
    }
}

class FormLinkClickObserver {
    constructor(delegate, element) {
        this.delegate = delegate;
        this.linkInterceptor = new LinkClickObserver(this, element);
    }
    start() {
        this.linkInterceptor.start();
    }
    stop() {
        this.linkInterceptor.stop();
    }
    willFollowLinkToLocation(link, location, originalEvent) {
        return (this.delegate.willSubmitFormLinkToLocation(link, location, originalEvent) &&
            link.hasAttribute("data-turbo-method"));
    }
    followedLinkToLocation(link, location) {
        const form = document.createElement("form");
        const type = "hidden";
        for (const [name, value] of location.searchParams) {
            form.append(Object.assign(document.createElement("input"), { type, name, value }));
        }
        const action = Object.assign(location, { search: "" });
        form.setAttribute("data-turbo", "true");
        form.setAttribute("action", action.href);
        form.setAttribute("hidden", "");
        const method = link.getAttribute("data-turbo-method");
        if (method)
            form.setAttribute("method", method);
        const turboFrame = link.getAttribute("data-turbo-frame");
        if (turboFrame)
            form.setAttribute("data-turbo-frame", turboFrame);
        const turboAction = getVisitAction(link);
        if (turboAction)
            form.setAttribute("data-turbo-action", turboAction);
        const turboConfirm = link.getAttribute("data-turbo-confirm");
        if (turboConfirm)
            form.setAttribute("data-turbo-confirm", turboConfirm);
        const turboStream = link.hasAttribute("data-turbo-stream");
        if (turboStream)
            form.setAttribute("data-turbo-stream", "");
        this.delegate.submittedFormLinkToLocation(link, location, form);
        document.body.appendChild(form);
        form.addEventListener("turbo:submit-end", () => form.remove(), { once: true });
        requestAnimationFrame(() => form.requestSubmit());
    }
}

class Bardo {
    static async preservingPermanentElements(delegate, permanentElementMap, callback) {
        const bardo = new this(delegate, permanentElementMap);
        bardo.enter();
        await callback();
        bardo.leave();
    }
    constructor(delegate, permanentElementMap) {
        this.delegate = delegate;
        this.permanentElementMap = permanentElementMap;
    }
    enter() {
        for (const id in this.permanentElementMap) {
            const [currentPermanentElement, newPermanentElement] = this.permanentElementMap[id];
            this.delegate.enteringBardo(currentPermanentElement, newPermanentElement);
            this.replaceNewPermanentElementWithPlaceholder(newPermanentElement);
        }
    }
    leave() {
        for (const id in this.permanentElementMap) {
            const [currentPermanentElement] = this.permanentElementMap[id];
            this.replaceCurrentPermanentElementWithClone(currentPermanentElement);
            this.replacePlaceholderWithPermanentElement(currentPermanentElement);
            this.delegate.leavingBardo(currentPermanentElement);
        }
    }
    replaceNewPermanentElementWithPlaceholder(permanentElement) {
        const placeholder = createPlaceholderForPermanentElement(permanentElement);
        permanentElement.replaceWith(placeholder);
    }
    replaceCurrentPermanentElementWithClone(permanentElement) {
        const clone = permanentElement.cloneNode(true);
        permanentElement.replaceWith(clone);
    }
    replacePlaceholderWithPermanentElement(permanentElement) {
        const placeholder = this.getPlaceholderById(permanentElement.id);
        placeholder === null || placeholder === void 0 ? void 0 : placeholder.replaceWith(permanentElement);
    }
    getPlaceholderById(id) {
        return this.placeholders.find((element) => element.content == id);
    }
    get placeholders() {
        return [...document.querySelectorAll("meta[name=turbo-permanent-placeholder][content]")];
    }
}
function createPlaceholderForPermanentElement(permanentElement) {
    const element = document.createElement("meta");
    element.setAttribute("name", "turbo-permanent-placeholder");
    element.setAttribute("content", permanentElement.id);
    return element;
}

class Renderer {
    constructor(currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
        this.activeElement = null;
        this.currentSnapshot = currentSnapshot;
        this.newSnapshot = newSnapshot;
        this.isPreview = isPreview;
        this.willRender = willRender;
        this.renderElement = renderElement;
        this.promise = new Promise((resolve, reject) => (this.resolvingFunctions = { resolve, reject }));
    }
    get shouldRender() {
        return true;
    }
    get reloadReason() {
        return;
    }
    prepareToRender() {
        return;
    }
    finishRendering() {
        if (this.resolvingFunctions) {
            this.resolvingFunctions.resolve();
            delete this.resolvingFunctions;
        }
    }
    async preservingPermanentElements(callback) {
        await Bardo.preservingPermanentElements(this, this.permanentElementMap, callback);
    }
    focusFirstAutofocusableElement() {
        const element = this.connectedSnapshot.firstAutofocusableElement;
        if (elementIsFocusable(element)) {
            element.focus();
        }
    }
    enteringBardo(currentPermanentElement) {
        if (this.activeElement)
            return;
        if (currentPermanentElement.contains(this.currentSnapshot.activeElement)) {
            this.activeElement = this.currentSnapshot.activeElement;
        }
    }
    leavingBardo(currentPermanentElement) {
        if (currentPermanentElement.contains(this.activeElement) && this.activeElement instanceof HTMLElement) {
            this.activeElement.focus();
            this.activeElement = null;
        }
    }
    get connectedSnapshot() {
        return this.newSnapshot.isConnected ? this.newSnapshot : this.currentSnapshot;
    }
    get currentElement() {
        return this.currentSnapshot.element;
    }
    get newElement() {
        return this.newSnapshot.element;
    }
    get permanentElementMap() {
        return this.currentSnapshot.getPermanentElementMapForSnapshot(this.newSnapshot);
    }
}
function elementIsFocusable(element) {
    return element && typeof element.focus == "function";
}

class FrameRenderer extends Renderer {
    static renderElement(currentElement, newElement) {
        var _a;
        const destinationRange = document.createRange();
        destinationRange.selectNodeContents(currentElement);
        destinationRange.deleteContents();
        const frameElement = newElement;
        const sourceRange = (_a = frameElement.ownerDocument) === null || _a === void 0 ? void 0 : _a.createRange();
        if (sourceRange) {
            sourceRange.selectNodeContents(frameElement);
            currentElement.appendChild(sourceRange.extractContents());
        }
    }
    constructor(delegate, currentSnapshot, newSnapshot, renderElement, isPreview, willRender = true) {
        super(currentSnapshot, newSnapshot, renderElement, isPreview, willRender);
        this.delegate = delegate;
    }
    get shouldRender() {
        return true;
    }
    async render() {
        await nextAnimationFrame();
        this.preservingPermanentElements(() => {
            this.loadFrameElement();
        });
        this.scrollFrameIntoView();
        await nextAnimationFrame();
        this.focusFirstAutofocusableElement();
        await nextAnimationFrame();
        this.activateScriptElements();
    }
    loadFrameElement() {
        this.delegate.willRenderFrame(this.currentElement, this.newElement);
        this.renderElement(this.currentElement, this.newElement);
    }
    scrollFrameIntoView() {
        if (this.currentElement.autoscroll || this.newElement.autoscroll) {
            const element = this.currentElement.firstElementChild;
            const block = readScrollLogicalPosition(this.currentElement.getAttribute("data-autoscroll-block"), "end");
            const behavior = readScrollBehavior(this.currentElement.getAttribute("data-autoscroll-behavior"), "auto");
            if (element) {
                element.scrollIntoView({ block, behavior });
                return true;
            }
        }
        return false;
    }
    activateScriptElements() {
        for (const inertScriptElement of this.newScriptElements) {
            const activatedScriptElement = activateScriptElement(inertScriptElement);
            inertScriptElement.replaceWith(activatedScriptElement);
        }
    }
    get newScriptElements() {
        return this.currentElement.querySelectorAll("script");
    }
}
function readScrollLogicalPosition(value, defaultValue) {
    if (value == "end" || value == "start" || value == "center" || value == "nearest") {
        return value;
    }
    else {
        return defaultValue;
    }
}
function readScrollBehavior(value, defaultValue) {
    if (value == "auto" || value == "smooth") {
        return value;
    }
    else {
        return defaultValue;
    }
}

class ProgressBar {
    static get defaultCSS() {
        return unindent `
      .turbo-progress-bar {
        position: fixed;
        display: block;
        top: 0;
        left: 0;
        height: 3px;
        background: #0076ff;
        z-index: 2147483647;
        transition:
          width ${ProgressBar.animationDuration}ms ease-out,
          opacity ${ProgressBar.animationDuration / 2}ms ${ProgressBar.animationDuration / 2}ms ease-in;
        transform: translate3d(0, 0, 0);
      }
    `;
    }
    constructor() {
        this.hiding = false;
        this.value = 0;
        this.visible = false;
        this.trickle = () => {
            this.setValue(this.value + Math.random() / 100);
        };
        this.stylesheetElement = this.createStylesheetElement();
        this.progressElement = this.createProgressElement();
        this.installStylesheetElement();
        this.setValue(0);
    }
    show() {
        if (!this.visible) {
            this.visible = true;
            this.installProgressElement();
            this.startTrickling();
        }
    }
    hide() {
        if (this.visible && !this.hiding) {
            this.hiding = true;
            this.fadeProgressElement(() => {
                this.uninstallProgressElement();
                this.stopTrickling();
                this.visible = false;
                this.hiding = false;
            });
        }
    }
    setValue(value) {
        this.value = value;
        this.refresh();
    }
    installStylesheetElement() {
        document.head.insertBefore(this.stylesheetElement, document.head.firstChild);
    }
    installProgressElement() {
        this.progressElement.style.width = "0";
        this.progressElement.style.opacity = "1";
        document.documentElement.insertBefore(this.progressElement, document.body);
        this.refresh();
    }
    fadeProgressElement(callback) {
        this.progressElement.style.opacity = "0";
        setTimeout(callback, ProgressBar.animationDuration * 1.5);
    }
    uninstallProgressElement() {
        if (this.progressElement.parentNode) {
            document.documentElement.removeChild(this.progressElement);
        }
    }
    startTrickling() {
        if (!this.trickleInterval) {
            this.trickleInterval = window.setInterval(this.trickle, ProgressBar.animationDuration);
        }
    }
    stopTrickling() {
        window.clearInterval(this.trickleInterval);
        delete this.trickleInterval;
    }
    refresh() {
        requestAnimationFrame(() => {
            this.progressElement.style.width = `${10 + this.value * 90}%`;
        });
    }
    createStylesheetElement() {
        const element = document.createElement("style");
        element.type = "text/css";
        element.textContent = ProgressBar.defaultCSS;
        if (this.cspNonce) {
            element.nonce = this.cspNonce;
        }
        return element;
    }
    createProgressElement() {
        const element = document.createElement("div");
        element.className = "turbo-progress-bar";
        return element;
    }
    get cspNonce() {
        return getMetaContent("csp-nonce");
    }
}
ProgressBar.animationDuration = 300;

class HeadSnapshot extends Snapshot {
    constructor() {
        super(...arguments);
        this.detailsByOuterHTML = this.children
            .filter((element) => !elementIsNoscript(element))
            .map((element) => elementWithoutNonce(element))
            .reduce((result, element) => {
            const { outerHTML } = element;
            const details = outerHTML in result
                ? result[outerHTML]
                : {
                    type: elementType(element),
                    tracked: elementIsTracked(element),
                    elements: [],
                };
            return Object.assign(Object.assign({}, result), { [outerHTML]: Object.assign(Object.assign({}, details), { elements: [...details.elements, element] }) });
        }, {});
    }
    get trackedElementSignature() {
        return Object.keys(this.detailsByOuterHTML)
            .filter((outerHTML) => this.detailsByOuterHTML[outerHTML].tracked)
            .join("");
    }
    getScriptElementsNotInSnapshot(snapshot) {
        return this.getElementsMatchingTypeNotInSnapshot("script", snapshot);
    }
    getStylesheetElementsNotInSnapshot(snapshot) {
        return this.getElementsMatchingTypeNotInSnapshot("stylesheet", snapshot);
    }
    getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
        return Object.keys(this.detailsByOuterHTML)
            .filter((outerHTML) => !(outerHTML in snapshot.detailsByOuterHTML))
            .map((outerHTML) => this.detailsByOuterHTML[outerHTML])
            .filter(({ type }) => type == matchedType)
            .map(({ elements: [element] }) => element);
    }
    get provisionalElements() {
        return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
            const { type, tracked, elements } = this.detailsByOuterHTML[outerHTML];
            if (type == null && !tracked) {
                return [...result, ...elements];
            }
            else if (elements.length > 1) {
                return [...result, ...elements.slice(1)];
            }
            else {
                return result;
            }
        }, []);
    }
    getMetaValue(name) {
        const element = this.findMetaElementByName(name);
        return element ? element.getAttribute("content") : null;
    }
    findMetaElementByName(name) {
        return Object.keys(this.detailsByOuterHTML).reduce((result, outerHTML) => {
            const { elements: [element], } = this.detailsByOuterHTML[outerHTML];
            return elementIsMetaElementWithName(element, name) ? element : result;
        }, undefined);
    }
}
function elementType(element) {
    if (elementIsScript(element)) {
        return "script";
    }
    else if (elementIsStylesheet(element)) {
        return "stylesheet";
    }
}
function elementIsTracked(element) {
    return element.getAttribute("data-turbo-track") == "reload";
}
function elementIsScript(element) {
    const tagName = element.localName;
    return tagName == "script";
}
function elementIsNoscript(element) {
    const tagName = element.localName;
    return tagName == "noscript";
}
function elementIsStylesheet(element) {
    const tagName = element.localName;
    return tagName == "style" || (tagName == "link" && element.getAttribute("rel") == "stylesheet");
}
function elementIsMetaElementWithName(element, name) {
    const tagName = element.localName;
    return tagName == "meta" && element.getAttribute("name") == name;
}
function elementWithoutNonce(element) {
    if (element.hasAttribute("nonce")) {
        element.setAttribute("nonce", "");
    }
    return element;
}

class PageSnapshot extends Snapshot {
    static fromHTMLString(html = "") {
        return this.fromDocument(parseHTMLDocument(html));
    }
    static fromElement(element) {
        return this.fromDocument(element.ownerDocument);
    }
    static fromDocument({ head, body }) {
        return new this(body, new HeadSnapshot(head));
    }
    constructor(element, headSnapshot) {
        super(element);
        this.headSnapshot = headSnapshot;
    }
    clone() {
        const clonedElement = this.element.cloneNode(true);
        const selectElements = this.element.querySelectorAll("select");
        const clonedSelectElements = clonedElement.querySelectorAll("select");
        for (const [index, source] of selectElements.entries()) {
            const clone = clonedSelectElements[index];
            for (const option of clone.selectedOptions)
                option.selected = false;
            for (const option of source.selectedOptions)
                clone.options[option.index].selected = true;
        }
        for (const clonedPasswordInput of clonedElement.querySelectorAll('input[type="password"]')) {
            clonedPasswordInput.value = "";
        }
        return new PageSnapshot(clonedElement, this.headSnapshot);
    }
    get headElement() {
        return this.headSnapshot.element;
    }
    get rootLocation() {
        var _a;
        const root = (_a = this.getSetting("root")) !== null && _a !== void 0 ? _a : "/";
        return expandURL(root);
    }
    get cacheControlValue() {
        return this.getSetting("cache-control");
    }
    get isPreviewable() {
        return this.cacheControlValue != "no-preview";
    }
    get isCacheable() {
        return this.cacheControlValue != "no-cache";
    }
    get isVisitable() {
        return this.getSetting("visit-control") != "reload";
    }
    getSetting(name) {
        return this.headSnapshot.getMetaValue(`turbo-${name}`);
    }
}

var TimingMetric;
(function (TimingMetric) {
    TimingMetric["visitStart"] = "visitStart";
    TimingMetric["requestStart"] = "requestStart";
    TimingMetric["requestEnd"] = "requestEnd";
    TimingMetric["visitEnd"] = "visitEnd";
})(TimingMetric || (TimingMetric = {}));
var VisitState;
(function (VisitState) {
    VisitState["initialized"] = "initialized";
    VisitState["started"] = "started";
    VisitState["canceled"] = "canceled";
    VisitState["failed"] = "failed";
    VisitState["completed"] = "completed";
})(VisitState || (VisitState = {}));
const defaultOptions = {
    action: "advance",
    historyChanged: false,
    visitCachedSnapshot: () => { },
    willRender: true,
    updateHistory: true,
    shouldCacheSnapshot: true,
    acceptsStreamResponse: false,
};
var SystemStatusCode;
(function (SystemStatusCode) {
    SystemStatusCode[SystemStatusCode["networkFailure"] = 0] = "networkFailure";
    SystemStatusCode[SystemStatusCode["timeoutFailure"] = -1] = "timeoutFailure";
    SystemStatusCode[SystemStatusCode["contentTypeMismatch"] = -2] = "contentTypeMismatch";
})(SystemStatusCode || (SystemStatusCode = {}));
class Visit {
    constructor(delegate, location, restorationIdentifier, options = {}) {
        this.identifier = uuid();
        this.timingMetrics = {};
        this.followedRedirect = false;
        this.historyChanged = false;
        this.scrolled = false;
        this.shouldCacheSnapshot = true;
        this.acceptsStreamResponse = false;
        this.snapshotCached = false;
        this.state = VisitState.initialized;
        this.delegate = delegate;
        this.location = location;
        this.restorationIdentifier = restorationIdentifier || uuid();
        const { action, historyChanged, referrer, snapshot, snapshotHTML, response, visitCachedSnapshot, willRender, updateHistory, shouldCacheSnapshot, acceptsStreamResponse, } = Object.assign(Object.assign({}, defaultOptions), options);
        this.action = action;
        this.historyChanged = historyChanged;
        this.referrer = referrer;
        this.snapshot = snapshot;
        this.snapshotHTML = snapshotHTML;
        this.response = response;
        this.isSamePage = this.delegate.locationWithActionIsSamePage(this.location, this.action);
        this.visitCachedSnapshot = visitCachedSnapshot;
        this.willRender = willRender;
        this.updateHistory = updateHistory;
        this.scrolled = !willRender;
        this.shouldCacheSnapshot = shouldCacheSnapshot;
        this.acceptsStreamResponse = acceptsStreamResponse;
    }
    get adapter() {
        return this.delegate.adapter;
    }
    get view() {
        return this.delegate.view;
    }
    get history() {
        return this.delegate.history;
    }
    get restorationData() {
        return this.history.getRestorationDataForIdentifier(this.restorationIdentifier);
    }
    get silent() {
        return this.isSamePage;
    }
    start() {
        if (this.state == VisitState.initialized) {
            this.recordTimingMetric(TimingMetric.visitStart);
            this.state = VisitState.started;
            this.adapter.visitStarted(this);
            this.delegate.visitStarted(this);
        }
    }
    cancel() {
        if (this.state == VisitState.started) {
            if (this.request) {
                this.request.cancel();
            }
            this.cancelRender();
            this.state = VisitState.canceled;
        }
    }
    complete() {
        if (this.state == VisitState.started) {
            this.recordTimingMetric(TimingMetric.visitEnd);
            this.state = VisitState.completed;
            this.followRedirect();
            if (!this.followedRedirect) {
                this.adapter.visitCompleted(this);
                this.delegate.visitCompleted(this);
            }
        }
    }
    fail() {
        if (this.state == VisitState.started) {
            this.state = VisitState.failed;
            this.adapter.visitFailed(this);
        }
    }
    changeHistory() {
        var _a;
        if (!this.historyChanged && this.updateHistory) {
            const actionForHistory = this.location.href === ((_a = this.referrer) === null || _a === void 0 ? void 0 : _a.href) ? "replace" : this.action;
            const method = getHistoryMethodForAction(actionForHistory);
            this.history.update(method, this.location, this.restorationIdentifier);
            this.historyChanged = true;
        }
    }
    issueRequest() {
        if (this.hasPreloadedResponse()) {
            this.simulateRequest();
        }
        else if (this.shouldIssueRequest() && !this.request) {
            this.request = new FetchRequest(this, FetchMethod.get, this.location);
            this.request.perform();
        }
    }
    simulateRequest() {
        if (this.response) {
            this.startRequest();
            this.recordResponse();
            this.finishRequest();
        }
    }
    startRequest() {
        this.recordTimingMetric(TimingMetric.requestStart);
        this.adapter.visitRequestStarted(this);
    }
    recordResponse(response = this.response) {
        this.response = response;
        if (response) {
            const { statusCode } = response;
            if (isSuccessful(statusCode)) {
                this.adapter.visitRequestCompleted(this);
            }
            else {
                this.adapter.visitRequestFailedWithStatusCode(this, statusCode);
            }
        }
    }
    finishRequest() {
        this.recordTimingMetric(TimingMetric.requestEnd);
        this.adapter.visitRequestFinished(this);
    }
    loadResponse() {
        if (this.response) {
            const { statusCode, responseHTML } = this.response;
            this.render(async () => {
                if (this.shouldCacheSnapshot)
                    this.cacheSnapshot();
                if (this.view.renderPromise)
                    await this.view.renderPromise;
                if (isSuccessful(statusCode) && responseHTML != null) {
                    await this.view.renderPage(PageSnapshot.fromHTMLString(responseHTML), false, this.willRender, this);
                    this.performScroll();
                    this.adapter.visitRendered(this);
                    this.complete();
                }
                else {
                    await this.view.renderError(PageSnapshot.fromHTMLString(responseHTML), this);
                    this.adapter.visitRendered(this);
                    this.fail();
                }
            });
        }
    }
    getCachedSnapshot() {
        const snapshot = this.view.getCachedSnapshotForLocation(this.location) || this.getPreloadedSnapshot();
        if (snapshot && (!getAnchor(this.location) || snapshot.hasAnchor(getAnchor(this.location)))) {
            if (this.action == "restore" || snapshot.isPreviewable) {
                return snapshot;
            }
        }
    }
    getPreloadedSnapshot() {
        if (this.snapshotHTML) {
            return PageSnapshot.fromHTMLString(this.snapshotHTML);
        }
    }
    hasCachedSnapshot() {
        return this.getCachedSnapshot() != null;
    }
    loadCachedSnapshot() {
        const snapshot = this.getCachedSnapshot();
        if (snapshot) {
            const isPreview = this.shouldIssueRequest();
            this.render(async () => {
                this.cacheSnapshot();
                if (this.isSamePage) {
                    this.adapter.visitRendered(this);
                }
                else {
                    if (this.view.renderPromise)
                        await this.view.renderPromise;
                    await this.view.renderPage(snapshot, isPreview, this.willRender, this);
                    this.performScroll();
                    this.adapter.visitRendered(this);
                    if (!isPreview) {
                        this.complete();
                    }
                }
            });
        }
    }
    followRedirect() {
        var _a;
        if (this.redirectedToLocation && !this.followedRedirect && ((_a = this.response) === null || _a === void 0 ? void 0 : _a.redirected)) {
            this.adapter.visitProposedToLocation(this.redirectedToLocation, {
                action: "replace",
                response: this.response,
                shouldCacheSnapshot: false,
                willRender: false,
            });
            this.followedRedirect = true;
        }
    }
    goToSamePageAnchor() {
        if (this.isSamePage) {
            this.render(async () => {
                this.cacheSnapshot();
                this.performScroll();
                this.changeHistory();
                this.adapter.visitRendered(this);
            });
        }
    }
    prepareRequest(request) {
        if (this.acceptsStreamResponse) {
            request.acceptResponseType(StreamMessage.contentType);
        }
    }
    requestStarted() {
        this.startRequest();
    }
    requestPreventedHandlingResponse(_request, _response) { }
    async requestSucceededWithResponse(request, response) {
        const responseHTML = await response.responseHTML;
        const { redirected, statusCode } = response;
        if (responseHTML == undefined) {
            this.recordResponse({
                statusCode: SystemStatusCode.contentTypeMismatch,
                redirected,
            });
        }
        else {
            this.redirectedToLocation = response.redirected ? response.location : undefined;
            this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
        }
    }
    async requestFailedWithResponse(request, response) {
        const responseHTML = await response.responseHTML;
        const { redirected, statusCode } = response;
        if (responseHTML == undefined) {
            this.recordResponse({
                statusCode: SystemStatusCode.contentTypeMismatch,
                redirected,
            });
        }
        else {
            this.recordResponse({ statusCode: statusCode, responseHTML, redirected });
        }
    }
    requestErrored(_request, _error) {
        this.recordResponse({
            statusCode: SystemStatusCode.networkFailure,
            redirected: false,
        });
    }
    requestFinished() {
        this.finishRequest();
    }
    performScroll() {
        if (!this.scrolled && !this.view.forceReloaded) {
            if (this.action == "restore") {
                this.scrollToRestoredPosition() || this.scrollToAnchor() || this.view.scrollToTop();
            }
            else {
                this.scrollToAnchor() || this.view.scrollToTop();
            }
            if (this.isSamePage) {
                this.delegate.visitScrolledToSamePageLocation(this.view.lastRenderedLocation, this.location);
            }
            this.scrolled = true;
        }
    }
    scrollToRestoredPosition() {
        const { scrollPosition } = this.restorationData;
        if (scrollPosition) {
            this.view.scrollToPosition(scrollPosition);
            return true;
        }
    }
    scrollToAnchor() {
        const anchor = getAnchor(this.location);
        if (anchor != null) {
            this.view.scrollToAnchor(anchor);
            return true;
        }
    }
    recordTimingMetric(metric) {
        this.timingMetrics[metric] = new Date().getTime();
    }
    getTimingMetrics() {
        return Object.assign({}, this.timingMetrics);
    }
    getHistoryMethodForAction(action) {
        switch (action) {
            case "replace":
                return history.replaceState;
            case "advance":
            case "restore":
                return history.pushState;
        }
    }
    hasPreloadedResponse() {
        return typeof this.response == "object";
    }
    shouldIssueRequest() {
        if (this.isSamePage) {
            return false;
        }
        else if (this.action == "restore") {
            return !this.hasCachedSnapshot();
        }
        else {
            return this.willRender;
        }
    }
    cacheSnapshot() {
        if (!this.snapshotCached) {
            this.view.cacheSnapshot(this.snapshot).then((snapshot) => snapshot && this.visitCachedSnapshot(snapshot));
            this.snapshotCached = true;
        }
    }
    async render(callback) {
        this.cancelRender();
        await new Promise((resolve) => {
            this.frame = requestAnimationFrame(() => resolve());
        });
        await callback();
        delete this.frame;
    }
    cancelRender() {
        if (this.frame) {
            cancelAnimationFrame(this.frame);
            delete this.frame;
        }
    }
}
function isSuccessful(statusCode) {
    return statusCode >= 200 && statusCode < 300;
}

class BrowserAdapter {
    constructor(session) {
        this.progressBar = new ProgressBar();
        this.showProgressBar = () => {
            this.progressBar.show();
        };
        this.session = session;
    }
    visitProposedToLocation(location, options) {
        this.navigator.startVisit(location, (options === null || options === void 0 ? void 0 : options.restorationIdentifier) || uuid(), options);
    }
    visitStarted(visit) {
        this.location = visit.location;
        visit.loadCachedSnapshot();
        visit.issueRequest();
        visit.goToSamePageAnchor();
    }
    visitRequestStarted(visit) {
        this.progressBar.setValue(0);
        if (visit.hasCachedSnapshot() || visit.action != "restore") {
            this.showVisitProgressBarAfterDelay();
        }
        else {
            this.showProgressBar();
        }
    }
    visitRequestCompleted(visit) {
        visit.loadResponse();
    }
    visitRequestFailedWithStatusCode(visit, statusCode) {
        switch (statusCode) {
            case SystemStatusCode.networkFailure:
            case SystemStatusCode.timeoutFailure:
            case SystemStatusCode.contentTypeMismatch:
                return this.reload({
                    reason: "request_failed",
                    context: {
                        statusCode,
                    },
                });
            default:
                return visit.loadResponse();
        }
    }
    visitRequestFinished(_visit) {
        this.progressBar.setValue(1);
        this.hideVisitProgressBar();
    }
    visitCompleted(_visit) { }
    pageInvalidated(reason) {
        this.reload(reason);
    }
    visitFailed(_visit) { }
    visitRendered(_visit) { }
    formSubmissionStarted(_formSubmission) {
        this.progressBar.setValue(0);
        this.showFormProgressBarAfterDelay();
    }
    formSubmissionFinished(_formSubmission) {
        this.progressBar.setValue(1);
        this.hideFormProgressBar();
    }
    showVisitProgressBarAfterDelay() {
        this.visitProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
    }
    hideVisitProgressBar() {
        this.progressBar.hide();
        if (this.visitProgressBarTimeout != null) {
            window.clearTimeout(this.visitProgressBarTimeout);
            delete this.visitProgressBarTimeout;
        }
    }
    showFormProgressBarAfterDelay() {
        if (this.formProgressBarTimeout == null) {
            this.formProgressBarTimeout = window.setTimeout(this.showProgressBar, this.session.progressBarDelay);
        }
    }
    hideFormProgressBar() {
        this.progressBar.hide();
        if (this.formProgressBarTimeout != null) {
            window.clearTimeout(this.formProgressBarTimeout);
            delete this.formProgressBarTimeout;
        }
    }
    reload(reason) {
        var _a;
        dispatch("turbo:reload", { detail: reason });
        window.location.href = ((_a = this.location) === null || _a === void 0 ? void 0 : _a.toString()) || window.location.href;
    }
    get navigator() {
        return this.session.navigator;
    }
}

class CacheObserver {
    constructor() {
        this.selector = "[data-turbo-temporary]";
        this.deprecatedSelector = "[data-turbo-cache=false]";
        this.started = false;
        this.removeTemporaryElements = ((_event) => {
            for (const element of this.temporaryElements) {
                element.remove();
            }
        });
    }
    start() {
        if (!this.started) {
            this.started = true;
            addEventListener("turbo:before-cache", this.removeTemporaryElements, false);
        }
    }
    stop() {
        if (this.started) {
            this.started = false;
            removeEventListener("turbo:before-cache", this.removeTemporaryElements, false);
        }
    }
    get temporaryElements() {
        return [...document.querySelectorAll(this.selector), ...this.temporaryElementsWithDeprecation];
    }
    get temporaryElementsWithDeprecation() {
        const elements = document.querySelectorAll(this.deprecatedSelector);
        if (elements.length) {
            console.warn(`The ${this.deprecatedSelector} selector is deprecated and will be removed in a future version. Use ${this.selector} instead.`);
        }
        return [...elements];
    }
}

class FrameRedirector {
    constructor(session, element) {
        this.session = session;
        this.element = element;
        this.linkInterceptor = new LinkInterceptor(this, element);
        this.formSubmitObserver = new FormSubmitObserver(this, element);
    }
    start() {
        this.linkInterceptor.start();
        this.formSubmitObserver.start();
    }
    stop() {
        this.linkInterceptor.stop();
        this.formSubmitObserver.stop();
    }
    shouldInterceptLinkClick(element, _location, _event) {
        return this.shouldRedirect(element);
    }
    linkClickIntercepted(element, url, event) {
        const frame = this.findFrameElement(element);
        if (frame) {
            frame.delegate.linkClickIntercepted(element, url, event);
        }
    }
    willSubmitForm(element, submitter) {
        return (element.closest("turbo-frame") == null &&
            this.shouldSubmit(element, submitter) &&
            this.shouldRedirect(element, submitter));
    }
    formSubmitted(element, submitter) {
        const frame = this.findFrameElement(element, submitter);
        if (frame) {
            frame.delegate.formSubmitted(element, submitter);
        }
    }
    shouldSubmit(form, submitter) {
        var _a;
        const action = getAction(form, submitter);
        const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
        const rootLocation = expandURL((_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/");
        return this.shouldRedirect(form, submitter) && locationIsVisitable(action, rootLocation);
    }
    shouldRedirect(element, submitter) {
        const isNavigatable = element instanceof HTMLFormElement
            ? this.session.submissionIsNavigatable(element, submitter)
            : this.session.elementIsNavigatable(element);
        if (isNavigatable) {
            const frame = this.findFrameElement(element, submitter);
            return frame ? frame != element.closest("turbo-frame") : false;
        }
        else {
            return false;
        }
    }
    findFrameElement(element, submitter) {
        const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
        if (id && id != "_top") {
            const frame = this.element.querySelector(`#${id}:not([disabled])`);
            if (frame instanceof FrameElement) {
                return frame;
            }
        }
    }
}

class History {
    constructor(delegate) {
        this.restorationIdentifier = uuid();
        this.restorationData = {};
        this.started = false;
        this.pageLoaded = false;
        this.onPopState = (event) => {
            if (this.shouldHandlePopState()) {
                const { turbo } = event.state || {};
                if (turbo) {
                    this.location = new URL(window.location.href);
                    const { restorationIdentifier } = turbo;
                    this.restorationIdentifier = restorationIdentifier;
                    this.delegate.historyPoppedToLocationWithRestorationIdentifier(this.location, restorationIdentifier);
                }
            }
        };
        this.onPageLoad = async (_event) => {
            await nextMicrotask();
            this.pageLoaded = true;
        };
        this.delegate = delegate;
    }
    start() {
        if (!this.started) {
            addEventListener("popstate", this.onPopState, false);
            addEventListener("load", this.onPageLoad, false);
            this.started = true;
            this.replace(new URL(window.location.href));
        }
    }
    stop() {
        if (this.started) {
            removeEventListener("popstate", this.onPopState, false);
            removeEventListener("load", this.onPageLoad, false);
            this.started = false;
        }
    }
    push(location, restorationIdentifier) {
        this.update(history.pushState, location, restorationIdentifier);
    }
    replace(location, restorationIdentifier) {
        this.update(history.replaceState, location, restorationIdentifier);
    }
    update(method, location, restorationIdentifier = uuid()) {
        const state = { turbo: { restorationIdentifier } };
        method.call(history, state, "", location.href);
        this.location = location;
        this.restorationIdentifier = restorationIdentifier;
    }
    getRestorationDataForIdentifier(restorationIdentifier) {
        return this.restorationData[restorationIdentifier] || {};
    }
    updateRestorationData(additionalData) {
        const { restorationIdentifier } = this;
        const restorationData = this.restorationData[restorationIdentifier];
        this.restorationData[restorationIdentifier] = Object.assign(Object.assign({}, restorationData), additionalData);
    }
    assumeControlOfScrollRestoration() {
        var _a;
        if (!this.previousScrollRestoration) {
            this.previousScrollRestoration = (_a = history.scrollRestoration) !== null && _a !== void 0 ? _a : "auto";
            history.scrollRestoration = "manual";
        }
    }
    relinquishControlOfScrollRestoration() {
        if (this.previousScrollRestoration) {
            history.scrollRestoration = this.previousScrollRestoration;
            delete this.previousScrollRestoration;
        }
    }
    shouldHandlePopState() {
        return this.pageIsLoaded();
    }
    pageIsLoaded() {
        return this.pageLoaded || document.readyState == "complete";
    }
}

class Navigator {
    constructor(delegate) {
        this.delegate = delegate;
    }
    proposeVisit(location, options = {}) {
        if (this.delegate.allowsVisitingLocationWithAction(location, options.action)) {
            if (locationIsVisitable(location, this.view.snapshot.rootLocation)) {
                this.delegate.visitProposedToLocation(location, options);
            }
            else {
                window.location.href = location.toString();
            }
        }
    }
    startVisit(locatable, restorationIdentifier, options = {}) {
        this.stop();
        this.currentVisit = new Visit(this, expandURL(locatable), restorationIdentifier, Object.assign({ referrer: this.location }, options));
        this.currentVisit.start();
    }
    submitForm(form, submitter) {
        this.stop();
        this.formSubmission = new FormSubmission(this, form, submitter, true);
        this.formSubmission.start();
    }
    stop() {
        if (this.formSubmission) {
            this.formSubmission.stop();
            delete this.formSubmission;
        }
        if (this.currentVisit) {
            this.currentVisit.cancel();
            delete this.currentVisit;
        }
    }
    get adapter() {
        return this.delegate.adapter;
    }
    get view() {
        return this.delegate.view;
    }
    get history() {
        return this.delegate.history;
    }
    formSubmissionStarted(formSubmission) {
        if (typeof this.adapter.formSubmissionStarted === "function") {
            this.adapter.formSubmissionStarted(formSubmission);
        }
    }
    async formSubmissionSucceededWithResponse(formSubmission, fetchResponse) {
        if (formSubmission == this.formSubmission) {
            const responseHTML = await fetchResponse.responseHTML;
            if (responseHTML) {
                const shouldCacheSnapshot = formSubmission.isSafe;
                if (!shouldCacheSnapshot) {
                    this.view.clearSnapshotCache();
                }
                const { statusCode, redirected } = fetchResponse;
                const action = this.getActionForFormSubmission(formSubmission);
                const visitOptions = {
                    action,
                    shouldCacheSnapshot,
                    response: { statusCode, responseHTML, redirected },
                };
                this.proposeVisit(fetchResponse.location, visitOptions);
            }
        }
    }
    async formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
        const responseHTML = await fetchResponse.responseHTML;
        if (responseHTML) {
            const snapshot = PageSnapshot.fromHTMLString(responseHTML);
            if (fetchResponse.serverError) {
                await this.view.renderError(snapshot, this.currentVisit);
            }
            else {
                await this.view.renderPage(snapshot, false, true, this.currentVisit);
            }
            this.view.scrollToTop();
            this.view.clearSnapshotCache();
        }
    }
    formSubmissionErrored(formSubmission, error) {
        console.error(error);
    }
    formSubmissionFinished(formSubmission) {
        if (typeof this.adapter.formSubmissionFinished === "function") {
            this.adapter.formSubmissionFinished(formSubmission);
        }
    }
    visitStarted(visit) {
        this.delegate.visitStarted(visit);
    }
    visitCompleted(visit) {
        this.delegate.visitCompleted(visit);
    }
    locationWithActionIsSamePage(location, action) {
        const anchor = getAnchor(location);
        const currentAnchor = getAnchor(this.view.lastRenderedLocation);
        const isRestorationToTop = action === "restore" && typeof anchor === "undefined";
        return (action !== "replace" &&
            getRequestURL(location) === getRequestURL(this.view.lastRenderedLocation) &&
            (isRestorationToTop || (anchor != null && anchor !== currentAnchor)));
    }
    visitScrolledToSamePageLocation(oldURL, newURL) {
        this.delegate.visitScrolledToSamePageLocation(oldURL, newURL);
    }
    get location() {
        return this.history.location;
    }
    get restorationIdentifier() {
        return this.history.restorationIdentifier;
    }
    getActionForFormSubmission({ submitter, formElement }) {
        return getVisitAction(submitter, formElement) || "advance";
    }
}

var PageStage;
(function (PageStage) {
    PageStage[PageStage["initial"] = 0] = "initial";
    PageStage[PageStage["loading"] = 1] = "loading";
    PageStage[PageStage["interactive"] = 2] = "interactive";
    PageStage[PageStage["complete"] = 3] = "complete";
})(PageStage || (PageStage = {}));
class PageObserver {
    constructor(delegate) {
        this.stage = PageStage.initial;
        this.started = false;
        this.interpretReadyState = () => {
            const { readyState } = this;
            if (readyState == "interactive") {
                this.pageIsInteractive();
            }
            else if (readyState == "complete") {
                this.pageIsComplete();
            }
        };
        this.pageWillUnload = () => {
            this.delegate.pageWillUnload();
        };
        this.delegate = delegate;
    }
    start() {
        if (!this.started) {
            if (this.stage == PageStage.initial) {
                this.stage = PageStage.loading;
            }
            document.addEventListener("readystatechange", this.interpretReadyState, false);
            addEventListener("pagehide", this.pageWillUnload, false);
            this.started = true;
        }
    }
    stop() {
        if (this.started) {
            document.removeEventListener("readystatechange", this.interpretReadyState, false);
            removeEventListener("pagehide", this.pageWillUnload, false);
            this.started = false;
        }
    }
    pageIsInteractive() {
        if (this.stage == PageStage.loading) {
            this.stage = PageStage.interactive;
            this.delegate.pageBecameInteractive();
        }
    }
    pageIsComplete() {
        this.pageIsInteractive();
        if (this.stage == PageStage.interactive) {
            this.stage = PageStage.complete;
            this.delegate.pageLoaded();
        }
    }
    get readyState() {
        return document.readyState;
    }
}

class ScrollObserver {
    constructor(delegate) {
        this.started = false;
        this.onScroll = () => {
            this.updatePosition({ x: window.pageXOffset, y: window.pageYOffset });
        };
        this.delegate = delegate;
    }
    start() {
        if (!this.started) {
            addEventListener("scroll", this.onScroll, false);
            this.onScroll();
            this.started = true;
        }
    }
    stop() {
        if (this.started) {
            removeEventListener("scroll", this.onScroll, false);
            this.started = false;
        }
    }
    updatePosition(position) {
        this.delegate.scrollPositionChanged(position);
    }
}

class StreamMessageRenderer {
    render({ fragment }) {
        Bardo.preservingPermanentElements(this, getPermanentElementMapForFragment(fragment), () => document.documentElement.appendChild(fragment));
    }
    enteringBardo(currentPermanentElement, newPermanentElement) {
        newPermanentElement.replaceWith(currentPermanentElement.cloneNode(true));
    }
    leavingBardo() { }
}
function getPermanentElementMapForFragment(fragment) {
    const permanentElementsInDocument = queryPermanentElementsAll(document.documentElement);
    const permanentElementMap = {};
    for (const permanentElementInDocument of permanentElementsInDocument) {
        const { id } = permanentElementInDocument;
        for (const streamElement of fragment.querySelectorAll("turbo-stream")) {
            const elementInStream = getPermanentElementById(streamElement.templateElement.content, id);
            if (elementInStream) {
                permanentElementMap[id] = [permanentElementInDocument, elementInStream];
            }
        }
    }
    return permanentElementMap;
}

class StreamObserver {
    constructor(delegate) {
        this.sources = new Set();
        this.started = false;
        this.inspectFetchResponse = ((event) => {
            const response = fetchResponseFromEvent(event);
            if (response && fetchResponseIsStream(response)) {
                event.preventDefault();
                this.receiveMessageResponse(response);
            }
        });
        this.receiveMessageEvent = (event) => {
            if (this.started && typeof event.data == "string") {
                this.receiveMessageHTML(event.data);
            }
        };
        this.delegate = delegate;
    }
    start() {
        if (!this.started) {
            this.started = true;
            addEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
        }
    }
    stop() {
        if (this.started) {
            this.started = false;
            removeEventListener("turbo:before-fetch-response", this.inspectFetchResponse, false);
        }
    }
    connectStreamSource(source) {
        if (!this.streamSourceIsConnected(source)) {
            this.sources.add(source);
            source.addEventListener("message", this.receiveMessageEvent, false);
        }
    }
    disconnectStreamSource(source) {
        if (this.streamSourceIsConnected(source)) {
            this.sources.delete(source);
            source.removeEventListener("message", this.receiveMessageEvent, false);
        }
    }
    streamSourceIsConnected(source) {
        return this.sources.has(source);
    }
    async receiveMessageResponse(response) {
        const html = await response.responseHTML;
        if (html) {
            this.receiveMessageHTML(html);
        }
    }
    receiveMessageHTML(html) {
        this.delegate.receivedMessageFromStream(StreamMessage.wrap(html));
    }
}
function fetchResponseFromEvent(event) {
    var _a;
    const fetchResponse = (_a = event.detail) === null || _a === void 0 ? void 0 : _a.fetchResponse;
    if (fetchResponse instanceof FetchResponse) {
        return fetchResponse;
    }
}
function fetchResponseIsStream(response) {
    var _a;
    const contentType = (_a = response.contentType) !== null && _a !== void 0 ? _a : "";
    return contentType.startsWith(StreamMessage.contentType);
}

class ErrorRenderer extends Renderer {
    static renderElement(currentElement, newElement) {
        const { documentElement, body } = document;
        documentElement.replaceChild(newElement, body);
    }
    async render() {
        this.replaceHeadAndBody();
        this.activateScriptElements();
    }
    replaceHeadAndBody() {
        const { documentElement, head } = document;
        documentElement.replaceChild(this.newHead, head);
        this.renderElement(this.currentElement, this.newElement);
    }
    activateScriptElements() {
        for (const replaceableElement of this.scriptElements) {
            const parentNode = replaceableElement.parentNode;
            if (parentNode) {
                const element = activateScriptElement(replaceableElement);
                parentNode.replaceChild(element, replaceableElement);
            }
        }
    }
    get newHead() {
        return this.newSnapshot.headSnapshot.element;
    }
    get scriptElements() {
        return document.documentElement.querySelectorAll("script");
    }
}

class PageRenderer extends Renderer {
    static renderElement(currentElement, newElement) {
        if (document.body && newElement instanceof HTMLBodyElement) {
            document.body.replaceWith(newElement);
        }
        else {
            document.documentElement.appendChild(newElement);
        }
    }
    get shouldRender() {
        return this.newSnapshot.isVisitable && this.trackedElementsAreIdentical;
    }
    get reloadReason() {
        if (!this.newSnapshot.isVisitable) {
            return {
                reason: "turbo_visit_control_is_reload",
            };
        }
        if (!this.trackedElementsAreIdentical) {
            return {
                reason: "tracked_element_mismatch",
            };
        }
    }
    async prepareToRender() {
        await this.mergeHead();
    }
    async render() {
        if (this.willRender) {
            await this.replaceBody();
        }
    }
    finishRendering() {
        super.finishRendering();
        if (!this.isPreview) {
            this.focusFirstAutofocusableElement();
        }
    }
    get currentHeadSnapshot() {
        return this.currentSnapshot.headSnapshot;
    }
    get newHeadSnapshot() {
        return this.newSnapshot.headSnapshot;
    }
    get newElement() {
        return this.newSnapshot.element;
    }
    async mergeHead() {
        const mergedHeadElements = this.mergeProvisionalElements();
        const newStylesheetElements = this.copyNewHeadStylesheetElements();
        this.copyNewHeadScriptElements();
        await mergedHeadElements;
        await newStylesheetElements;
    }
    async replaceBody() {
        await this.preservingPermanentElements(async () => {
            this.activateNewBody();
            await this.assignNewBody();
        });
    }
    get trackedElementsAreIdentical() {
        return this.currentHeadSnapshot.trackedElementSignature == this.newHeadSnapshot.trackedElementSignature;
    }
    async copyNewHeadStylesheetElements() {
        const loadingElements = [];
        for (const element of this.newHeadStylesheetElements) {
            loadingElements.push(waitForLoad(element));
            document.head.appendChild(element);
        }
        await Promise.all(loadingElements);
    }
    copyNewHeadScriptElements() {
        for (const element of this.newHeadScriptElements) {
            document.head.appendChild(activateScriptElement(element));
        }
    }
    async mergeProvisionalElements() {
        const newHeadElements = [...this.newHeadProvisionalElements];
        for (const element of this.currentHeadProvisionalElements) {
            if (!this.isCurrentElementInElementList(element, newHeadElements)) {
                document.head.removeChild(element);
            }
        }
        for (const element of newHeadElements) {
            document.head.appendChild(element);
        }
    }
    isCurrentElementInElementList(element, elementList) {
        for (const [index, newElement] of elementList.entries()) {
            if (element.tagName == "TITLE") {
                if (newElement.tagName != "TITLE") {
                    continue;
                }
                if (element.innerHTML == newElement.innerHTML) {
                    elementList.splice(index, 1);
                    return true;
                }
            }
            if (newElement.isEqualNode(element)) {
                elementList.splice(index, 1);
                return true;
            }
        }
        return false;
    }
    removeCurrentHeadProvisionalElements() {
        for (const element of this.currentHeadProvisionalElements) {
            document.head.removeChild(element);
        }
    }
    copyNewHeadProvisionalElements() {
        for (const element of this.newHeadProvisionalElements) {
            document.head.appendChild(element);
        }
    }
    activateNewBody() {
        document.adoptNode(this.newElement);
        this.activateNewBodyScriptElements();
    }
    activateNewBodyScriptElements() {
        for (const inertScriptElement of this.newBodyScriptElements) {
            const activatedScriptElement = activateScriptElement(inertScriptElement);
            inertScriptElement.replaceWith(activatedScriptElement);
        }
    }
    async assignNewBody() {
        await this.renderElement(this.currentElement, this.newElement);
    }
    get newHeadStylesheetElements() {
        return this.newHeadSnapshot.getStylesheetElementsNotInSnapshot(this.currentHeadSnapshot);
    }
    get newHeadScriptElements() {
        return this.newHeadSnapshot.getScriptElementsNotInSnapshot(this.currentHeadSnapshot);
    }
    get currentHeadProvisionalElements() {
        return this.currentHeadSnapshot.provisionalElements;
    }
    get newHeadProvisionalElements() {
        return this.newHeadSnapshot.provisionalElements;
    }
    get newBodyScriptElements() {
        return this.newElement.querySelectorAll("script");
    }
}

class SnapshotCache {
    constructor(size) {
        this.keys = [];
        this.snapshots = {};
        this.size = size;
    }
    has(location) {
        return toCacheKey(location) in this.snapshots;
    }
    get(location) {
        if (this.has(location)) {
            const snapshot = this.read(location);
            this.touch(location);
            return snapshot;
        }
    }
    put(location, snapshot) {
        this.write(location, snapshot);
        this.touch(location);
        return snapshot;
    }
    clear() {
        this.snapshots = {};
    }
    read(location) {
        return this.snapshots[toCacheKey(location)];
    }
    write(location, snapshot) {
        this.snapshots[toCacheKey(location)] = snapshot;
    }
    touch(location) {
        const key = toCacheKey(location);
        const index = this.keys.indexOf(key);
        if (index > -1)
            this.keys.splice(index, 1);
        this.keys.unshift(key);
        this.trim();
    }
    trim() {
        for (const key of this.keys.splice(this.size)) {
            delete this.snapshots[key];
        }
    }
}

class PageView extends View {
    constructor() {
        super(...arguments);
        this.snapshotCache = new SnapshotCache(10);
        this.lastRenderedLocation = new URL(location.href);
        this.forceReloaded = false;
    }
    renderPage(snapshot, isPreview = false, willRender = true, visit) {
        const renderer = new PageRenderer(this.snapshot, snapshot, PageRenderer.renderElement, isPreview, willRender);
        if (!renderer.shouldRender) {
            this.forceReloaded = true;
        }
        else {
            visit === null || visit === void 0 ? void 0 : visit.changeHistory();
        }
        return this.render(renderer);
    }
    renderError(snapshot, visit) {
        visit === null || visit === void 0 ? void 0 : visit.changeHistory();
        const renderer = new ErrorRenderer(this.snapshot, snapshot, ErrorRenderer.renderElement, false);
        return this.render(renderer);
    }
    clearSnapshotCache() {
        this.snapshotCache.clear();
    }
    async cacheSnapshot(snapshot = this.snapshot) {
        if (snapshot.isCacheable) {
            this.delegate.viewWillCacheSnapshot();
            const { lastRenderedLocation: location } = this;
            await nextEventLoopTick();
            const cachedSnapshot = snapshot.clone();
            this.snapshotCache.put(location, cachedSnapshot);
            return cachedSnapshot;
        }
    }
    getCachedSnapshotForLocation(location) {
        return this.snapshotCache.get(location);
    }
    get snapshot() {
        return PageSnapshot.fromElement(this.element);
    }
}

class Preloader {
    constructor(delegate) {
        this.selector = "a[data-turbo-preload]";
        this.delegate = delegate;
    }
    get snapshotCache() {
        return this.delegate.navigator.view.snapshotCache;
    }
    start() {
        if (document.readyState === "loading") {
            return document.addEventListener("DOMContentLoaded", () => {
                this.preloadOnLoadLinksForView(document.body);
            });
        }
        else {
            this.preloadOnLoadLinksForView(document.body);
        }
    }
    preloadOnLoadLinksForView(element) {
        for (const link of element.querySelectorAll(this.selector)) {
            this.preloadURL(link);
        }
    }
    async preloadURL(link) {
        const location = new URL(link.href);
        if (this.snapshotCache.has(location)) {
            return;
        }
        try {
            const response = await fetch(location.toString(), { headers: { "VND.PREFETCH": "true", Accept: "text/html" } });
            const responseText = await response.text();
            const snapshot = PageSnapshot.fromHTMLString(responseText);
            this.snapshotCache.put(location, snapshot);
        }
        catch (_) {
        }
    }
}

class Session {
    constructor() {
        this.navigator = new Navigator(this);
        this.history = new History(this);
        this.preloader = new Preloader(this);
        this.view = new PageView(this, document.documentElement);
        this.adapter = new BrowserAdapter(this);
        this.pageObserver = new PageObserver(this);
        this.cacheObserver = new CacheObserver();
        this.linkClickObserver = new LinkClickObserver(this, window);
        this.formSubmitObserver = new FormSubmitObserver(this, document);
        this.scrollObserver = new ScrollObserver(this);
        this.streamObserver = new StreamObserver(this);
        this.formLinkClickObserver = new FormLinkClickObserver(this, document.documentElement);
        this.frameRedirector = new FrameRedirector(this, document.documentElement);
        this.streamMessageRenderer = new StreamMessageRenderer();
        this.drive = true;
        this.enabled = true;
        this.progressBarDelay = 500;
        this.started = false;
        this.formMode = "on";
    }
    start() {
        if (!this.started) {
            this.pageObserver.start();
            this.cacheObserver.start();
            this.formLinkClickObserver.start();
            this.linkClickObserver.start();
            this.formSubmitObserver.start();
            this.scrollObserver.start();
            this.streamObserver.start();
            this.frameRedirector.start();
            this.history.start();
            this.preloader.start();
            this.started = true;
            this.enabled = true;
        }
    }
    disable() {
        this.enabled = false;
    }
    stop() {
        if (this.started) {
            this.pageObserver.stop();
            this.cacheObserver.stop();
            this.formLinkClickObserver.stop();
            this.linkClickObserver.stop();
            this.formSubmitObserver.stop();
            this.scrollObserver.stop();
            this.streamObserver.stop();
            this.frameRedirector.stop();
            this.history.stop();
            this.started = false;
        }
    }
    registerAdapter(adapter) {
        this.adapter = adapter;
    }
    visit(location, options = {}) {
        const frameElement = options.frame ? document.getElementById(options.frame) : null;
        if (frameElement instanceof FrameElement) {
            frameElement.src = location.toString();
            frameElement.loaded;
        }
        else {
            this.navigator.proposeVisit(expandURL(location), options);
        }
    }
    connectStreamSource(source) {
        this.streamObserver.connectStreamSource(source);
    }
    disconnectStreamSource(source) {
        this.streamObserver.disconnectStreamSource(source);
    }
    renderStreamMessage(message) {
        this.streamMessageRenderer.render(StreamMessage.wrap(message));
    }
    clearCache() {
        this.view.clearSnapshotCache();
    }
    setProgressBarDelay(delay) {
        this.progressBarDelay = delay;
    }
    setFormMode(mode) {
        this.formMode = mode;
    }
    get location() {
        return this.history.location;
    }
    get restorationIdentifier() {
        return this.history.restorationIdentifier;
    }
    historyPoppedToLocationWithRestorationIdentifier(location, restorationIdentifier) {
        if (this.enabled) {
            this.navigator.startVisit(location, restorationIdentifier, {
                action: "restore",
                historyChanged: true,
            });
        }
        else {
            this.adapter.pageInvalidated({
                reason: "turbo_disabled",
            });
        }
    }
    scrollPositionChanged(position) {
        this.history.updateRestorationData({ scrollPosition: position });
    }
    willSubmitFormLinkToLocation(link, location) {
        return this.elementIsNavigatable(link) && locationIsVisitable(location, this.snapshot.rootLocation);
    }
    submittedFormLinkToLocation() { }
    willFollowLinkToLocation(link, location, event) {
        return (this.elementIsNavigatable(link) &&
            locationIsVisitable(location, this.snapshot.rootLocation) &&
            this.applicationAllowsFollowingLinkToLocation(link, location, event));
    }
    followedLinkToLocation(link, location) {
        const action = this.getActionForLink(link);
        const acceptsStreamResponse = link.hasAttribute("data-turbo-stream");
        this.visit(location.href, { action, acceptsStreamResponse });
    }
    allowsVisitingLocationWithAction(location, action) {
        return this.locationWithActionIsSamePage(location, action) || this.applicationAllowsVisitingLocation(location);
    }
    visitProposedToLocation(location, options) {
        extendURLWithDeprecatedProperties(location);
        this.adapter.visitProposedToLocation(location, options);
    }
    visitStarted(visit) {
        if (!visit.acceptsStreamResponse) {
            markAsBusy(document.documentElement);
        }
        extendURLWithDeprecatedProperties(visit.location);
        if (!visit.silent) {
            this.notifyApplicationAfterVisitingLocation(visit.location, visit.action);
        }
    }
    visitCompleted(visit) {
        clearBusyState(document.documentElement);
        this.notifyApplicationAfterPageLoad(visit.getTimingMetrics());
    }
    locationWithActionIsSamePage(location, action) {
        return this.navigator.locationWithActionIsSamePage(location, action);
    }
    visitScrolledToSamePageLocation(oldURL, newURL) {
        this.notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL);
    }
    willSubmitForm(form, submitter) {
        const action = getAction(form, submitter);
        return (this.submissionIsNavigatable(form, submitter) &&
            locationIsVisitable(expandURL(action), this.snapshot.rootLocation));
    }
    formSubmitted(form, submitter) {
        this.navigator.submitForm(form, submitter);
    }
    pageBecameInteractive() {
        this.view.lastRenderedLocation = this.location;
        this.notifyApplicationAfterPageLoad();
    }
    pageLoaded() {
        this.history.assumeControlOfScrollRestoration();
    }
    pageWillUnload() {
        this.history.relinquishControlOfScrollRestoration();
    }
    receivedMessageFromStream(message) {
        this.renderStreamMessage(message);
    }
    viewWillCacheSnapshot() {
        var _a;
        if (!((_a = this.navigator.currentVisit) === null || _a === void 0 ? void 0 : _a.silent)) {
            this.notifyApplicationBeforeCachingSnapshot();
        }
    }
    allowsImmediateRender({ element }, options) {
        const event = this.notifyApplicationBeforeRender(element, options);
        const { defaultPrevented, detail: { render }, } = event;
        if (this.view.renderer && render) {
            this.view.renderer.renderElement = render;
        }
        return !defaultPrevented;
    }
    viewRenderedSnapshot(_snapshot, _isPreview) {
        this.view.lastRenderedLocation = this.history.location;
        this.notifyApplicationAfterRender();
    }
    preloadOnLoadLinksForView(element) {
        this.preloader.preloadOnLoadLinksForView(element);
    }
    viewInvalidated(reason) {
        this.adapter.pageInvalidated(reason);
    }
    frameLoaded(frame) {
        this.notifyApplicationAfterFrameLoad(frame);
    }
    frameRendered(fetchResponse, frame) {
        this.notifyApplicationAfterFrameRender(fetchResponse, frame);
    }
    applicationAllowsFollowingLinkToLocation(link, location, ev) {
        const event = this.notifyApplicationAfterClickingLinkToLocation(link, location, ev);
        return !event.defaultPrevented;
    }
    applicationAllowsVisitingLocation(location) {
        const event = this.notifyApplicationBeforeVisitingLocation(location);
        return !event.defaultPrevented;
    }
    notifyApplicationAfterClickingLinkToLocation(link, location, event) {
        return dispatch("turbo:click", {
            target: link,
            detail: { url: location.href, originalEvent: event },
            cancelable: true,
        });
    }
    notifyApplicationBeforeVisitingLocation(location) {
        return dispatch("turbo:before-visit", {
            detail: { url: location.href },
            cancelable: true,
        });
    }
    notifyApplicationAfterVisitingLocation(location, action) {
        return dispatch("turbo:visit", { detail: { url: location.href, action } });
    }
    notifyApplicationBeforeCachingSnapshot() {
        return dispatch("turbo:before-cache");
    }
    notifyApplicationBeforeRender(newBody, options) {
        return dispatch("turbo:before-render", {
            detail: Object.assign({ newBody }, options),
            cancelable: true,
        });
    }
    notifyApplicationAfterRender() {
        return dispatch("turbo:render");
    }
    notifyApplicationAfterPageLoad(timing = {}) {
        return dispatch("turbo:load", {
            detail: { url: this.location.href, timing },
        });
    }
    notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
        dispatchEvent(new HashChangeEvent("hashchange", {
            oldURL: oldURL.toString(),
            newURL: newURL.toString(),
        }));
    }
    notifyApplicationAfterFrameLoad(frame) {
        return dispatch("turbo:frame-load", { target: frame });
    }
    notifyApplicationAfterFrameRender(fetchResponse, frame) {
        return dispatch("turbo:frame-render", {
            detail: { fetchResponse },
            target: frame,
            cancelable: true,
        });
    }
    submissionIsNavigatable(form, submitter) {
        if (this.formMode == "off") {
            return false;
        }
        else {
            const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true;
            if (this.formMode == "optin") {
                return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null;
            }
            else {
                return submitterIsNavigatable && this.elementIsNavigatable(form);
            }
        }
    }
    elementIsNavigatable(element) {
        const container = findClosestRecursively(element, "[data-turbo]");
        const withinFrame = findClosestRecursively(element, "turbo-frame");
        if (this.drive || withinFrame) {
            if (container) {
                return container.getAttribute("data-turbo") != "false";
            }
            else {
                return true;
            }
        }
        else {
            if (container) {
                return container.getAttribute("data-turbo") == "true";
            }
            else {
                return false;
            }
        }
    }
    getActionForLink(link) {
        return getVisitAction(link) || "advance";
    }
    get snapshot() {
        return this.view.snapshot;
    }
}
function extendURLWithDeprecatedProperties(url) {
    Object.defineProperties(url, deprecatedLocationPropertyDescriptors);
}
const deprecatedLocationPropertyDescriptors = {
    absoluteURL: {
        get() {
            return this.toString();
        },
    },
};

class Cache {
    constructor(session) {
        this.session = session;
    }
    clear() {
        this.session.clearCache();
    }
    resetCacheControl() {
        this.setCacheControl("");
    }
    exemptPageFromCache() {
        this.setCacheControl("no-cache");
    }
    exemptPageFromPreview() {
        this.setCacheControl("no-preview");
    }
    setCacheControl(value) {
        setMetaContent("turbo-cache-control", value);
    }
}

const StreamActions = {
    after() {
        this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e.nextSibling); });
    },
    append() {
        this.removeDuplicateTargetChildren();
        this.targetElements.forEach((e) => e.append(this.templateContent));
    },
    before() {
        this.targetElements.forEach((e) => { var _a; return (_a = e.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(this.templateContent, e); });
    },
    prepend() {
        this.removeDuplicateTargetChildren();
        this.targetElements.forEach((e) => e.prepend(this.templateContent));
    },
    remove() {
        this.targetElements.forEach((e) => e.remove());
    },
    replace() {
        this.targetElements.forEach((e) => e.replaceWith(this.templateContent));
    },
    update() {
        this.targetElements.forEach((targetElement) => {
            targetElement.innerHTML = "";
            targetElement.append(this.templateContent);
        });
    },
};

const session = new Session();
const cache = new Cache(session);
const { navigator: navigator$1 } = session;
function start() {
    session.start();
}
function registerAdapter(adapter) {
    session.registerAdapter(adapter);
}
function visit(location, options) {
    session.visit(location, options);
}
function connectStreamSource(source) {
    session.connectStreamSource(source);
}
function disconnectStreamSource(source) {
    session.disconnectStreamSource(source);
}
function renderStreamMessage(message) {
    session.renderStreamMessage(message);
}
function clearCache() {
    console.warn("Please replace `Turbo.clearCache()` with `Turbo.cache.clear()`. The top-level function is deprecated and will be removed in a future version of Turbo.`");
    session.clearCache();
}
function setProgressBarDelay(delay) {
    session.setProgressBarDelay(delay);
}
function setConfirmMethod(confirmMethod) {
    FormSubmission.confirmMethod = confirmMethod;
}
function setFormMode(mode) {
    session.setFormMode(mode);
}

var Turbo = /*#__PURE__*/Object.freeze({
    __proto__: null,
    navigator: navigator$1,
    session: session,
    cache: cache,
    PageRenderer: PageRenderer,
    PageSnapshot: PageSnapshot,
    FrameRenderer: FrameRenderer,
    start: start,
    registerAdapter: registerAdapter,
    visit: visit,
    connectStreamSource: connectStreamSource,
    disconnectStreamSource: disconnectStreamSource,
    renderStreamMessage: renderStreamMessage,
    clearCache: clearCache,
    setProgressBarDelay: setProgressBarDelay,
    setConfirmMethod: setConfirmMethod,
    setFormMode: setFormMode,
    StreamActions: StreamActions
});

class TurboFrameMissingError extends Error {
}

class FrameController {
    constructor(element) {
        this.fetchResponseLoaded = (_fetchResponse) => { };
        this.currentFetchRequest = null;
        this.resolveVisitPromise = () => { };
        this.connected = false;
        this.hasBeenLoaded = false;
        this.ignoredAttributes = new Set();
        this.action = null;
        this.visitCachedSnapshot = ({ element }) => {
            const frame = element.querySelector("#" + this.element.id);
            if (frame && this.previousFrameElement) {
                frame.replaceChildren(...this.previousFrameElement.children);
            }
            delete this.previousFrameElement;
        };
        this.element = element;
        this.view = new FrameView(this, this.element);
        this.appearanceObserver = new AppearanceObserver(this, this.element);
        this.formLinkClickObserver = new FormLinkClickObserver(this, this.element);
        this.linkInterceptor = new LinkInterceptor(this, this.element);
        this.restorationIdentifier = uuid();
        this.formSubmitObserver = new FormSubmitObserver(this, this.element);
    }
    connect() {
        if (!this.connected) {
            this.connected = true;
            if (this.loadingStyle == FrameLoadingStyle.lazy) {
                this.appearanceObserver.start();
            }
            else {
                this.loadSourceURL();
            }
            this.formLinkClickObserver.start();
            this.linkInterceptor.start();
            this.formSubmitObserver.start();
        }
    }
    disconnect() {
        if (this.connected) {
            this.connected = false;
            this.appearanceObserver.stop();
            this.formLinkClickObserver.stop();
            this.linkInterceptor.stop();
            this.formSubmitObserver.stop();
        }
    }
    disabledChanged() {
        if (this.loadingStyle == FrameLoadingStyle.eager) {
            this.loadSourceURL();
        }
    }
    sourceURLChanged() {
        if (this.isIgnoringChangesTo("src"))
            return;
        if (this.element.isConnected) {
            this.complete = false;
        }
        if (this.loadingStyle == FrameLoadingStyle.eager || this.hasBeenLoaded) {
            this.loadSourceURL();
        }
    }
    sourceURLReloaded() {
        const { src } = this.element;
        this.ignoringChangesToAttribute("complete", () => {
            this.element.removeAttribute("complete");
        });
        this.element.src = null;
        this.element.src = src;
        return this.element.loaded;
    }
    completeChanged() {
        if (this.isIgnoringChangesTo("complete"))
            return;
        this.loadSourceURL();
    }
    loadingStyleChanged() {
        if (this.loadingStyle == FrameLoadingStyle.lazy) {
            this.appearanceObserver.start();
        }
        else {
            this.appearanceObserver.stop();
            this.loadSourceURL();
        }
    }
    async loadSourceURL() {
        if (this.enabled && this.isActive && !this.complete && this.sourceURL) {
            this.element.loaded = this.visit(expandURL(this.sourceURL));
            this.appearanceObserver.stop();
            await this.element.loaded;
            this.hasBeenLoaded = true;
        }
    }
    async loadResponse(fetchResponse) {
        if (fetchResponse.redirected || (fetchResponse.succeeded && fetchResponse.isHTML)) {
            this.sourceURL = fetchResponse.response.url;
        }
        try {
            const html = await fetchResponse.responseHTML;
            if (html) {
                const document = parseHTMLDocument(html);
                const pageSnapshot = PageSnapshot.fromDocument(document);
                if (pageSnapshot.isVisitable) {
                    await this.loadFrameResponse(fetchResponse, document);
                }
                else {
                    await this.handleUnvisitableFrameResponse(fetchResponse);
                }
            }
        }
        finally {
            this.fetchResponseLoaded = () => { };
        }
    }
    elementAppearedInViewport(element) {
        this.proposeVisitIfNavigatedWithAction(element, element);
        this.loadSourceURL();
    }
    willSubmitFormLinkToLocation(link) {
        return this.shouldInterceptNavigation(link);
    }
    submittedFormLinkToLocation(link, _location, form) {
        const frame = this.findFrameElement(link);
        if (frame)
            form.setAttribute("data-turbo-frame", frame.id);
    }
    shouldInterceptLinkClick(element, _location, _event) {
        return this.shouldInterceptNavigation(element);
    }
    linkClickIntercepted(element, location) {
        this.navigateFrame(element, location);
    }
    willSubmitForm(element, submitter) {
        return element.closest("turbo-frame") == this.element && this.shouldInterceptNavigation(element, submitter);
    }
    formSubmitted(element, submitter) {
        if (this.formSubmission) {
            this.formSubmission.stop();
        }
        this.formSubmission = new FormSubmission(this, element, submitter);
        const { fetchRequest } = this.formSubmission;
        this.prepareRequest(fetchRequest);
        this.formSubmission.start();
    }
    prepareRequest(request) {
        var _a;
        request.headers["Turbo-Frame"] = this.id;
        if ((_a = this.currentNavigationElement) === null || _a === void 0 ? void 0 : _a.hasAttribute("data-turbo-stream")) {
            request.acceptResponseType(StreamMessage.contentType);
        }
    }
    requestStarted(_request) {
        markAsBusy(this.element);
    }
    requestPreventedHandlingResponse(_request, _response) {
        this.resolveVisitPromise();
    }
    async requestSucceededWithResponse(request, response) {
        await this.loadResponse(response);
        this.resolveVisitPromise();
    }
    async requestFailedWithResponse(request, response) {
        await this.loadResponse(response);
        this.resolveVisitPromise();
    }
    requestErrored(request, error) {
        console.error(error);
        this.resolveVisitPromise();
    }
    requestFinished(_request) {
        clearBusyState(this.element);
    }
    formSubmissionStarted({ formElement }) {
        markAsBusy(formElement, this.findFrameElement(formElement));
    }
    formSubmissionSucceededWithResponse(formSubmission, response) {
        const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
        frame.delegate.proposeVisitIfNavigatedWithAction(frame, formSubmission.formElement, formSubmission.submitter);
        frame.delegate.loadResponse(response);
        if (!formSubmission.isSafe) {
            session.clearCache();
        }
    }
    formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
        this.element.delegate.loadResponse(fetchResponse);
        session.clearCache();
    }
    formSubmissionErrored(formSubmission, error) {
        console.error(error);
    }
    formSubmissionFinished({ formElement }) {
        clearBusyState(formElement, this.findFrameElement(formElement));
    }
    allowsImmediateRender({ element: newFrame }, options) {
        const event = dispatch("turbo:before-frame-render", {
            target: this.element,
            detail: Object.assign({ newFrame }, options),
            cancelable: true,
        });
        const { defaultPrevented, detail: { render }, } = event;
        if (this.view.renderer && render) {
            this.view.renderer.renderElement = render;
        }
        return !defaultPrevented;
    }
    viewRenderedSnapshot(_snapshot, _isPreview) { }
    preloadOnLoadLinksForView(element) {
        session.preloadOnLoadLinksForView(element);
    }
    viewInvalidated() { }
    willRenderFrame(currentElement, _newElement) {
        this.previousFrameElement = currentElement.cloneNode(true);
    }
    async loadFrameResponse(fetchResponse, document) {
        const newFrameElement = await this.extractForeignFrameElement(document.body);
        if (newFrameElement) {
            const snapshot = new Snapshot(newFrameElement);
            const renderer = new FrameRenderer(this, this.view.snapshot, snapshot, FrameRenderer.renderElement, false, false);
            if (this.view.renderPromise)
                await this.view.renderPromise;
            this.changeHistory();
            await this.view.render(renderer);
            this.complete = true;
            session.frameRendered(fetchResponse, this.element);
            session.frameLoaded(this.element);
            this.fetchResponseLoaded(fetchResponse);
        }
        else if (this.willHandleFrameMissingFromResponse(fetchResponse)) {
            this.handleFrameMissingFromResponse(fetchResponse);
        }
    }
    async visit(url) {
        var _a;
        const request = new FetchRequest(this, FetchMethod.get, url, new URLSearchParams(), this.element);
        (_a = this.currentFetchRequest) === null || _a === void 0 ? void 0 : _a.cancel();
        this.currentFetchRequest = request;
        return new Promise((resolve) => {
            this.resolveVisitPromise = () => {
                this.resolveVisitPromise = () => { };
                this.currentFetchRequest = null;
                resolve();
            };
            request.perform();
        });
    }
    navigateFrame(element, url, submitter) {
        const frame = this.findFrameElement(element, submitter);
        frame.delegate.proposeVisitIfNavigatedWithAction(frame, element, submitter);
        this.withCurrentNavigationElement(element, () => {
            frame.src = url;
        });
    }
    proposeVisitIfNavigatedWithAction(frame, element, submitter) {
        this.action = getVisitAction(submitter, element, frame);
        if (this.action) {
            const pageSnapshot = PageSnapshot.fromElement(frame).clone();
            const { visitCachedSnapshot } = frame.delegate;
            frame.delegate.fetchResponseLoaded = (fetchResponse) => {
                if (frame.src) {
                    const { statusCode, redirected } = fetchResponse;
                    const responseHTML = frame.ownerDocument.documentElement.outerHTML;
                    const response = { statusCode, redirected, responseHTML };
                    const options = {
                        response,
                        visitCachedSnapshot,
                        willRender: false,
                        updateHistory: false,
                        restorationIdentifier: this.restorationIdentifier,
                        snapshot: pageSnapshot,
                    };
                    if (this.action)
                        options.action = this.action;
                    session.visit(frame.src, options);
                }
            };
        }
    }
    changeHistory() {
        if (this.action) {
            const method = getHistoryMethodForAction(this.action);
            session.history.update(method, expandURL(this.element.src || ""), this.restorationIdentifier);
        }
    }
    async handleUnvisitableFrameResponse(fetchResponse) {
        console.warn(`The response (${fetchResponse.statusCode}) from <turbo-frame id="${this.element.id}"> is performing a full page visit due to turbo-visit-control.`);
        await this.visitResponse(fetchResponse.response);
    }
    willHandleFrameMissingFromResponse(fetchResponse) {
        this.element.setAttribute("complete", "");
        const response = fetchResponse.response;
        const visit = async (url, options = {}) => {
            if (url instanceof Response) {
                this.visitResponse(url);
            }
            else {
                session.visit(url, options);
            }
        };
        const event = dispatch("turbo:frame-missing", {
            target: this.element,
            detail: { response, visit },
            cancelable: true,
        });
        return !event.defaultPrevented;
    }
    handleFrameMissingFromResponse(fetchResponse) {
        this.view.missing();
        this.throwFrameMissingError(fetchResponse);
    }
    throwFrameMissingError(fetchResponse) {
        const message = `The response (${fetchResponse.statusCode}) did not contain the expected <turbo-frame id="${this.element.id}"> and will be ignored. To perform a full page visit instead, set turbo-visit-control to reload.`;
        throw new TurboFrameMissingError(message);
    }
    async visitResponse(response) {
        const wrapped = new FetchResponse(response);
        const responseHTML = await wrapped.responseHTML;
        const { location, redirected, statusCode } = wrapped;
        return session.visit(location, { response: { redirected, statusCode, responseHTML } });
    }
    findFrameElement(element, submitter) {
        var _a;
        const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
        return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
    }
    async extractForeignFrameElement(container) {
        let element;
        const id = CSS.escape(this.id);
        try {
            element = activateElement(container.querySelector(`turbo-frame#${id}`), this.sourceURL);
            if (element) {
                return element;
            }
            element = activateElement(container.querySelector(`turbo-frame[src][recurse~=${id}]`), this.sourceURL);
            if (element) {
                await element.loaded;
                return await this.extractForeignFrameElement(element);
            }
        }
        catch (error) {
            console.error(error);
            return new FrameElement();
        }
        return null;
    }
    formActionIsVisitable(form, submitter) {
        const action = getAction(form, submitter);
        return locationIsVisitable(expandURL(action), this.rootLocation);
    }
    shouldInterceptNavigation(element, submitter) {
        const id = getAttribute("data-turbo-frame", submitter, element) || this.element.getAttribute("target");
        if (element instanceof HTMLFormElement && !this.formActionIsVisitable(element, submitter)) {
            return false;
        }
        if (!this.enabled || id == "_top") {
            return false;
        }
        if (id) {
            const frameElement = getFrameElementById(id);
            if (frameElement) {
                return !frameElement.disabled;
            }
        }
        if (!session.elementIsNavigatable(element)) {
            return false;
        }
        if (submitter && !session.elementIsNavigatable(submitter)) {
            return false;
        }
        return true;
    }
    get id() {
        return this.element.id;
    }
    get enabled() {
        return !this.element.disabled;
    }
    get sourceURL() {
        if (this.element.src) {
            return this.element.src;
        }
    }
    set sourceURL(sourceURL) {
        this.ignoringChangesToAttribute("src", () => {
            this.element.src = sourceURL !== null && sourceURL !== void 0 ? sourceURL : null;
        });
    }
    get loadingStyle() {
        return this.element.loading;
    }
    get isLoading() {
        return this.formSubmission !== undefined || this.resolveVisitPromise() !== undefined;
    }
    get complete() {
        return this.element.hasAttribute("complete");
    }
    set complete(value) {
        this.ignoringChangesToAttribute("complete", () => {
            if (value) {
                this.element.setAttribute("complete", "");
            }
            else {
                this.element.removeAttribute("complete");
            }
        });
    }
    get isActive() {
        return this.element.isActive && this.connected;
    }
    get rootLocation() {
        var _a;
        const meta = this.element.ownerDocument.querySelector(`meta[name="turbo-root"]`);
        const root = (_a = meta === null || meta === void 0 ? void 0 : meta.content) !== null && _a !== void 0 ? _a : "/";
        return expandURL(root);
    }
    isIgnoringChangesTo(attributeName) {
        return this.ignoredAttributes.has(attributeName);
    }
    ignoringChangesToAttribute(attributeName, callback) {
        this.ignoredAttributes.add(attributeName);
        callback();
        this.ignoredAttributes.delete(attributeName);
    }
    withCurrentNavigationElement(element, callback) {
        this.currentNavigationElement = element;
        callback();
        delete this.currentNavigationElement;
    }
}
function getFrameElementById(id) {
    if (id != null) {
        const element = document.getElementById(id);
        if (element instanceof FrameElement) {
            return element;
        }
    }
}
function activateElement(element, currentURL) {
    if (element) {
        const src = element.getAttribute("src");
        if (src != null && currentURL != null && urlsAreEqual(src, currentURL)) {
            throw new Error(`Matching <turbo-frame id="${element.id}"> element has a source URL which references itself`);
        }
        if (element.ownerDocument !== document) {
            element = document.importNode(element, true);
        }
        if (element instanceof FrameElement) {
            element.connectedCallback();
            element.disconnectedCallback();
            return element;
        }
    }
}

class StreamElement extends HTMLElement {
    static async renderElement(newElement) {
        await newElement.performAction();
    }
    async connectedCallback() {
        try {
            await this.render();
        }
        catch (error) {
            console.error(error);
        }
        finally {
            this.disconnect();
        }
    }
    async render() {
        var _a;
        return ((_a = this.renderPromise) !== null && _a !== void 0 ? _a : (this.renderPromise = (async () => {
            const event = this.beforeRenderEvent;
            if (this.dispatchEvent(event)) {
                await nextAnimationFrame();
                await event.detail.render(this);
            }
        })()));
    }
    disconnect() {
        try {
            this.remove();
        }
        catch (_a) { }
    }
    removeDuplicateTargetChildren() {
        this.duplicateChildren.forEach((c) => c.remove());
    }
    get duplicateChildren() {
        var _a;
        const existingChildren = this.targetElements.flatMap((e) => [...e.children]).filter((c) => !!c.id);
        const newChildrenIds = [...(((_a = this.templateContent) === null || _a === void 0 ? void 0 : _a.children) || [])].filter((c) => !!c.id).map((c) => c.id);
        return existingChildren.filter((c) => newChildrenIds.includes(c.id));
    }
    get performAction() {
        if (this.action) {
            const actionFunction = StreamActions[this.action];
            if (actionFunction) {
                return actionFunction;
            }
            this.raise("unknown action");
        }
        this.raise("action attribute is missing");
    }
    get targetElements() {
        if (this.target) {
            return this.targetElementsById;
        }
        else if (this.targets) {
            return this.targetElementsByQuery;
        }
        else {
            this.raise("target or targets attribute is missing");
        }
    }
    get templateContent() {
        return this.templateElement.content.cloneNode(true);
    }
    get templateElement() {
        if (this.firstElementChild === null) {
            const template = this.ownerDocument.createElement("template");
            this.appendChild(template);
            return template;
        }
        else if (this.firstElementChild instanceof HTMLTemplateElement) {
            return this.firstElementChild;
        }
        this.raise("first child element must be a <template> element");
    }
    get action() {
        return this.getAttribute("action");
    }
    get target() {
        return this.getAttribute("target");
    }
    get targets() {
        return this.getAttribute("targets");
    }
    raise(message) {
        throw new Error(`${this.description}: ${message}`);
    }
    get description() {
        var _a, _b;
        return (_b = ((_a = this.outerHTML.match(/<[^>]+>/)) !== null && _a !== void 0 ? _a : [])[0]) !== null && _b !== void 0 ? _b : "<turbo-stream>";
    }
    get beforeRenderEvent() {
        return new CustomEvent("turbo:before-stream-render", {
            bubbles: true,
            cancelable: true,
            detail: { newStream: this, render: StreamElement.renderElement },
        });
    }
    get targetElementsById() {
        var _a;
        const element = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.getElementById(this.target);
        if (element !== null) {
            return [element];
        }
        else {
            return [];
        }
    }
    get targetElementsByQuery() {
        var _a;
        const elements = (_a = this.ownerDocument) === null || _a === void 0 ? void 0 : _a.querySelectorAll(this.targets);
        if (elements.length !== 0) {
            return Array.prototype.slice.call(elements);
        }
        else {
            return [];
        }
    }
}

class StreamSourceElement extends HTMLElement {
    constructor() {
        super(...arguments);
        this.streamSource = null;
    }
    connectedCallback() {
        this.streamSource = this.src.match(/^ws{1,2}:/) ? new WebSocket(this.src) : new EventSource(this.src);
        connectStreamSource(this.streamSource);
    }
    disconnectedCallback(
Download .txt
gitextract_kxlx5hx4/

├── .devcontainer/
│   └── devcontainer.json
├── .github/
│   └── workflows/
│       └── test.yml
├── .gitignore
├── CHANGELOG.md
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── bin/
│   └── sdoc
├── config.ru
├── lib/
│   ├── rdoc/
│   │   ├── discover.rb
│   │   └── generator/
│   │       └── template/
│   │           └── rails/
│   │               ├── _context.rhtml
│   │               ├── _file_nav.rhtml
│   │               ├── _head.rhtml
│   │               ├── _index_nav.rhtml
│   │               ├── _module_nav.rhtml
│   │               ├── _panel.rhtml
│   │               ├── class.rhtml
│   │               ├── file.rhtml
│   │               ├── index.rhtml
│   │               └── resources/
│   │                   ├── css/
│   │                   │   ├── highlight.css
│   │                   │   └── main.css
│   │                   └── js/
│   │                       ├── .gitattributes
│   │                       ├── @hotwired--turbo.js
│   │                       ├── main.js
│   │                       └── search.js
│   ├── sdoc/
│   │   ├── generator.rb
│   │   ├── helpers/
│   │   │   └── git.rb
│   │   ├── helpers.rb
│   │   ├── name_list.rb
│   │   ├── postprocessor.rb
│   │   ├── rdoc_monkey_patches.rb
│   │   ├── renderer.rb
│   │   ├── search_index.rb
│   │   └── version.rb
│   └── sdoc.rb
├── netlify.toml
├── sdoc.gemspec
└── spec/
    ├── helpers_spec.rb
    ├── postprocessor_spec.rb
    ├── rdoc_generator_spec.rb
    ├── rdoc_monkey_patches_spec.rb
    ├── renderer_spec.rb
    ├── search_index_spec.rb
    └── spec_helper.rb
Download .txt
SYMBOL INDEX (776 symbols across 16 files)

FILE: lib/rdoc/generator/template/rails/resources/js/@hotwired--turbo.js
  function validateSubmitter (line 64) | function validateSubmitter(submitter, form) {
  function raise (line 70) | function raise(errorConstructor, message, name) {
  function findSubmitterFromClickTarget (line 76) | function findSubmitterFromClickTarget(target) {
  function clickCaptured (line 81) | function clickCaptured(event) {
  method get (line 99) | get() {
  class FrameElement (line 112) | class FrameElement extends HTMLElement {
    method observedAttributes (line 113) | static get observedAttributes() {
    method constructor (line 116) | constructor() {
    method connectedCallback (line 121) | connectedCallback() {
    method disconnectedCallback (line 124) | disconnectedCallback() {
    method reload (line 127) | reload() {
    method attributeChangedCallback (line 130) | attributeChangedCallback(name) {
    method src (line 144) | get src() {
    method src (line 147) | set src(value) {
    method loading (line 155) | get loading() {
    method loading (line 158) | set loading(value) {
    method disabled (line 166) | get disabled() {
    method disabled (line 169) | set disabled(value) {
    method autoscroll (line 177) | get autoscroll() {
    method autoscroll (line 180) | set autoscroll(value) {
    method complete (line 188) | get complete() {
    method isActive (line 191) | get isActive() {
    method isPreview (line 194) | get isPreview() {
  function frameLoadingStyleFromString (line 199) | function frameLoadingStyleFromString(style) {
  function expandURL (line 208) | function expandURL(locatable) {
  function getAnchor (line 211) | function getAnchor(url) {
  function getAction (line 220) | function getAction(form, submitter) {
  function getExtension (line 224) | function getExtension(url) {
  function isHTML (line 227) | function isHTML(url) {
  function isPrefixedBy (line 230) | function isPrefixedBy(baseURL, url) {
  function locationIsVisitable (line 234) | function locationIsVisitable(location, rootLocation) {
  function getRequestURL (line 237) | function getRequestURL(url) {
  function toCacheKey (line 241) | function toCacheKey(url) {
  function urlsAreEqual (line 244) | function urlsAreEqual(left, right) {
  function getPathComponents (line 247) | function getPathComponents(url) {
  function getLastPathComponent (line 250) | function getLastPathComponent(url) {
  function getPrefix (line 253) | function getPrefix(url) {
  function addTrailingSlash (line 256) | function addTrailingSlash(value) {
  class FetchResponse (line 260) | class FetchResponse {
    method constructor (line 261) | constructor(response) {
    method succeeded (line 264) | get succeeded() {
    method failed (line 267) | get failed() {
    method clientError (line 270) | get clientError() {
    method serverError (line 273) | get serverError() {
    method redirected (line 276) | get redirected() {
    method location (line 279) | get location() {
    method isHTML (line 282) | get isHTML() {
    method statusCode (line 285) | get statusCode() {
    method contentType (line 288) | get contentType() {
    method responseText (line 291) | get responseText() {
    method responseHTML (line 294) | get responseHTML() {
    method header (line 302) | header(name) {
  function activateScriptElement (line 307) | function activateScriptElement(element) {
  function copyElementAttributes (line 323) | function copyElementAttributes(destinationElement, sourceElement) {
  function createDocumentFragment (line 328) | function createDocumentFragment(html) {
  function dispatch (line 333) | function dispatch(eventName, { target, cancelable, detail } = {}) {
  function nextAnimationFrame (line 348) | function nextAnimationFrame() {
  function nextEventLoopTick (line 351) | function nextEventLoopTick() {
  function nextMicrotask (line 354) | function nextMicrotask() {
  function parseHTMLDocument (line 357) | function parseHTMLDocument(html = "") {
  function unindent (line 360) | function unindent(strings, ...values) {
  function interpolate (line 366) | function interpolate(strings, values) {
  function uuid (line 372) | function uuid() {
  function getAttribute (line 390) | function getAttribute(attributeName, ...elements) {
  function hasAttribute (line 397) | function hasAttribute(attributeName, ...elements) {
  function markAsBusy (line 400) | function markAsBusy(...elements) {
  function clearBusyState (line 408) | function clearBusyState(...elements) {
  function waitForLoad (line 416) | function waitForLoad(element, timeoutInMilliseconds = 2000) {
  function getHistoryMethodForAction (line 428) | function getHistoryMethodForAction(action) {
  function isAction (line 437) | function isAction(action) {
  function getVisitAction (line 440) | function getVisitAction(...elements) {
  function getMetaElement (line 444) | function getMetaElement(name) {
  function getMetaContent (line 447) | function getMetaContent(name) {
  function setMetaContent (line 451) | function setMetaContent(name, content) {
  function findClosestRecursively (line 461) | function findClosestRecursively(element, selector) {
  function fetchMethodFromString (line 477) | function fetchMethodFromString(method) {
  class FetchRequest (line 491) | class FetchRequest {
    method constructor (line 492) | constructor(delegate, method, location, body = new URLSearchParams(), ...
    method location (line 502) | get location() {
    method params (line 505) | get params() {
    method entries (line 508) | get entries() {
    method cancel (line 511) | cancel() {
    method perform (line 514) | async perform() {
    method receive (line 535) | async receive(response) {
    method fetchOptions (line 553) | get fetchOptions() {
    method defaultHeaders (line 565) | get defaultHeaders() {
    method isSafe (line 570) | get isSafe() {
    method abortSignal (line 573) | get abortSignal() {
    method acceptResponseType (line 576) | acceptResponseType(mimeType) {
    method allowRequestToBeIntercepted (line 579) | async allowRequestToBeIntercepted(fetchOptions) {
    method willDelegateErrorHandling (line 593) | willDelegateErrorHandling(error) {
  class AppearanceObserver (line 603) | class AppearanceObserver {
    method constructor (line 604) | constructor(delegate, element) {
    method start (line 616) | start() {
    method stop (line 622) | stop() {
  class StreamMessage (line 630) | class StreamMessage {
    method wrap (line 631) | static wrap(message) {
    method constructor (line 639) | constructor(fragment) {
  function importStreamElements (line 644) | function importStreamElements(fragment) {
  function formEnctypeFromString (line 670) | function formEnctypeFromString(encoding) {
  class FormSubmission (line 680) | class FormSubmission {
    method confirmMethod (line 681) | static confirmMethod(message, _element, _submitter) {
    method constructor (line 684) | constructor(delegate, formElement, submitter, mustRedirect = false) {
    method method (line 697) | get method() {
    method action (line 702) | get action() {
    method body (line 712) | get body() {
    method enctype (line 720) | get enctype() {
    method isSafe (line 724) | get isSafe() {
    method stringFormData (line 727) | get stringFormData() {
    method start (line 732) | async start() {
    method stop (line 746) | stop() {
    method prepareRequest (line 754) | prepareRequest(request) {
    method requestStarted (line 765) | requestStarted(_request) {
    method requestPreventedHandlingResponse (line 776) | requestPreventedHandlingResponse(request, response) {
    method requestSucceededWithResponse (line 779) | requestSucceededWithResponse(request, response) {
    method requestFailedWithResponse (line 793) | requestFailedWithResponse(request, response) {
    method requestErrored (line 797) | requestErrored(request, error) {
    method requestFinished (line 801) | requestFinished(_request) {
    method setSubmitsWith (line 812) | setSubmitsWith() {
    method resetSubmitterText (line 825) | resetSubmitterText() {
    method requestMustRedirect (line 836) | requestMustRedirect(request) {
    method requestAcceptsTurboStreamResponse (line 839) | requestAcceptsTurboStreamResponse(request) {
    method submitsWith (line 842) | get submitsWith() {
  function buildFormData (line 847) | function buildFormData(formElement, submitter) {
  function getCookieValue (line 856) | function getCookieValue(cookieName) {
  function responseSucceededWithoutRedirect (line 866) | function responseSucceededWithoutRedirect(response) {
  function mergeFormDataEntries (line 869) | function mergeFormDataEntries(url, entries) {
  class Snapshot (line 880) | class Snapshot {
    method constructor (line 881) | constructor(element) {
    method activeElement (line 884) | get activeElement() {
    method children (line 887) | get children() {
    method hasAnchor (line 890) | hasAnchor(anchor) {
    method getElementForAnchor (line 893) | getElementForAnchor(anchor) {
    method isConnected (line 896) | get isConnected() {
    method firstAutofocusableElement (line 899) | get firstAutofocusableElement() {
    method permanentElements (line 909) | get permanentElements() {
    method getPermanentElementById (line 912) | getPermanentElementById(id) {
    method getPermanentElementMapForSnapshot (line 915) | getPermanentElementMapForSnapshot(snapshot) {
  function getPermanentElementById (line 927) | function getPermanentElementById(node, id) {
  function queryPermanentElementsAll (line 930) | function queryPermanentElementsAll(node) {
  class FormSubmitObserver (line 934) | class FormSubmitObserver {
    method constructor (line 935) | constructor(delegate, eventTarget) {
    method start (line 958) | start() {
    method stop (line 964) | stop() {
  function submissionDoesNotDismissDialog (line 971) | function submissionDoesNotDismissDialog(form, submitter) {
  function submissionDoesNotTargetIFrame (line 975) | function submissionDoesNotTargetIFrame(form, submitter) {
  class View (line 989) | class View {
    method constructor (line 990) | constructor(delegate, element) {
    method scrollToAnchor (line 996) | scrollToAnchor(anchor) {
    method scrollToAnchorFromLocation (line 1006) | scrollToAnchorFromLocation(location) {
    method scrollToElement (line 1009) | scrollToElement(element) {
    method focusElement (line 1012) | focusElement(element) {
    method scrollToPosition (line 1024) | scrollToPosition({ x, y }) {
    method scrollToTop (line 1027) | scrollToTop() {
    method scrollRoot (line 1030) | get scrollRoot() {
    method render (line 1033) | async render(renderer) {
    method invalidate (line 1060) | invalidate(reason) {
    method prepareToRenderSnapshot (line 1063) | async prepareToRenderSnapshot(renderer) {
    method markAsPreview (line 1067) | markAsPreview(isPreview) {
    method renderSnapshot (line 1075) | async renderSnapshot(renderer) {
    method finishRenderingSnapshot (line 1078) | finishRenderingSnapshot(renderer) {
  class FrameView (line 1083) | class FrameView extends View {
    method missing (line 1084) | missing() {
    method snapshot (line 1087) | get snapshot() {
  class LinkInterceptor (line 1092) | class LinkInterceptor {
    method constructor (line 1093) | constructor(delegate, element) {
    method start (line 1118) | start() {
    method stop (line 1123) | stop() {
    method respondsToEventTarget (line 1128) | respondsToEventTarget(target) {
  class LinkClickObserver (line 1134) | class LinkClickObserver {
    method constructor (line 1135) | constructor(delegate, eventTarget) {
    method start (line 1157) | start() {
    method stop (line 1163) | stop() {
    method clickEventIsSignificant (line 1169) | clickEventIsSignificant(event) {
    method findLinkFromClickTarget (line 1178) | findLinkFromClickTarget(target) {
    method getLocationForLink (line 1181) | getLocationForLink(link) {
  function doesNotTargetIFrame (line 1185) | function doesNotTargetIFrame(anchor) {
  class FormLinkClickObserver (line 1198) | class FormLinkClickObserver {
    method constructor (line 1199) | constructor(delegate, element) {
    method start (line 1203) | start() {
    method stop (line 1206) | stop() {
    method willFollowLinkToLocation (line 1209) | willFollowLinkToLocation(link, location, originalEvent) {
    method followedLinkToLocation (line 1213) | followedLinkToLocation(link, location) {
  class Bardo (line 1245) | class Bardo {
    method preservingPermanentElements (line 1246) | static async preservingPermanentElements(delegate, permanentElementMap...
    method constructor (line 1252) | constructor(delegate, permanentElementMap) {
    method enter (line 1256) | enter() {
    method leave (line 1263) | leave() {
    method replaceNewPermanentElementWithPlaceholder (line 1271) | replaceNewPermanentElementWithPlaceholder(permanentElement) {
    method replaceCurrentPermanentElementWithClone (line 1275) | replaceCurrentPermanentElementWithClone(permanentElement) {
    method replacePlaceholderWithPermanentElement (line 1279) | replacePlaceholderWithPermanentElement(permanentElement) {
    method getPlaceholderById (line 1283) | getPlaceholderById(id) {
    method placeholders (line 1286) | get placeholders() {
  function createPlaceholderForPermanentElement (line 1290) | function createPlaceholderForPermanentElement(permanentElement) {
  class Renderer (line 1297) | class Renderer {
    method constructor (line 1298) | constructor(currentSnapshot, newSnapshot, renderElement, isPreview, wi...
    method shouldRender (line 1307) | get shouldRender() {
    method reloadReason (line 1310) | get reloadReason() {
    method prepareToRender (line 1313) | prepareToRender() {
    method finishRendering (line 1316) | finishRendering() {
    method preservingPermanentElements (line 1322) | async preservingPermanentElements(callback) {
    method focusFirstAutofocusableElement (line 1325) | focusFirstAutofocusableElement() {
    method enteringBardo (line 1331) | enteringBardo(currentPermanentElement) {
    method leavingBardo (line 1338) | leavingBardo(currentPermanentElement) {
    method connectedSnapshot (line 1344) | get connectedSnapshot() {
    method currentElement (line 1347) | get currentElement() {
    method newElement (line 1350) | get newElement() {
    method permanentElementMap (line 1353) | get permanentElementMap() {
  function elementIsFocusable (line 1357) | function elementIsFocusable(element) {
  class FrameRenderer (line 1361) | class FrameRenderer extends Renderer {
    method renderElement (line 1362) | static renderElement(currentElement, newElement) {
    method constructor (line 1374) | constructor(delegate, currentSnapshot, newSnapshot, renderElement, isP...
    method shouldRender (line 1378) | get shouldRender() {
    method render (line 1381) | async render() {
    method loadFrameElement (line 1392) | loadFrameElement() {
    method scrollFrameIntoView (line 1396) | scrollFrameIntoView() {
    method activateScriptElements (line 1408) | activateScriptElements() {
    method newScriptElements (line 1414) | get newScriptElements() {
  function readScrollLogicalPosition (line 1418) | function readScrollLogicalPosition(value, defaultValue) {
  function readScrollBehavior (line 1426) | function readScrollBehavior(value, defaultValue) {
  class ProgressBar (line 1435) | class ProgressBar {
    method defaultCSS (line 1436) | static get defaultCSS() {
    method constructor (line 1453) | constructor() {
    method show (line 1465) | show() {
    method hide (line 1472) | hide() {
    method setValue (line 1483) | setValue(value) {
    method installStylesheetElement (line 1487) | installStylesheetElement() {
    method installProgressElement (line 1490) | installProgressElement() {
    method fadeProgressElement (line 1496) | fadeProgressElement(callback) {
    method uninstallProgressElement (line 1500) | uninstallProgressElement() {
    method startTrickling (line 1505) | startTrickling() {
    method stopTrickling (line 1510) | stopTrickling() {
    method refresh (line 1514) | refresh() {
    method createStylesheetElement (line 1519) | createStylesheetElement() {
    method createProgressElement (line 1528) | createProgressElement() {
    method cspNonce (line 1533) | get cspNonce() {
  class HeadSnapshot (line 1539) | class HeadSnapshot extends Snapshot {
    method constructor (line 1540) | constructor() {
    method trackedElementSignature (line 1557) | get trackedElementSignature() {
    method getScriptElementsNotInSnapshot (line 1562) | getScriptElementsNotInSnapshot(snapshot) {
    method getStylesheetElementsNotInSnapshot (line 1565) | getStylesheetElementsNotInSnapshot(snapshot) {
    method getElementsMatchingTypeNotInSnapshot (line 1568) | getElementsMatchingTypeNotInSnapshot(matchedType, snapshot) {
    method provisionalElements (line 1575) | get provisionalElements() {
    method getMetaValue (line 1589) | getMetaValue(name) {
    method findMetaElementByName (line 1593) | findMetaElementByName(name) {
  function elementType (line 1600) | function elementType(element) {
  function elementIsTracked (line 1608) | function elementIsTracked(element) {
  function elementIsScript (line 1611) | function elementIsScript(element) {
  function elementIsNoscript (line 1615) | function elementIsNoscript(element) {
  function elementIsStylesheet (line 1619) | function elementIsStylesheet(element) {
  function elementIsMetaElementWithName (line 1623) | function elementIsMetaElementWithName(element, name) {
  function elementWithoutNonce (line 1627) | function elementWithoutNonce(element) {
  class PageSnapshot (line 1634) | class PageSnapshot extends Snapshot {
    method fromHTMLString (line 1635) | static fromHTMLString(html = "") {
    method fromElement (line 1638) | static fromElement(element) {
    method fromDocument (line 1641) | static fromDocument({ head, body }) {
    method constructor (line 1644) | constructor(element, headSnapshot) {
    method clone (line 1648) | clone() {
    method headElement (line 1664) | get headElement() {
    method rootLocation (line 1667) | get rootLocation() {
    method cacheControlValue (line 1672) | get cacheControlValue() {
    method isPreviewable (line 1675) | get isPreviewable() {
    method isCacheable (line 1678) | get isCacheable() {
    method isVisitable (line 1681) | get isVisitable() {
    method getSetting (line 1684) | getSetting(name) {
  class Visit (line 1719) | class Visit {
    method constructor (line 1720) | constructor(delegate, location, restorationIdentifier, options = {}) {
    method adapter (line 1748) | get adapter() {
    method view (line 1751) | get view() {
    method history (line 1754) | get history() {
    method restorationData (line 1757) | get restorationData() {
    method silent (line 1760) | get silent() {
    method start (line 1763) | start() {
    method cancel (line 1771) | cancel() {
    method complete (line 1780) | complete() {
    method fail (line 1791) | fail() {
    method changeHistory (line 1797) | changeHistory() {
    method issueRequest (line 1806) | issueRequest() {
    method simulateRequest (line 1815) | simulateRequest() {
    method startRequest (line 1822) | startRequest() {
    method recordResponse (line 1826) | recordResponse(response = this.response) {
    method finishRequest (line 1838) | finishRequest() {
    method loadResponse (line 1842) | loadResponse() {
    method getCachedSnapshot (line 1864) | getCachedSnapshot() {
    method getPreloadedSnapshot (line 1872) | getPreloadedSnapshot() {
    method hasCachedSnapshot (line 1877) | hasCachedSnapshot() {
    method loadCachedSnapshot (line 1880) | loadCachedSnapshot() {
    method followRedirect (line 1902) | followRedirect() {
    method goToSamePageAnchor (line 1914) | goToSamePageAnchor() {
    method prepareRequest (line 1924) | prepareRequest(request) {
    method requestStarted (line 1929) | requestStarted() {
    method requestPreventedHandlingResponse (line 1932) | requestPreventedHandlingResponse(_request, _response) { }
    method requestSucceededWithResponse (line 1933) | async requestSucceededWithResponse(request, response) {
    method requestFailedWithResponse (line 1947) | async requestFailedWithResponse(request, response) {
    method requestErrored (line 1960) | requestErrored(_request, _error) {
    method requestFinished (line 1966) | requestFinished() {
    method performScroll (line 1969) | performScroll() {
    method scrollToRestoredPosition (line 1983) | scrollToRestoredPosition() {
    method scrollToAnchor (line 1990) | scrollToAnchor() {
    method recordTimingMetric (line 1997) | recordTimingMetric(metric) {
    method getTimingMetrics (line 2000) | getTimingMetrics() {
    method getHistoryMethodForAction (line 2003) | getHistoryMethodForAction(action) {
    method hasPreloadedResponse (line 2012) | hasPreloadedResponse() {
    method shouldIssueRequest (line 2015) | shouldIssueRequest() {
    method cacheSnapshot (line 2026) | cacheSnapshot() {
    method render (line 2032) | async render(callback) {
    method cancelRender (line 2040) | cancelRender() {
  function isSuccessful (line 2047) | function isSuccessful(statusCode) {
  class BrowserAdapter (line 2051) | class BrowserAdapter {
    method constructor (line 2052) | constructor(session) {
    method visitProposedToLocation (line 2059) | visitProposedToLocation(location, options) {
    method visitStarted (line 2062) | visitStarted(visit) {
    method visitRequestStarted (line 2068) | visitRequestStarted(visit) {
    method visitRequestCompleted (line 2077) | visitRequestCompleted(visit) {
    method visitRequestFailedWithStatusCode (line 2080) | visitRequestFailedWithStatusCode(visit, statusCode) {
    method visitRequestFinished (line 2095) | visitRequestFinished(_visit) {
    method visitCompleted (line 2099) | visitCompleted(_visit) { }
    method pageInvalidated (line 2100) | pageInvalidated(reason) {
    method visitFailed (line 2103) | visitFailed(_visit) { }
    method visitRendered (line 2104) | visitRendered(_visit) { }
    method formSubmissionStarted (line 2105) | formSubmissionStarted(_formSubmission) {
    method formSubmissionFinished (line 2109) | formSubmissionFinished(_formSubmission) {
    method showVisitProgressBarAfterDelay (line 2113) | showVisitProgressBarAfterDelay() {
    method hideVisitProgressBar (line 2116) | hideVisitProgressBar() {
    method showFormProgressBarAfterDelay (line 2123) | showFormProgressBarAfterDelay() {
    method hideFormProgressBar (line 2128) | hideFormProgressBar() {
    method reload (line 2135) | reload(reason) {
    method navigator (line 2140) | get navigator() {
  class CacheObserver (line 2145) | class CacheObserver {
    method constructor (line 2146) | constructor() {
    method start (line 2156) | start() {
    method stop (line 2162) | stop() {
    method temporaryElements (line 2168) | get temporaryElements() {
    method temporaryElementsWithDeprecation (line 2171) | get temporaryElementsWithDeprecation() {
  class FrameRedirector (line 2180) | class FrameRedirector {
    method constructor (line 2181) | constructor(session, element) {
    method start (line 2187) | start() {
    method stop (line 2191) | stop() {
    method shouldInterceptLinkClick (line 2195) | shouldInterceptLinkClick(element, _location, _event) {
    method linkClickIntercepted (line 2198) | linkClickIntercepted(element, url, event) {
    method willSubmitForm (line 2204) | willSubmitForm(element, submitter) {
    method formSubmitted (line 2209) | formSubmitted(element, submitter) {
    method shouldSubmit (line 2215) | shouldSubmit(form, submitter) {
    method shouldRedirect (line 2222) | shouldRedirect(element, submitter) {
    method findFrameElement (line 2234) | findFrameElement(element, submitter) {
  class History (line 2245) | class History {
    method constructor (line 2246) | constructor(delegate) {
    method start (line 2268) | start() {
    method stop (line 2276) | stop() {
    method push (line 2283) | push(location, restorationIdentifier) {
    method replace (line 2286) | replace(location, restorationIdentifier) {
    method update (line 2289) | update(method, location, restorationIdentifier = uuid()) {
    method getRestorationDataForIdentifier (line 2295) | getRestorationDataForIdentifier(restorationIdentifier) {
    method updateRestorationData (line 2298) | updateRestorationData(additionalData) {
    method assumeControlOfScrollRestoration (line 2303) | assumeControlOfScrollRestoration() {
    method relinquishControlOfScrollRestoration (line 2310) | relinquishControlOfScrollRestoration() {
    method shouldHandlePopState (line 2316) | shouldHandlePopState() {
    method pageIsLoaded (line 2319) | pageIsLoaded() {
  class Navigator (line 2324) | class Navigator {
    method constructor (line 2325) | constructor(delegate) {
    method proposeVisit (line 2328) | proposeVisit(location, options = {}) {
    method startVisit (line 2338) | startVisit(locatable, restorationIdentifier, options = {}) {
    method submitForm (line 2343) | submitForm(form, submitter) {
    method stop (line 2348) | stop() {
    method adapter (line 2358) | get adapter() {
    method view (line 2361) | get view() {
    method history (line 2364) | get history() {
    method formSubmissionStarted (line 2367) | formSubmissionStarted(formSubmission) {
    method formSubmissionSucceededWithResponse (line 2372) | async formSubmissionSucceededWithResponse(formSubmission, fetchRespons...
    method formSubmissionFailedWithResponse (line 2391) | async formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
    method formSubmissionErrored (line 2405) | formSubmissionErrored(formSubmission, error) {
    method formSubmissionFinished (line 2408) | formSubmissionFinished(formSubmission) {
    method visitStarted (line 2413) | visitStarted(visit) {
    method visitCompleted (line 2416) | visitCompleted(visit) {
    method locationWithActionIsSamePage (line 2419) | locationWithActionIsSamePage(location, action) {
    method visitScrolledToSamePageLocation (line 2427) | visitScrolledToSamePageLocation(oldURL, newURL) {
    method location (line 2430) | get location() {
    method restorationIdentifier (line 2433) | get restorationIdentifier() {
    method getActionForFormSubmission (line 2436) | getActionForFormSubmission({ submitter, formElement }) {
  class PageObserver (line 2448) | class PageObserver {
    method constructor (line 2449) | constructor(delegate) {
    method start (line 2466) | start() {
    method stop (line 2476) | stop() {
    method pageIsInteractive (line 2483) | pageIsInteractive() {
    method pageIsComplete (line 2489) | pageIsComplete() {
    method readyState (line 2496) | get readyState() {
  class ScrollObserver (line 2501) | class ScrollObserver {
    method constructor (line 2502) | constructor(delegate) {
    method start (line 2509) | start() {
    method stop (line 2516) | stop() {
    method updatePosition (line 2522) | updatePosition(position) {
  class StreamMessageRenderer (line 2527) | class StreamMessageRenderer {
    method render (line 2528) | render({ fragment }) {
    method enteringBardo (line 2531) | enteringBardo(currentPermanentElement, newPermanentElement) {
    method leavingBardo (line 2534) | leavingBardo() { }
  function getPermanentElementMapForFragment (line 2536) | function getPermanentElementMapForFragment(fragment) {
  class StreamObserver (line 2551) | class StreamObserver {
    method constructor (line 2552) | constructor(delegate) {
    method start (line 2569) | start() {
    method stop (line 2575) | stop() {
    method connectStreamSource (line 2581) | connectStreamSource(source) {
    method disconnectStreamSource (line 2587) | disconnectStreamSource(source) {
    method streamSourceIsConnected (line 2593) | streamSourceIsConnected(source) {
    method receiveMessageResponse (line 2596) | async receiveMessageResponse(response) {
    method receiveMessageHTML (line 2602) | receiveMessageHTML(html) {
  function fetchResponseFromEvent (line 2606) | function fetchResponseFromEvent(event) {
  function fetchResponseIsStream (line 2613) | function fetchResponseIsStream(response) {
  class ErrorRenderer (line 2619) | class ErrorRenderer extends Renderer {
    method renderElement (line 2620) | static renderElement(currentElement, newElement) {
    method render (line 2624) | async render() {
    method replaceHeadAndBody (line 2628) | replaceHeadAndBody() {
    method activateScriptElements (line 2633) | activateScriptElements() {
    method newHead (line 2642) | get newHead() {
    method scriptElements (line 2645) | get scriptElements() {
  class PageRenderer (line 2650) | class PageRenderer extends Renderer {
    method renderElement (line 2651) | static renderElement(currentElement, newElement) {
    method shouldRender (line 2659) | get shouldRender() {
    method reloadReason (line 2662) | get reloadReason() {
    method prepareToRender (line 2674) | async prepareToRender() {
    method render (line 2677) | async render() {
    method finishRendering (line 2682) | finishRendering() {
    method currentHeadSnapshot (line 2688) | get currentHeadSnapshot() {
    method newHeadSnapshot (line 2691) | get newHeadSnapshot() {
    method newElement (line 2694) | get newElement() {
    method mergeHead (line 2697) | async mergeHead() {
    method replaceBody (line 2704) | async replaceBody() {
    method trackedElementsAreIdentical (line 2710) | get trackedElementsAreIdentical() {
    method copyNewHeadStylesheetElements (line 2713) | async copyNewHeadStylesheetElements() {
    method copyNewHeadScriptElements (line 2721) | copyNewHeadScriptElements() {
    method mergeProvisionalElements (line 2726) | async mergeProvisionalElements() {
    method isCurrentElementInElementList (line 2737) | isCurrentElementInElementList(element, elementList) {
    method removeCurrentHeadProvisionalElements (line 2755) | removeCurrentHeadProvisionalElements() {
    method copyNewHeadProvisionalElements (line 2760) | copyNewHeadProvisionalElements() {
    method activateNewBody (line 2765) | activateNewBody() {
    method activateNewBodyScriptElements (line 2769) | activateNewBodyScriptElements() {
    method assignNewBody (line 2775) | async assignNewBody() {
    method newHeadStylesheetElements (line 2778) | get newHeadStylesheetElements() {
    method newHeadScriptElements (line 2781) | get newHeadScriptElements() {
    method currentHeadProvisionalElements (line 2784) | get currentHeadProvisionalElements() {
    method newHeadProvisionalElements (line 2787) | get newHeadProvisionalElements() {
    method newBodyScriptElements (line 2790) | get newBodyScriptElements() {
  class SnapshotCache (line 2795) | class SnapshotCache {
    method constructor (line 2796) | constructor(size) {
    method has (line 2801) | has(location) {
    method get (line 2804) | get(location) {
    method put (line 2811) | put(location, snapshot) {
    method clear (line 2816) | clear() {
    method read (line 2819) | read(location) {
    method write (line 2822) | write(location, snapshot) {
    method touch (line 2825) | touch(location) {
    method trim (line 2833) | trim() {
  class PageView (line 2840) | class PageView extends View {
    method constructor (line 2841) | constructor() {
    method renderPage (line 2847) | renderPage(snapshot, isPreview = false, willRender = true, visit) {
    method renderError (line 2857) | renderError(snapshot, visit) {
    method clearSnapshotCache (line 2862) | clearSnapshotCache() {
    method cacheSnapshot (line 2865) | async cacheSnapshot(snapshot = this.snapshot) {
    method getCachedSnapshotForLocation (line 2875) | getCachedSnapshotForLocation(location) {
    method snapshot (line 2878) | get snapshot() {
  class Preloader (line 2883) | class Preloader {
    method constructor (line 2884) | constructor(delegate) {
    method snapshotCache (line 2888) | get snapshotCache() {
    method start (line 2891) | start() {
    method preloadOnLoadLinksForView (line 2901) | preloadOnLoadLinksForView(element) {
    method preloadURL (line 2906) | async preloadURL(link) {
  class Session (line 2922) | class Session {
    method constructor (line 2923) | constructor() {
    method start (line 2944) | start() {
    method disable (line 2960) | disable() {
    method stop (line 2963) | stop() {
    method registerAdapter (line 2977) | registerAdapter(adapter) {
    method visit (line 2980) | visit(location, options = {}) {
    method connectStreamSource (line 2990) | connectStreamSource(source) {
    method disconnectStreamSource (line 2993) | disconnectStreamSource(source) {
    method renderStreamMessage (line 2996) | renderStreamMessage(message) {
    method clearCache (line 2999) | clearCache() {
    method setProgressBarDelay (line 3002) | setProgressBarDelay(delay) {
    method setFormMode (line 3005) | setFormMode(mode) {
    method location (line 3008) | get location() {
    method restorationIdentifier (line 3011) | get restorationIdentifier() {
    method historyPoppedToLocationWithRestorationIdentifier (line 3014) | historyPoppedToLocationWithRestorationIdentifier(location, restoration...
    method scrollPositionChanged (line 3027) | scrollPositionChanged(position) {
    method willSubmitFormLinkToLocation (line 3030) | willSubmitFormLinkToLocation(link, location) {
    method submittedFormLinkToLocation (line 3033) | submittedFormLinkToLocation() { }
    method willFollowLinkToLocation (line 3034) | willFollowLinkToLocation(link, location, event) {
    method followedLinkToLocation (line 3039) | followedLinkToLocation(link, location) {
    method allowsVisitingLocationWithAction (line 3044) | allowsVisitingLocationWithAction(location, action) {
    method visitProposedToLocation (line 3047) | visitProposedToLocation(location, options) {
    method visitStarted (line 3051) | visitStarted(visit) {
    method visitCompleted (line 3060) | visitCompleted(visit) {
    method locationWithActionIsSamePage (line 3064) | locationWithActionIsSamePage(location, action) {
    method visitScrolledToSamePageLocation (line 3067) | visitScrolledToSamePageLocation(oldURL, newURL) {
    method willSubmitForm (line 3070) | willSubmitForm(form, submitter) {
    method formSubmitted (line 3075) | formSubmitted(form, submitter) {
    method pageBecameInteractive (line 3078) | pageBecameInteractive() {
    method pageLoaded (line 3082) | pageLoaded() {
    method pageWillUnload (line 3085) | pageWillUnload() {
    method receivedMessageFromStream (line 3088) | receivedMessageFromStream(message) {
    method viewWillCacheSnapshot (line 3091) | viewWillCacheSnapshot() {
    method allowsImmediateRender (line 3097) | allowsImmediateRender({ element }, options) {
    method viewRenderedSnapshot (line 3105) | viewRenderedSnapshot(_snapshot, _isPreview) {
    method preloadOnLoadLinksForView (line 3109) | preloadOnLoadLinksForView(element) {
    method viewInvalidated (line 3112) | viewInvalidated(reason) {
    method frameLoaded (line 3115) | frameLoaded(frame) {
    method frameRendered (line 3118) | frameRendered(fetchResponse, frame) {
    method applicationAllowsFollowingLinkToLocation (line 3121) | applicationAllowsFollowingLinkToLocation(link, location, ev) {
    method applicationAllowsVisitingLocation (line 3125) | applicationAllowsVisitingLocation(location) {
    method notifyApplicationAfterClickingLinkToLocation (line 3129) | notifyApplicationAfterClickingLinkToLocation(link, location, event) {
    method notifyApplicationBeforeVisitingLocation (line 3136) | notifyApplicationBeforeVisitingLocation(location) {
    method notifyApplicationAfterVisitingLocation (line 3142) | notifyApplicationAfterVisitingLocation(location, action) {
    method notifyApplicationBeforeCachingSnapshot (line 3145) | notifyApplicationBeforeCachingSnapshot() {
    method notifyApplicationBeforeRender (line 3148) | notifyApplicationBeforeRender(newBody, options) {
    method notifyApplicationAfterRender (line 3154) | notifyApplicationAfterRender() {
    method notifyApplicationAfterPageLoad (line 3157) | notifyApplicationAfterPageLoad(timing = {}) {
    method notifyApplicationAfterVisitingSamePageLocation (line 3162) | notifyApplicationAfterVisitingSamePageLocation(oldURL, newURL) {
    method notifyApplicationAfterFrameLoad (line 3168) | notifyApplicationAfterFrameLoad(frame) {
    method notifyApplicationAfterFrameRender (line 3171) | notifyApplicationAfterFrameRender(fetchResponse, frame) {
    method submissionIsNavigatable (line 3178) | submissionIsNavigatable(form, submitter) {
    method elementIsNavigatable (line 3192) | elementIsNavigatable(element) {
    method getActionForLink (line 3212) | getActionForLink(link) {
    method snapshot (line 3215) | get snapshot() {
  function extendURLWithDeprecatedProperties (line 3219) | function extendURLWithDeprecatedProperties(url) {
  method get (line 3224) | get() {
  class Cache (line 3230) | class Cache {
    method constructor (line 3231) | constructor(session) {
    method clear (line 3234) | clear() {
    method resetCacheControl (line 3237) | resetCacheControl() {
    method exemptPageFromCache (line 3240) | exemptPageFromCache() {
    method exemptPageFromPreview (line 3243) | exemptPageFromPreview() {
    method setCacheControl (line 3246) | setCacheControl(value) {
  method after (line 3252) | after() {
  method append (line 3255) | append() {
  method before (line 3259) | before() {
  method prepend (line 3262) | prepend() {
  method remove (line 3266) | remove() {
  method replace (line 3269) | replace() {
  method update (line 3272) | update() {
  function start (line 3283) | function start() {
  function registerAdapter (line 3286) | function registerAdapter(adapter) {
  function visit (line 3289) | function visit(location, options) {
  function connectStreamSource (line 3292) | function connectStreamSource(source) {
  function disconnectStreamSource (line 3295) | function disconnectStreamSource(source) {
  function renderStreamMessage (line 3298) | function renderStreamMessage(message) {
  function clearCache (line 3301) | function clearCache() {
  function setProgressBarDelay (line 3305) | function setProgressBarDelay(delay) {
  function setConfirmMethod (line 3308) | function setConfirmMethod(confirmMethod) {
  function setFormMode (line 3311) | function setFormMode(mode) {
  class TurboFrameMissingError (line 3336) | class TurboFrameMissingError extends Error {
  class FrameController (line 3339) | class FrameController {
    method constructor (line 3340) | constructor(element) {
    method connect (line 3363) | connect() {
    method disconnect (line 3377) | disconnect() {
    method disabledChanged (line 3386) | disabledChanged() {
    method sourceURLChanged (line 3391) | sourceURLChanged() {
    method sourceURLReloaded (line 3401) | sourceURLReloaded() {
    method completeChanged (line 3410) | completeChanged() {
    method loadingStyleChanged (line 3415) | loadingStyleChanged() {
    method loadSourceURL (line 3424) | async loadSourceURL() {
    method loadResponse (line 3432) | async loadResponse(fetchResponse) {
    method elementAppearedInViewport (line 3453) | elementAppearedInViewport(element) {
    method willSubmitFormLinkToLocation (line 3457) | willSubmitFormLinkToLocation(link) {
    method submittedFormLinkToLocation (line 3460) | submittedFormLinkToLocation(link, _location, form) {
    method shouldInterceptLinkClick (line 3465) | shouldInterceptLinkClick(element, _location, _event) {
    method linkClickIntercepted (line 3468) | linkClickIntercepted(element, location) {
    method willSubmitForm (line 3471) | willSubmitForm(element, submitter) {
    method formSubmitted (line 3474) | formSubmitted(element, submitter) {
    method prepareRequest (line 3483) | prepareRequest(request) {
    method requestStarted (line 3490) | requestStarted(_request) {
    method requestPreventedHandlingResponse (line 3493) | requestPreventedHandlingResponse(_request, _response) {
    method requestSucceededWithResponse (line 3496) | async requestSucceededWithResponse(request, response) {
    method requestFailedWithResponse (line 3500) | async requestFailedWithResponse(request, response) {
    method requestErrored (line 3504) | requestErrored(request, error) {
    method requestFinished (line 3508) | requestFinished(_request) {
    method formSubmissionStarted (line 3511) | formSubmissionStarted({ formElement }) {
    method formSubmissionSucceededWithResponse (line 3514) | formSubmissionSucceededWithResponse(formSubmission, response) {
    method formSubmissionFailedWithResponse (line 3522) | formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
    method formSubmissionErrored (line 3526) | formSubmissionErrored(formSubmission, error) {
    method formSubmissionFinished (line 3529) | formSubmissionFinished({ formElement }) {
    method allowsImmediateRender (line 3532) | allowsImmediateRender({ element: newFrame }, options) {
    method viewRenderedSnapshot (line 3544) | viewRenderedSnapshot(_snapshot, _isPreview) { }
    method preloadOnLoadLinksForView (line 3545) | preloadOnLoadLinksForView(element) {
    method viewInvalidated (line 3548) | viewInvalidated() { }
    method willRenderFrame (line 3549) | willRenderFrame(currentElement, _newElement) {
    method loadFrameResponse (line 3552) | async loadFrameResponse(fetchResponse, document) {
    method visit (line 3570) | async visit(url) {
    method navigateFrame (line 3584) | navigateFrame(element, url, submitter) {
    method proposeVisitIfNavigatedWithAction (line 3591) | proposeVisitIfNavigatedWithAction(frame, element, submitter) {
    method changeHistory (line 3616) | changeHistory() {
    method handleUnvisitableFrameResponse (line 3622) | async handleUnvisitableFrameResponse(fetchResponse) {
    method willHandleFrameMissingFromResponse (line 3626) | willHandleFrameMissingFromResponse(fetchResponse) {
    method handleFrameMissingFromResponse (line 3644) | handleFrameMissingFromResponse(fetchResponse) {
    method throwFrameMissingError (line 3648) | throwFrameMissingError(fetchResponse) {
    method visitResponse (line 3652) | async visitResponse(response) {
    method findFrameElement (line 3658) | findFrameElement(element, submitter) {
    method extractForeignFrameElement (line 3663) | async extractForeignFrameElement(container) {
    method formActionIsVisitable (line 3683) | formActionIsVisitable(form, submitter) {
    method shouldInterceptNavigation (line 3687) | shouldInterceptNavigation(element, submitter) {
    method id (line 3709) | get id() {
    method enabled (line 3712) | get enabled() {
    method sourceURL (line 3715) | get sourceURL() {
    method sourceURL (line 3720) | set sourceURL(sourceURL) {
    method loadingStyle (line 3725) | get loadingStyle() {
    method isLoading (line 3728) | get isLoading() {
    method complete (line 3731) | get complete() {
    method complete (line 3734) | set complete(value) {
    method isActive (line 3744) | get isActive() {
    method rootLocation (line 3747) | get rootLocation() {
    method isIgnoringChangesTo (line 3753) | isIgnoringChangesTo(attributeName) {
    method ignoringChangesToAttribute (line 3756) | ignoringChangesToAttribute(attributeName, callback) {
    method withCurrentNavigationElement (line 3761) | withCurrentNavigationElement(element, callback) {
  function getFrameElementById (line 3767) | function getFrameElementById(id) {
  function activateElement (line 3775) | function activateElement(element, currentURL) {
  class StreamElement (line 3792) | class StreamElement extends HTMLElement {
    method renderElement (line 3793) | static async renderElement(newElement) {
    method connectedCallback (line 3796) | async connectedCallback() {
    method render (line 3807) | async render() {
    method disconnect (line 3817) | disconnect() {
    method removeDuplicateTargetChildren (line 3823) | removeDuplicateTargetChildren() {
    method duplicateChildren (line 3826) | get duplicateChildren() {
    method performAction (line 3832) | get performAction() {
    method targetElements (line 3842) | get targetElements() {
    method templateContent (line 3853) | get templateContent() {
    method templateElement (line 3856) | get templateElement() {
    method action (line 3867) | get action() {
    method target (line 3870) | get target() {
    method targets (line 3873) | get targets() {
    method raise (line 3876) | raise(message) {
    method description (line 3879) | get description() {
    method beforeRenderEvent (line 3883) | get beforeRenderEvent() {
    method targetElementsById (line 3890) | get targetElementsById() {
    method targetElementsByQuery (line 3900) | get targetElementsByQuery() {
  class StreamSourceElement (line 3912) | class StreamSourceElement extends HTMLElement {
    method constructor (line 3913) | constructor() {
    method connectedCallback (line 3917) | connectedCallback() {
    method disconnectedCallback (line 3921) | disconnectedCallback() {
    method src (line 3926) | get src() {

FILE: lib/rdoc/generator/template/rails/resources/js/search.js
  class Search (line 3) | class Search {
    method constructor (line 4) | constructor(inputEl, outputEl, resultRenderer) {
    method search (line 20) | search() {
    method compileQuery (line 39) | compileQuery(query) {
    method computeScore (line 54) | computeScore(bitPositions, bytes, tiebreakerBonus) {
    method clearResults (line 73) | clearResults() {
    method worstResult (line 80) | get worstResult() {
    method renderResults (line 84) | renderResults() {
    method feelingLucky (line 99) | feelingLucky(query) {
    method focus (line 104) | focus() {
    method blur (line 108) | blur() {
    method active (line 112) | get active() {
    method active (line 116) | set active(value) {
    method query (line 121) | get query() {
    method query (line 125) | set query(value) {
    method cursorEl (line 130) | get cursorEl() {
    method cursorEl (line 134) | set cursorEl(el) {
    method incrementCursor (line 141) | incrementCursor() {
    method decrementCursor (line 147) | decrementCursor() {
    method clickCursor (line 153) | clickCursor() {
    method handleFocusIn (line 158) | handleFocusIn() {
    method handleFocusOut (line 162) | handleFocusOut({ relatedTarget }) {
    method handleKey (line 177) | handleKey(event) {

FILE: lib/sdoc.rb
  type SDoc (line 3) | module SDoc; end

FILE: lib/sdoc/generator.rb
  class RDoc::Options (line 13) | class RDoc::Options
    method core_ext_pattern (line 16) | def core_ext_pattern
  class RDoc::Generator::SDoc (line 23) | class RDoc::Generator::SDoc
    method setup_options (line 40) | def self.setup_options(options)
    method initialize (line 79) | def initialize(store, options)
    method generate (line 92) | def generate
    method class_dir (line 105) | def class_dir
    method file_dir (line 110) | def file_dir
    method index (line 115) | def index
    method debug_msg (line 130) | def debug_msg(*msg)
    method render_file (line 134) | def render_file(template_path, output_path, context = nil)
    method generate_index_file (line 146) | def generate_index_file
    method generate_class_files (line 150) | def generate_class_files
    method generate_file_files (line 154) | def generate_file_files
    method generate_search_index (line 158) | def generate_search_index
    method copy_resources (line 172) | def copy_resources

FILE: lib/sdoc/helpers.rb
  type SDoc::Helpers (line 3) | module SDoc::Helpers
    function link_to (line 12) | def link_to(text, url = nil, html_attributes = {})
    function _link_body (line 30) | def _link_body(text)
    function link_to_if (line 34) | def link_to_if(condition, text, *args)
    function link_to_external (line 38) | def link_to_external(text, url, html_attributes = {})
    function button_to_search (line 46) | def button_to_search(query, display_name: full_name_for(query))
    function full_name_for (line 51) | def full_name_for(named)
    function short_name_for (line 56) | def short_name_for(named)
    function description_for (line 61) | def description_for(rdoc_object)
    function base_tag_for_context (line 67) | def base_tag_for_context(context)
    function canonical_url (line 72) | def canonical_url(path = nil)
    function project_name (line 77) | def project_name
    function project_version (line 81) | def project_version
    function project_git_head (line 86) | def project_git_head
    function page_title (line 90) | def page_title(title = nil)
    function og_title (line 94) | def og_title(title)
    function og_modified_time (line 99) | def og_modified_time
    function page_description (line 103) | def page_description(leading_html, max_length: 160)
    function outline (line 117) | def outline(context)
    function _outline_list (line 127) | def _outline_list(context, headings, following: 0)
    function _outline_list_item (line 135) | def _outline_list_item(context, headings)
    function more_less_ul (line 142) | def more_less_ul(items, limit)
    function top_modules (line 162) | def top_modules(rdoc_store)
    function core_extensions (line 166) | def core_extensions(rdoc_store)
    function _top_modules (line 170) | def _top_modules(rdoc_store)
    function _core_ext? (line 176) | def _core_ext?(rdoc_module)
    function module_breadcrumbs (line 187) | def module_breadcrumbs(rdoc_module)
    function module_ancestors (line 198) | def module_ancestors(rdoc_module)
    function module_methods (line 209) | def module_methods(rdoc_module)
    function method_signature (line 215) | def method_signature(rdoc_method)
    function method_source_code_and_url (line 228) | def method_source_code_and_url(rdoc_method)

FILE: lib/sdoc/helpers/git.rb
  type SDoc::Helpers::Git (line 1) | module SDoc::Helpers::Git
    function _git (line 2) | def _git
    function github_url (line 6) | def github_url(relative_path, line: nil)
    function github? (line 12) | def github?
    function git? (line 16) | def git?
    function git_command (line 21) | def git_command(command)
    function git_head_branch (line 25) | def git_head_branch
    function git_head_sha1 (line 29) | def git_head_sha1
    function git_head_timestamp (line 33) | def git_head_timestamp
    function git_origin_url (line 37) | def git_origin_url
    function github_repository (line 41) | def github_repository

FILE: lib/sdoc/name_list.rb
  class RDoc::Generator::NameList (line 3) | class RDoc::Generator::NameList
    method initialize (line 14) | def initialize store, options
    method build_index (line 26) | def build_index
    method debug_msg (line 38) | def debug_msg *msg
    method generate (line 46) | def generate
    method generate_classes_index (line 60) | def generate_classes_index data, out_dir
    method generate_methods_index (line 71) | def generate_methods_index data, out_dir
    method index_classes (line 85) | def index_classes
    method index_methods (line 101) | def index_methods
    method class_dir (line 116) | def class_dir # :nodoc:
    method file_dir (line 120) | def file_dir # :nodoc:
    method reset (line 124) | def reset files, classes # :nodoc:

FILE: lib/sdoc/postprocessor.rb
  type SDoc::Postprocessor (line 6) | module SDoc::Postprocessor
    function process (line 9) | def process(rendered)
    function rebase_urls! (line 28) | def rebase_urls!(document)
    function rebase_url (line 39) | def rebase_url(url, current_path)
    function version_rubyonrails_urls! (line 52) | def version_rubyonrails_urls!(document)
    function version_url (line 63) | def version_url(url, version)
    function add_ref_link_classes! (line 77) | def add_ref_link_classes!(document)
    function unify_h1_headings! (line 85) | def unify_h1_headings!(document)
    function highlight_code_blocks! (line 94) | def highlight_code_blocks!(document)
    function highlight_code (line 103) | def highlight_code(code, language)
    function guess_code_language (line 108) | def guess_code_language(code)

FILE: lib/sdoc/rdoc_monkey_patches.rb
  function path (line 6) | def path
  function aref_prefix (line 13) | def aref_prefix
  function aref (line 17) | def aref
  function path (line 21) | def path
  function params (line 28) | def params
  function cross_reference (line 35) | def cross_reference(name, text = nil, code = true, *, **)
  function get_class_or_module (line 50) | def get_class_or_module(container, ignore_constants = false)
  function record_location (line 58) | def record_location(*)

FILE: lib/sdoc/renderer.rb
  class SDoc::Renderer (line 4) | class SDoc::Renderer
    method compile_erb (line 7) | def self.compile_erb(path)
    method buffer= (line 17) | def buffer=(*); end
    method initialize (line 19) | def initialize(context, rdoc_options)
    method render (line 25) | def render(...)
    method inline (line 32) | def inline(template_path, local_assigns = {})

FILE: lib/sdoc/search_index.rb
  type SDoc::SearchIndex (line 4) | module SDoc::SearchIndex
    class Uint8Array (line 7) | class Uint8Array < Array
      method to_json (line 10) | def to_json(*)
    function generate (line 15) | def generate(rdoc_modules)
    function build_entry (line 46) | def build_entry(rdoc_object, fingerprint, member_label = nil)
    function derive_ngrams (line 60) | def derive_ngrams(name)
    function compile_ngrams (line 87) | def compile_ngrams(ngram_sets)
    function generate_fingerprint (line 94) | def generate_fingerprint(ngrams, ngram_bit_positions)
    function compute_bit_weights (line 113) | def compute_bit_weights(ngram_bit_positions)
    function compute_tiebreaker_bonus (line 121) | def compute_tiebreaker_bonus(module_name, member_name, description)
    function signature_for (line 132) | def signature_for(rdoc_method)
    function truncate_description (line 150) | def truncate_description(description, limit)

FILE: lib/sdoc/version.rb
  type SDoc (line 1) | module SDoc

FILE: spec/helpers_spec.rb
  function expected (line 537) | def expected(html, context:)
  function ul (line 630) | def ul(items)

FILE: spec/rdoc_generator_spec.rb
  function parse_options (line 4) | def parse_options(*options)

FILE: spec/renderer_spec.rb
  function create_template (line 15) | def create_template(name, erb)

FILE: spec/spec_helper.rb
  function with_env (line 7) | def with_env(env, &block)
  function rdoc_run (line 15) | def rdoc_run(*options)
  function rdoc_dry_run (line 21) | def rdoc_dry_run(*options)
  function rdoc_top_level_for (line 26) | def rdoc_top_level_for(ruby_code)
Condensed preview — 45 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (325K chars).
[
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 938,
    "preview": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the\n// README at: https://github.co"
  },
  {
    "path": ".github/workflows/test.yml",
    "chars": 603,
    "preview": "name: Tests\n\non:\n  push:\n  pull_request:\n    branches: [ main ]\n  schedule:\n    - cron: '0 0 * * *'\n\njobs:\n  test:\n    r"
  },
  {
    "path": ".gitignore",
    "chars": 80,
    "preview": "*.gem\n.bundle\npkg\ndoc\n/test.rb\nGemfile.lock\n/.rake_tasks~\n/*.gem\n/rails/\n/ruby/\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 9746,
    "preview": "Main (3.0.0.alpha)\n==================\n\n* [#198](https://github.com/rails/sdoc/pull/198) Bump version to 3.0.0.alpha [@zz"
  },
  {
    "path": "Gemfile",
    "chars": 215,
    "preview": "source \"https://rubygems.org\"\n\ngemspec\n\ngem \"rack\", \"~> 3.0\"\ngem \"rake\"\ngem \"hoe\"\ngem \"minitest\"\ngem \"puma\"\n\nif ENV[\"rdo"
  },
  {
    "path": "LICENSE",
    "chars": 5158,
    "preview": "Copyright (c) 2014 Vladimir Kolesnikov, and Nathan Broadbent\nCopyright (c) 2014-2017 Zachary Scott\n\nPermission is hereby"
  },
  {
    "path": "README.md",
    "chars": 2998,
    "preview": "# SDoc\n\n[![Tests](https://github.com/rails/sdoc/actions/workflows/test.yml/badge.svg)](https://github.com/rails/sdoc/act"
  },
  {
    "path": "Rakefile",
    "chars": 2435,
    "preview": "require 'bundler'\nBundler::GemHelper.install_tasks\n\nrequire 'rake/testtask'\n\nRake::TestTask.new do |t|\n  t.pattern = \"sp"
  },
  {
    "path": "bin/sdoc",
    "chars": 590,
    "preview": "#!/usr/bin/env ruby\nrequire 'sdoc'\n\nbegin\n  ARGV.unshift('--format=sdoc') if ARGV.grep(/\\A(-f|--fmt|--format|-r|-R|--ri|"
  },
  {
    "path": "config.ru",
    "chars": 734,
    "preview": "# Rack application for serving the documentation locally.\n# After generating the documentation run:\n#\n#   bundle exec ra"
  },
  {
    "path": "lib/rdoc/discover.rb",
    "chars": 106,
    "preview": "begin\n  gem 'rdoc', '>= 5.0'\n  require_relative \"../sdoc\" unless defined?(SDoc)\nrescue Gem::LoadError\nend\n"
  },
  {
    "path": "lib/rdoc/generator/template/rails/_context.rhtml",
    "chars": 5108,
    "preview": "<div id=\"context\">\n  <% unless (description = @context.description).empty? %>\n    <div class=\"description\">\n      <%= de"
  },
  {
    "path": "lib/rdoc/generator/template/rails/_file_nav.rhtml",
    "chars": 257,
    "preview": "<% if @context.text? %>\n  <div class=\"nav__heading\">Outline</div>\n  <div class=\"nav__outline\">\n    <%= outline(@context)"
  },
  {
    "path": "lib/rdoc/generator/template/rails/_head.rhtml",
    "chars": 1390,
    "preview": "<%= base_tag_for_context(@context) %>\n\n<link rel=\"preload\" href=\"/fonts/Bitter-Roman.woff2\" as=\"font\" type=\"font/woff2\" "
  },
  {
    "path": "lib/rdoc/generator/template/rails/_index_nav.rhtml",
    "chars": 603,
    "preview": "<div class=\"nav__heading\">Outline</div>\n<div class=\"nav__outline\">\n  <%= outline(@context) %>\n</div>\n\n<% unless (modules"
  },
  {
    "path": "lib/rdoc/generator/template/rails/_module_nav.rhtml",
    "chars": 1011,
    "preview": "<% unless @context.classes_and_modules.empty? %>\n  <a href=\"#namespace\" class=\"namespace-link\"><%= short_name_for(@conte"
  },
  {
    "path": "lib/rdoc/generator/template/rails/_panel.rhtml",
    "chars": 863,
    "preview": "<nav id=\"panel\" class=\"panel\">\n  <div class=\"banner\">\n    <div class=\"banner__segment\">\n      <label class=\"banner__menu"
  },
  {
    "path": "lib/rdoc/generator/template/rails/class.rhtml",
    "chars": 1000,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"<%= @options.charset %>\">\n    <title><%= page_title @context."
  },
  {
    "path": "lib/rdoc/generator/template/rails/file.rhtml",
    "chars": 1069,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"<%= @options.charset %>\">\n    <title><%= page_title @context."
  },
  {
    "path": "lib/rdoc/generator/template/rails/index.rhtml",
    "chars": 605,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"<%= @options.charset %>\">\n    <title><%= page_title %></title"
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/css/highlight.css",
    "chars": 7025,
    "preview": "/* From https://github.com/rails/rails/blob/a3b26873ebf80da6e218cf58b2c9c6669f2d2f1e/guides/assets/stylesheets/highlight"
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/css/main.css",
    "chars": 15666,
    "preview": "@font-face {\n  font-family: \"Bitter\";\n  src: url(\"../fonts/Bitter-Roman.woff2\") format(\"woff2\");\n  font-weight: 100 900;"
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/js/.gitattributes",
    "chars": 27,
    "preview": "@hotwired--turbo.js binary\n"
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/js/@hotwired--turbo.js",
    "chars": 140247,
    "preview": "/*\nTurbo 7.3.0\nCopyright © 2023 37signals LLC\n */\n(function () {\n    if (window.Reflect === undefined ||\n        window."
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/js/main.js",
    "chars": 2558,
    "preview": "import { Search } from \"./search.js\";\n\ndocument.addEventListener(\"turbo:load\", () => {\n  const searchInput = document.ge"
  },
  {
    "path": "lib/rdoc/generator/template/rails/resources/js/search.js",
    "chars": 4402,
    "preview": "import searchIndex from \"./search-index.js\";\n\nexport class Search {\n  constructor(inputEl, outputEl, resultRenderer) {\n "
  },
  {
    "path": "lib/sdoc/generator.rb",
    "chars": 4332,
    "preview": "require 'pathname'\nrequire 'fileutils'\nrequire 'json'\n\nrequire \"rdoc\"\nrequire_relative \"rdoc_monkey_patches\"\n\nrequire \"s"
  },
  {
    "path": "lib/sdoc/helpers/git.rb",
    "chars": 1135,
    "preview": "module SDoc::Helpers::Git\n  def _git\n    @@_git ||= {}\n  end\n\n  def github_url(relative_path, line: nil)\n    return unle"
  },
  {
    "path": "lib/sdoc/helpers.rb",
    "chars": 7533,
    "preview": "require \"erb\"\n\nmodule SDoc::Helpers\n  include ERB::Util\n\n  require_relative \"helpers/git\"\n  include SDoc::Helpers::Git\n\n"
  },
  {
    "path": "lib/sdoc/name_list.rb",
    "chars": 2616,
    "preview": "# frozen_string_literal: true\n\nclass RDoc::Generator::NameList\n\n  include RDoc::Text\n\n  attr_reader :index # :nodoc:\n\n  "
  },
  {
    "path": "lib/sdoc/postprocessor.rb",
    "chars": 3436,
    "preview": "require \"nokogiri\"\nrequire \"pathname\"\nrequire \"rouge\"\nrequire \"uri\"\n\nmodule SDoc::Postprocessor\n  extend self\n\n  def pro"
  },
  {
    "path": "lib/sdoc/rdoc_monkey_patches.rb",
    "chars": 1264,
    "preview": "require \"rdoc\"\n\nRDoc::TopLevel.prepend(Module.new do\n  attr_writer :path\n\n  def path\n    @path ||= super\n  end\nend)\n\n\nRD"
  },
  {
    "path": "lib/sdoc/renderer.rb",
    "chars": 926,
    "preview": "require \"erb\"\nrequire_relative \"helpers\"\n\nclass SDoc::Renderer\n  include SDoc::Helpers\n\n  def self.compile_erb(path)\n   "
  },
  {
    "path": "lib/sdoc/search_index.rb",
    "chars": 6565,
    "preview": "require \"nokogiri\"\nrequire_relative \"helpers\"\n\nmodule SDoc::SearchIndex\n  extend self\n\n  class Uint8Array < Array\n    # "
  },
  {
    "path": "lib/sdoc/version.rb",
    "chars": 42,
    "preview": "module SDoc\n  VERSION = '3.0.0.alpha'\nend\n"
  },
  {
    "path": "lib/sdoc.rb",
    "chars": 79,
    "preview": "gem 'rdoc'\n\nmodule SDoc; end\n\nrequire 'sdoc/generator'\nrequire 'sdoc/name_list'"
  },
  {
    "path": "netlify.toml",
    "chars": 744,
    "preview": "[build]\n  command = \"bundle exec rake test:rails\"\n  publish = \"doc/public\"\n\n[[headers]]\n  for = \"*\"\n  [headers.values]\n "
  },
  {
    "path": "sdoc.gemspec",
    "chars": 918,
    "preview": "# -*- encoding: utf-8 -*-\n$:.push File.expand_path(\"../lib\", __FILE__)\nrequire 'sdoc/version'\n\nGem::Specification.new do"
  },
  {
    "path": "spec/helpers_spec.rb",
    "chars": 30842,
    "preview": "require \"spec_helper\"\n\ndescribe SDoc::Helpers do\n  before :each do\n    @helpers = Class.new do\n      include SDoc::Helpe"
  },
  {
    "path": "spec/postprocessor_spec.rb",
    "chars": 14109,
    "preview": "require \"spec_helper\"\n\ndescribe SDoc::Postprocessor do\n  describe \"#process\" do\n    it \"rebases URLs\" do\n      rendered "
  },
  {
    "path": "spec/rdoc_generator_spec.rb",
    "chars": 5603,
    "preview": "require File.join(File.dirname(__FILE__), '/spec_helper')\n\ndescribe RDoc::Generator::SDoc do\n  def parse_options(*option"
  },
  {
    "path": "spec/rdoc_monkey_patches_spec.rb",
    "chars": 3490,
    "preview": "require \"spec_helper\"\n\ndescribe \"RDoc monkey patches\" do\n  describe RDoc::TopLevel do\n    it \"supports setting #path\" do"
  },
  {
    "path": "spec/renderer_spec.rb",
    "chars": 3303,
    "preview": "require \"spec_helper\"\n\ndescribe SDoc::Renderer do\n  before do\n    @template_dir = Dir.mktmpdir\n    @rdoc_options = RDoc:"
  },
  {
    "path": "spec/search_index_spec.rb",
    "chars": 14495,
    "preview": "require \"spec_helper\"\n\ndescribe SDoc::SearchIndex do\n  describe \"#generate\" do\n    it \"generates a search index for the "
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 915,
    "preview": "require 'bundler/setup'\n\nrequire 'sdoc'\n\nrequire 'minitest/autorun'\n\ndef with_env(env, &block)\n  original_env = ENV.to_h"
  }
]

About this extraction

This page contains the full source code of the voloko/sdoc GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 45 files (300.6 KB), approximately 78.4k tokens, and a symbol index with 776 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!