review-retrovert 0.3.1 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/retrovert.yml +61 -0
- data/.gitignore +2 -2
- data/.ruby-version +1 -0
- data/Dockerfile +1 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +82 -17
- data/README.md +6 -3
- data/lib/review/retrovert/cli.rb +4 -0
- data/lib/review/retrovert/converter.rb +375 -9
- data/lib/review/retrovert/version.rb +1 -1
- data/lib/review/retrovert/yamlconfig.rb +13 -1
- data/review-retrovert.gemspec +2 -2
- 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 -10
- data/.travis.yml +0 -6
@@ -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
|