review-retrovert 0.2.2 → 0.9.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 +4 -4
- data/.github/workflows/retrovert.yml +39 -0
- data/.gitignore +2 -2
- data/.ruby-version +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +68 -2
- data/README.md +6 -3
- data/lib/review/retrovert/cli.rb +2 -0
- data/lib/review/retrovert/converter.rb +255 -16
- data/lib/review/retrovert/version.rb +1 -1
- data/review-retrovert.gemspec +1 -1
- data/testdata/mybook/.gitignore +7 -0
- data/testdata/mybook/README.md +43 -0
- data/testdata/mybook/Rakefile +16 -0
- data/testdata/mybook/catalog.yml +33 -0
- data/testdata/mybook/config-starter.yml +139 -0
- data/testdata/mybook/config.yml +375 -0
- data/testdata/mybook/contents/00-preface.re +83 -0
- data/testdata/mybook/contents/01-install.re +272 -0
- data/testdata/mybook/contents/02-tutorial.re +1008 -0
- data/testdata/mybook/contents/03-syntax.re +2613 -0
- data/testdata/mybook/contents/04-customize.re +728 -0
- data/testdata/mybook/contents/05-faq.re +328 -0
- data/testdata/mybook/contents/06-bestpractice.re +971 -0
- data/testdata/mybook/contents/91-compare.re +18 -0
- data/testdata/mybook/contents/92-filelist.re +119 -0
- data/testdata/mybook/contents/93-background.re +267 -0
- data/testdata/mybook/contents/99-postface.re +38 -0
- data/testdata/mybook/css/normalize.css +349 -0
- data/testdata/mybook/css/webstyle.css +514 -0
- data/testdata/mybook/images/03-syntax/favicon-16x16.png +0 -0
- data/testdata/mybook/images/03-syntax/figure_heretop.png +0 -0
- data/testdata/mybook/images/03-syntax/tw-icon1.jpg +0 -0
- data/testdata/mybook/images/03-syntax/tw-icon2.jpg +0 -0
- data/testdata/mybook/images/03-syntax/tw-icon3.jpg +0 -0
- data/testdata/mybook/images/03-syntax/tw-icon4.jpg +0 -0
- data/testdata/mybook/images/04-customize/caption_pagebreak.png +0 -0
- data/testdata/mybook/images/04-customize/chaptitlepage_sample.png +0 -0
- data/testdata/mybook/images/05-faq/codeblock_rpadding1.png +0 -0
- data/testdata/mybook/images/05-faq/codeblock_rpadding2.png +0 -0
- data/testdata/mybook/images/06-bestpractice/figure_heretop.png +0 -0
- data/testdata/mybook/images/06-bestpractice/font_beramono.png +0 -0
- data/testdata/mybook/images/06-bestpractice/heading_design1.png +0 -0
- data/testdata/mybook/images/06-bestpractice/heading_design2.png +0 -0
- data/testdata/mybook/images/06-bestpractice/margin_book.png +0 -0
- data/testdata/mybook/images/06-bestpractice/multiline-title.png +0 -0
- data/testdata/mybook/images/06-bestpractice/preface_numbered.png +0 -0
- data/testdata/mybook/images/06-bestpractice/program_border.png +0 -0
- data/testdata/mybook/images/06-bestpractice/sechead_design_4.png +0 -0
- data/testdata/mybook/images/06-bestpractice/titlepage-samples.png +0 -0
- data/testdata/mybook/images/93-background/bug913.png +0 -0
- data/testdata/mybook/images/93-background/slide2.png +0 -0
- data/testdata/mybook/images/cover_a5.pdf +0 -0
- data/testdata/mybook/images/cover_b5.pdf +0 -0
- data/testdata/mybook/images/tw-icon.jpg +0 -0
- data/testdata/mybook/layouts/layout.epub.erb +29 -0
- data/testdata/mybook/layouts/layout.html5.erb +106 -0
- data/testdata/mybook/layouts/layout.tex.erb +546 -0
- data/testdata/mybook/lib/hooks/beforetexcompile.rb +55 -0
- data/testdata/mybook/lib/ruby/review-builder.rb +503 -0
- data/testdata/mybook/lib/ruby/review-cli.rb +58 -0
- data/testdata/mybook/lib/ruby/review-compiler.rb +523 -0
- data/testdata/mybook/lib/ruby/review-epubmaker.rb +606 -0
- data/testdata/mybook/lib/ruby/review-htmlbuilder.rb +661 -0
- data/testdata/mybook/lib/ruby/review-latexbuilder.rb +782 -0
- data/testdata/mybook/lib/ruby/review-maker.rb +235 -0
- data/testdata/mybook/lib/ruby/review-monkeypatch.rb +91 -0
- data/testdata/mybook/lib/ruby/review-pdfmaker.rb +468 -0
- data/testdata/mybook/lib/ruby/review-textbuilder.rb +36 -0
- data/testdata/mybook/lib/ruby/review-tocparser.rb +285 -0
- data/testdata/mybook/lib/ruby/review-webmaker.rb +433 -0
- data/testdata/mybook/lib/tasks/mytasks.rake +31 -0
- data/testdata/mybook/lib/tasks/review.rake +142 -0
- data/testdata/mybook/lib/tasks/review.rake.orig +72 -0
- data/testdata/mybook/lib/tasks/starter.rake +326 -0
- data/testdata/mybook/locale.yml +6 -0
- data/testdata/mybook/review-ext.rb +206 -0
- data/testdata/mybook/sty/jumoline.sty +310 -0
- data/testdata/mybook/sty/mycolophon.sty +81 -0
- data/testdata/mybook/sty/mystyle.sty +8 -0
- data/testdata/mybook/sty/mytextsize.sty +61 -0
- data/testdata/mybook/sty/mytitlepage.sty +103 -0
- data/testdata/mybook/sty/reviewmacro.sty +60 -0
- data/testdata/mybook/sty/starter-codeblock.sty +332 -0
- data/testdata/mybook/sty/starter-color.sty +79 -0
- data/testdata/mybook/sty/starter-font.sty +112 -0
- data/testdata/mybook/sty/starter-heading.sty +514 -0
- data/testdata/mybook/sty/starter-note.sty +127 -0
- data/testdata/mybook/sty/starter-section.sty +262 -0
- data/testdata/mybook/sty/starter-toc.sty +72 -0
- data/testdata/mybook/sty/starter.sty +554 -0
- data/testdata/mybook/style.css +597 -0
- metadata +100 -3
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##
|
4
|
+
## これはreviewstarterが用意したファイル。
|
5
|
+
## ユーザ独自のRakeタスクをここに定義する。
|
6
|
+
##
|
7
|
+
|
8
|
+
|
9
|
+
#
|
10
|
+
#def render_eruby_files(param) # 要 Ruby >= 2.2
|
11
|
+
# Dir.glob('**/*.eruby').each do |erubyfile|
|
12
|
+
# origfile = erubyfile.sub(/\.eruby$/, '')
|
13
|
+
# sh "erb -T 2 '#{param}' #{erubyfile} > #{origfile}"
|
14
|
+
# end
|
15
|
+
#end
|
16
|
+
#
|
17
|
+
#
|
18
|
+
#namespace :setup do
|
19
|
+
#
|
20
|
+
# desc "*印刷用に設定 (B5, 10pt, mono)"
|
21
|
+
# task :printing do
|
22
|
+
# render_eruby_files('buildmode=printing')
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# desc "*タブレット用に設定 (A5, 10pt, color)"
|
26
|
+
# task :tablet do
|
27
|
+
# render_eruby_files('buildmode=tablet')
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
#end
|
31
|
+
#
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rake/clean'
|
3
|
+
|
4
|
+
BOOK = 'book'
|
5
|
+
BOOK_PDF = BOOK + '.pdf'
|
6
|
+
BOOK_EPUB = BOOK + '.epub'
|
7
|
+
CONFIG_FILE = 'config.yml'
|
8
|
+
WEBROOT = 'webroot'
|
9
|
+
|
10
|
+
def build(mode, chapter)
|
11
|
+
sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp"
|
12
|
+
mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml' }
|
13
|
+
FileUtils.mv 'tmp', chapter.gsub(/re\z/, mode_ext[mode])
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_all(mode)
|
17
|
+
sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css"
|
18
|
+
end
|
19
|
+
|
20
|
+
def config_file()
|
21
|
+
conf = ENV['config']
|
22
|
+
conf = CONFIG_FILE if conf.nil? || conf.empty?
|
23
|
+
return conf
|
24
|
+
end
|
25
|
+
|
26
|
+
task default: :html_all
|
27
|
+
|
28
|
+
desc 'build html (Usage: rake build re=target.re)'
|
29
|
+
task :html => :prepare do
|
30
|
+
if ENV['re'].nil?
|
31
|
+
puts 'Usage: rake build re=target.re'
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
build('html', ENV['re'])
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'build all html'
|
38
|
+
task :html_all => :prepare do
|
39
|
+
build_all('html')
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'preproc all'
|
43
|
+
task :preproc => :prepare do
|
44
|
+
Dir.glob('*.re').each do |file|
|
45
|
+
sh "review-preproc --replace #{file}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'generate PDF and EPUB file'
|
50
|
+
task all: %i[pdf epub]
|
51
|
+
|
52
|
+
desc 'generate PDF file'
|
53
|
+
task :pdf => :prepare do
|
54
|
+
require 'review'
|
55
|
+
#require 'review/pdfmaker'
|
56
|
+
require './lib/ruby/review-pdfmaker'
|
57
|
+
#
|
58
|
+
FileUtils.rm_rf [BOOK_PDF, BOOK, BOOK + '-pdf']
|
59
|
+
begin
|
60
|
+
ReVIEW::PDFMaker.execute(config_file())
|
61
|
+
rescue RuntimeError => ex
|
62
|
+
if ex.message =~ /^failed to run command:/
|
63
|
+
abort "*\n* ERROR (review-pdfmaker):\n* #{ex.message}\n*"
|
64
|
+
else
|
65
|
+
raise
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
desc 'generate EPUB file'
|
71
|
+
task :epub => :prepare do
|
72
|
+
FileUtils.rm_rf [BOOK_EPUB, BOOK, BOOK + '-epub']
|
73
|
+
#sh "review-epubmaker #{config_file()}"
|
74
|
+
require 'review'
|
75
|
+
require './lib/ruby/review-epubmaker'
|
76
|
+
ReVIEW::EpubMaker.execute(config_file())
|
77
|
+
end
|
78
|
+
|
79
|
+
desc 'generate stagic HTML file for web'
|
80
|
+
task :web => :prepare do
|
81
|
+
FileUtils.rm_rf [WEBROOT]
|
82
|
+
#sh "review-webmaker #{config_file()}"
|
83
|
+
require 'review'
|
84
|
+
#require 'review/webmaker'
|
85
|
+
require './lib/ruby/review-webmaker'
|
86
|
+
ReVIEW::WEBMaker.execute(config_file())
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
#desc "+ copy *.re files under 'contents/' into here."
|
91
|
+
task :prepare do
|
92
|
+
require 'yaml'
|
93
|
+
config = YAML.load_file(config_file())
|
94
|
+
PREPARES.each do |x|
|
95
|
+
case x
|
96
|
+
when Proc; x.call(config)
|
97
|
+
else ; __send__(x, config)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
## 前処理を追加したい場合は、関数名またはProcオブジェクトをこの配列に追加する
|
103
|
+
PREPARES = [:copy_files_under_contentdir]
|
104
|
+
|
105
|
+
def copy_files_under_contentdir(config)
|
106
|
+
## 設定ファイル (config.yml) の「contentdir:」の値を調べる
|
107
|
+
contdir = config['contentdir']
|
108
|
+
if contdir && contdir != '.' # '.' はカレントディレクトリを表すので対象外
|
109
|
+
## もし contentdir が存在しなければエラー
|
110
|
+
unless File.directory?(contdir)
|
111
|
+
abort_with_message <<END
|
112
|
+
ERROR: Content directory '#{contdir}' not exist.
|
113
|
+
Please check 'contentdir:' value in config file,
|
114
|
+
or create '#{contdir}' directory and put *.re files into there.
|
115
|
+
END
|
116
|
+
end
|
117
|
+
## カレントディレクトリに *.re ファイルがあればエラー
|
118
|
+
unless Dir.glob('*.re').empty?
|
119
|
+
re_file = Dir.glob('*.re').sort.first
|
120
|
+
abort_with_message <<END
|
121
|
+
ERROR: File '#{re_file}' found in current directory.
|
122
|
+
When 'contentdir:' specifieid in config file,
|
123
|
+
you must put all *.re files into that directory.
|
124
|
+
Please remove *.re files from current directory.
|
125
|
+
END
|
126
|
+
end
|
127
|
+
## contentdir にある *.re ファイルをカレントディレクトリにコピー
|
128
|
+
cp Dir.glob(File.join(contdir, '*.re')), '.', :verbose=>false
|
129
|
+
## コピーしたファイルをRakeプロセス終了時に削除
|
130
|
+
at_exit { rm_f Dir.glob('*.re'), :verbose=>false }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def abort_with_message(error_msg)
|
135
|
+
$stderr.puts "***"
|
136
|
+
$stderr.puts error_msg.gsub(/^/, '*** ')
|
137
|
+
$stderr.puts "***"
|
138
|
+
abort()
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT, 'images/_review_math'])
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rake/clean'
|
3
|
+
|
4
|
+
BOOK = 'book'
|
5
|
+
BOOK_PDF = BOOK + '.pdf'
|
6
|
+
BOOK_EPUB = BOOK + '.epub'
|
7
|
+
CONFIG_FILE = 'config.yml'
|
8
|
+
WEBROOT = 'webroot'
|
9
|
+
|
10
|
+
def build(mode, chapter)
|
11
|
+
sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css #{chapter} > tmp"
|
12
|
+
mode_ext = { 'html' => 'html', 'latex' => 'tex', 'idgxml' => 'xml' }
|
13
|
+
FileUtils.mv 'tmp', chapter.gsub(/re\z/, mode_ext[mode])
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_all(mode)
|
17
|
+
sh "review-compile --target=#{mode} --footnotetext --stylesheet=style.css"
|
18
|
+
end
|
19
|
+
|
20
|
+
task default: :html_all
|
21
|
+
|
22
|
+
desc 'build html (Usage: rake build re=target.re)'
|
23
|
+
task :html do
|
24
|
+
if ENV['re'].nil?
|
25
|
+
puts 'Usage: rake build re=target.re'
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
build('html', ENV['re'])
|
29
|
+
end
|
30
|
+
|
31
|
+
desc 'build all html'
|
32
|
+
task :html_all do
|
33
|
+
build_all('html')
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'preproc all'
|
37
|
+
task :preproc do
|
38
|
+
Dir.glob('*.re').each do |file|
|
39
|
+
sh "review-preproc --replace #{file}"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc 'generate PDF and EPUB file'
|
44
|
+
task all: %i[pdf epub]
|
45
|
+
|
46
|
+
desc 'generate PDF file'
|
47
|
+
task pdf: BOOK_PDF
|
48
|
+
|
49
|
+
desc 'generate stagic HTML file for web'
|
50
|
+
task web: WEBROOT
|
51
|
+
|
52
|
+
desc 'generate EPUB file'
|
53
|
+
task epub: BOOK_EPUB
|
54
|
+
|
55
|
+
SRC = FileList['*.re'] + [CONFIG_FILE]
|
56
|
+
|
57
|
+
file BOOK_PDF => SRC do
|
58
|
+
FileUtils.rm_rf [BOOK_PDF, BOOK, BOOK + '-pdf']
|
59
|
+
sh "review-pdfmaker #{CONFIG_FILE}"
|
60
|
+
end
|
61
|
+
|
62
|
+
file BOOK_EPUB => SRC do
|
63
|
+
FileUtils.rm_rf [BOOK_EPUB, BOOK, BOOK + '-epub']
|
64
|
+
sh "review-epubmaker #{CONFIG_FILE}"
|
65
|
+
end
|
66
|
+
|
67
|
+
file WEBROOT => SRC do
|
68
|
+
FileUtils.rm_rf [WEBROOT]
|
69
|
+
sh "review-webmaker #{CONFIG_FILE}"
|
70
|
+
end
|
71
|
+
|
72
|
+
CLEAN.include([BOOK, BOOK_PDF, BOOK_EPUB, BOOK + '-pdf', BOOK + '-epub', WEBROOT, 'images/_review_math'])
|
@@ -0,0 +1,326 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
|
4
|
+
WEBSERVER_PORT = 9000
|
5
|
+
|
6
|
+
|
7
|
+
##
|
8
|
+
## 生成したファイルを削除
|
9
|
+
##
|
10
|
+
task :clean do
|
11
|
+
require 'yaml'
|
12
|
+
config = File.open("config.yml", 'r', encoding: 'utf-8') {|f| YAML.load(f) }
|
13
|
+
x = config['bookname'] or abort("ERROR: missing 'bookname' in config.yml")
|
14
|
+
files = [x+".pdf", x+"-pdf", x+".epub", x+"-epub", "webroot"]
|
15
|
+
files = files.select {|x| File.exist?(x) }
|
16
|
+
rm_rf files unless files.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
##
|
22
|
+
## Docker用のタスク。
|
23
|
+
##
|
24
|
+
namespace :docker do
|
25
|
+
|
26
|
+
docker_image = ENV['DOCKER_IMAGE']
|
27
|
+
docker_image = "kauplan/review2.5" if docker_image.to_s.empty?
|
28
|
+
docker_opts = "--rm -v $PWD:/work -w /work"
|
29
|
+
docker_opts += ENV.keys().grep(/^STARTER_/).map {|k| " -e #{k}" }.join()
|
30
|
+
|
31
|
+
desc "+ pull docker image for building PDF file"
|
32
|
+
task :setup do
|
33
|
+
sh "docker pull #{docker_image}"
|
34
|
+
end
|
35
|
+
|
36
|
+
docker_run = proc do |command, opt=nil|
|
37
|
+
sh "docker run #{docker_opts} #{opt} #{docker_image} #{command}"
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "+ run 'rake pdf' on docker"
|
41
|
+
task :pdf do docker_run.call('rake pdf') end
|
42
|
+
|
43
|
+
desc "+ run 'rake pdf:nombre' on docker"
|
44
|
+
task :'pdf:nombre' do docker_run.call('rake pdf:nombre') end
|
45
|
+
|
46
|
+
desc "+ run 'rake epub' on docker"
|
47
|
+
task :epub do docker_run.call('rake epub') end
|
48
|
+
|
49
|
+
desc "+ run 'rake web' on docker"
|
50
|
+
task :web do docker_run.call('rake web') end
|
51
|
+
|
52
|
+
desc "+ run 'rake web:server' on docker"
|
53
|
+
task :'web:server' do
|
54
|
+
port = WEBSERVER_PORT
|
55
|
+
opt = "-it -p #{port}:#{port+1} -e WEBSERVER_PORT=#{port+1}"
|
56
|
+
docker_run.call('rake web:server', opt)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
##
|
63
|
+
## PDFにノンブルを入れるためのRakeタスク。
|
64
|
+
## ノンブルについては「ワンストップ!技術同人誌を書こう」第10章を参照のこと。
|
65
|
+
## https://booth.pm/ja/items/708196
|
66
|
+
##
|
67
|
+
namespace :pdf do
|
68
|
+
|
69
|
+
desc "+ add nombre (rake pdf:nombre [file=*.pdf] [out=*.pdf])"
|
70
|
+
task :nombre do
|
71
|
+
infile = ENV['file']; infile = nil if infile && infile.empty?
|
72
|
+
outfile = ENV['out'] ; outfile = nil if outfile && outfile.empty?
|
73
|
+
#
|
74
|
+
begin
|
75
|
+
require 'combine_pdf'
|
76
|
+
rescue LoadError
|
77
|
+
abort "ERROR: 'combine_pdf' gem not installed; please run `gem install combine_pdf` at first."
|
78
|
+
end
|
79
|
+
#
|
80
|
+
class CombinePDF::PDF
|
81
|
+
def add_nombre(options={})
|
82
|
+
start = options[:start] || 1
|
83
|
+
margin_h = options[:margin_h] || 5
|
84
|
+
margin_w = options[:margin_w] || 2
|
85
|
+
font = options[:font] || :Helvetica
|
86
|
+
size = options[:size] || 6
|
87
|
+
color = options[:color] || [0.5, 0.5, 0.5] # gray
|
88
|
+
binding = options[:binding] || :left
|
89
|
+
digit_w, digit_h = CombinePDF::Fonts.dimensions_of("9", font, size)
|
90
|
+
box_w = digit_w * 1.2
|
91
|
+
box_h = digit_h * 1.3
|
92
|
+
is_left = binding == :left
|
93
|
+
params = {
|
94
|
+
x: nil, y: nil, width: box_w, height: box_h,
|
95
|
+
font: font, font_size: size, font_color: color,
|
96
|
+
}
|
97
|
+
self.pages.each.with_index(start) do |page, page_num|
|
98
|
+
mediabox = page[:CropBox] || page[:MediaBox] or
|
99
|
+
abort "ERROR: failed to get page size of pdf"
|
100
|
+
page_w = mediabox[2]
|
101
|
+
page_h = mediabox[3]
|
102
|
+
top = page_h - margin_h
|
103
|
+
bottom = margin_h
|
104
|
+
left = margin_w
|
105
|
+
right = page_w - margin_w - box_w
|
106
|
+
params[:x] = is_left ? left : right
|
107
|
+
params[:y] = bottom
|
108
|
+
page_num.to_s.reverse.each_char do |c|
|
109
|
+
page.textbox(c, params)
|
110
|
+
params[:y] += box_h
|
111
|
+
end
|
112
|
+
is_left = ! is_left
|
113
|
+
end
|
114
|
+
self
|
115
|
+
end
|
116
|
+
end
|
117
|
+
#
|
118
|
+
if infile.nil?
|
119
|
+
require 'yaml'
|
120
|
+
config = File.open("config.yml", 'r', encoding: 'utf-8') {|f| YAML.load(f) }
|
121
|
+
bookname = config['bookname'] or abort("ERROR: missing 'bookname' in config.yml")
|
122
|
+
infile = bookname + ".pdf"
|
123
|
+
end
|
124
|
+
File.file?(infile) or abort("ERROR: #{infile}: pdf file not found.")
|
125
|
+
if outfile.nil?
|
126
|
+
#outfile = infile.sub(/\.pdf$/, '_nombre.pdf')
|
127
|
+
outfile = infile
|
128
|
+
end
|
129
|
+
#
|
130
|
+
#pdf = CombinePDF.parse(File.binread(infile))
|
131
|
+
#pdf.add_nombre()
|
132
|
+
#File.binwrite(outfile, pdf.to_pdf())
|
133
|
+
pdf = CombinePDF.load(infile)
|
134
|
+
pdf.add_nombre()
|
135
|
+
pdf.save(outfile)
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
##
|
142
|
+
## プレビュー用のサーバを起動する
|
143
|
+
##
|
144
|
+
namespace :web do
|
145
|
+
|
146
|
+
invoke_web_task = proc do
|
147
|
+
#sh "rake web"
|
148
|
+
Process.fork { Rake::Task['web'].invoke() }
|
149
|
+
Process.wait()
|
150
|
+
end
|
151
|
+
|
152
|
+
helper_message_when_start_server = <<END
|
153
|
+
*
|
154
|
+
* Please open http://localhost:#{WEBSERVER_PORT}/ in browser.
|
155
|
+
*
|
156
|
+
END
|
157
|
+
|
158
|
+
helper_message_when_address_already_in_use = <<END
|
159
|
+
**
|
160
|
+
** ERROR: Failed to start web server.
|
161
|
+
**
|
162
|
+
** Other webserver process seems running. Kill it and restart webserver.
|
163
|
+
**
|
164
|
+
** How to:
|
165
|
+
** $ ps | head -1; ps | grep web[:]server
|
166
|
+
** PID TTY TIME CMD
|
167
|
+
** 12345 ttys002 0.00.35 /usr/bin/ruby /usr/bin/rake web:server
|
168
|
+
** $ kill -KILL 12345
|
169
|
+
** $ rake web:server
|
170
|
+
**
|
171
|
+
END
|
172
|
+
|
173
|
+
favicon_base64 = <<END
|
174
|
+
AAABAAEAEBACAAEAAQCwAAAAFgAAACgAAAAQAAAAIAAAAAEAAQAAAAAAgAAA
|
175
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
176
|
+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
|
177
|
+
/wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//
|
178
|
+
AAD//wAA//8AAP//AAD//wAA
|
179
|
+
END
|
180
|
+
|
181
|
+
desc "+ start web server for preview"
|
182
|
+
task :server do
|
183
|
+
rebuild_js = (ENV['STARTER_REBUILD_JS'] ||= '/rebuild.js')
|
184
|
+
invoke_web_task.call()
|
185
|
+
#
|
186
|
+
require 'yaml'
|
187
|
+
config = File.open('config.yml') {|f| YAML.load(f) }
|
188
|
+
contdir = config['contentdir']
|
189
|
+
#
|
190
|
+
require 'webrick'
|
191
|
+
root = 'webroot/'
|
192
|
+
host = '0.0.0.0' # don't use '127.0.0.1' to work on Docker
|
193
|
+
port = ENV['WEBSERVER_PORT'] ? ENV['WEBSERVER_PORT'].to_i : WEBSERVER_PORT
|
194
|
+
onstart = proc { puts helper_message_when_start_server }
|
195
|
+
srvconf = {DocumentRoot: root, BindAddress: host, Port: port, StartCallback: onstart}
|
196
|
+
begin
|
197
|
+
srv = WEBrick::HTTPServer.new(srvconf)
|
198
|
+
rescue Errno::EADDRINUSE => ex
|
199
|
+
at_exit { $stderr.puts helper_message_when_address_already_in_use }
|
200
|
+
raise
|
201
|
+
end
|
202
|
+
#
|
203
|
+
srv.mount_proc('/favicon.ico') do |req, res|
|
204
|
+
res.content_type = "image/x-icon"
|
205
|
+
res['Cache-Control'] = "public, max-age=#{60*60*24}"
|
206
|
+
res.body = favicon_base64.unpack("m")[0]
|
207
|
+
end
|
208
|
+
#
|
209
|
+
flag_quit = false
|
210
|
+
interval = 0.8 # seconds
|
211
|
+
srv.mount_proc(rebuild_js) do |req, res|
|
212
|
+
file = nil
|
213
|
+
if req.query_string =~ /\Afile=([^&]*)/
|
214
|
+
file = $1.strip
|
215
|
+
file = nil if file.empty?
|
216
|
+
end
|
217
|
+
#
|
218
|
+
errmsg = nil
|
219
|
+
if file.nil?
|
220
|
+
# pass
|
221
|
+
elsif file !~ /\A[-\w]+\.re\z/
|
222
|
+
errmsg = "invalid file"
|
223
|
+
else
|
224
|
+
file = File.join(contdir, file) if contdir
|
225
|
+
errmsg = "file not found." if ! File.exist?(file)
|
226
|
+
end
|
227
|
+
#
|
228
|
+
if errmsg
|
229
|
+
body = "alert('ERROR: #{errmsg}');"
|
230
|
+
else
|
231
|
+
body = "window.location.reload();"
|
232
|
+
## sleep until '*.re' file modified
|
233
|
+
if file
|
234
|
+
mtime = File.mtime(file)
|
235
|
+
sleep interval while !flag_quit && mtime == File.mtime(file)
|
236
|
+
end
|
237
|
+
## generate html file from '*.re'
|
238
|
+
invoke_web_task.call() unless flag_quit
|
239
|
+
end
|
240
|
+
res.content_type = "application/javascript"
|
241
|
+
msg = "Server seems down. Press OK to reload."
|
242
|
+
res.body = !flag_quit ? body : "alert('#{msg}');window.location.reload();"
|
243
|
+
end
|
244
|
+
#
|
245
|
+
trap(:INT) { flag_quit = true; srv.shutdown() }
|
246
|
+
srv.start()
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
##
|
253
|
+
## 高解像度用の画像から低解像度の画像を生成するRakeタスク。
|
254
|
+
## 詳細は「ワンストップ!技術同人誌を書こう」第8章を参照のこと。
|
255
|
+
## https://booth.pm/ja/items/708196
|
256
|
+
##
|
257
|
+
desc "+ convert images (high resolution -> low resolution)"
|
258
|
+
task :images do
|
259
|
+
## macOSならsipsコマンドを使い、それ以外ではImageMagickを使う
|
260
|
+
has_sips = File.exist?("/usr/bin/sips")
|
261
|
+
if ! has_sips
|
262
|
+
ok = system("convert --version >/dev/null")
|
263
|
+
if ! ok
|
264
|
+
abort "ERROR: 'convert' command not found; please install ImageMagick."
|
265
|
+
end
|
266
|
+
end
|
267
|
+
## 高解像度の画像をもとに低解像度の画像を作成する
|
268
|
+
for src in Dir.glob("images_highres/**/*.{png,jpg,jpeg}")
|
269
|
+
## 低解像度の画像を作成済みなら残りの処理をスキップ
|
270
|
+
dest = src.sub("images_highres/", "images_lowres/")
|
271
|
+
next if File.exist?(dest) && File.mtime(src) == File.mtime(dest)
|
272
|
+
## 必要ならフォルダを作成
|
273
|
+
dir = File.dirname(dest)
|
274
|
+
mkdir_p dir if ! File.directory?(dir)
|
275
|
+
## 高解像度の画像のDPIを変更(72dpi→360dpi)
|
276
|
+
if has_sips
|
277
|
+
sh "sips -s dpiHeight 360 -s dpiWidth 360 #{src}"
|
278
|
+
else
|
279
|
+
sh "convert -density 360 -units PixelsPerInch #{src} #{src}"
|
280
|
+
end
|
281
|
+
## 低解像度の画像を作成(72dpi、横幅1/5)
|
282
|
+
if has_sips
|
283
|
+
`sips -g pixelWidth #{src}` =~ /pixelWidth: (\d+)/
|
284
|
+
option = "-s dpiHeight 72 -s dpiWidth 72 --resampleWidth #{$1.to_i / 5}"
|
285
|
+
sh "sips #{option} --out #{dest} #{src}"
|
286
|
+
else
|
287
|
+
sh "convert -density 72 -units PixelsPerInch -resize 20% #{src} #{dest}"
|
288
|
+
end
|
289
|
+
## 低解像度の画像のタイムスタンプを、高解像度の画像と同じにする
|
290
|
+
## (=画像のタイムスタンプが違ったら、画像が更新されたと見なす)
|
291
|
+
File.utime(File.atime(dest), File.mtime(src), dest)
|
292
|
+
end
|
293
|
+
## 高解像度の画像が消されたら、低解像度の画像も消す
|
294
|
+
for dest in Dir.glob("images_lowres/**/*").sort().reverse()
|
295
|
+
src = dest.sub("images_lowres/", "images_highres/")
|
296
|
+
rm_r dest if ! File.exist?(src)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
##
|
302
|
+
## 低解像度と高解像度を切り替えるRakeタスク。
|
303
|
+
## 詳細は「ワンストップ!技術同人誌を書こう」第8章を参照のこと。
|
304
|
+
## https://booth.pm/ja/items/708196
|
305
|
+
##
|
306
|
+
namespace "images" do
|
307
|
+
|
308
|
+
desc "+ toggle image directories ('images_{lowres,highres}')"
|
309
|
+
task :toggle do
|
310
|
+
if ! File.symlink?("images")
|
311
|
+
msg = "ERROR: 'images' directory should be a symbolic link.\n"
|
312
|
+
msg << " rename it and create symbolic link, for example:\n"
|
313
|
+
msg << " $ mv images images_highres\n"
|
314
|
+
msg << " $ ln -s images_highres images\n"
|
315
|
+
abort msg
|
316
|
+
end
|
317
|
+
link = File.readlink("images")
|
318
|
+
rm "images"
|
319
|
+
if link == "images_lowres"
|
320
|
+
ln_s "images_highres", "images"
|
321
|
+
else
|
322
|
+
ln_s "images_lowres", "images"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
end
|