diff --git a/.gitignore b/.gitignore
index 6ea3aceb..f99bbb6d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,5 @@ assets/js/bundle.js
node_modules
_site
Gemfile.lock
+.idea
+_previews/
diff --git a/Gemfile b/Gemfile
index 67fab5d7..3f1b01d3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -13,3 +13,5 @@ gem "image_optim"
gem "image_optim_pack"
gem "webrick"
gem 'psych', '< 4'
+gem 'wkhtmltoimage-binary', git: 'https://github.com/GlitchSecure/wkhtmltoimage-binary'
+gem 'imgkit', '< 1.6.2'
diff --git a/_config.yml b/_config.yml
index 3867ab2a..9b97a0fa 100644
--- a/_config.yml
+++ b/_config.yml
@@ -31,6 +31,9 @@ collections:
pages:
output: true
permalink: "/:title"
+ previews:
+ output: true
+ permalink: /previews/:slug/
pagination:
diff --git a/_layouts/autopage_collection.html b/_layouts/autopage_collection.html
new file mode 100644
index 00000000..e69de29b
diff --git a/_layouts/preview.html b/_layouts/preview.html
new file mode 100644
index 00000000..9f499e25
--- /dev/null
+++ b/_layouts/preview.html
@@ -0,0 +1,48 @@
+
+
+
+Page Title
+
+
+
+
+
+
+
+{{ page.title | escape }}
+
+
+
+

+
+ {{ page.coauthor }}
+
+
+
+
+

