Add target config setting and front matter variables so one could create multiple outputs from a single site codebase with various target site included files

This commit is contained in:
Dan Ballard 2025-08-17 09:35:02 -05:00
parent 40ac06ed3e
commit af57ed4871
9 changed files with 63 additions and 10 deletions

View File

@ -43,6 +43,7 @@ show_drafts : null
limit_posts : 0 limit_posts : 0
future : false future : false
unpublished : false unpublished : false
target : "default"
# Plugins # Plugins
whitelist : [] whitelist : []

View File

@ -9,3 +9,4 @@ Sites built using Jekyll can be deployed in a large number of ways due to the st
* [Manually]({{ '/docs/deployment/manual/' | relative_url }}) * [Manually]({{ '/docs/deployment/manual/' | relative_url }})
* [Automated]({{ '/docs/deployment/automated/' | relative_url }}) * [Automated]({{ '/docs/deployment/automated/' | relative_url }})
* [Third Party]({{ '/docs/deployment/third-party/' | relative_url }}) * [Third Party]({{ '/docs/deployment/third-party/' | relative_url }})
* [Multiple Sites and Target]({{ '/docs/deployment/multiple-sites' | relative_url }})

View File

@ -0,0 +1,44 @@
---
title: Multiple Sites and Target
permalink: /docs/deployment/multiple-sites/
---
The `target` setting in `_config.yml` and frontmatter in conjunction with config stacking allows multiple sites with varitation to be built from one codebase.
## Use Case
You may have multiple access paths to your site, and want to offer unique content on some of them, for examples you may have a open web version of your site at `https://foo.com` and you may also have an [onion service](https://community.torproject.org/onion-services/setup/) version of your site accesible via `http://foo000...abc.onion`. Alternately you may have a public facing version of the site, and an internal network or VPN accessible version that you want additional content to be included on.
## Method
By default the `target` config option is set to "default" in `_site_config.yml` and when comparing with frontmatter of content, if none is set, it inherit's the site's value. So by default all content will be published. To make content only appear on a specific version of a site, in frontmatter add `target: xVersion` where "xVersion" will be a `target` option set in a second `_site_x.yml`.
You generate the normal site the same
`bundle exec jekyll build`
For the second site, you create a mini site specific config, like
```yml
url: https://altDomain.com
destination: _site_xVersion
target: xVersion
```
and build it with
`bundle exec jekyll build --config "_config.yml,_config_xversion.yml"`
Jekyll configs stack, and overrides from additional configs override earlier ones, so this will get all the default site config options and then just change `url`, `destination` and `target`
Then any content with a frontmatter `target` of "xVersion" will be included in this build which will be output to the new `_site_xVersion`.
If there is any content you want on the default version of the site but not any alternative ones, just add `target: default` to it's frontmatter.
Then configure your webserver with a second site config with the alternative access path and pointing to `_site_xVersion` directory.
### Potential Cons
This does result in multiple builds, which is potentially the one negative of this method if you are very constrained for space or your jekyll site is very large.

View File

@ -183,9 +183,12 @@ module Jekyll
# Whether the collection's documents ought to be written as individual # Whether the collection's documents ought to be written as individual
# files in the output. # files in the output.
# #
# Returns true if the 'write' metadata is true, false otherwise. # Returns true if the 'write' metadata is true and
# if the collection's target matches the site's target,
# false otherwise.
def write? def write?
!!metadata.fetch("output", false) !!metadata.fetch("output", false) &&
(site.target == metadata.fetch("target", site.target))
end end
# The URL template to render collection's documents at. # The URL template to render collection's documents at.

View File

@ -30,6 +30,7 @@ module Jekyll
"limit_posts" => 0, "limit_posts" => 0,
"future" => false, "future" => false,
"unpublished" => false, "unpublished" => false,
"target" => "default",
# Plugins # Plugins
"whitelist" => [], "whitelist" => [],

View File

@ -348,17 +348,20 @@ module Jekyll
end end
# Determine whether this document should be written. # Determine whether this document should be written.
# Based on the Collection to which it belongs. # Based on the Collection to which it belongs
# and site and document target.
# #
# True if the document has a collection and if that collection's #write? # True if the document has a collection and if that collection's #write?
# method returns true, and if the site's Publisher will publish the document. # method returns true, and if the site's Publisher will publish the document,
# and if the document's target matches the site target or is undefined.
# False otherwise. # False otherwise.
# #
# rubocop:disable Naming/MemoizedInstanceVariableName # rubocop:disable Naming/MemoizedInstanceVariableName
def write? def write?
return @write_p if defined?(@write_p) return @write_p if defined?(@write_p)
@write_p = collection&.write? && site.publisher.publish?(self) @write_p = collection&.write? && site.publisher.publish?(self) &&
(site.target == data.fetch("target", site.target))
end end
# rubocop:enable Naming/MemoizedInstanceVariableName # rubocop:enable Naming/MemoizedInstanceVariableName

View File

@ -15,7 +15,7 @@ module Jekyll
private delegate_method_as :data, :fallback_data private delegate_method_as :data, :fallback_data
delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date
data_delegators "title", "categories", "tags" data_delegators "title", "categories", "tags", :target
def collection def collection
@obj.collection.label @obj.collection.label

View File

@ -180,7 +180,7 @@ module Jekyll
end end
def write? def write?
true site.config["target"] == data.fetch("target", site.config["target"])
end end
def excerpt_separator def excerpt_separator

View File

@ -6,7 +6,7 @@ module Jekyll
:file_read_opts, :future, :gems, :generators, :highlighter, :file_read_opts, :future, :gems, :generators, :highlighter,
:include, :inclusions, :keep_files, :layouts, :limit_posts, :include, :inclusions, :keep_files, :layouts, :limit_posts,
:lsi, :pages, :permalink_style, :plugin_manager, :plugins, :lsi, :pages, :permalink_style, :plugin_manager, :plugins,
:reader, :safe, :show_drafts, :static_files, :theme, :time, :reader, :safe, :target, :show_drafts, :static_files, :theme, :time,
:unpublished :unpublished
attr_reader :cache_dir, :config, :dest, :filter_cache, :includes_load_paths, attr_reader :cache_dir, :config, :dest, :filter_cache, :includes_load_paths,
@ -47,7 +47,7 @@ module Jekyll
def config=(config) def config=(config)
@config = config.clone @config = config.clone
%w(safe lsi highlighter baseurl exclude include future unpublished %w(safe lsi highlighter baseurl exclude include future unpublished target
show_drafts limit_posts keep_files).each do |opt| show_drafts limit_posts keep_files).each do |opt|
send(:"#{opt}=", config[opt]) send(:"#{opt}=", config[opt])
end end
@ -360,7 +360,7 @@ module Jekyll
end end
def each_site_file def each_site_file
pages.each { |page| yield page } pages.each { |page| yield (page) if page.write? }
static_files.each { |file| yield(file) if file.write? } static_files.each { |file| yield(file) if file.write? }
collections.each_value { |coll| coll.docs.each { |doc| yield(doc) if doc.write? } } collections.each_value { |coll| coll.docs.each { |doc| yield(doc) if doc.write? } }
end end