require'rack/mime'require'middleman-core/sitemap/extensions/traversal'require'middleman-core/file_renderer'require'middleman-core/template_renderer'require'middleman-core/contracts'moduleMiddleman# Sitemap namespacemoduleSitemap# Sitemap Resource classclassResourceincludeContractsincludeMiddleman::Sitemap::Extensions::Traversal# The source path of this resource (relative to the source directory,# without template extensions)# @return [String]attr_reader:path# The output path in the build directory for this resource# @return [String]attr_accessor:destination_path# The on-disk source file for this resource, if there is one# @return [String]ContractMaybe[IsA['Middleman::SourceFile']]attr_reader:file_descriptor# The path to use when requesting this resource. Normally it's# the same as {#destination_path} but it can be overridden in subclasses.# @return [String]aliasrequest_pathdestination_pathMETADATA_HASH={options: Maybe[Hash],locals: Maybe[Hash],page: Maybe[Hash]}.freeze# The metadata for this resource# @return [Hash]ContractMETADATA_HASHattr_reader:metadataattr_accessor:ignored# Initialize resource with parent store and URL# @param [Middleman::Sitemap::Store] store# @param [String] path# @param [String] sourceContractIsA['Middleman::Sitemap::Store'],String,Maybe[Or[IsA['Middleman::SourceFile'],String]]=>Anydefinitialize(store,path,source=nil)@store=store@app=@store.app@path=path@ignored=falsesource=Pathname(source)ifsource&&source.is_a?(String)@file_descriptor=ifsource&&source.is_a?(Pathname)::Middleman::SourceFile.new(source.relative_path_from(@app.source_dir),source,@app.source_dir,Set.new([:source]),0)elsesourceend@destination_path=@path# Options are generally rendering/sitemap options# Locals are local variables for rendering this resource's template# Page are data that is exposed through this resource's data member.# Note: It is named 'page' for backwards compatibility with older MM.@metadata={options: {},locals: {},page: {}}@page_data=nilend# Whether this resource has a template file# @return [Boolean]ContractBooldeftemplate?returnfalseiffile_descriptor.nil?!::Middleman::Util.tilt_class(file_descriptor[:full_path].to_s).nil?end# Backwards compatible method for turning descriptor into a string.# @return [String]ContractMaybe[String]defsource_filefile_descriptor&&file_descriptor[:full_path].to_sendContractOr[Symbol,String,Integer]defpage_idmetadata[:page][:id]||make_implicit_page_id(destination_path)end# Merge in new metadata specific to this resource.# @param [Hash] meta A metadata block with keys :options, :locals, :page.# Options are generally rendering/sitemap options# Locals are local variables for rendering this resource's template# Page are data that is exposed through this resource's data member.# Note: It is named 'page' for backwards compatibility with older MM.ContractMETADATA_HASH,Maybe[Bool]=>METADATA_HASHdefadd_metadata(meta={},reverse=false)@page_data=nil@metadata=ifreversemeta.deep_merge(@metadata)else@metadata.deep_merge(meta)endend# Data about this resource, populated from frontmatter or extensions.# @return [Hash]ContractRespondTo[:indifferent_access?]defdata@page_data||=::Middleman::Util.recursively_enhance(metadata[:page])end# Options about how this resource is rendered, such as its :layout,# :renderer_options, and whether or not to use :directory_indexes.# @return [Hash]ContractHashdefoptionsmetadata[:options]end# Local variable mappings that are used when rendering the template for this resource.# @return [Hash]ContractHashdeflocalsmetadata[:locals]end# Extension of the path (i.e. '.js')# @return [String]ContractStringdefextFile.extname(path)end# Render this resource# @return [String]ContractHash,Hash=>Stringdefrender(opts={},locs={})return::Middleman::FileRenderer.new(@app,file_descriptor[:full_path].to_s).template_data_for_fileunlesstemplate?md=metadataopts=md[:options].deep_merge(opts)locs=md[:locals].deep_merge(locs)locs[:current_path]||=destination_path# Certain output file types don't use layoutsopts[:layout]=falseif!opts.key?(:layout)&&!@app.config.extensions_with_layout.include?(ext)renderer=::Middleman::TemplateRenderer.new(@app,file_descriptor[:full_path].to_s)renderer.render(locs,opts)end# A path without the directory index - so foo/index.html becomes# just foo. Best for linking.# @return [String]ContractStringdefurlurl_path=destination_pathif@app.config[:strip_index_file]url_path=url_path.sub(/(^|\/)#{Regexp.escape(@app.config[:index_file])}$/,@app.config[:trailing_slash]?'/':'')endFile.join(@app.config[:http_prefix],url_path)end# Whether the source file is binary.## @return [Boolean]ContractBooldefbinary?!file_descriptor.nil?&&(file_descriptor[:types].include?(:binary)||::Middleman::Util.binary?(file_descriptor[:full_path].to_s))end# Ignore a resource directly, without going through the whole# ignore filter stuff.# @return [void]ContractAnydefignore!@ignored=trueend# Whether the Resource is ignored# @return [Boolean]ContractBooldefignored?@ignoredend# The preferred MIME content type for this resource based on extension or metadata# @return [String] MIME type for this resourceContractMaybe[String]defcontent_typeoptions[:content_type]||::Rack::Mime.mime_type(ext,nil)end# The normalized source path of this resource (relative to the source directory,# without template extensions)# @return [String]defnormalized_path@normalized_path||=::Middleman::Util.normalize_path@pathenddefto_s"#<#{self.class} path=#{@path}>"endaliasinspectto_s# Ruby 2.0 calls inspect for NoMethodError instead of to_sprotected# Makes a page id based on path (when not otherwise given)## Removes .html extension and potential leading slashes or dots# eg. "foo/bar/baz.foo.html" => "foo/bar/baz.foo"ContractString=>Stringdefmake_implicit_page_id(path)@id||=beginifprok=@app.config[:page_id_generator]returnprok.call(path)endbasename=ifext=='.html'File.basename(path,ext)elseFile.basename(path)end# Remove leading dot or slash if presentFile.join(File.dirname(path),basename).gsub(/^\.?\//,'')endendendclassStringResource<Resourcedefinitialize(store,path,contents=nil,&block)@request_path=path@contents=block_given??block:contentssuper(store,path)enddeftemplate?trueenddefrender(*)@contents.respond_to?(:call)?@contents.call:@contentsenddefbinary?falseendendendend