octopress-printable 0.0.1
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 +7 -0
- data/CHANGELOG.md +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/assets/config.yml +17 -0
- data/assets/images/printer.png +0 -0
- data/assets/includes/printable.html +13 -0
- data/assets/stylesheets/printable.scss +8 -0
- data/lib/octopress-printable.rb +26 -0
- data/lib/octopress-printable/bib.rb +69 -0
- data/lib/octopress-printable/converter.rb +37 -0
- data/lib/octopress-printable/filters.rb +16 -0
- data/lib/octopress-printable/gist.rb +42 -0
- data/lib/octopress-printable/gist_cache.rb +124 -0
- data/lib/octopress-printable/img.rb +60 -0
- data/lib/octopress-printable/latex.rb +21 -0
- data/lib/octopress-printable/math.rb +24 -0
- data/lib/octopress-printable/plugin.rb +246 -0
- data/lib/octopress-printable/post_link.rb +38 -0
- data/lib/octopress-printable/tags.rb +82 -0
- data/lib/octopress-printable/version.rb +5 -0
- metadata +162 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 08895c17e55c60513b22e894ad0d273f20275276
|
4
|
+
data.tar.gz: c92e6d6cfafd0b8f00e2496935f9f4bf5b0a5f6a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a0dd29e2f8ec949cc655bfef4b52321cbedef3545d746aad4ad179f0fd9b609ba9079aec1489e21523931940d7b1fa4855c7bd47b71f227c4993ea901aa5498a
|
7
|
+
data.tar.gz: 8ae4905565a407993dbf2c81c008838b2243756544aca556d510690939f4f96cfe1d6ad4d27aaba43fc41b99ecedc4a2719b7f0a62990e2114bc90eb2371de46
|
data/CHANGELOG.md
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Wang Jian
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# octopress-printable
|
2
|
+
|
3
|
+
An octopress ink plugin generating printable version of markdown posts.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/wantee/octopress-printable)
|
6
|
+
[](http://badge.fury.io/rb/octopress-printable)
|
7
|
+
[](https://github.com/wantee/octopress-printable/blob/master/LICENSE.txt)
|
8
|
+
|
9
|
+
## Prerequisites
|
10
|
+
* [Pandoc](pandoc.org/), >= 1.13.2
|
11
|
+
* TeX Live 2013
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
Add this line to your application's Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'octopress-printable'
|
19
|
+
```
|
20
|
+
|
21
|
+
And then execute:
|
22
|
+
|
23
|
+
$ bundle
|
24
|
+
|
25
|
+
Or install it yourself as:
|
26
|
+
|
27
|
+
$ gem install octopress-printable
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Add `{% include octopress-printable:printable.html %}` to your site's layout, this will create a link to the pdf files corresponding current post or page.
|
32
|
+
|
33
|
+
Tags will be converted includes `img` (from [octopress-image-tag](https://github.com/octopress/image-tag)), `gist` (from [octopress-gist](https://github.com/octopress/gist)), `bibliography` and `cite` (from [jekyll-scholar](https://github.com/inukshuk/jekyll-scholar)).
|
34
|
+
|
35
|
+
Details please refer to `test/test-site/_posts/2015-04-29-foo.markdown`.
|
36
|
+
|
37
|
+
## Configuration
|
38
|
+
|
39
|
+
To configure this plugin, run `$ octopress ink copy octopress-printable --config`, then the config should be in `_plugins/octopress-printable/config.yml` and add your settings. Here are
|
40
|
+
the defaults.
|
41
|
+
|
42
|
+
```yaml config
|
43
|
+
posts_dir: "_posts"
|
44
|
+
printables_dir: "assets/printables"
|
45
|
+
source_dir: "."
|
46
|
+
blog_url: "http://example.com" # used in pdf post_links
|
47
|
+
bibliography_dir: "_bibliography"
|
48
|
+
bibliography: "references.bib"
|
49
|
+
|
50
|
+
# only convert markdowns, without running pandoc and xelatex
|
51
|
+
dry_run : false
|
52
|
+
|
53
|
+
# debug files
|
54
|
+
dump_tex_file: false
|
55
|
+
dump_markdown_file: false
|
56
|
+
dump_bib_file: false
|
57
|
+
dump_cmds: false
|
58
|
+
keep_tmp_files: false
|
59
|
+
|
60
|
+
```
|
61
|
+
|
62
|
+
## Contributing
|
63
|
+
|
64
|
+
1. Fork it ( https://github.com/wantee/octopress-printable/fork )
|
65
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
66
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
67
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
68
|
+
5. Create a new Pull Request
|
data/assets/config.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
posts_dir: "_posts"
|
2
|
+
printables_dir: "assets/printables"
|
3
|
+
source_dir: "."
|
4
|
+
blog_url: "http://example.com" # used in pdf post_links
|
5
|
+
bibliography_dir: "_bibliography"
|
6
|
+
bibliography: "references.bib"
|
7
|
+
|
8
|
+
# only convert markdowns, without running pandoc and xelatex
|
9
|
+
dry_run : false
|
10
|
+
|
11
|
+
# debug files
|
12
|
+
dump_tex_file: false
|
13
|
+
dump_markdown_file: false
|
14
|
+
dump_bib_file: false
|
15
|
+
dump_cmds: false
|
16
|
+
keep_tmp_files: false
|
17
|
+
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<span class="printable">
|
2
|
+
|
3
|
+
{% if post %}
|
4
|
+
{% capture url %}assets/printables/{{ post.url | url2filename }}.pdf{% endcapture %}
|
5
|
+
{% else %}
|
6
|
+
{% capture url %}assets/printables/{{ page.id | url2filename }}.pdf{% endcapture %}
|
7
|
+
{% endif %}
|
8
|
+
|
9
|
+
{% if url %}
|
10
|
+
<a href="{{ root_url }}/{{ url }}"> <img src="/images/octopress-printable/printer.png" alt="printable version"> </a>
|
11
|
+
{% endif %}
|
12
|
+
|
13
|
+
</span>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'octopress-printable/version'
|
2
|
+
require 'octopress-ink'
|
3
|
+
|
4
|
+
module Octopress
|
5
|
+
module Printable
|
6
|
+
autoload :Filters, 'octopress-printable/filters'
|
7
|
+
autoload :Tags, 'octopress-printable/tags'
|
8
|
+
autoload :Plugin, 'octopress-printable/plugin'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
Liquid::Template.register_filter(Octopress::Printable::Filters)
|
13
|
+
|
14
|
+
Liquid::Template.register_tag('post_link', Octopress::Printable::Tags)
|
15
|
+
|
16
|
+
Octopress::Ink.register_plugin(Octopress::Printable::Plugin, {
|
17
|
+
name: "Octopress Printable",
|
18
|
+
slug: "octopress-printable",
|
19
|
+
gem: "octopress-printable",
|
20
|
+
path: File.expand_path(File.join(File.dirname(__FILE__), "..")),
|
21
|
+
type: "plugin",
|
22
|
+
version: Octopress::Printable::VERSION,
|
23
|
+
description: "Printable version for post generator.",
|
24
|
+
source_url: "https://github.com/wantee/octopress-printable",
|
25
|
+
website: ""
|
26
|
+
})
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class BibConverter < Converter
|
4
|
+
|
5
|
+
def initialize(src_bib, tgt_bib)
|
6
|
+
super()
|
7
|
+
|
8
|
+
@src_bib = src_bib
|
9
|
+
@tgt_bib = tgt_bib
|
10
|
+
end
|
11
|
+
|
12
|
+
def convert(line)
|
13
|
+
str = line
|
14
|
+
if /##*\s*References/ =~ str
|
15
|
+
return ""
|
16
|
+
end
|
17
|
+
|
18
|
+
if /{% bibliography .*? %}/ =~ str
|
19
|
+
@match = true
|
20
|
+
|
21
|
+
str = "\\bibliographystyle{unsrt}\\bibliography{#{@tgt_bib.sub(/\..*$/, "")}}"
|
22
|
+
|
23
|
+
gen_bib("#{@src_bib}", "#{@tgt_bib}")
|
24
|
+
end
|
25
|
+
|
26
|
+
while /{% cite\s+(?<citation>.*?)\s+%}/ =~ str
|
27
|
+
@match = true
|
28
|
+
citation = citation.sub(/\s+/, ',')
|
29
|
+
str = str.sub(/{% cite\s+(.*?)\s+%}/, "\\cite{#{citation}}")
|
30
|
+
end
|
31
|
+
|
32
|
+
str
|
33
|
+
end
|
34
|
+
|
35
|
+
def gen_bib(obib, bib)
|
36
|
+
File.open(obib, 'r') do |f|
|
37
|
+
File.open(bib, 'w') do |o|
|
38
|
+
while l = f.gets
|
39
|
+
if /<a\s+href="?(?<url>.*?)"?\s*>(?<text>.*?)<\/a>/ =~ l
|
40
|
+
l = l.sub(/<a\s+href=(.*?)>(.*?)<\/a>/, "\\href{#{url}}{#{text}}")
|
41
|
+
end
|
42
|
+
|
43
|
+
o.puts l
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def cleanup()
|
50
|
+
File.delete(@tgt_bib)
|
51
|
+
end
|
52
|
+
|
53
|
+
def header
|
54
|
+
lines = []
|
55
|
+
lines << '\\usepackage[sort&compress, numbers]{natbib}'
|
56
|
+
end
|
57
|
+
|
58
|
+
def before_xelatex(step, texfile)
|
59
|
+
cmds = []
|
60
|
+
if step == 2
|
61
|
+
cmds << "bibtex #{texfile.sub(/\.tex$/, "")} >/dev/null"
|
62
|
+
end
|
63
|
+
cmds
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class Converter
|
4
|
+
|
5
|
+
attr_accessor :match
|
6
|
+
|
7
|
+
def initialize()
|
8
|
+
@match = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def convert(line)
|
12
|
+
line
|
13
|
+
end
|
14
|
+
|
15
|
+
def header()
|
16
|
+
[]
|
17
|
+
end
|
18
|
+
|
19
|
+
def pandoc_args
|
20
|
+
[]
|
21
|
+
end
|
22
|
+
|
23
|
+
def xelatex_args(step)
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
|
27
|
+
def before_xelatex(step, texfile)
|
28
|
+
[]
|
29
|
+
end
|
30
|
+
|
31
|
+
def last_xelatex(texfile)
|
32
|
+
[]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'octopress-printable/gist_cache'
|
2
|
+
|
3
|
+
module Octopress
|
4
|
+
module Printable
|
5
|
+
class GistConverter < Converter
|
6
|
+
|
7
|
+
def convert(line)
|
8
|
+
str = line
|
9
|
+
|
10
|
+
if /{%\s+gist\s+(?<gist_txt>.*?)\s+%}/ =~ str
|
11
|
+
@match = true
|
12
|
+
|
13
|
+
gist = GistCache.new(gist_txt)
|
14
|
+
gist_file = gist.render()
|
15
|
+
if gist_file == ""
|
16
|
+
str = ""
|
17
|
+
else
|
18
|
+
lang = "text"
|
19
|
+
if /\.py$/ =~ gist_file
|
20
|
+
lang = 'Python'
|
21
|
+
end
|
22
|
+
|
23
|
+
str = "\\inputminted[mathescape, linenos, frame=lines, framesep=2mm]{#{lang}}{#{gist_file}}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
str
|
28
|
+
end
|
29
|
+
|
30
|
+
def header
|
31
|
+
lines = []
|
32
|
+
lines << '\\usepackage{minted}'
|
33
|
+
end
|
34
|
+
|
35
|
+
def xelatex_args(step)
|
36
|
+
args = []
|
37
|
+
args << "-shell-escape"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,124 @@
|
|
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 Octopress
|
14
|
+
module Printable
|
15
|
+
class GistCache
|
16
|
+
|
17
|
+
def initialize(text)
|
18
|
+
@text = text
|
19
|
+
@cache_disabled = false
|
20
|
+
@cache_folder = '.gist-cache'
|
21
|
+
FileUtils.mkdir_p @cache_folder
|
22
|
+
end
|
23
|
+
|
24
|
+
def render()
|
25
|
+
if parts = @text.match(/([a-zA-Z\d]*) (.*)/)
|
26
|
+
gist, file = parts[1].strip, parts[2].strip
|
27
|
+
else
|
28
|
+
gist, file = @text.strip, ""
|
29
|
+
end
|
30
|
+
if gist.empty?
|
31
|
+
""
|
32
|
+
else
|
33
|
+
script_url = script_url_for gist, file
|
34
|
+
code = get_cached_gist(gist, file) || get_gist_from_web(gist, file)
|
35
|
+
#html_output_for script_url, code
|
36
|
+
cache_file = get_cache_file_for gist, file
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def html_output_for(script_url, code)
|
41
|
+
code = CGI.escapeHTML code
|
42
|
+
<<-HTML
|
43
|
+
iv><script src='#{script_url}'></script>
|
44
|
+
oscript><pre><code>#{code}</code></pre></noscript></div>
|
45
|
+
HTML
|
46
|
+
end
|
47
|
+
|
48
|
+
def script_url_for(gist_id, filename)
|
49
|
+
url = "https://gist.github.com/#{gist_id}.js"
|
50
|
+
url = "#{url}?file=#{filename}" unless filename.nil? or filename.empty?
|
51
|
+
url
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_gist_url_for(gist, file)
|
55
|
+
"https://gist.githubusercontent.com/raw/#{gist}/#{file}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def cache(gist, file, data)
|
59
|
+
cache_file = get_cache_file_for gist, file
|
60
|
+
File.open(cache_file, "w") do |io|
|
61
|
+
io.write data
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_cached_gist(gist, file)
|
66
|
+
return nil if @cache_disabled
|
67
|
+
cache_file = get_cache_file_for gist, file
|
68
|
+
File.read cache_file if File.exist? cache_file
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_cache_file_for(gist, file)
|
72
|
+
bad_chars = /[^a-zA-Z0-9\-_.]/
|
73
|
+
gist = gist.gsub bad_chars, ''
|
74
|
+
file = file.gsub bad_chars, ''
|
75
|
+
md5 = Digest::MD5.hexdigest "#{gist}-#{file}"
|
76
|
+
File.join @cache_folder, "cache.#{md5}-#{gist}-#{file}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_gist_from_web(gist, file)
|
80
|
+
gist_url = get_gist_url_for(gist, file)
|
81
|
+
data = get_web_content(gist_url)
|
82
|
+
|
83
|
+
locations = Array.new
|
84
|
+
while (data.code.to_i == 301 || data.code.to_i == 302)
|
85
|
+
data = handle_gist_redirecting(data)
|
86
|
+
break if locations.include? data.header['Location']
|
87
|
+
locations << data.header['Location']
|
88
|
+
end
|
89
|
+
|
90
|
+
if data.code.to_i != 200
|
91
|
+
raise RuntimeError, "Gist replied with #{data.code} for #{gist_url}"
|
92
|
+
end
|
93
|
+
|
94
|
+
cache(gist, file, data.body) unless @cache_disabled
|
95
|
+
data.body
|
96
|
+
end
|
97
|
+
|
98
|
+
def handle_gist_redirecting(data)
|
99
|
+
redirected_url = data.header['Location']
|
100
|
+
if redirected_url.nil? || redirected_url.empty?
|
101
|
+
raise ArgumentError, "GitHub replied with a 302 but didn't provide a location in the response headers."
|
102
|
+
end
|
103
|
+
|
104
|
+
get_web_content(redirected_url)
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_web_content(url)
|
108
|
+
raw_uri = URI.parse url
|
109
|
+
proxy = ENV['http_proxy']
|
110
|
+
if proxy
|
111
|
+
proxy_uri = URI.parse(proxy)
|
112
|
+
https = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port).new raw_uri.host, raw_uri.port
|
113
|
+
else
|
114
|
+
https = Net::HTTP.new raw_uri.host, raw_uri.port
|
115
|
+
end
|
116
|
+
https.use_ssl = true
|
117
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
118
|
+
request = Net::HTTP::Get.new raw_uri.request_uri
|
119
|
+
data = https.request request
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class ImgConverter < Converter
|
4
|
+
|
5
|
+
TITLE_REGEX = /title:['|"](.+?)['|"]/
|
6
|
+
|
7
|
+
def initialize(source_dir)
|
8
|
+
super()
|
9
|
+
|
10
|
+
@source_dir = source_dir
|
11
|
+
end
|
12
|
+
|
13
|
+
def convert(line)
|
14
|
+
str = line
|
15
|
+
|
16
|
+
if /{% img (?<markup>.*) %}/ =~ str
|
17
|
+
@match = true
|
18
|
+
|
19
|
+
img = get_img_label(markup)
|
20
|
+
str="\\begin{figure}[h]\\centering\\includegraphics[width=\\textwidth]{#{@source_dir}/#{img['src']}}\\caption{#{img['title']}}\\label{#{img['alt']}}\\end{figure}"
|
21
|
+
end
|
22
|
+
|
23
|
+
str
|
24
|
+
end
|
25
|
+
|
26
|
+
# from octopress-image-tag plugin
|
27
|
+
def get_img_label(markup)
|
28
|
+
title = markup.scan(TITLE_REGEX).flatten.compact.last
|
29
|
+
markup.gsub!(TITLE_REGEX, '')
|
30
|
+
|
31
|
+
if markup =~ /(?<class>\S.*\s+)?(?<src>(?:https?:\/\/|\/|\S+\/)\S+)(?:\s+(?<width>\d\S+))?(?:\s+(?<height>\d\S+))?(?<alt>\s+.+)?/i
|
32
|
+
attributes = ['class', 'src', 'width', 'height', 'alt']
|
33
|
+
image = attributes.reduce({}) { |img, attr| img[attr] ||= $~[attr].strip if $~[attr]; img }
|
34
|
+
text = image['alt']
|
35
|
+
|
36
|
+
# Allow parsing "title" "alt"
|
37
|
+
if text =~ /(?:"|')(?<title>[^"']+)?(?:"|')\s+(?:"|')(?<alt>[^"']+)?(?:"|')/
|
38
|
+
image['title'] = title
|
39
|
+
image['alt'] = alt
|
40
|
+
else
|
41
|
+
# Set alt text and title from text
|
42
|
+
image['alt'].gsub!(/"/, '') if image['alt']
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
image['title'] ||= title
|
47
|
+
image['alt'] ||= title
|
48
|
+
|
49
|
+
image
|
50
|
+
end
|
51
|
+
|
52
|
+
def header
|
53
|
+
lines = []
|
54
|
+
lines << '\\usepackage{graphicx}'
|
55
|
+
lines << '\\usepackage[all]{hypcap}'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class LatexConverter < Converter
|
4
|
+
|
5
|
+
def convert(line)
|
6
|
+
str = line
|
7
|
+
while /{{\s+(?<arg>\S+)\s*\|\s*latex:(?<cmd>\S+)\s*\s*}}/ =~ str
|
8
|
+
@match = true
|
9
|
+
if ! arg.gsub!(/\A"|"\Z/, '')
|
10
|
+
arg.gsub!(/\A'|'\Z/, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
str.sub!(/{{\s+\S+\s*\|\s*latex:\S+\s*}}/, "(\\#{cmd}{#{arg}})")
|
14
|
+
end
|
15
|
+
|
16
|
+
str
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class MathConverter < Converter
|
4
|
+
|
5
|
+
def convert(line)
|
6
|
+
str = line.gsub(/\$\$\s*\\begin{equation}/, '\\begin{equation}')
|
7
|
+
str.gsub!(/\\end{equation}\s*\$\$/, '\\end{equation}')
|
8
|
+
|
9
|
+
str.gsub!(/\\\*/, '*')
|
10
|
+
str.gsub!(/\\\|/, '|')
|
11
|
+
str.gsub!(/\\_/, '_')
|
12
|
+
|
13
|
+
if !@match
|
14
|
+
if str != line
|
15
|
+
@match = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
str
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,246 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
autoload :Converter, 'octopress-printable/converter'
|
4
|
+
autoload :MathConverter, 'octopress-printable/math'
|
5
|
+
autoload :ImgConverter, 'octopress-printable/img'
|
6
|
+
autoload :BibConverter, 'octopress-printable/bib'
|
7
|
+
autoload :GistConverter, 'octopress-printable/gist'
|
8
|
+
autoload :PostLinkConverter, 'octopress-printable/post_link'
|
9
|
+
autoload :LatexConverter, 'octopress-printable/latex'
|
10
|
+
|
11
|
+
class Plugin < Ink::Plugin
|
12
|
+
|
13
|
+
def register
|
14
|
+
super
|
15
|
+
if Octopress::Ink.enabled?
|
16
|
+
self.generate(Octopress.site, config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate(site, config)
|
21
|
+
@conf = inject_configs
|
22
|
+
|
23
|
+
posts_dir = @conf['posts_dir']
|
24
|
+
printables_dir = @conf['printables_dir']
|
25
|
+
source_dir = @conf['source_dir']
|
26
|
+
blog_url = @conf['blog_url']
|
27
|
+
bib_dir = @conf['bibliography_dir']
|
28
|
+
bib = @conf['bibliography']
|
29
|
+
|
30
|
+
if !File.exists?(printables_dir)
|
31
|
+
FileUtils.mkdir_p(printables_dir)
|
32
|
+
end
|
33
|
+
|
34
|
+
site.posts.each do |p|
|
35
|
+
post = p.path
|
36
|
+
pdf = post.sub(/#{posts_dir}\//, "#{printables_dir}/")
|
37
|
+
pdf = pdf.sub(/\.markdown$/, ".pdf")
|
38
|
+
pdf = pdf.sub(/\.md$/, ".pdf")
|
39
|
+
|
40
|
+
if !File.exists?(pdf) || File.stat(post).mtime > File.stat(pdf).mtime
|
41
|
+
puts "Converting #{post} to #{pdf}"
|
42
|
+
gen_pdf(post, pdf, source_dir, posts_dir, blog_url, bib_dir, bib)
|
43
|
+
if File.exists?(pdf)
|
44
|
+
site.static_files << Jekyll::StaticFile.new(site,
|
45
|
+
site.source, printables_dir, File.basename(pdf))
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def inject_configs
|
52
|
+
@conf = self.config
|
53
|
+
@conf = Jekyll::Utils.deep_merge_hashes(YAML.load(Plugin.default_config), @conf)
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.default_config
|
57
|
+
<<-CONFIG
|
58
|
+
posts_dir: "_posts"
|
59
|
+
printables_dir: "assets/printables"
|
60
|
+
source_dir: "."
|
61
|
+
blog_url: "http://example.com" # used in pdf post_links
|
62
|
+
bibliography_dir: "_bibliography"
|
63
|
+
bibliography: "references.bib"
|
64
|
+
|
65
|
+
# only convert markdowns, without running pandoc and xelatex
|
66
|
+
dry_run : false
|
67
|
+
|
68
|
+
# debug files
|
69
|
+
dump_tex_file: false
|
70
|
+
dump_markdown_file: false
|
71
|
+
dump_bib_file: false
|
72
|
+
dump_cmds: false
|
73
|
+
keep_tmp_files: false
|
74
|
+
|
75
|
+
CONFIG
|
76
|
+
end
|
77
|
+
|
78
|
+
def gen_pdf(mdfile, pdffile, source_dir, posts_dir, blog_url, bib_dir, bib)
|
79
|
+
pdfdir = File.dirname(pdffile)
|
80
|
+
if ! File.exists?(pdfdir)
|
81
|
+
FileUtils.mkdir_p pdfdir
|
82
|
+
end
|
83
|
+
|
84
|
+
converters = []
|
85
|
+
math = MathConverter.new
|
86
|
+
converters << math
|
87
|
+
img = ImgConverter.new(source_dir)
|
88
|
+
converters << img
|
89
|
+
bib = BibConverter.new("#{source_dir}/#{bib_dir}/#{bib}",
|
90
|
+
"#{pdfdir}/#{bib}")
|
91
|
+
converters << bib
|
92
|
+
gist = GistConverter.new
|
93
|
+
converters << gist
|
94
|
+
post_link = PostLinkConverter.new(source_dir, posts_dir, blog_url)
|
95
|
+
converters << post_link
|
96
|
+
latex = LatexConverter.new
|
97
|
+
converters << latex
|
98
|
+
|
99
|
+
tmpfile="#{pdffile}.markdown"
|
100
|
+
comment = false
|
101
|
+
File.open(tmpfile, 'w') do |post|
|
102
|
+
File.open(mdfile, "r") do |file|
|
103
|
+
while line = file.gets
|
104
|
+
line = line.strip
|
105
|
+
|
106
|
+
if /^{% comment %}$/ =~ line
|
107
|
+
comment = true
|
108
|
+
next
|
109
|
+
end
|
110
|
+
|
111
|
+
if /^{% endcomment %}$/ =~ line
|
112
|
+
comment = false
|
113
|
+
next
|
114
|
+
end
|
115
|
+
|
116
|
+
if comment
|
117
|
+
next
|
118
|
+
end
|
119
|
+
|
120
|
+
line = line.gsub(/{% comment %} (.*?) {% endcomment %}/, "")
|
121
|
+
|
122
|
+
line = line.gsub(/\* list element with functor item/, '')
|
123
|
+
line = line.gsub(/{:toc}/, '\tableofcontents')
|
124
|
+
|
125
|
+
line = line.sub(/^#(#*)/, '\1')
|
126
|
+
|
127
|
+
for converter in converters
|
128
|
+
line = converter.convert(line)
|
129
|
+
end
|
130
|
+
|
131
|
+
post.puts line
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
cts = []
|
137
|
+
for converter in converters
|
138
|
+
if converter.match
|
139
|
+
cts << converter
|
140
|
+
end
|
141
|
+
end
|
142
|
+
converters = cts
|
143
|
+
|
144
|
+
texfile = pdffile.sub(/.pdf$/, '.tex')
|
145
|
+
base = pdffile.sub(/.pdf$/, '')
|
146
|
+
pkgfile = "#{pdffile}.header.tex"
|
147
|
+
|
148
|
+
File.open(pkgfile, "w") { |f|
|
149
|
+
for converter in converters
|
150
|
+
converter.header.each do |h|
|
151
|
+
f.puts h
|
152
|
+
end
|
153
|
+
end
|
154
|
+
}
|
155
|
+
|
156
|
+
cmds = []
|
157
|
+
args = []
|
158
|
+
for converter in converters
|
159
|
+
args += converter.pandoc_args
|
160
|
+
end
|
161
|
+
|
162
|
+
cmds << "pandoc -s -N #{args.join(" ")} --include-in-header=#{pkgfile} #{tmpfile} -o #{texfile} "
|
163
|
+
|
164
|
+
(1..2).each do |step|
|
165
|
+
args = []
|
166
|
+
extra_cmds = []
|
167
|
+
for converter in converters
|
168
|
+
extra_cmds += converter.before_xelatex(step, texfile)
|
169
|
+
end
|
170
|
+
for cmd in extra_cmds
|
171
|
+
cmds << cmd
|
172
|
+
end
|
173
|
+
|
174
|
+
for converter in converters
|
175
|
+
args += converter.xelatex_args(step)
|
176
|
+
end
|
177
|
+
cmds << "xelatex #{args.join(" ")} -output-directory=#{pdfdir} -no-pdf --interaction=nonstopmode #{base} >/dev/null"
|
178
|
+
end
|
179
|
+
|
180
|
+
extra_cmds = []
|
181
|
+
for converter in converters
|
182
|
+
extra_cmds += converter.before_xelatex(3, texfile)
|
183
|
+
end
|
184
|
+
for cmd in extra_cmds
|
185
|
+
cmds << cmd
|
186
|
+
end
|
187
|
+
cmds << "xelatex #{args.join(" ")} -output-directory=#{pdfdir} --interaction=nonstopmode #{base} >/dev/null"
|
188
|
+
|
189
|
+
extra_cmds = []
|
190
|
+
for converter in converters
|
191
|
+
extra_cmds += converter.last_xelatex(texfile)
|
192
|
+
end
|
193
|
+
for cmd in extra_cmds
|
194
|
+
cmds << cmd
|
195
|
+
end
|
196
|
+
|
197
|
+
if ! @conf['dry_run']
|
198
|
+
for cmd in cmds
|
199
|
+
system cmd
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
if @conf['dump_cmds']
|
204
|
+
File.open("#{base}.sh", 'w') { |f|
|
205
|
+
f.write(cmds.join("\n"))
|
206
|
+
}
|
207
|
+
FileUtils.chmod(0755, "#{base}.sh")
|
208
|
+
end
|
209
|
+
|
210
|
+
if File.exists?("#{File.basename(base)}.pyg")
|
211
|
+
FileUtils.mv("#{File.basename(base)}.pyg", pdfdir)
|
212
|
+
end
|
213
|
+
|
214
|
+
if !@conf['keep_tmp_files']
|
215
|
+
FileUtils.rm_f("#{base}.aux")
|
216
|
+
FileUtils.rm_f("#{base}.log")
|
217
|
+
FileUtils.rm_f("#{base}.lot")
|
218
|
+
FileUtils.rm_f("#{base}.out")
|
219
|
+
FileUtils.rm_f("#{base}.toc")
|
220
|
+
FileUtils.rm_f("#{base}.blg")
|
221
|
+
FileUtils.rm_f("#{base}.bbl")
|
222
|
+
FileUtils.rm_f("#{base}.lof")
|
223
|
+
FileUtils.rm_f("#{base}.xdv")
|
224
|
+
FileUtils.rm_f("#{base}.hst")
|
225
|
+
FileUtils.rm_f("#{base}.ver")
|
226
|
+
FileUtils.rm_f("#{base}.synctex.gz")
|
227
|
+
FileUtils.rm_f("#{base}.pyg")
|
228
|
+
end
|
229
|
+
|
230
|
+
if !@conf['dump_tex_file']
|
231
|
+
FileUtils.rm_f("#{texfile}")
|
232
|
+
FileUtils.rm_f("#{pkgfile}")
|
233
|
+
end
|
234
|
+
|
235
|
+
if !@conf['dump_markdown_file']
|
236
|
+
FileUtils.rm_f("#{tmpfile}")
|
237
|
+
end
|
238
|
+
|
239
|
+
if !@conf['dump_bib_file']
|
240
|
+
bib.cleanup
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Octopress
|
2
|
+
module Printable
|
3
|
+
class PostLinkConverter < Converter
|
4
|
+
|
5
|
+
def initialize(source_dir, posts_dir, blog_url)
|
6
|
+
super()
|
7
|
+
|
8
|
+
@source_dir = source_dir
|
9
|
+
@posts_dir = posts_dir
|
10
|
+
@blog_url = blog_url
|
11
|
+
end
|
12
|
+
|
13
|
+
def convert(line)
|
14
|
+
str = line
|
15
|
+
|
16
|
+
while /{% post_link (?<markup>[^\s]+)(?<text>\s+.+)? %}/ =~ str
|
17
|
+
@match = true
|
18
|
+
|
19
|
+
/^(?<year>\d+)-(?<month>\d+)-(?<day>\d+)-(?<title>.*)/ =~ markup
|
20
|
+
|
21
|
+
if ! text
|
22
|
+
File.open("#{@source_dir}/#{@posts_dir}/#{markup}.markdown", 'r') do |f|
|
23
|
+
while l = f.gets
|
24
|
+
if /title: (?:"|')(?<text>.*)(?:"|')/ =~ l
|
25
|
+
break
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
str = str.sub(/{% post_link (.*?) %}/, "\\href{#{@blog_url}/#{year}/#{month}/#{day}/#{title}/}{#{text}}")
|
31
|
+
end
|
32
|
+
|
33
|
+
str
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# post_link
|
2
|
+
# http://brm.io/jekyll-post-links/
|
3
|
+
#
|
4
|
+
# usage {% post_link post text %}
|
5
|
+
#
|
6
|
+
# Where post is a post in the usual date-slug format.
|
7
|
+
# If text is specified, it uses that as the anchor text, otherwise it's the post title.
|
8
|
+
#
|
9
|
+
# Output is a full anchor tag. Broken links will be detected by compiler.
|
10
|
+
#
|
11
|
+
# based on post_url.rb
|
12
|
+
# https://github.com/jekyll/jekyll/blob/master/lib/jekyll/tags/post_url.rb
|
13
|
+
|
14
|
+
module Octopress
|
15
|
+
module Printable
|
16
|
+
class PostLinkComparer
|
17
|
+
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-([^\s]*)(\s.*)?$/
|
18
|
+
|
19
|
+
attr_accessor :date, :slug, :text
|
20
|
+
|
21
|
+
def initialize(name)
|
22
|
+
all, path, date, slug, text = *name.sub(/^\//, "").match(MATCHER)
|
23
|
+
raise ArgumentError.new("'#{name}' does not contain valid date and/or title") unless all
|
24
|
+
@slug = path ? path + slug : slug
|
25
|
+
@date = Time.parse(date)
|
26
|
+
@text = text
|
27
|
+
end
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
slug == post_slug(other)
|
31
|
+
|
32
|
+
# disabled the date check below (used in post_url.rb)
|
33
|
+
# otherwise posts with a custom date front-matter will fail if it's different to the slug
|
34
|
+
|
35
|
+
#&& date.year == other.date.year &&
|
36
|
+
#date.month == other.date.month &&
|
37
|
+
#date.day == other.date.day
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def post_slug(other)
|
42
|
+
path = other.name.split("/")[0...-1].join("/")
|
43
|
+
if path.nil? || path == ""
|
44
|
+
other.slug
|
45
|
+
else
|
46
|
+
path + '/' + other.slug
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Tags < Liquid::Tag
|
52
|
+
def initialize(tag_name, post, tokens)
|
53
|
+
super
|
54
|
+
@orig_post = post.strip
|
55
|
+
begin
|
56
|
+
@post = PostLinkComparer.new(@orig_post)
|
57
|
+
rescue
|
58
|
+
raise ArgumentError.new <<-eos
|
59
|
+
Could not parse name of post "#{@orig_post}" in tag 'post_link'.
|
60
|
+
Make sure the post exists and the name and date is correct.
|
61
|
+
eos
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def render(context)
|
66
|
+
site = context.registers[:site]
|
67
|
+
|
68
|
+
site.posts.each do |p|
|
69
|
+
if @post == p
|
70
|
+
return "<a href=\"#{ p.url }\">#{ @post.text ? @post.text.strip! : p.title }</a>"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
raise ArgumentError.new <<-eos
|
75
|
+
Could not find post "#{@orig_post}" in tag 'post_link'.
|
76
|
+
Make sure the post exists and the name and date is correct.
|
77
|
+
eos
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: octopress-printable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Wang Jian
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: clash
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.2.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.2.2
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: octopress-image-tag
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.1.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.1.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: octopress-ink
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: jekyll-gist
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.2.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.2.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: jekyll-scholar
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.3.5
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.3.5
|
111
|
+
description: Printable version for post generator.
|
112
|
+
email:
|
113
|
+
- wantee.wang@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- CHANGELOG.md
|
119
|
+
- LICENSE.txt
|
120
|
+
- README.md
|
121
|
+
- assets/config.yml
|
122
|
+
- assets/images/printer.png
|
123
|
+
- assets/includes/printable.html
|
124
|
+
- assets/stylesheets/printable.scss
|
125
|
+
- lib/octopress-printable.rb
|
126
|
+
- lib/octopress-printable/bib.rb
|
127
|
+
- lib/octopress-printable/converter.rb
|
128
|
+
- lib/octopress-printable/filters.rb
|
129
|
+
- lib/octopress-printable/gist.rb
|
130
|
+
- lib/octopress-printable/gist_cache.rb
|
131
|
+
- lib/octopress-printable/img.rb
|
132
|
+
- lib/octopress-printable/latex.rb
|
133
|
+
- lib/octopress-printable/math.rb
|
134
|
+
- lib/octopress-printable/plugin.rb
|
135
|
+
- lib/octopress-printable/post_link.rb
|
136
|
+
- lib/octopress-printable/tags.rb
|
137
|
+
- lib/octopress-printable/version.rb
|
138
|
+
homepage: https://github.com/wantee/octopress-printable
|
139
|
+
licenses:
|
140
|
+
- MIT
|
141
|
+
metadata: {}
|
142
|
+
post_install_message:
|
143
|
+
rdoc_options: []
|
144
|
+
require_paths:
|
145
|
+
- lib
|
146
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
151
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
requirements: []
|
157
|
+
rubyforge_project:
|
158
|
+
rubygems_version: 2.4.5
|
159
|
+
signing_key:
|
160
|
+
specification_version: 4
|
161
|
+
summary: Printable version for post generator.
|
162
|
+
test_files: []
|