# frozen_string_literal: true# Public: Registry for accessing resources managed by Vite, using a generated# manifest file which maps entrypoint names to file paths.## Example:# lookup_entrypoint('calendar', type: :javascript)# => { "file" => "/vite/assets/calendar-1016838bab065ae1e314.js", "imports" => [] }## NOTE: Using `"autoBuild": true` in `config/vite.json` file will trigger a build# on demand as needed, before performing any lookup.classViteRuby::Manifestdefinitialize(vite_ruby)@vite_ruby=vite_ruby@build_mutex=Mutex.newifconfig.auto_buildend# Public: Returns the path for the specified Vite entrypoint file.## Raises an error if the resource could not be found in the manifest.defpath_for(name,**options)lookup!(name,**options).fetch("file")end# Public: Returns scripts, imported modules, and stylesheets for the specified# entrypoint files.defresolve_entries(*names,**options)entries=names.map{|name|lookup!(name,**options)}script_paths=entries.map{|entry|entry.fetch("file")}imports=dev_server_running??[]:entries.flat_map{|entry|entry["imports"]}.compact{scripts: script_paths,imports: imports.filter_map{|entry|entry.fetch("file")}.uniq,stylesheets: dev_server_running??[]:(entries+imports).flat_map{|entry|entry["css"]}.compact.uniq,}end# Public: Refreshes the cached mappings by reading the updated manifest files.defrefresh@manifest=load_manifestend# Public: The path from where the browser can download the Vite HMR client.defvite_client_srcprefix_asset_with_host("@vite/client")ifdev_server_running?end# Public: The content of the preamble needed by the React Refresh plugin.defreact_refresh_preambleifdev_server_running?<<~REACT_REFRESH
<script type="module">
#{react_preamble_code}
</script>
REACT_REFRESHendend# Public: Source script for the React Refresh plugin.defreact_preamble_codeifdev_server_running?<<~REACT_PREAMBLE_CODE
import RefreshRuntime from '#{prefix_asset_with_host("@react-refresh")}'
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
REACT_PREAMBLE_CODEendendprotected# Internal: Strict version of lookup.## Returns a relative path for the asset, or raises an error if not found.deflookup!(name,**options)lookup(name,**options)||missing_entry_error(name,**options)end# Internal: Computes the path for a given Vite asset using manifest.json.## Returns a relative path, or nil if the asset is not found.## Example:# manifest.lookup('calendar.js')# => { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }deflookup(name,**options)@build_mutex.synchronize{builder.build||(returnnil)}ifshould_build?find_manifest_entryresolve_entry_name(name,**options)endprivate# Internal: The prefix used by Vite.js to request files with an absolute path.FS_PREFIX="/@fs/"extendForwardabledef_delegators:@vite_ruby,:config,:builder,:dev_server_running?# NOTE: Auto compilation is convenient when running tests, when the developer# won't focus on the frontend, or when running the Vite server is not desired.defshould_build?config.auto_build&&!dev_server_running?end# Internal: Finds the specified entry in the manifest.deffind_manifest_entry(name)ifdev_server_running?{"file"=>prefix_vite_asset(name)}elsemanifest[name]endend# Internal: The parsed data from manifest.json.## NOTE: When using build-on-demand in development and testing, the manifest# is reloaded automatically before each lookup, to ensure it's always fresh.defmanifestreturnrefreshifconfig.auto_build@manifest||=load_manifestend# Internal: Loads and merges the manifest files, resolving the asset paths.defload_manifestconfig.manifest_paths.map{|path|JSON.parse(path.read)}.inject({},&:merge).tap{|manifest|resolve_references(manifest)}end# Internal: Scopes an asset to the output folder in public, as a path.defprefix_vite_asset(path)File.join(vite_asset_origin||"/",config.public_output_dir,path)end# Internal: Prefixes an asset with the `asset_host` for tags that do not use# the framework tag helpers.defprefix_asset_with_host(path)File.join(vite_asset_origin||config.asset_host||"/",config.public_output_dir,path)end# Internal: The origin of assets managed by Vite.defvite_asset_originconfig.originifdev_server_running?&&config.skip_proxyend# Internal: Resolves the paths that reference a manifest entry.defresolve_references(manifest)manifest.each_valuedo|entry|entry["file"]=prefix_vite_asset(entry["file"])%w[css assets].eachdo|key|entry[key]=entry[key].map{|path|prefix_vite_asset(path)}ifentry[key]endentry["imports"]&.map!{|name|manifest.fetch(name)}endend# Internal: Resolves the manifest entry name for the specified resource.defresolve_entry_name(name,type: nil)returnresolve_virtual_entry(name)iftype==:virtualname=with_file_extension(name.to_s,type)raiseArgumentError,"Asset names can not be relative. Found: #{name}"ifname.start_with?(".")# Explicit path, relative to the source_code_dir.name.sub(%r{^~/(.+)$}){returnRegexp.last_match(1)}# Explicit path, relative to the project root.name.sub(%r{^/(.+)$}){returnresolve_absolute_entry(Regexp.last_match(1))}# Sugar: Prefix with the entrypoints dir if the path is not nested.name.include?("/")?name:File.join(config.entrypoints_dir,name)end# Internal: Entry names in the manifest are relative to the Vite.js.# During develoment, files outside the root must be requested explicitly.defresolve_absolute_entry(name)ifdev_server_running?File.join(FS_PREFIX,config.root,name)elseconfig.root.join(name).relative_path_from(config.vite_root_dir).to_sendend# Internal: Resolves a virtual entry by walking all the manifest keys.defresolve_virtual_entry(name)manifest.keys.find{|file|file.include?(name)}||nameend# Internal: Adds a file extension to the file name, unless it already has one.defwith_file_extension(name,entry_type)ifFile.extname(name).empty?&&(ext=extension_for_type(entry_type))"#{name}.#{ext}"elsenameendend# Internal: Allows to receive :javascript and :stylesheet as :type in helpers.defextension_for_type(entry_type)caseentry_typewhen:javascriptthen"js"when:stylesheetthen"css"when:typescriptthen"ts"elseentry_typeendend# Internal: Raises a detailed message when an entry is missing in the manifest.defmissing_entry_error(name,**options)raiseViteRuby::MissingEntrypointError.new(file_name: resolve_entry_name(name,**options),last_build: builder.last_build_metadata,manifest: @manifest,config: config,)endend