+
+ {{ page.author }}
+
+ {{ page.date | date: "%b %-d, %Y" }}
+ ยท {% assign words = content | number_of_words %} {% if words < 360 %} 1 MINUTE READ {% else %} {{ words | divided_by:180 }} MINUTE READ {% endif %}
+
+
+
+
+
+
+
diff --git a/_layouts/preview1.html b/_layouts/preview1.html
new file mode 100644
index 00000000..9d5e3353
--- /dev/null
+++ b/_layouts/preview1.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
{{ post.category }}
+
+ {{ post.title | escape }}
+
+
+
+
+ {% if post.subtitle %}{{ post.subtitle | strip_html | strip_newlines | truncate: 120 }} {% else %} {{ post.content | strip_html | strip_newlines | truncate: 120 }} {% endif %}
+
+
+
+
+
+
+
+
diff --git a/_plugins/jekyll_image_optim.rb b/_plugins/jekyll_image_optim.rb
deleted file mode 100644
index 2f159b50..00000000
--- a/_plugins/jekyll_image_optim.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright 2018 Shane F. Carr
-#
-# 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.
-# https://gist.github.com/sffc/a828267913591159ab1cc3e1bfde20d7
-
-require "digest"
-require "fileutils"
-require "image_optim"
-require "yaml"
-
-Jekyll::Hooks.register :site, :pre_render do |site|
- # Load configuration options
- config = YAML::load_file(File.join(site.source, "_config.yml"))
- config = config["jekyll_image_optim"] || {}
- image_optim_options = config["image_optim"] || {}
- cache_relative_dir = config["cache_dir"] || ".jekyll-image-optim-cache"
- cache_dir = File.join(site.source, cache_relative_dir)
- out_dir = File.join(cache_dir, "out")
- index_yaml_path = File.join(cache_dir, "index.yml")
- FileUtils.mkdir_p(cache_dir)
- FileUtils.mkdir_p(out_dir)
- FileUtils.touch(index_yaml_path)
- cache_index = YAML::load_file(index_yaml_path) || {}
-
- # Exclude the cache directory from the jekyll watch
- site.exclude << cache_relative_dir
-
- # Process the images
- image_optim = ImageOptim.new(image_optim_options)
- site.static_files.map! do |static_file|
- if not image_optim.optimizable?(static_file.path)
- # Not an image file; no change necessary
- next static_file
- end
-
- relative_path = static_file.relative_path
- new_path = File.join(out_dir, relative_path)
- cc = cache_index[relative_path]
- image_md5 = Digest::MD5.file(static_file.path).hexdigest
-
- if not cc or not File.exists?(new_path) or cc[:md5] != image_md5 or cc[:options] != image_optim_options
- # Need to compute the optimized image
- puts "Optimizing image: #{relative_path}"
- FileUtils.mkdir_p(File.dirname(new_path))
- FileUtils.cp(static_file.path, new_path)
- image_optim.optimize_image!(new_path)
- cache_index[relative_path] = { md5: image_md5, options: image_optim_options }
-
- # Save the cache index file (do this for every image to allow restart after an interrupt)
- File.open(index_yaml_path, "w") { |f| f.write(cache_index.to_yaml) }
- end
-
- # Replace the Jekyll::StaticFile to point to the new location
- next Jekyll::StaticFile.new(site, out_dir, File.dirname(relative_path), File.basename(relative_path))
- end
-end
diff --git a/_plugins/opengraph.rb b/_plugins/opengraph.rb
new file mode 100644
index 00000000..4fc10080
--- /dev/null
+++ b/_plugins/opengraph.rb
@@ -0,0 +1,56 @@
+require 'fileutils'
+require 'imgkit'
+
+module Previews
+ def self.process(site, payload)
+ begin
+ # On first run it's necessary to create the previews
+ # directory in the generated site
+ FileUtils.mkdir('./_opengraph')
+
+ rescue
+ end
+
+ # Loop through all the previews
+ site.collections['previews'].docs.each do |p|
+ slug = p.data['slug']
+
+ # If the image already exists skip,
+ # in order to speed up generation
+ # To regenerate the preview, delete the file
+ if !File.exists?('./_opengraph/' + slug + '.png')
+
+ # Read the generated html for the preview
+ # And set imgkit up for generating a
+ # 600x315 image at 75 quality
+ kit = IMGKit.new(
+ File.read('./_site/previews/' + slug + '/index.html'),
+ quality: 75,
+ width: 600,
+ height: 315
+ )
+
+ # Attach the local stylesheet for wkhtmltoimage to pick up
+ kit.stylesheets << './_site/assets/css/style.css'
+
+ # Then save the image to the previews directory
+ kit.to_file('./_opengraph/' + slug + '.png')
+
+ # This step requires pngquant
+ # It removes color depth from images and reduces their
+ # size to about a third
+ # And copy it to the generated site
+
+ end
+ end
+ end
+end
+
+# Add a hook that's run after html is written
+Jekyll::Hooks.register :site, :post_write do |site, payload|
+
+ # Check if the site is being built or served locally
+ if !site.config['serving']
+ Previews.process(site, payload)
+ end
+end
diff --git a/_plugins/previews.rb b/_plugins/previews.rb
new file mode 100644
index 00000000..cd8e0cec
--- /dev/null
+++ b/_plugins/previews.rb
@@ -0,0 +1,47 @@
+require 'fileutils'
+
+module Filter
+ def self.process(site, payload)
+ site.collections['posts'].docs.select{|x| x.data['auto_image']}.each do |post|
+
+ # Set the path where the copied content will live
+ path = './_previews/' + post.data['slug'] + '.md'
+
+ # Copy the content of the post to the preview collection
+ File.write(path, File.read(post.path))
+
+ # Create a new document in the preview collection
+ preview_doc = Jekyll::Document.new(
+ path,
+ {site: site, collection: site.collections['previews']}
+ )
+
+ preview_doc.read
+
+ # Set the layout to preview
+ preview_doc.data['layout'] = 'preview'
+
+ # Add document to the collection
+ site.collections['previews'].docs << preview_doc
+
+ end
+ end
+end
+
+Jekyll::Hooks.register :site, :post_read do |site, payload|
+ # If the site is being served locally
+ # skip generating previews
+ # Otherwise there'll be an endless loop of previews being
+ # written and regenerated
+ if !site.config['serving']
+ Filter.process(site, payload)
+ end
+end
+
+# At the bottom of previews.rb
+
+module RemovePreviews
+ def self.process(site, payload)
+ FileUtils.rm_rf("./_previews/.", secure: true)
+ end
+end
diff --git a/_posts/2022-07-01-introducing-glitchsecure.md b/_posts/2022-07-01-introducing-glitchsecure.md
index 1c13a529..870ea113 100644
--- a/_posts/2022-07-01-introducing-glitchsecure.md
+++ b/_posts/2022-07-01-introducing-glitchsecure.md
@@ -7,7 +7,7 @@ date-updated: 2023-09-29 # Add this if a change is made after the date above
author: Jade Null # Use "GlitchSecure" if no author
coauthor:
category: Updates
-
+auto_image: true
image:
feature: blog/1/feature.jpg # Upload a 1200x630px image
hero: blog/1/header.jpg # Upload a 1920x1008 image