squidpress-plugins 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6da27e5d6a2b22cb1ac20996e56585a82676b47235e862493aa714cb755dc61c
4
+ data.tar.gz: 97bbcbc9c7b56b05e43fca7fcee3379e94c0c55fd2e2cd5ac8a851e7f2ae467d
5
+ SHA512:
6
+ metadata.gz: affdcaa40eac64be3d479c3973aaa7b7ea31a3860463675ee052907260d7944486f12255ea688228266a0b74deba1584a56476937de5d7d1c7ed1ef9c6bdc319
7
+ data.tar.gz: 9c389bc633d7de92f91baf2436c1efc9af4c824a2f1c299eaa003e1c02078d18d9fba89adeef7039134ea5d4593538804b440b1f1243f769a791f849c71f3e3a
@@ -0,0 +1,82 @@
1
+ #
2
+ # Author: Brandon Mathis
3
+ # A full rewrite based on the work of: Josediaz Gonzalez - https://github.com/josegonzalez/josediazgonzalez.com/blob/master/_plugins/blockquote.rb
4
+ #
5
+ # Outputs a string with a given attribution as a quote
6
+ #
7
+ # {% blockquote Bobby Willis http://google.com/search?q=pants the search for bobby's pants %}
8
+ # Wheeee!
9
+ # {% endblockquote %}
10
+ # ...
11
+ # <blockquote>
12
+ # <p>Wheeee!</p>
13
+ # <footer>
14
+ # <strong>Bobby Willis</strong><cite><a href="http://google.com/search?q=pants">The Search For Bobby's Pants</a>
15
+ # </blockquote>
16
+ #
17
+ require 'squidpress-plugins/titlecase'
18
+
19
+ module Jekyll
20
+
21
+ class Blockquote < Liquid::Block
22
+ FullCiteWithTitle = /(\S.*)\s+(https?:\/\/)(\S+)\s+(.+)/i
23
+ FullCite = /(\S.*)\s+(https?:\/\/)(\S+)/i
24
+ AuthorTitle = /([^,]+),([^,]+)/
25
+ Author = /(.+)/
26
+
27
+ def initialize(tag_name, markup, tokens)
28
+ @by = nil
29
+ @source = nil
30
+ @title = nil
31
+ if markup =~ FullCiteWithTitle
32
+ @by = $1
33
+ @source = $2 + $3
34
+ @title = $4.titlecase.strip
35
+ elsif markup =~ FullCite
36
+ @by = $1
37
+ @source = $2 + $3
38
+ elsif markup =~ AuthorTitle
39
+ @by = $1
40
+ @title = $2.titlecase.strip
41
+ elsif markup =~ Author
42
+ @by = $1
43
+ end
44
+ super
45
+ end
46
+
47
+ def render(context)
48
+ quote = paragraphize(super)
49
+ author = "<strong>#{@by.strip}</strong>" if @by
50
+ if @source
51
+ url = @source.match(/https?:\/\/(.+)/)[1].split('/')
52
+ parts = []
53
+ url.each do |part|
54
+ if (parts + [part]).join('/').length < 32
55
+ parts << part
56
+ end
57
+ end
58
+ source = parts.join('/')
59
+ source << '/&hellip;' unless source == @source
60
+ end
61
+ if !@source.nil?
62
+ cite = " <cite><a href='#{@source}'>#{(@title || source)}</a></cite>"
63
+ elsif !@title.nil?
64
+ cite = " <cite>#{@title}</cite>"
65
+ end
66
+ blockquote = if @by.nil?
67
+ quote
68
+ elsif cite
69
+ "#{quote}<footer>#{author + cite}</footer>"
70
+ else
71
+ "#{quote}<footer>#{author}</footer>"
72
+ end
73
+ "<blockquote>#{blockquote}</blockquote>"
74
+ end
75
+
76
+ def paragraphize(input)
77
+ "<p>#{input.lstrip.rstrip.gsub(/\n\n/, '</p><p>').gsub(/\n/, '<br/>')}</p>"
78
+ end
79
+ end
80
+ end
81
+
82
+ Liquid::Template.register_tag('blockquote', Jekyll::Blockquote)
@@ -0,0 +1,186 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Jekyll category page generator.
4
+ # http://recursive-design.com/projects/jekyll-plugins/
5
+ #
6
+ # Version: 0.1.4 (201101061053)
7
+ #
8
+ # Copyright (c) 2010 Dave Perrett, http://recursive-design.com/
9
+ # Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
10
+ #
11
+ # A generator that creates category pages for jekyll sites.
12
+ #
13
+ # Included filters :
14
+ # - category_links: Outputs the list of categories as comma-separated <a> links.
15
+ # - date_to_html_string: Outputs the post.date as formatted html, with hooks for CSS styling.
16
+ #
17
+ # Available _config.yml settings :
18
+ # - category_dir: The subfolder to build category pages in (default is 'categories').
19
+ # - category_title_prefix: The string used before the category name in the page title (default is
20
+ # 'Category: ').
21
+
22
+ require 'stringex'
23
+
24
+ I18n.config.available_locales = :en
25
+
26
+ module Jekyll
27
+
28
+ # The CategoryIndex class creates a single category page for the specified category.
29
+ class CategoryIndex < Page
30
+
31
+ # Initializes a new CategoryIndex.
32
+ #
33
+ # +base+ is the String path to the <source>.
34
+ # +category_dir+ is the String path between <source> and the category folder.
35
+ # +category+ is the category currently being processed.
36
+ def initialize(site, base, category_dir, category)
37
+ @site = site
38
+ @base = base
39
+ @dir = category_dir
40
+ @name = 'index.html'
41
+ self.process(@name)
42
+ # Read the YAML data from the layout page.
43
+ self.read_yaml(File.join(base, '_layouts'), 'category_index.html')
44
+ self.data['category'] = category
45
+ # Set the title for this page.
46
+ title_prefix = site.config['category_title_prefix'] || 'Category: '
47
+ self.data['title'] = "#{title_prefix}#{category}"
48
+ # Set the meta-description for this page.
49
+ meta_description_prefix = site.config['category_meta_description_prefix'] || 'Category: '
50
+ self.data['description'] = "#{meta_description_prefix}#{category}"
51
+ end
52
+
53
+ end
54
+
55
+ # The CategoryFeed class creates an Atom feed for the specified category.
56
+ class CategoryFeed < Page
57
+
58
+ # Initializes a new CategoryFeed.
59
+ #
60
+ # +base+ is the String path to the <source>.
61
+ # +category_dir+ is the String path between <source> and the category folder.
62
+ # +category+ is the category currently being processed.
63
+ def initialize(site, base, category_dir, category)
64
+ @site = site
65
+ @base = base
66
+ @dir = category_dir
67
+ @name = 'atom.xml'
68
+ self.process(@name)
69
+ # Read the YAML data from the layout page.
70
+ self.read_yaml(File.join(base, '_includes/custom'), 'category_feed.xml')
71
+ self.data['category'] = category
72
+ # Set the title for this page.
73
+ title_prefix = site.config['category_title_prefix'] || 'Category: '
74
+ self.data['title'] = "#{title_prefix}#{category}"
75
+ # Set the meta-description for this page.
76
+ meta_description_prefix = site.config['category_meta_description_prefix'] || 'Category: '
77
+ self.data['description'] = "#{meta_description_prefix}#{category}"
78
+
79
+ # Set the correct feed URL.
80
+ self.data['feed_url'] = "#{category_dir}/#{name}"
81
+ end
82
+
83
+ end
84
+
85
+ # The Site class is a built-in Jekyll class with access to global site config information.
86
+ class Site
87
+
88
+ # Creates an instance of CategoryIndex for each category page, renders it, and
89
+ # writes the output to a file.
90
+ #
91
+ # +category_dir+ is the String path to the category folder.
92
+ # +category+ is the category currently being processed.
93
+ def write_category_index(category_dir, category)
94
+ index = CategoryIndex.new(self, self.source, category_dir, category)
95
+ index.render(self.layouts, site_payload)
96
+ index.write(self.dest)
97
+ # Record the fact that this page has been added, otherwise Site::cleanup will remove it.
98
+ self.pages << index
99
+
100
+ # Create an Atom-feed for each index.
101
+ feed = CategoryFeed.new(self, self.source, category_dir, category)
102
+ feed.render(self.layouts, site_payload)
103
+ feed.write(self.dest)
104
+ # Record the fact that this page has been added, otherwise Site::cleanup will remove it.
105
+ self.pages << feed
106
+ end
107
+
108
+ # Loops through the list of category pages and processes each one.
109
+ def write_category_indexes
110
+ if self.layouts.key? 'category_index'
111
+ dir = self.config['category_dir'] || 'categories'
112
+ self.categories.keys.each do |category|
113
+ self.write_category_index(File.join(dir, category.to_url), category)
114
+ end
115
+
116
+ # Throw an exception if the layout couldn't be found.
117
+ else
118
+ raise <<-ERR
119
+
120
+
121
+ ===============================================
122
+ Error for category_generator.rb plugin
123
+ -----------------------------------------------
124
+ No 'category_index.html' in source/_layouts/
125
+ Perhaps you haven't installed a theme yet.
126
+ ===============================================
127
+
128
+ ERR
129
+ end
130
+ end
131
+
132
+ end
133
+
134
+
135
+ # Jekyll hook - the generate method is called by jekyll, and generates all of the category pages.
136
+ class GenerateCategories < Generator
137
+ safe true
138
+ priority :low
139
+
140
+ def generate(site)
141
+ site.write_category_indexes
142
+ end
143
+
144
+ end
145
+
146
+
147
+ # Adds some extra filters used during the category creation process.
148
+ module Filters
149
+
150
+ # Outputs a list of categories as comma-separated <a> links. This is used
151
+ # to output the category list for each post on a category page.
152
+ #
153
+ # +categories+ is the list of categories to format.
154
+ #
155
+ # Returns string
156
+ #
157
+ def category_links(categories)
158
+ categories.sort.map { |c| category_link c }.join(', ')
159
+ end
160
+
161
+ # Outputs a single category as an <a> link.
162
+ #
163
+ # +category+ is a category string to format as an <a> link
164
+ #
165
+ # Returns string
166
+ #
167
+ def category_link(category)
168
+ dir = @context.registers[:site].config['category_dir']
169
+ "<a class='category' href='/#{dir}/#{category.to_url}/'>#{category}</a>"
170
+ end
171
+
172
+ # Outputs the post.date as formatted html, with hooks for CSS styling.
173
+ #
174
+ # +date+ is the date object to format as HTML.
175
+ #
176
+ # Returns string
177
+ def date_to_html_string(date)
178
+ result = '<span class="month">' + date.strftime('%b').upcase + '</span> '
179
+ result << date.strftime('<span class="day">%d</span> ')
180
+ result << date.strftime('<span class="year">%Y</span> ')
181
+ result
182
+ end
183
+
184
+ end
185
+
186
+ end
@@ -0,0 +1,44 @@
1
+ require 'json'
2
+
3
+ class ConfigTag < Liquid::Tag
4
+ def initialize(tag_name, options, tokens)
5
+ super
6
+ options = options.split(' ').map {|i| i.strip }
7
+ @key = options.slice!(0)
8
+ @tag = nil
9
+ @classname = nil
10
+ options.each do |option|
11
+ @tag = $1 if option =~ /tag:(\S+)/
12
+ @classname = $1 if option =~ /classname:(\S+)/
13
+ end
14
+ end
15
+
16
+ def render(context)
17
+ config_tag(context.registers[:site].config, @key, @tag, @classname)
18
+ end
19
+ end
20
+
21
+ def config_tag(config, key, tag=nil, classname=nil)
22
+ options = key.split('.').map { |k| config[k] }.last #reference objects with dot notation
23
+ tag ||= 'div'
24
+ classname ||= key.sub(/_/, '-').sub(/\./, '-')
25
+ output = "<#{tag} class='#{classname}'"
26
+
27
+ if options.respond_to? 'keys'
28
+ options.each do |k,v|
29
+ unless v.nil?
30
+ v = v.join ',' if v.respond_to? 'join'
31
+ v = v.to_json if v.respond_to? 'keys'
32
+ output += " data-#{k.sub'_','-'}='#{v}'"
33
+ end
34
+ end
35
+ elsif options.respond_to? 'join'
36
+ output += " data-value='#{config[key].join(',')}'"
37
+ else
38
+ output += " data-value='#{config[key]}'"
39
+ end
40
+ output += "></#{tag}>"
41
+ end
42
+
43
+ Liquid::Template.register_tag('config_tag', ConfigTag)
44
+
@@ -0,0 +1,130 @@
1
+ # A Liquid tag for Jekyll sites that allows embedding Gists and showing code for non-JavaScript enabled browsers and readers.
2
+ # by: Brandon Tilly
3
+ # Source URL: https://gist.github.com/1027674
4
+ # Post http://brandontilley.com/2011/01/31/gist-tag-for-jekyll.html
5
+ #
6
+ # Example usage: {% gist 1027674 gist_tag.rb %} //embeds a gist for this plugin
7
+
8
+ require 'cgi'
9
+ require 'digest/md5'
10
+ require 'net/https'
11
+ require 'uri'
12
+
13
+ module Jekyll
14
+ class GistTag < Liquid::Tag
15
+ def initialize(tag_name, text, token)
16
+ super
17
+ @text = text
18
+ @cache_disabled = false
19
+ @cache_folder = File.expand_path "../.gist-cache", File.dirname(__FILE__)
20
+ FileUtils.mkdir_p @cache_folder
21
+ end
22
+
23
+ def render(context)
24
+ if parts = @text.match(/([a-zA-Z\d]*) (.*)/)
25
+ gist, file = parts[1].strip, parts[2].strip
26
+ else
27
+ gist, file = @text.strip, ""
28
+ end
29
+ if gist.empty?
30
+ ""
31
+ else
32
+ script_url = script_url_for gist, file
33
+ code = get_cached_gist(gist, file) || get_gist_from_web(gist, file)
34
+ html_output_for script_url, code
35
+ end
36
+ end
37
+
38
+ def html_output_for(script_url, code)
39
+ code = CGI.escapeHTML code
40
+ <<-HTML
41
+ <div><script src='#{script_url}'></script>
42
+ <noscript><pre><code>#{code}</code></pre></noscript></div>
43
+ HTML
44
+ end
45
+
46
+ def script_url_for(gist_id, filename)
47
+ url = "https://gist.github.com/#{gist_id}.js"
48
+ url = "#{url}?file=#{filename}" unless filename.nil? or filename.empty?
49
+ url
50
+ end
51
+
52
+ def get_gist_url_for(gist, file)
53
+ "https://gist.githubusercontent.com/raw/#{gist}/#{file}"
54
+ end
55
+
56
+ def cache(gist, file, data)
57
+ cache_file = get_cache_file_for gist, file
58
+ File.open(cache_file, "w") do |io|
59
+ io.write data
60
+ end
61
+ end
62
+
63
+ def get_cached_gist(gist, file)
64
+ return nil if @cache_disabled
65
+ cache_file = get_cache_file_for gist, file
66
+ File.read cache_file if File.exist? cache_file
67
+ end
68
+
69
+ def get_cache_file_for(gist, file)
70
+ bad_chars = /[^a-zA-Z0-9\-_.]/
71
+ gist = gist.gsub bad_chars, ''
72
+ file = file.gsub bad_chars, ''
73
+ md5 = Digest::MD5.hexdigest "#{gist}-#{file}"
74
+ File.join @cache_folder, "#{gist}-#{file}-#{md5}.cache"
75
+ end
76
+
77
+ def get_gist_from_web(gist, file)
78
+ gist_url = get_gist_url_for(gist, file)
79
+ data = get_web_content(gist_url)
80
+
81
+ locations = Array.new
82
+ while (data.code.to_i == 301 || data.code.to_i == 302)
83
+ data = handle_gist_redirecting(data)
84
+ break if locations.include? data.header['Location']
85
+ locations << data.header['Location']
86
+ end
87
+
88
+ if data.code.to_i != 200
89
+ raise RuntimeError, "Gist replied with #{data.code} for #{gist_url}"
90
+ end
91
+
92
+ cache(gist, file, data.body) unless @cache_disabled
93
+ data.body
94
+ end
95
+
96
+ def handle_gist_redirecting(data)
97
+ redirected_url = data.header['Location']
98
+ if redirected_url.nil? || redirected_url.empty?
99
+ raise ArgumentError, "GitHub replied with a 302 but didn't provide a location in the response headers."
100
+ end
101
+
102
+ get_web_content(redirected_url)
103
+ end
104
+
105
+ def get_web_content(url)
106
+ raw_uri = URI.parse url
107
+ proxy = ENV['http_proxy']
108
+ if proxy
109
+ proxy_uri = URI.parse(proxy)
110
+ https = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new raw_uri.host, raw_uri.port
111
+ else
112
+ https = Net::HTTP.new raw_uri.host, raw_uri.port
113
+ end
114
+ https.use_ssl = true
115
+ https.verify_mode = OpenSSL::SSL::VERIFY_NONE
116
+ request = Net::HTTP::Get.new raw_uri.request_uri
117
+ data = https.request request
118
+ end
119
+ end
120
+
121
+ class GistTagNoCache < GistTag
122
+ def initialize(tag_name, text, token)
123
+ super
124
+ @cache_disabled = true
125
+ end
126
+ end
127
+ end
128
+
129
+ Liquid::Template.register_tag('gist', Jekyll::GistTag)
130
+ Liquid::Template.register_tag('gistnocache', Jekyll::GistTagNoCache)
@@ -0,0 +1,24 @@
1
+ module Jekyll
2
+ require 'haml'
3
+ class HamlConverter < Converter
4
+ safe true
5
+ priority :low
6
+
7
+ def matches(ext)
8
+ ext =~ /haml/i
9
+ end
10
+
11
+ def output_ext(ext)
12
+ ".html"
13
+ end
14
+
15
+ def convert(content)
16
+ begin
17
+ engine = Haml::Engine.new(content)
18
+ engine.render
19
+ rescue StandardError => e
20
+ puts "!!! HAML Error: " + e.message
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,50 @@
1
+ # Title: Simple Image tag for Jekyll
2
+ # Authors: Brandon Mathis http://brandonmathis.com
3
+ # Felix Schäfer, Frederic Hemberger
4
+ # Description: Easily output images with optional class names, width, height, title and alt attributes
5
+ #
6
+ # Syntax {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | "title text" ["alt text"]] %}
7
+ #
8
+ # Examples:
9
+ # {% img /images/ninja.png Ninja Attack! %}
10
+ # {% img left half http://site.com/images/ninja.png Ninja Attack! %}
11
+ # {% img left half http://site.com/images/ninja.png 150 150 "Ninja Attack!" "Ninja in attack posture" %}
12
+ #
13
+ # Output:
14
+ # <img src="/images/ninja.png">
15
+ # <img class="left half" src="http://site.com/images/ninja.png" title="Ninja Attack!" alt="Ninja Attack!">
16
+ # <img class="left half" src="http://site.com/images/ninja.png" width="150" height="150" title="Ninja Attack!" alt="Ninja in attack posture">
17
+ #
18
+
19
+ module Jekyll
20
+
21
+ class ImageTag < Liquid::Tag
22
+ @img = nil
23
+
24
+ def initialize(tag_name, markup, tokens)
25
+ attributes = ['class', 'src', 'width', 'height', 'title']
26
+
27
+ if markup =~ /(?<class>\S.*\s+)?(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?<width>\d+))?(?:\s+(?<height>\d+))?(?<title>\s+.+)?/i
28
+ @img = attributes.reduce({}) { |img, attr| img[attr] = $~[attr].strip if $~[attr]; img }
29
+ if /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/ =~ @img['title']
30
+ @img['title'] = title
31
+ @img['alt'] = alt
32
+ else
33
+ @img['alt'] = @img['title'].gsub!(/"/, '&#34;') if @img['title']
34
+ end
35
+ @img['class'].gsub!(/"/, '') if @img['class']
36
+ end
37
+ super
38
+ end
39
+
40
+ def render(context)
41
+ if @img
42
+ "<img #{@img.collect {|k,v| "#{k}=\"#{v}\"" if v}.join(" ")}>"
43
+ else
44
+ "Error processing input, expected syntax: {% img [class name(s)] [http[s]:/]/path/to/image [width [height]] [title text | \"title text\" [\"alt text\"]] %}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Liquid::Template.register_tag('img', Jekyll::ImageTag)
@@ -0,0 +1,58 @@
1
+ # Title: Include Array Tag for Jekyll
2
+ # Author: Jason Woodward http://www.woodwardjd.com
3
+ # Description: Import files on your filesystem as specified in a configuration variable in _config.yml. Mostly cribbed from Jekyll's include tag.
4
+ # Syntax: {% include_array variable_name_from_config.yml %}
5
+ #
6
+ # Example 1:
7
+ # {% include_array asides %}
8
+ #
9
+ # _config.yml snippet:
10
+ # asides: [asides/twitter.html, asides/custom/my_picture.html]
11
+ #
12
+ module Jekyll
13
+
14
+ class IncludeArrayTag < Liquid::Tag
15
+ Syntax = /(#{Liquid::QuotedFragment}+)/
16
+ def initialize(tag_name, markup, tokens)
17
+ if markup =~ Syntax
18
+ @array_name = $1
19
+ else
20
+ raise SyntaxError.new("Error in tag 'include_array' - Valid syntax: include_array [array from _config.yml]")
21
+ end
22
+
23
+ super
24
+ end
25
+
26
+ def render(context)
27
+ includes_dir = File.join(context.registers[:site].source, '_includes')
28
+
29
+ if File.symlink?(includes_dir)
30
+ return "Includes directory '#{includes_dir}' cannot be a symlink"
31
+ end
32
+
33
+ rtn = ''
34
+ (context.environments.first['site'][@array_name] || []).each do |file|
35
+ if file !~ /^[a-zA-Z0-9_\/\.-]+$/ || file =~ /\.\// || file =~ /\/\./
36
+ rtn = rtn + "Include file '#{file}' contains invalid characters or sequences"
37
+ end
38
+
39
+ Dir.chdir(includes_dir) do
40
+ choices = Dir['**/*'].reject { |x| File.symlink?(x) }
41
+ if choices.include?(file)
42
+ source = File.read(file)
43
+ partial = Liquid::Template.parse(source)
44
+ context.stack do
45
+ rtn = rtn + partial.render(context)
46
+ end
47
+ else
48
+ rtn = rtn + "Included file '#{file}' not found in _includes directory"
49
+ end
50
+ end
51
+ end
52
+ rtn
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ Liquid::Template.register_tag('include_array', Jekyll::IncludeArrayTag)
@@ -0,0 +1,40 @@
1
+ # Title: jsFiddle tag for Jekyll
2
+ # Author: Brian Arnold (@brianarn)
3
+ # Description:
4
+ # Given a jsFiddle shortcode, outputs the jsFiddle iframe code.
5
+ # Using 'default' will preserve defaults as specified by jsFiddle.
6
+ #
7
+ # Syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %}
8
+ #
9
+ # Examples:
10
+ #
11
+ # Input: {% jsfiddle ccWP7 %}
12
+ # Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,resources,html,css,result/light/"></iframe>
13
+ #
14
+ # Input: {% jsfiddle ccWP7 js,html,result %}
15
+ # Output: <iframe style="width: 100%; height: 300px" src="http://jsfiddle.net/ccWP7/embedded/js,html,result/light/"></iframe>
16
+ #
17
+
18
+ module Jekyll
19
+ class JsFiddle < Liquid::Tag
20
+ def initialize(tag_name, markup, tokens)
21
+ if /(?<fiddle>\w+\/?\d?)(?:\s+(?<sequence>[\w,]+))?(?:\s+(?<skin>\w+))?(?:\s+(?<height>\w+))?(?:\s+(?<width>\w+))?/ =~ markup
22
+ @fiddle = fiddle
23
+ @sequence = (sequence unless sequence == 'default') || 'js,resources,html,css,result'
24
+ @skin = (skin unless skin == 'default') || 'light'
25
+ @width = width || '100%'
26
+ @height = height || '300px'
27
+ end
28
+ end
29
+
30
+ def render(context)
31
+ if @fiddle
32
+ "<iframe style=\"width: #{@width}; height: #{@height}\" frameborder=\"0\" seamless=\"seamless\" src=\"http://jsfiddle.net/#{@fiddle}/embedded/#{@sequence}/#{@skin}/\"></iframe>"
33
+ else
34
+ "Error processing input, expected syntax: {% jsfiddle shorttag [tabs] [skin] [height] [width] %}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ Liquid::Template.register_tag('jsfiddle', Jekyll::JsFiddle)
@@ -0,0 +1,45 @@
1
+ #
2
+ # Author: Brandon Mathis
3
+ # Based on the semantic pullquote technique by Maykel Loomans at http://miekd.com/articles/pull-quotes-with-html5-and-css/
4
+ #
5
+ # Outputs a span with a data-pullquote attribute set from the marked pullquote. Example:
6
+ #
7
+ # {% pullquote %}
8
+ # When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
9
+ # It is important to note, {" pullquotes are merely visual in presentation and should not appear twice in the text. "} That is why it is prefered
10
+ # to use a CSS only technique for styling pullquotes.
11
+ # {% endpullquote %}
12
+ # ...will output...
13
+ # <p>
14
+ # <span data-pullquote="pullquotes are merely visual in presentation and should not appear twice in the text.">
15
+ # When writing longform posts, I find it helpful to include pullquotes, which help those scanning a post discern whether or not a post is helpful.
16
+ # It is important to note, pullquotes are merely visual in presentation and should not appear twice in the text. This is why a CSS only approach
17
+ # for styling pullquotes is prefered.
18
+ # </span>
19
+ # </p>
20
+ #
21
+ # {% pullquote left %} will create a left-aligned pullquote instead.
22
+ #
23
+ # Note: this plugin now creates pullquotes with the class of pullquote-right by default
24
+
25
+ module Jekyll
26
+
27
+ class PullquoteTag < Liquid::Block
28
+ def initialize(tag_name, markup, tokens)
29
+ @align = (markup =~ /left/i) ? "left" : "right"
30
+ super
31
+ end
32
+
33
+ def render(context)
34
+ output = super
35
+ if output =~ /\{"\s*(.+?)\s*"\}/m
36
+ @quote = RubyPants.new($1).to_html
37
+ "<span class='pullquote-#{@align}' data-pullquote='#{@quote}'>#{output.gsub(/\{"\s*|\s*"\}/, '')}</span>"
38
+ else
39
+ return "Surround your pullquote like this {\" text to be quoted \"}"
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ Liquid::Template.register_tag('pullquote', Jekyll::PullquoteTag)
@@ -0,0 +1,40 @@
1
+ # Author: Brandon Mathis
2
+ # Description: Provides plugins with a method for wrapping and unwrapping input to prevent Markdown and Textile from parsing it.
3
+ # Purpose: This is useful for preventing Markdown and Textile from being too aggressive and incorrectly parsing in-line HTML.
4
+ module TemplateWrapper
5
+ # Wrap input with a <div>
6
+ def self.safe_wrap(input)
7
+ "<div class='bogus-wrapper'><notextile>#{input}</notextile></div>"
8
+ end
9
+ # This must be applied after the
10
+ def self.unwrap(input)
11
+ input.gsub /<div class=['"]bogus-wrapper['"]><notextile>(.+?)<\/notextile><\/div>/m do
12
+ $1
13
+ end
14
+ end
15
+ end
16
+
17
+ # Author: phaer, https://github.com/phaer
18
+ # Source: https://gist.github.com/1020852
19
+ # Description: Raw tag for jekyll. Keeps liquid from parsing text betweeen {% raw %} and {% endraw %}
20
+
21
+ module Jekyll
22
+ class RawTag < Liquid::Block
23
+ def parse(tokens)
24
+ @nodelist ||= []
25
+ @nodelist.clear
26
+
27
+ while token = tokens.shift
28
+ if token =~ FullToken
29
+ if block_delimiter == $1
30
+ end_tag
31
+ return
32
+ end
33
+ end
34
+ @nodelist << token if not token.empty?
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ Liquid::Template.register_tag('raw', Jekyll::RawTag)
@@ -0,0 +1,36 @@
1
+ class String
2
+ def titlecase
3
+ small_words = %w(a an and as at but by en for if in of on or the to v v. via vs vs.)
4
+
5
+ x = split(" ").map do |word|
6
+ # note: word could contain non-word characters!
7
+ # downcase all small_words, capitalize the rest
8
+ small_words.include?(word.gsub(/\W/, "").downcase) ? word.downcase! : word.smart_capitalize!
9
+ word
10
+ end
11
+ # capitalize first and last words
12
+ x.first.to_s.smart_capitalize!
13
+ x.last.to_s.smart_capitalize!
14
+ # small words are capitalized after colon, period, exclamation mark, question mark
15
+ x.join(" ").gsub(/(:|\.|!|\?)\s?(\W*#{small_words.join("|")}\W*)\s/) { "#{$1} #{$2.smart_capitalize} " }
16
+ end
17
+
18
+ def titlecase!
19
+ replace(titlecase)
20
+ end
21
+
22
+ def smart_capitalize
23
+ # ignore any leading crazy characters and capitalize the first real character
24
+ if self =~ /^['"\(\[']*([a-z])/
25
+ i = index($1)
26
+ x = self[i,self.length]
27
+ # word with capitals and periods mid-word are left alone
28
+ self[i,1] = self[i,1].upcase unless x =~ /[A-Z]/ or x =~ /\.\w+/
29
+ end
30
+ self
31
+ end
32
+
33
+ def smart_capitalize!
34
+ replace(smart_capitalize)
35
+ end
36
+ end
@@ -0,0 +1,62 @@
1
+ # Title: Simple Video tag for Jekyll
2
+ # Author: Brandon Mathis http://brandonmathis.com
3
+ # Description: Easily output MPEG4 HTML5 video with a flash backup.
4
+ #
5
+ # Syntax {% video url/to/video [width height] [url/to/poster] %}
6
+ #
7
+ # Example:
8
+ # {% video http://site.com/video.mp4 720 480 http://site.com/poster-frame.jpg %}
9
+ #
10
+ # Output:
11
+ # <video width='720' height='480' preload='none' controls poster='http://site.com/poster-frame.jpg'>
12
+ # <source src='http://site.com/video.mp4' type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'/>
13
+ # </video>
14
+ #
15
+
16
+ module Jekyll
17
+
18
+ class VideoTag < Liquid::Tag
19
+ @video = nil
20
+ @poster = ''
21
+ @height = ''
22
+ @width = ''
23
+
24
+ def initialize(tag_name, markup, tokens)
25
+ @videos = markup.scan(/((https?:\/\/|\/)\S+\.(webm|ogv|mp4)\S*)/i).map(&:first).compact
26
+ @poster = markup.scan(/((https?:\/\/|\/)\S+\.(png|gif|jpe?g)\S*)/i).map(&:first).compact.first
27
+ @sizes = markup.scan(/\s(\d\S+)/i).map(&:first).compact
28
+ super
29
+ end
30
+
31
+ def render(context)
32
+ output = super
33
+ types = {
34
+ '.mp4' => "type='video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'",
35
+ '.ogv' => "type='video/ogg; codecs=theora, vorbis'",
36
+ '.webm' => "type='video/webm; codecs=vp8, vorbis'"
37
+ }
38
+ if @videos.size > 0
39
+ video = "<video #{sizes} preload='metadata' controls #{poster}>"
40
+ @videos.each do |v|
41
+ video << "<source src='#{v}' #{types[File.extname(v)]}>"
42
+ end
43
+ video += "</video>"
44
+ else
45
+ "Error processing input, expected syntax: {% video url/to/video [url/to/video] [url/to/video] [width height] [url/to/poster] %}"
46
+ end
47
+ end
48
+
49
+ def poster
50
+ "poster='#{@poster}'" if @poster
51
+ end
52
+
53
+ def sizes
54
+ attrs = "width='#{@sizes[0]}'" if @sizes[0]
55
+ attrs += " height='#{@sizes[1]}'" if @sizes[1]
56
+ attrs
57
+ end
58
+ end
59
+ end
60
+
61
+ Liquid::Template.register_tag('video', Jekyll::VideoTag)
62
+
@@ -0,0 +1,15 @@
1
+ require "jekyll"
2
+ require "liquid"
3
+
4
+ require "squidpress-plugins/blockquote"
5
+ require "squidpress-plugins/category_generator"
6
+ require "squidpress-plugins/config_tag"
7
+ require "squidpress-plugins/gist_tag"
8
+ require "squidpress-plugins/haml"
9
+ require "squidpress-plugins/image_tag"
10
+ require "squidpress-plugins/include_array"
11
+ require "squidpress-plugins/jsfiddle"
12
+ require "squidpress-plugins/pullquote"
13
+ require "squidpress-plugins/raw"
14
+ require "squidpress-plugins/titlecase"
15
+ require "squidpress-plugins/video_tag"
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squidpress-plugins
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Misty De Méo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-09-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: jekyll
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.7'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3.7'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ - !ruby/object:Gem::Dependency
34
+ name: haml
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '7.5'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '7.5'
47
+ - !ruby/object:Gem::Dependency
48
+ name: ostruct
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.6'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '0.6'
61
+ - !ruby/object:Gem::Dependency
62
+ name: stringex
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.8'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.8'
75
+ description:
76
+ email:
77
+ - squidpress@mistydemeo.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - lib/squidpress-plugins.rb
83
+ - lib/squidpress-plugins/blockquote.rb
84
+ - lib/squidpress-plugins/category_generator.rb
85
+ - lib/squidpress-plugins/config_tag.rb
86
+ - lib/squidpress-plugins/gist_tag.rb
87
+ - lib/squidpress-plugins/haml.rb
88
+ - lib/squidpress-plugins/image_tag.rb
89
+ - lib/squidpress-plugins/include_array.rb
90
+ - lib/squidpress-plugins/jsfiddle.rb
91
+ - lib/squidpress-plugins/pullquote.rb
92
+ - lib/squidpress-plugins/raw.rb
93
+ - lib/squidpress-plugins/titlecase.rb
94
+ - lib/squidpress-plugins/video_tag.rb
95
+ homepage: https://codeberg.org/mistydemeo/squidpress-plugins
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubygems_version: 3.0.3.1
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Port of Octopress's theme to modern Jekyll.
118
+ test_files: []