Skip to content

Instantly share code, notes, and snippets.

@maximebf
Last active February 19, 2016 08:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maximebf/5992910 to your computer and use it in GitHub Desktop.
Save maximebf/5992910 to your computer and use it in GitHub Desktop.
Plugins, configuration files and fabfile to help you manage a multi-site jekyll setup
module Jekyll
class Site
def read
self.read_config
self.read_layouts
self.read_directories
end
def read_config(dir='')
base = File.join(self.source, dir)
entries = Dir.chdir(base) { filter_config_entries(Dir.entries('.')) }
entries.each do |f|
f_abs = File.join(base, f)
f_rel = File.join(dir, f)
if f.end_with?('.config.yml')
read_config_file(f_abs)
elsif File.directory?(f_abs)
next if self.dest.sub(/\/$/, '') == f_abs
read_config(f_rel)
end
end
end
def read_config_file(f)
content = File.read(f)
data = YAML.load(content)
self.config = self.config.merge(data)
end
def filter_config_entries(entries)
entries = entries.reject do |e|
['.', '#'].include?(e[0..0])
end
end
end
end
module Jekyll
class RenamedStaticFile < StaticFile
def initialize(site, base, original_name, new_name)
@site = site
@base = base
@original_name = original_name
@new_name = new_name
end
def path
File.join(@base, @original_name)
end
def destination(dest)
File.join(dest, @new_name)
end
end
class CopyAssetsGenerator < Generator
safe true
def generate(site)
read_directories(site, '../_assets')
end
def read_directories(site, base, dir = '')
entries = Dir.chdir(File.join(base, dir)) { site.filter_entries(Dir.entries('.')) }
entries.each do |f|
f_abs = File.join(base, dir, f)
if File.directory?(f_abs)
read_directories(site, base, File.join(dir, f))
elsif !File.symlink?(f_abs)
site.static_files << RenamedStaticFile.new(site, base, File.join(dir, f), File.join("assets", dir, f))
end
end
end
end
end
from fabric.api import task, env, execute, local, put, lcd, cd
import os
env.domains = ['maximebf.com', 'travelingcoder.com']
env.build_path = '/tmp/jekyll'
env.publish_path = '/home/maxime/sites'
env.nginx_path = "/etc/nginx"
env.supervisor_path = "/etc/supervisor"
def _copy_tpl(tpl_filename, target_filename, vars):
with open(tpl_filename) as f:
content = f.read()
for k, v in vars.iteritems():
content = content.replace(k, v)
if not os.path.exists(os.path.dirname(target_filename)):
os.makedirs(os.path.dirname(target_filename))
with open(target_filename, 'w') as f:
f.write(content)
def _iter_domains(domains):
if domains == 'all':
return env.domains
if isinstance(domains, str):
return domains.split(',')
return domains
@task
def serve(domain, future='yes', drafts='yes', port=4000):
with lcd(domain):
flags = []
if future == 'yes':
flags.append("--future")
if drafts == 'yes':
flags.append('--drafts')
build_path = os.path.join(env.build_path, domain)
local('/usr/local/bin/jekyll serve --port %s --trace --watch %s --destination %s' % (port, ' '.join(flags), build_path))
@task
def build(domains):
for domain in _iter_domains(domains):
with lcd(domain):
build_path = os.path.join(env.build_path, domain)
local("/usr/local/bin/jekyll build --destination %s" % build_path)
@task
def publish(domains):
for domain in _iter_domains(domains):
execute(build, domain)
local('rsync -rlpzvi --delete %s/ %s' % (os.path.join(env.build_path, domain), os.path.join(env.publish_path, domain)))
def _publish_conf_file(template_filename, filename, other_params=None):
params = {"$PUBLISH_PATH": env.publish_path,
"$WORK_PATH": os.getcwd()}
if other_params is not None:
params.update(other_params)
_copy_tpl(template_filename, filename, params)
def _gen_nginx_conf_for_domain(domain):
filename = os.path.join(env.nginx_path, "sites-available", domain)
includes = []
for f in os.listdir(domain):
if f.startswith('nginx') and f.endswith('.conf'):
includes.append("include %s/%s;" % (os.path.join(os.getcwd(), domain), f))
params = {"$DOMAIN": domain,
"$INCLUDES": "\n".join(includes)}
_publish_conf_file("nginx.conf", filename, params)
def _gen_supervisor_conf_for_domain(domain):
filename = os.path.join(env.supervisor_path, "conf.d", domain + ".conf")
_publish_conf_file("supervisor.conf", filename, {"$DOMAIN": domain})
@task
def gen_nginx_conf(domains='all'):
for domain in _iter_domains(domains):
_gen_nginx_conf_for_domain(domain)
@task
def gen_supervisor_conf(domains='all'):
for domain in _iter_domains(domains):
_gen_supervisor_conf_for_domain(domain)
@task
def gen_conf(domains='all'):
execute(gen_nginx_conf, domains)
execute(gen_supervisor_conf, domains)
module Jekyll
module Tags
class IncludeTag
def render_from_dir(context, f)
includes_dir = File.join(context.registers[:site].source, f)
Dir.chdir(includes_dir) do
choices = Dir['**/*'].reject { |x| File.symlink?(x) }
if choices.include?(@file)
source = File.read(@file)
partial = Liquid::Template.parse(source)
content = ""
context.stack do
content = partial.render(context)
end
return content
end
end
false
end
def render(context)
if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
return "Include file '#{@file}' contains invalid characters or sequences"
end
context.registers[:site].config['includes'].each do |f|
content = render_from_dir(context, f)
if content != false
return content
end
end
"Included file '#{@file}' not found in _includes directory"
end
end
end
end
module Jekyll
class Site
def read_layouts_dir(dir)
base = File.join(self.source, dir)
return unless File.exists?(base)
entries = []
Dir.chdir(base) { entries = filter_entries(Dir['*.*']) }
entries.each do |f|
name = f.split(".")[0..-2].join(".")
self.layouts[name] = Layout.new(self, base, f)
end
end
def read_layouts
self.config['layouts'].each do |f|
read_layouts_dir(f)
end
end
end
end
#
# Auto generated config for jekyll site: $DOMAIN
#
server {
listen 8080;
server_name $DOMAIN;
root $PUBLISH_PATH/$DOMAIN;
access_log /home/logs/nginx/$DOMAIN.access.log;
error_log /home/logs/nginx/errors.log;
try_files $uri.html $uri/ =404;
location /assets {
access_log off;
expires max;
}
$INCLUDES
}
server {
listen 8080;
server_name draft.$DOMAIN;
root $PUBLISH_PATH/draft.$DOMAIN;
access_log off;
error_log /home/logs/nginx/errors.log;
auth_basic "Restricted access";
auth_basic_user_file /etc/nginx/users.conf;
try_files $uri.html $uri/ =404;
}
server {
listen 8080;
server_name www.$DOMAIN;
rewrite ^/(.*) http://$DOMAIN/$1 permanent;
}
[program:draft$DOMAIN]
directory=$WORK_PATH/$DOMAIN
command=jekyll build --watch --future --drafts --destination $PUBLISH_PATH/draft.$DOMAIN
autostart=true
autorestart=true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment