review-retrovert 0.9.6 → 0.9.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.dockerignore +9 -0
  3. data/.editorconfig +3 -0
  4. data/.github/workflows/retrovert.yml +20 -5
  5. data/.gitignore +1 -0
  6. data/.vscode/launch.json +48 -0
  7. data/Gemfile.lock +13 -4
  8. data/Makefile +24 -0
  9. data/README.md +8 -1
  10. data/docker/review.Dockerfile +10 -0
  11. data/lib/review/retrovert/converter.rb +470 -114
  12. data/lib/review/retrovert/ext/review-ext.rb +71 -0
  13. data/lib/review/retrovert/reviewcompat.rb +57 -0
  14. data/lib/review/retrovert/reviewdef.rb +70 -0
  15. data/lib/review/retrovert/sty/ird.sty.erb +326 -0
  16. data/lib/review/retrovert/sty/review-retrovert-custom.sty.erb +6 -0
  17. data/lib/review/retrovert/utils.rb +35 -0
  18. data/lib/review/retrovert/version.rb +1 -1
  19. data/lib/review/retrovert/yamlconfig.rb +0 -1
  20. data/package-lock.json +6 -0
  21. data/package.json +1 -0
  22. data/review-retrovert.gemspec +5 -1
  23. data/testdata/mybook/.gitignore +3 -1
  24. data/testdata/mybook/.textlintrc +11 -0
  25. data/testdata/mybook/Rakefile +8 -0
  26. data/testdata/mybook/catalog.yml +36 -10
  27. data/testdata/mybook/config-noretrovert.yml +404 -0
  28. data/testdata/mybook/config-retrovert.yml +9 -0
  29. data/testdata/mybook/config-starter.yml +134 -9
  30. data/testdata/mybook/config.yml +44 -15
  31. data/testdata/mybook/contents/00-preface.re +48 -2
  32. data/testdata/mybook/contents/01-install.re +38 -5
  33. data/testdata/mybook/contents/02-tutorial.re +333 -113
  34. data/testdata/mybook/contents/03-syntax.re +2370 -373
  35. data/testdata/mybook/contents/04-customize.re +424 -88
  36. data/testdata/mybook/contents/05-faq.re +288 -10
  37. data/testdata/mybook/contents/06-bestpractice.re +431 -59
  38. data/testdata/mybook/contents/91-compare.re +402 -2
  39. data/testdata/mybook/contents/92-filelist.re +14 -8
  40. data/testdata/mybook/contents/93-background.re +10 -10
  41. data/testdata/mybook/contents/99-postface.re +2 -1
  42. data/testdata/mybook/contents/r0-root.re +24 -2
  43. data/testdata/mybook/contents/table.csv +4 -0
  44. data/testdata/mybook/contents/test.txt +1 -0
  45. data/testdata/mybook/css/webstyle.css +180 -2
  46. data/testdata/mybook/data/terms.txt +3 -0
  47. data/testdata/mybook/data/words.txt +15 -0
  48. data/testdata/mybook/images/03-syntax/index-page.png +0 -0
  49. data/testdata/mybook/images/03-syntax/order-detail.png +0 -0
  50. data/testdata/mybook/images/04-customize/section_decoration_samples.png +0 -0
  51. data/testdata/mybook/images/05-faq/dummy-image.png +0 -0
  52. data/testdata/mybook/images/06-bestpractice/section_title_wlines.png +0 -0
  53. data/testdata/mybook/images/avatar-b.png +0 -0
  54. data/testdata/mybook/images/avatar-g.png +0 -0
  55. data/testdata/mybook/images/avatar-r.png +0 -0
  56. data/testdata/mybook/images/caution-icon.png +0 -0
  57. data/testdata/mybook/images/info-icon.png +0 -0
  58. data/testdata/mybook/images/warning-icon.png +0 -0
  59. data/testdata/mybook/layouts/layout.html5.erb +3 -1
  60. data/testdata/mybook/layouts/layout.tex.erb +265 -379
  61. data/testdata/mybook/layouts/layout.tex.erb.orig +386 -0
  62. data/testdata/mybook/lib/ruby/review-book.rb +64 -0
  63. data/testdata/mybook/lib/ruby/review-builder.rb +902 -63
  64. data/testdata/mybook/lib/ruby/review-compiler.rb +675 -22
  65. data/testdata/mybook/lib/ruby/review-epubbuilder.rb +33 -0
  66. data/testdata/mybook/lib/ruby/review-epubmaker.rb +10 -7
  67. data/testdata/mybook/lib/ruby/review-htmlbuilder.rb +354 -66
  68. data/testdata/mybook/lib/ruby/review-latexbuilder.rb +429 -146
  69. data/testdata/mybook/lib/ruby/review-maker.rb +117 -6
  70. data/testdata/mybook/lib/ruby/review-markdownbuilder.rb +945 -0
  71. data/testdata/mybook/lib/ruby/review-markdownmaker.rb +91 -0
  72. data/testdata/mybook/lib/ruby/review-monkeypatch.rb +2 -0
  73. data/testdata/mybook/lib/ruby/review-pdfmaker.rb +160 -82
  74. data/testdata/mybook/lib/ruby/review-webmaker.rb +20 -5
  75. data/testdata/mybook/lib/tasks/review.rake +14 -0
  76. data/testdata/mybook/lib/tasks/starter.rake +148 -4
  77. data/testdata/mybook/sty/indexstyle.ist +25 -0
  78. data/testdata/mybook/sty/mytextsize.sty +29 -0
  79. data/testdata/mybook/sty/mytitlepage.sty +34 -11
  80. data/testdata/mybook/sty/review-base.sty +276 -0
  81. data/testdata/mybook/sty/starter-codeblock.sty +237 -106
  82. data/testdata/mybook/sty/starter-color.sty +72 -17
  83. data/testdata/mybook/sty/starter-heading.sty +60 -13
  84. data/testdata/mybook/sty/starter-misc.sty +894 -0
  85. data/testdata/mybook/sty/starter-note.sty +67 -14
  86. data/testdata/mybook/sty/starter-talklist.sty +105 -0
  87. data/testdata/mybook/sty/starter-util.sty +35 -0
  88. data/testdata/mybook/sty/starter.sty +8 -526
  89. metadata +84 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02507e93743d82045d68c54d9aa2acec9666def48b1187b7577e1e70ade8a4f5
4
- data.tar.gz: f2121fe5b228534e7f1ada87cbce40d35674cc7f1b92f2de14d04e500ef5b640
3
+ metadata.gz: e21f93fe0df30502c299d24fe3a761d631b1e9cd596df35234dcf756cdb3538e
4
+ data.tar.gz: 594ea8b9d78c9da30c8e4915b98665f3c74b61bca108ed29db983616a57153c3
5
5
  SHA512:
6
- metadata.gz: edcf427bdad063863a08aff465863a8a6f6f0fc626b8491aab77df8902b46439239298fe21e220b2a7e8e712f93367267ae3a7a7a3a67eb89780a56f3e72ab03
7
- data.tar.gz: 66b55029a3127ad59626c8852c883a9c1d264be675686d4562d56ec9e58ee41458aa89e9a6a49e9a506684902256f18924b68f0a68bafa7fd53de37af1088f13
6
+ metadata.gz: 2dd96eb3d003ede0d79444972f09e6d19bd5ecd6e5c84aa2a124bee99eedba47a636b7c6b29d4d215d5a9d7a46fb2918db3a7bc765260df42b282c5d782080a3
7
+ data.tar.gz: c40f1bd244de3e41b863a1a4070874fd9e33b02e2c70e62d580cf734282023a35dfdca7401a8aaf1f1ca8a7f06146cca36e70e52b0a59a5d2a9de4ce94b13b56
data/.dockerignore ADDED
@@ -0,0 +1,9 @@
1
+ .bundle
2
+ .idea
3
+ .vscode
4
+ pkg
5
+ bin
6
+ tmp
7
+ .rake*
8
+ .rspec_status
9
+ Gemfile.lock
data/.editorconfig CHANGED
@@ -11,3 +11,6 @@ indent_size = 2
11
11
 
12
12
  [*.yml]
13
13
  indent_size = 2
14
+
15
+ [Makefile]
16
+ indent_style = tab
@@ -10,7 +10,17 @@ jobs:
10
10
  runs-on: ubuntu-latest
11
11
  strategy:
12
12
  matrix:
13
- review-version: [ "3.2", "4.2", "5.0" ]
13
+ review-version:
14
+ - "3.0"
15
+ - "3.1"
16
+ - "3.2"
17
+ - "4.0"
18
+ - "4.1"
19
+ - "4.2"
20
+ - "5.0"
21
+ - "5.1"
22
+ - "5.2"
23
+ - "latest"
14
24
  fail-fast: false
15
25
  steps:
16
26
  - uses: actions/checkout@v2
@@ -23,13 +33,17 @@ jobs:
23
33
  echo 'gem "review", "${{ matrix.review-version }}"' >> Gemfile-${{ matrix.review-version }}
24
34
  cat Gemfile-${{ matrix.review-version }}
25
35
  echo "BUNDLE_GEMFILE=Gemfile-${{ matrix.review-version }}" >> $GITHUB_ENV
36
+ if: ${{ matrix.review-version != 'latest' }}
26
37
  - run: bundle install --gemfile=Gemfile-${{ matrix.review-version }}
38
+ if: ${{ matrix.review-version != 'latest' }}
39
+ - run: bundle install
40
+ if: ${{ matrix.review-version == 'latest' }}
27
41
  # spec
28
42
  - name: spec
29
43
  run: bundle exec rake spec
30
44
  # convert
31
45
  - name: convert
32
- run: bundle exec review-retrovert convert testdata/mybook/config.yml tmp -f
46
+ run: bundle exec review-retrovert convert testdata/mybook/config.yml tmp-${{ matrix.review-version }} -f
33
47
  # build
34
48
  # - name: review build
35
49
  # uses: ${{ matrix.uses }}
@@ -44,16 +58,17 @@ jobs:
44
58
  password: ${{ secrets.DOCKERHUB_TOKEN }}
45
59
  - name: build html
46
60
  run: |
47
- docker run --rm -v "$(pwd)/tmp":/work -w /work vvakame/review:${{ matrix.review-version }} rake preproc html
61
+ docker run --rm -v "$(pwd)/tmp-${{ matrix.review-version }}":/work -w /work vvakame/review:${{ matrix.review-version }} rake preproc html
48
62
  - name: build pdf
49
63
  run: |
50
- docker run --rm -v "$(pwd)/tmp":/work -w /work vvakame/review:${{ matrix.review-version }} rake preproc pdf
64
+ docker run --rm -v "$(pwd)/tmp-${{ matrix.review-version }}":/work -w /work vvakame/review:${{ matrix.review-version }} rake preproc pdf
65
+ cp tmp-${{ matrix.review-version }}/mybook.pdf mybook-${{ matrix.review-version }}.pdf
51
66
  # artifacts
52
67
  - name: artifacts
53
68
  uses: actions/upload-artifact@v1
54
69
  with:
55
70
  name: mybook
56
- path: tmp/mybook.pdf
71
+ path: mybook-${{ matrix.review-version }}.pdf
57
72
  # - name: artifacts
58
73
  # uses: actions/upload-artifact@v1
59
74
  # with:
data/.gitignore CHANGED
@@ -13,3 +13,4 @@ tmp/
13
13
  .idea
14
14
 
15
15
  *.gem
16
+ mybook.pdf
@@ -0,0 +1,48 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Debug review-retrovert",
9
+ "type": "Ruby",
10
+ "request": "launch",
11
+ "env": {
12
+ "RUBYLIB":"lib"
13
+ },
14
+ "cwd": "${workspaceRoot}",
15
+ "program": "${workspaceRoot}/exe/review-retrovert",
16
+ "args": [
17
+ "convert",
18
+ "--preproc",
19
+ "--tabwidth", "4",
20
+ "--ird",
21
+ "testdata/mybook/config.yml",
22
+ "-f",
23
+ "tmp/debug"
24
+ ]
25
+ },
26
+ {
27
+ "name": "RSpec - active spec file only",
28
+ "type": "Ruby",
29
+ "request": "launch",
30
+ "program": "${workspaceRoot}/bin/rspec",
31
+ "args": [
32
+ "-I",
33
+ "${workspaceRoot}",
34
+ "${file}"
35
+ ]
36
+ },
37
+ {
38
+ "name": "RSpec - all",
39
+ "type": "Ruby",
40
+ "request": "launch",
41
+ "program": "${workspaceRoot}/bin/rspec",
42
+ "args": [
43
+ "-I",
44
+ "${workspaceRoot}"
45
+ ]
46
+ },
47
+ ]
48
+ }
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- review-retrovert (0.9.6)
4
+ review-retrovert (0.9.10)
5
5
  review (>= 3.0.0)
6
6
  thor
7
7
 
@@ -59,20 +59,23 @@ GEM
59
59
  ffi (1.14.2)
60
60
  i18n (1.8.7)
61
61
  concurrent-ruby (~> 1.0)
62
- image_size (2.1.0)
62
+ image_size (2.1.1)
63
63
  middleware (0.1.0)
64
64
  minitest (5.14.3)
65
65
  multi_test (0.1.2)
66
+ pastel (0.8.0)
67
+ tty-color (~> 0.5)
66
68
  protobuf-cucumber (3.10.8)
67
69
  activesupport (>= 3.2)
68
70
  middleware
69
71
  thor
70
72
  thread_safe
71
73
  rake (12.3.3)
72
- review (5.0.0)
74
+ review (5.2.0)
73
75
  image_size
74
76
  rouge
75
77
  rubyzip
78
+ tty-logger
76
79
  rouge (3.26.0)
77
80
  rspec (3.10.0)
78
81
  rspec-core (~> 3.10.0)
@@ -87,11 +90,16 @@ GEM
87
90
  diff-lcs (>= 1.2.0, < 2.0)
88
91
  rspec-support (~> 3.10.0)
89
92
  rspec-support (3.10.1)
90
- rubyzip (2.3.0)
93
+ ruby-debug-ide (0.7.2)
94
+ rake (>= 0.8.1)
95
+ rubyzip (2.3.2)
91
96
  sys-uname (1.2.2)
92
97
  ffi (~> 1.1)
93
98
  thor (1.0.1)
94
99
  thread_safe (0.3.6)
100
+ tty-color (0.6.0)
101
+ tty-logger (0.6.0)
102
+ pastel (~> 0.8)
95
103
  tzinfo (2.0.4)
96
104
  concurrent-ruby (~> 1.0)
97
105
  zeitwerk (2.4.2)
@@ -104,6 +112,7 @@ DEPENDENCIES
104
112
  rake (~> 12.0)
105
113
  review-retrovert!
106
114
  rspec (~> 3.0)
115
+ ruby-debug-ide
107
116
 
108
117
  BUNDLED WITH
109
118
  2.1.4
data/Makefile ADDED
@@ -0,0 +1,24 @@
1
+ help: ## show help
2
+ @grep -E '^[a-zA-Z][a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sed -e 's/^GNUmakefile://' | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
3
+
4
+ init:
5
+ bundle install --binstubs
6
+
7
+ review3:
8
+ docker build . -t review-3-retrovert -f docker/review.Dockerfile --build-arg REVIEW_VERSION=3.2
9
+ docker run -it --rm -w /work review-3-retrovert bash
10
+
11
+ test:
12
+ RUBYLIB=lib ./exe/review-retrovert convert --preproc --tabwidth 4 testdata/mybook/config.yml -f tmp/debug
13
+
14
+ test-ird:
15
+ RUBYLIB=lib ./exe/review-retrovert convert --preproc --tabwidth 4 --ird testdata/mybook/config.yml -f tmp/debug
16
+
17
+ REVIEW_VERSION:=latest
18
+
19
+ debug-build:
20
+ docker run --rm -v "${PWD}/tmp/debug":/work -w /work vvakame/review:${REVIEW_VERSION} rake preproc pdf
21
+ # docker run --rm -v "${PWD}":/work -w /work vvakame/review rake preproc pdf
22
+
23
+ testdata-pdf:
24
+ docker run --rm -v ${PWD}/testdata/mybook:/work -w /work kauplan/review2.5 rake pdf
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/review-retrovert.svg)](https://badge.fury.io/rb/review-retrovert)
2
- [![Build Status](https://travis-ci.com/srz-zumix/review-retrovert.svg?token=ArNHjRjvfZfyqQUCbXSt&branch=master)](https://travis-ci.com/srz-zumix/review-retrovert)
2
+ [![Retrovert](https://github.com/srz-zumix/review-retrovert/actions/workflows/retrovert.yml/badge.svg?branch=master)](https://github.com/srz-zumix/review-retrovert/actions/workflows/retrovert.yml)
3
3
  [![Docker Cloud Build Status](https://img.shields.io/docker/cloud/build/srzzumix/review-retrovert.svg)](https://hub.docker.com/r/srzzumix/review-retrovert/)
4
4
 
5
5
  # ReVIEW::Retrovert
@@ -93,6 +93,13 @@ inherit: ["config-base.yml", "config-starter.yml", "config-retrovert.yml"]
93
93
  #chapterlink: true
94
94
  ```
95
95
 
96
+ ## Experimental
97
+
98
+ ### IRD sty
99
+
100
+ --ird オプションを付けると IRD 組版に近いレイアウトにするために ird.sty と reveiw-ext.rb をプロジェクトに追加します。
101
+ こちらは実験的機能です。
102
+
96
103
  ## Development
97
104
 
98
105
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,10 @@
1
+ ARG REVIEW_VERSION=lastest
2
+ FROM vvakame/review:$REVIEW_VERSION
3
+ ARG REVIEW_VERSION
4
+
5
+ WORKDIR /work
6
+ COPY . .
7
+ ENV BUNDLE_GEMFILE=Gemfile-$REVIEW_VERSION
8
+ RUN cp Gemfile Gemfile-$REVIEW_VERSION && \
9
+ echo "gem \"review\", \"$REVIEW_VERSION\"" >> Gemfile-$REVIEW_VERSION && \
10
+ bundle install
@@ -1,7 +1,11 @@
1
- require "review"
1
+ require 'review'
2
+ require 'erb'
2
3
  require 'fileutils'
3
4
  require 'tmpdir'
4
- require "review/retrovert/yamlconfig"
5
+ require 'review/retrovert/yamlconfig'
6
+ require 'review/retrovert/reviewcompat'
7
+ require 'review/retrovert/reviewdef'
8
+ require 'review/retrovert/utils'
5
9
 
6
10
  module ReVIEW
7
11
  module Retrovert
@@ -16,7 +20,13 @@ module ReVIEW
16
20
  @configs = YamlConfig.new
17
21
  @embeded_contents = []
18
22
  @catalog_contents = []
23
+ @talk_shortcuts = {}
19
24
  @ird = false
25
+ @talklist_replace_cmd = "note"
26
+ @desclist_replace_cmd = "info"
27
+ @talk_icon_scale = 0.1
28
+
29
+ @r_option_inner = ReViewDef::r_option_inner
20
30
  end
21
31
 
22
32
  def error(msg)
@@ -96,30 +106,87 @@ module ReVIEW
96
106
  @configs.rewrite_yml('imagedir', outimagedir)
97
107
  end
98
108
 
109
+ def copy_wards(outdir, words_file)
110
+ new_file = words_file
111
+ FileUtils.mkdir_p(File.join(outdir, File.dirname(words_file)))
112
+ if File.extname(words_file) == ".csv"
113
+ FileUtils.copy(File.join(@basedir, words_file), File.join(outdir, new_file))
114
+ else
115
+ new_file += ".csv"
116
+ Utils.Tsv2Csv(File.join(@basedir, words_file), File.join(outdir, new_file))
117
+ end
118
+ new_file
119
+ end
120
+
99
121
  def update_config(outdir)
100
122
  @configs.rewrite_yml('contentdir', '.')
101
123
  @configs.rewrite_yml('hook_beforetexcompile', 'null')
102
124
  @configs.rewrite_yml('texstyle', '["reviewmacro"]')
103
125
  pagesize = @config['starter']['pagesize'].downcase
104
- @configs.rewrite_yml_array('texdocumentclass', "[\"review-jsbook\", \"media=print,paper=#{pagesize}\"]")
105
- @config['retrovert'].each{ |k,v|
106
- unless v..is_a?(Hash)
107
- @configs.commentout_root_yml(k)
126
+ jsbook_config = "media=print,paper=#{pagesize}"
127
+
128
+ # words
129
+ words_files = @config['words_file']
130
+ if words_files
131
+ if words_files.is_a?(Array)
132
+ new_words_files = []
133
+ words_files.each do |words_file|
134
+ new_words_files.push copy_wards(outdir, words_file)
135
+ end
136
+ @configs.rewrite_yml('words_file', "[#{new_words_files.join(',')}]")
137
+ else
138
+ new_words_file = copy_wards(outdir, words_files)
139
+ @configs.rewrite_yml('words_file', new_words_file)
108
140
  end
109
- }
141
+ end
142
+
143
+ # makeindex_dic
144
+ makeindex_dic = @config['pdfmaker']['makeindex_dic']
145
+ if makeindex_dic
146
+ FileUtils.copy(File.join(@basedir, makeindex_dic), File.join(outdir, makeindex_dic))
147
+ end
148
+
149
+ if @ird
150
+ # # リュウミン Pr6N R-KL 12.5Q 22H (9pt = 12.7Q 15.5pt = 21.8Q(H))
151
+ # texdocumentclass: ["review-jsbook", "media=ebook,openany,paper=b5,fontsize=9pt,baselineskip=15.5pt,head_space=15mm,gutter=22mm,footskip=16mm,line_length=45zw,number_of_lines=38"]
152
+ jsbook_config = "media=ebook,openany,paper=b5,fontsize=9pt,baselineskip=15.5pt,head_space=15mm,gutter=22mm,footskip=16mm,line_length=45zw,number_of_lines=38"
153
+ end
154
+ @configs.rewrite_yml_array('texdocumentclass', "[\"review-jsbook\", \"#{jsbook_config}\"]")
155
+ if @config.key?('retrovert')
156
+ @config['retrovert'].each{ |k,v|
157
+ unless v..is_a?(Hash)
158
+ @configs.commentout_root_yml(k)
159
+ end
160
+ }
161
+ end
110
162
  if @ird
111
163
  @configs.rewrite_yml('chapterlink', 'null')
112
164
  end
113
165
  end
114
166
 
115
- def replace_compatible_block_command_outline(content, command, new_command, option_count)
116
- if option_count > 0
117
- content.gsub!(/^\/\/#{command}(?<option>(\[[^\r\n]*?\]){0,#{option_count}})(\[[^\r\n]*\])*{(?<inner>.*?)\/\/}/m, "//#{new_command}\\k<option>{\\k<inner>//}")
118
- else
119
- content.gsub!(/^\/\/#{command}(\[[^\r\n]*\])*{(?<inner>.*?)\/\/}/m, "//#{new_command}{\\k<inner>//}")
167
+ def replace_compatible_block_command_outline(content, command, new_command, option_count, begin_option_pos=0)
168
+ content.gsub!(/^\/\/#{command}(\[[^\r\n]*?\]){0,#{begin_option_pos}}(?<option>(\[[^\r\n]*?\]){0,#{option_count}})(\[[^\r\n]*\])*{(?<inner>.*?)\/\/}/m, "//#{new_command}\\k<option>{\\k<inner>//}")
169
+ content.gsub!(/^\/\/#{command}(\[[^\r\n]*?\]){0,#{begin_option_pos}}(?<option>(\[[^\r\n]*?\]){0,#{option_count}})(\[[^\r\n]*\])*$/, "//#{new_command}\\k<option>")
170
+ # if begin_option_pos > 0
171
+ # content.gsub!(/^\/\/#{command}(\[[^\r\n]*?\]){0,#{begin_option_pos}}{(?<inner>.*?)\/\/}/m, "//#{new_command}{\\k<inner>//}")
172
+ # content.gsub!(/^\/\/#{command}(\[[^\r\n]*?\]){0,#{begin_option_pos}}$/, "//#{new_command}")
173
+ # end
174
+ end
175
+
176
+ def exclude_exta_option(content, cmd, max_option_num)
177
+ replace_compatible_block_command_outline(content, cmd, cmd, max_option_num)
178
+ end
179
+
180
+ def exclude_exta_options(content, commands, max_option_num)
181
+ commands.each do |cmd|
182
+ exclude_exta_option(content, cmd, max_option_num)
120
183
  end
121
184
  end
122
185
 
186
+ def starter_caption_to_text(content, command, n)
187
+ content.gsub!(/^\/\/#{command}(?<option>(\[[^\r\n]*?\]){0,#{n-1}})\[(?<caption>#{@r_option_inner})\](?<post>.*)$/, "\\k<caption>\n//#{command}\\k<option>\\k<post>")
188
+ end
189
+
123
190
  def replace_compatible_block_command_to_outside(content, command, new_command, option_count, add_options="", new_body="")
124
191
  body = new_body
125
192
  body += '\n' unless body.empty?
@@ -143,37 +210,30 @@ module ReVIEW
143
210
  content.gsub!(/^\/\/#{command}(\[.*?\])*\s*\R/, '')
144
211
  end
145
212
 
146
- def delete_inline_command(content, command)
147
- # FIXME: 入れ子のフェンス記法({}|$)
148
- content.gsub!(/@<#{command}>(?:(\$)|(?:({)|(\|)))((?:.*@<\w*>[\|${].*?[\|$}].*?|.*?)*)(?(1)(\$)|(?(2)(})|(\|)))/){"#{$4}"}
149
- end
150
-
151
- def replace_inline_command(content, command, new_command)
152
- content.gsub!(/@<#{command}>/, "@<#{new_command}>")
153
- end
154
-
155
213
  def replace_block_command_nested_boxed_article_i(content, box, depth)
156
214
  found = false
157
215
  content.dup.scan(/(^\/\/#{box})(\[[^\r\n]*?\])*(?:(\$)|(?:({)|(\|)))(.*?)(^\/\/)(?(3)(\$)|(?(4)(})|(\|)).*?[\r\n]+)/m) { |m|
158
216
  matched = m[0..-1].join
159
217
  inner = m[5]
160
218
  # info depth
161
- im = inner.match(/^\/\/(\w+)((\[.*?\])*)([$|{])/)
219
+ im = inner.match(/^\/\/(?<command>\w+)(?<options>(\[#{@r_option_inner}\])*)(?<open>[$|{])/)
162
220
  unless im.nil?
163
- inner_cmd = im[1]
164
- inner_open = im[4]
165
- inner_opts = im[2]
166
- first_opt_m = inner_opts.match(/^\[(.*?)\]/)
167
- first_opt = ""
221
+ inner_cmd = im['command']
222
+ inner_open = im['open']
223
+ inner_opts = im['options']
224
+ id_opt = ""
168
225
 
169
226
  # is_commentout = false
170
227
  is_commentout = true
171
- if first_opt_m
172
- first_opt_v = first_opt_m[1]
173
- unless first_opt_v.empty?
174
- if inner.match(/@<.*?>[$|{]#{first_opt}/)
175
- is_commentout = false
176
- first_opt = "\\[#{first_opt_v}\\]"
228
+ if ReViewDef::is_has_id_block_command(inner_cmd)
229
+ first_opt_m = inner_opts.match(/^\[(.*?)\]/)
230
+ if first_opt_m
231
+ first_opt_v = first_opt_m[1]
232
+ unless first_opt_v.empty?
233
+ if inner.match(/@<#{ReViewDef::id_ref_inline_commands().join('|')}>[$|{]#{first_opt_v}/)
234
+ is_commentout = false
235
+ id_opt = "\\[#{first_opt_v}\\]"
236
+ end
177
237
  end
178
238
  end
179
239
  end
@@ -183,24 +243,44 @@ module ReVIEW
183
243
  if inner_open == m[2..4].join
184
244
  # if same fence then cmd_end == inner_end
185
245
  if is_commentout
186
- inner.gsub!(/(^\/\/(\w+(\[.*?\]|))*#{inner_open})/, '#@#\1')
187
- content.gsub!(/#{Regexp.escape(matched)}/m, "#{cmd_begin}#{inner}#@##{cmd_end}")
246
+ inner.gsub!(/(^\/\/(\w+(\[#{@r_option_inner}\]|))*#{inner_open})/) {
247
+ line = $1
248
+ caption = ReViewDef::get_caption(line)
249
+ s = ""
250
+ s += "「#{caption}」\n\n" unless caption.blank?
251
+ s += "#@##{line}"
252
+ s
253
+ }
254
+ rep = "#{cmd_begin}#{inner}#@##{cmd_end}"
255
+ content.gsub!(matched) { |mm| rep }
188
256
  else
189
- imb = inner.match(/(\R((^\/\/\w+(\[.*?\])*)\s*)*^\/\/#{inner_cmd}#{first_opt}(\[.*?\])*#{inner_open}.*)\R/m)
257
+ imb = inner.match(/(\R((^\/\/\w+(\[#{@r_option_inner}\])*)\s*)*^\/\/#{inner_cmd}#{id_opt}(\[#{@r_option_inner}\])*#{inner_open}.*)\R/m)
190
258
  to_out_block = imb[1]
191
259
  inner.gsub!(/#{Regexp.escape(to_out_block)}/m, '')
192
- content.gsub!(/#{Regexp.escape(matched)}/m, "#{cmd_begin}#{inner}#{cmd_end}#{to_out_block}")
260
+ rep = "#{cmd_begin}#{inner}#{cmd_end}#{to_out_block}"
261
+ content.gsub!(matched) { |mm| rep }
193
262
  end
194
263
  else
195
- close = inner_open == '{' ? '}' : inner_open
264
+ close = ReViewDef::fence_close(inner_open)
196
265
  if is_commentout
197
- inner.gsub!(/(^\/\/(\w+(\[.*?\]|))*#{inner_open})(.*?)(^\/\/#{close})/m, '#@#\1\2#@#\3')
198
- content.gsub!(/#{Regexp.escape(matched)}/m, "#{cmd_begin}#{inner}#{cmd_end}")
266
+ inner.gsub!(/(^\/\/(\w+(\[#{@r_option_inner}\]|))*#{inner_open})(.*?)(^\/\/#{close})/m) {
267
+ first = $1
268
+ body = $2
269
+ last = $3
270
+ caption = ReViewDef::get_caption(first)
271
+ s = ""
272
+ s += "「#{caption}」\n\n" unless caption.blank?
273
+ s += "#@##{first}#{body}@##{last}"
274
+ s
275
+ }
276
+ rep = "#{cmd_begin}#{inner}#{cmd_end}"
277
+ content.gsub!(matched) { |mm| rep }
199
278
  else
200
- imb = inner.match(/\R((^\/\/\w+(\[.*?\])*)\s*)*^\/\/(#{inner_cmd})#{first_opt}(\[[^\r\n]*?\])*(?:(\$)|(?:({)|(\|)))(.*?)(^\/\/)(?(3)(\$)|(?(4)(})|(\|)))/m)
279
+ imb = inner.match(/\R((^\/\/\w+(\[#{@r_option_inner}\])*)\s*)*^\/\/(#{inner_cmd})#{id_opt}(\[[^\r\n]*?\])*(?:(\$)|(?:({)|(\|)))(.*?)(^\/\/)(?(3)(\$)|(?(4)(})|(\|)))/m)
201
280
  to_out_block = imb[0]
202
281
  inner.gsub!(/#{Regexp.escape(to_out_block)}/m, '')
203
- content.gsub!(/#{Regexp.escape(matched)}/m, "#{cmd_begin}#{inner}#{cmd_end}#{to_out_block}")
282
+ rep = "#{cmd_begin}#{inner}#{cmd_end}#{to_out_block}"
283
+ content.gsub!(matched) { |mm| rep }
204
284
  end
205
285
  end
206
286
  found = true
@@ -216,7 +296,7 @@ module ReVIEW
216
296
  end
217
297
 
218
298
  def replace_block_command_nested_boxed_articles(content)
219
- unless Gem::Version.new(ReVIEW::VERSION) >= Gem::Version.new('5.0.0')
299
+ unless ReViewCompat::has_nested_minicolumn()
220
300
  replace_block_command_nested_boxed_article(content, 'note')
221
301
  replace_block_command_nested_boxed_article(content, 'memo')
222
302
  replace_block_command_nested_boxed_article(content, 'tip')
@@ -228,24 +308,27 @@ module ReVIEW
228
308
  end
229
309
  end
230
310
 
311
+ # #@+++ ~ #@--- to #@#+++ #@#~ #@#---
231
312
  def replace_block_commentout(content)
232
313
  d = content.dup
233
- d.scan(/(^#@)(\++)(.*?)(^#@)(-+)/m) { |m|
314
+ d.scan(/(^#@)(\++\R)(.*?)(^#@)(-+)/m) { |m|
234
315
  matched = m[0..-1].join
235
316
  inner = m[2]
236
- inner.gsub!(/(^.)/, '#@#\1')
237
- content.gsub!(/#{Regexp.escape(matched)}/m, "#@##{m[1]}#{inner}#@##{m[4]}")
317
+ inner.gsub!(/^/, '#@#')
318
+ rep = "#@##{m[1]}#{inner}#@##{m[4]}"
319
+ content.gsub!(matched) { |mm| rep }
238
320
  }
239
321
  end
240
322
 
241
323
  def replace_block_commentout_without_sampleout(content)
242
324
  d = content.dup
243
325
  d.gsub!(/(^\/\/sampleoutputbegin\[)(.*?)(\])(.*?)(^\/\/sampleoutputend)/m, '')
244
- d.scan(/(^#@)(\++)(.*?)(^#@)(-+)/m) { |m|
326
+ d.scan(/(^#@)(\++\R)(.*?)(^#@)(-+)/m) { |m|
245
327
  matched = m[0..-1].join
246
328
  inner = m[2]
247
- inner.gsub!(/(^.)/, '#@#\1')
248
- content.gsub!(/#{Regexp.escape(matched)}/m, "#@##{m[1]}#{inner}#@##{m[4]}")
329
+ inner.gsub!(/^/, '#@#\1')
330
+ rep = "#@##{m[1]}#{inner}#@##{m[4]}"
331
+ content.gsub!(matched) { |mm| rep }
249
332
  }
250
333
  end
251
334
 
@@ -258,7 +341,8 @@ module ReVIEW
258
341
  option = m[1]
259
342
  inner = m[3]
260
343
  # inner.gsub!(/^\/\//, '//@<nop>{}')
261
- content.gsub!(/#{Regexp.escape(matched)}/m, "#{option}\n#@##{sampleoutputbegin}#{inner}#@##{sampleoutputend}")
344
+ rep = "#{option}\n#@##{sampleoutputbegin}#{inner}#@##{sampleoutputend}"
345
+ content.gsub!(matched) { |mm| rep }
262
346
  }
263
347
  end
264
348
 
@@ -272,7 +356,7 @@ module ReVIEW
272
356
  end
273
357
 
274
358
  def fix_deprecated_list(content)
275
- if Gem::Version.new(ReVIEW::VERSION) >= Gem::Version.new('4.0.0')
359
+ if ReViewCompat::is_need_space_term_list()
276
360
  content.gsub!(/^: (.*)/, ' : \1')
277
361
  end
278
362
  end
@@ -284,57 +368,181 @@ module ReVIEW
284
368
  ref = m[4]
285
369
  n = content.match(/^\/\/note\[#{ref}\](\[.*?\])/)
286
370
  unless n.nil?
287
- content.gsub!(/#{Regexp.escape(matched)}/, n[1])
371
+ rep = n[1]
372
+ content.gsub!(matched) { |mm| rep }
288
373
  content.gsub!(/^\/\/note\[#{ref}\](\[.*?\])/, '//note\1')
289
374
  else
290
- # content.gsub!(/#{Regexp.escape(matched)}/, "noteref<#{ref}>")
375
+ # content.gsub!(matched, "noteref<#{ref}>")
291
376
  end
292
377
  }
293
378
  end
294
379
 
380
+ def remove_option_param(content, commands, n, param)
381
+ content.gsub!(/(^\/\/(#{commands.join('|')})(\[.*?\]){#{n-1}}\[.*?)((,|)\s*#{param}=[^,\]]*)(.*?\])/) {
382
+ prev = $1
383
+ cmd = $2
384
+ opt = $4
385
+ post = $6
386
+ "#{prev}#{post}"
387
+ }
388
+ end
389
+
295
390
  def remove_starter_options(content)
391
+ # image width
392
+ content.gsub!(/(^\/\/image\[.*?\]\[.*?\]\[.*?)(,|)(\s*)width=\s*([0-9.]+)%(?<after>.*?\])/) { |m|
393
+ m.gsub!(/width=\s*([0-9.]+)%/) {
394
+ value = $1
395
+ "scale=#{value.to_i * 0.01}"
396
+ }
397
+ }
398
+ remove_option_param(content, ["image"], 3, "width")
296
399
  # image border
297
- content.gsub!(/(^\/\/image\[.*?\]\[.*?\]\[.*?)((,|)border=[^,\]]*)(.*?\])/, '\1\4')
400
+ remove_option_param(content, ["image"], 3, "border")
401
+ # image pos
402
+ remove_option_param(content, ["image"], 3, "pos")
298
403
  # list lineno
299
- content.gsub!(/(^\/\/list\[.*?\]\[.*?\]\[.*?)((,|)lineno=[^,\]]*)(.*?\])/, '\1\4')
300
- end
301
-
302
- def expand_nested_inline_command(content)
303
- found = false
304
- content.dup.scan(/(@<.*?>)(?:(\$)|(?:({)|(\|)))(.*?)(?(2)(\$)|(?(3)(})|(\|)))/) { |m|
305
- matched = m.join
306
- body = m[4]
307
- im = body.match(/(.*)(@<.*?>)(?:(\$)|(?:({)|(\|)))(.*?)(?(3)(\$)|(?(4)(})|(\|)))(.*)/)
308
- if im.nil?
309
- im = body.match(/(.*)(@<.*?>)#{m[1..3].join}/)
310
- unless im.nil?
311
- outcmd_begin = m[0] + "$|{".gsub(m[1..3].join, '')
312
- outcmd_end = "$|}".gsub(m[5..7].join, '')
313
- rep = "#{outcmd_begin}#{body}#{outcmd_end}"
314
- content.gsub!(matched, rep)
315
- found = true
404
+ remove_option_param(content, ["list", "listnum"], 3, "lineno")
405
+ end
406
+
407
+ # talklist to //#{cmd}[]{ //emlist[]{}... }
408
+ def talklist_to_nested_contents_list(content, cmd)
409
+ content.gsub!(/^\/\/talklist(.*?){/, "//#{cmd}\\1{")
410
+ content.gsub!(/^\/\/talk(?<options>\[#{@r_option_inner}\]\[#{@r_option_inner}\])\[(?<body>#{@r_option_inner})\]$/, "//talk\\k<options>{\n\\k<body>\n//}")
411
+ content.gsub!(/^\/\/t(?<options>\[#{@r_option_inner}\])\[(?<body>#{@r_option_inner})\]$/, "//talk\\k<options>{\n\\k<body>\n//}")
412
+ content.gsub!(/^\/\/(t|talk)((\[#{@r_option_inner}\])*){/) { |s|
413
+ m = s.scan(/(\[(#{@r_option_inner})\])/)
414
+ # 1st option is image id
415
+ avatar = m[0][1]
416
+ first_option = m[0][0]
417
+ traling_options = m[1..-1].map{ |x| x[0] }.join
418
+ if avatar.length > 0
419
+ kv = @talk_shortcuts[avatar]
420
+ if kv&.key?('image')
421
+ "//indepimage[#{kv['image']}][][scale=#{@talk_icon_scale}]{\n//}\n//emlist[]#{traling_options}{"
422
+ elsif kv&.key?('name')
423
+ "//emlist[#{kv['name']}]{"
424
+ else
425
+ "//indepimage#{first_option}[][scale=#{@talk_icon_scale}]{\n//}\n//emlist[]#{traling_options}{"
316
426
  end
317
427
  else
318
- outcmd_begin = m[0..3].join
319
- outcmd_end = m[5..7].join
320
- rep = "#{outcmd_begin}#{im[1]}#{outcmd_end}#{im[2..9].join}#{outcmd_begin}#{im[-1]}#{outcmd_end}"
321
- content.gsub!(matched, rep)
322
- found = true
428
+ "//emlist#{traling_options}{"
323
429
  end
324
430
  }
325
- if found
326
- expand_nested_inline_command(content)
431
+ end
432
+
433
+ # desclist to //#{cmd}[]{ //emlist[]{}... }
434
+ def desclist_to_nested_contents_list(content, cmd)
435
+ content.gsub!(/^\/\/desclist(.*?){/, "//#{cmd}\\1{")
436
+ content.gsub!(/^\/\/desc(?<options>\[#{@r_option_inner}\])\[(?<body>#{@r_option_inner})\]$/, "//desc\\k<options>{\n\\k<body>\n//}")
437
+ content.gsub!(/^\/\/desc((\[#{@r_option_inner}\])*){/, '//emlist\1{')
438
+ end
439
+
440
+ def starter_list_to_nested_contents_list(content)
441
+ # talklist
442
+ talklist_to_nested_contents_list(content, @talklist_replace_cmd)
443
+ # desclist
444
+ desclist_to_nested_contents_list(content, @desclist_replace_cmd)
445
+ replace_block_command_nested_boxed_article(content, 'emlist')
446
+ end
447
+
448
+ def replace_file_option(content, matched, fence_open, option)
449
+ file_param_m = option.match(/\s*file\s*=\s*([^,\]]*)/)
450
+ if file_param_m
451
+ fence_close = ReViewDef::fence_close(fence_open)
452
+ filepath = file_param_m[1]
453
+ if fence_close
454
+ content.gsub!(/#{Regexp.escape(matched)}(.*?)^\/\/#{fence_close}/m) {
455
+ "#{matched}\n\#@mapfile(#{filepath})\n\#@end\n//#{fence_close}"
456
+ }
457
+ end
327
458
  end
328
459
  end
329
460
 
461
+ def convert_starter_option(content)
462
+ # file
463
+ r = /^(?<matched>\/\/(list|listnum|table)\[#{@r_option_inner}\]\[#{@r_option_inner}\]\[(?<options>#{@r_option_inner})\](?<open>.))$/
464
+ content.dup.scan(r) { |m|
465
+ matched = m[0]
466
+ options = m[1]
467
+ fence_open = m[2]
468
+ options.split(',').each { |option|
469
+ replace_file_option(content, matched, fence_open, option)
470
+ }
471
+ }
472
+ remove_option_param(content, ["list", "listnum", "table"], 3, "file")
473
+ # csv
474
+ convert_csv_option(content)
475
+ end
476
+
477
+ def convert_csv_option(content)
478
+ r_table = /^(?<matched>\/\/table\[#{@r_option_inner}\]\[#{@r_option_inner}\]\[(?<options>#{@r_option_inner})\](?<open>.))$/
479
+ content.dup.scan(r_table) { |m|
480
+ matched = m[0]
481
+ options = m[1]
482
+ options.split(',').each { |option|
483
+ if option.match(/\s*csv\s*=\s*on\s*/)
484
+ open = m[2]
485
+ close = ReViewDef::fence_close(open)
486
+ if close
487
+ tm = content.match(/#{Regexp.escape(matched)}(.*?)^\/\/#{close}/m)
488
+ outer = tm[0]
489
+ inner = tm[1]
490
+ im = inner.match(/(.*?)([=\-]{12,}\R)(.*)/m)
491
+ if im
492
+ header = im[1]
493
+ sep = im[2]
494
+ body = im[3]
495
+ new_header = ""
496
+ new_body = ""
497
+ CSV.parse(header) do |h|
498
+ new_header += Utils::GenerateTsv(h)
499
+ end
500
+ CSV.parse(body) do |c|
501
+ new_body += Utils::GenerateTsv(c)
502
+ end
503
+ content.gsub!(outer, "#{matched}#{new_header}#{sep}#{new_body}//#{close}")
504
+ else
505
+ im = inner.match(/^\#@mapfile\((.*?)\)\R^\#@end/m)
506
+ if im
507
+ inner_file = im[1]
508
+ csv_text = "\n"
509
+ csv_text += File.open(File.join(@basedir, inner_file)).read()
510
+ else
511
+ csv_text = inner
512
+ end
513
+ new_body = ""
514
+ CSV.parse(csv_text) do |c|
515
+ new_body += Utils::GenerateTsv(c)
516
+ end
517
+ content.gsub!(outer, "#{matched}#{new_body}//#{close}")
518
+ end
519
+ end
520
+ end
521
+ }
522
+ }
523
+ end
524
+
525
+ # tsize[builder][xxx] to tsize[|builder|xxx]
526
+ def replace_tsize(content)
527
+ content.gsub!(/^\/\/tsize\[(.*?)\]\[(.*?)\]/) {
528
+ builder = $1
529
+ builder = "" if $1 == '*'
530
+ "//tsize[|#{builder}|#{$2}]"
531
+ }
532
+ end
533
+
330
534
  def copy_embedded_contents(outdir, content)
331
- content.scan(/\#@mapfile\((.*?)\)/).each do |filepath|
535
+ content.scan(/\#@mapfile\((.*?)\)/).each do |filepath_|
536
+ filepath = filepath_[0]
537
+ if filepath.blank?
538
+ next
539
+ end
332
540
  srcpath = File.join(@basedir, filepath)
333
541
  if File.exist?(srcpath)
334
542
  outpath = File.join(File.absolute_path(outdir), filepath)
335
543
  FileUtils.mkdir_p(File.dirname(outpath))
336
544
  FileUtils.cp(srcpath, outpath)
337
- @embeded_contents.push(filepath[0])
545
+ @embeded_contents.push(filepath)
338
546
  update_content(outpath, outpath)
339
547
  end
340
548
  end
@@ -370,39 +578,131 @@ module ReVIEW
370
578
  }
371
579
  end
372
580
 
373
- def update_content(outdir, contentfile)
374
- info contentfile
375
- filename = File.basename(contentfile, '.*')
376
- content = File.read(contentfile)
377
- content.gsub!(/@<href>{(.*?)#.*?,(.*?)}/, '@<href>{\1,\2}')
378
- content.gsub!(/@<href>{(.*?)#.*?}/, '@<href>{\1}')
379
- linkurl_footnote = @config['starter']['linkurl_footnote']
380
- # table 内の @ コマンドは不安定らしい
381
- while !content.gsub!(/(\/\/table.*)@<br>{}(.*?\/\/})/m, "\\1#{@table_br_replace}\\2").nil? do
382
- end
383
- # 空セルが2行になることがあるらしい
384
- while !content.gsub!(/(\/\/table.*\s)\.(\s.*?\/\/})/m, "\\1#{@table_empty_replace}\\2").nil? do
385
- end
386
- # Re:VIEW Starter commands
387
- replace_compatible_block_command_outline(content, 'terminal', 'cmd', 1)
388
- replace_compatible_block_command_outline(content, 'cmd', 'cmd', 0)
581
+ def replace_starter_command(content)
582
+ replace_compatible_block_command_outline(content, 'program', 'list', 2)
583
+ replace_compatible_block_command_outline(content, 'terminal', 'cmd', 1, 1)
584
+ replace_compatible_block_command_outline(content, 'output', 'list', 3)
389
585
  replace_compatible_block_command_to_outside(content, 'sideimage', 'image', 1, '[]')
390
586
  replace_block_command_outline(content, 'abstract', 'lead', true)
587
+ delete_block_command(content, 'vspace')
391
588
  delete_block_command(content, 'needvspace')
392
589
  delete_block_command(content, 'clearpage')
393
590
  delete_block_command(content, 'flushright')
394
- delete_block_command(content, 'centering')
395
591
  delete_block_command(content, 'paragraphend')
592
+ delete_block_command_outer(content, 'centering')
593
+
594
+ # convert starter option
595
+ convert_starter_option(content)
596
+
597
+ # delete starter option
598
+ # exclude_exta_option(content, 'cmd', 0)
599
+ starter_caption_to_text(content, 'cmd', 1)
600
+ exclude_exta_options(content, [
601
+ 'imgtable',
602
+ 'table',
603
+ # list/listnum の第3引数は言語指定だが、Starter の第3引数と全く異なるため 2 引数にしている
604
+ # Starter 側が言語指定対応したら修正
605
+ 'list',
606
+ 'listnum',
607
+ ], 2)
608
+ # exclude_exta_option(content, 'tsize', 1)
609
+ replace_tsize(content)
396
610
 
397
611
  # delete IRD unsupported commands
398
612
  if @ird
399
613
  delete_block_command(content, 'noindent')
400
614
  end
401
615
 
616
+ # chapterauthor
617
+ content.gsub!(/^\/\/chapterauthor\[(.*?)\]/, "//lead{\n\\1\n//}")
618
+ # talklist/desclist
619
+ starter_list_to_nested_contents_list(content)
620
+ # empty caption imaget to indepimage
621
+ content.gsub!(/^\/\/image(\[#{@r_option_inner}\]\[\].*)$/, '//indepimage\1')
622
+ end
623
+
624
+ def delete_inline_command(content, command)
625
+ # 既に入れ子は展開されている前提
626
+ content.gsub!(/@<#{command}>(?:(\$)|(?:({)|(\|)))(.*?)(?(1)(\$)|(?(2)(})|(\|)))/, '\4')
627
+ end
628
+
629
+ def do_replace_inline_command(content, command, &blk)
630
+ # 既に入れ子は展開されている前提
631
+ content.gsub!(/@<#{command}>(?:(\$)|(?:({)|(\|)))(.*?)(?(1)(\$)|(?(2)(})|(\|)))/) { blk.call([$1, $2, $3].join, $4, [$5, $6, $7].join) }
632
+ end
633
+
634
+ def replace_inline_command(content, command, new_command)
635
+ do_replace_inline_command(content, command) { |open, inner, close|
636
+ "@<#{new_command}>#{open}#{inner}#{close}"
637
+ }
638
+ end
639
+
640
+ # @<XXX>{AAA@<YYY>{BBB}} to @<XXX>{AAA}@<YYY>{BBB}
641
+ def expand_nested_inline_command(content)
642
+ found = false
643
+ content.dup.each_line do |line|
644
+ if line.match(/^#@#/)
645
+ next
646
+ end
647
+ line.scan(/(@<.*?>)(?:(\$)|(?:({)|(\|)))(.*?)(?(2)(\$)|(?(3)(})|(\|)))/) { |m|
648
+ matched = m.join
649
+ body = m[4]
650
+ outcmd_cmd = m[0]
651
+ outcmd_open = m[1..3].join
652
+ outcmd_begin = outcmd_cmd + outcmd_open
653
+ outcmd_close = m[5..7].join
654
+ im = body.match(/(.*)(@<.*?>)(?:(\$)|(?:({)|(\|)))(.*?)(?(3)(\$)|(?(4)(})|(\|)))(.*)/)
655
+ if im.nil?
656
+ # for {}
657
+ im2 = body.match(/(.*)(@<.*?>)#{Regexp.escape(outcmd_open)}(.*)/)
658
+ unless im2.nil?
659
+ rep = ""
660
+ if im2[3].length > 0
661
+ incmd_begin = im2[1..2].join + "$|{".gsub(outcmd_open, '')[0]
662
+ incmd_end = "$|}".gsub(outcmd_close, '')[0]
663
+ rep = "#{outcmd_begin}#{incmd_begin}#{im2[3]}#{incmd_end}"
664
+ else
665
+ rep = outcmd_begin + im2[1]
666
+ end
667
+ content.gsub!(matched) { |mm| rep }
668
+ found = true
669
+ else
670
+ # for |$
671
+ if body.match(/.*@<.*?>$/)
672
+ incmd_fence = "$|".gsub(outcmd_open, '')
673
+ rep = "#{outcmd_begin}#{body}#{incmd_fence}"
674
+ content.gsub!(/#{Regexp.escape(matched)}(.*?)#{Regexp.escape(outcmd_open)}/, "#{rep}\\1#{incmd_fence}")
675
+ found = true
676
+ end
677
+ end
678
+ else
679
+ rep = ""
680
+ rep += "#{outcmd_begin}#{im[1]}#{outcmd_close}" if im[1].length > 0
681
+ rep += "#{im[2..9].join}"
682
+ rep += "#{outcmd_begin}#{im[-1]}#{outcmd_close}" if im[-1].length > 0
683
+ content.gsub!(matched) { |mm| rep }
684
+ found = true
685
+ end
686
+ }
687
+ end
688
+ if found
689
+ expand_nested_inline_command(content)
690
+ end
691
+ end
692
+
693
+ def replace_starter_inline_command(content)
694
+ expand_nested_inline_command(content)
695
+
402
696
  replace_inline_command(content, 'secref', 'hd')
403
697
  replace_inline_command(content, 'file', 'kw')
404
698
  replace_inline_command(content, 'hlink', 'href')
405
699
  replace_inline_command(content, 'B', 'strong')
700
+ replace_inline_command(content, 'W', 'wb')
701
+ replace_inline_command(content, 'term', 'idx')
702
+ replace_inline_command(content, 'termnoidx', 'hidx')
703
+ unless ReViewCompat::has_bou()
704
+ replace_inline_command(content, 'bou', 'b')
705
+ end
406
706
  delete_inline_command(content, 'userinput')
407
707
  delete_inline_command(content, 'weak')
408
708
  delete_inline_command(content, 'cursor')
@@ -414,12 +714,37 @@ module ReVIEW
414
714
  delete_inline_command(content, 'xlarge')
415
715
  delete_inline_command(content, 'xxlarge')
416
716
 
717
+ do_replace_inline_command(content, 'par') { |open, inner, close| "@<br>#{open}#{close}" }
718
+ do_replace_inline_command(content, 'qq' ) { |open, inner, close| "\"#{inner}\"" }
719
+ end
720
+
721
+ def update_content(outdir, contentfile)
722
+ info contentfile
723
+ filename = File.basename(contentfile, '.*')
724
+ content = File.read(contentfile)
725
+ content.gsub!(/@<href>{(.*?)#.*?,(.*?)}/, '@<href>{\1,\2}')
726
+ content.gsub!(/@<href>{(.*?)#.*?}/, '@<href>{\1}')
727
+ linkurl_footnote = @config['starter']['linkurl_footnote']
728
+ # table 内の @ コマンドは不安定らしい
729
+ while !content.gsub!(/(\/\/table.*)@<br>{}(.*?\/\/})/m, "\\1#{Regexp.escape(@table_br_replace)}\\2").nil? do
730
+ end
731
+ # 空セルが2行になることがあるらしい
732
+ while !content.gsub!(/(\/\/table.*\s)\.(\s.*?\/\/})/m, "\\1#{Regexp.escape(@table_empty_replace)}\\2").nil? do
733
+ end
734
+ # noop を最後に消すためにダミーに変える
735
+ content.gsub!('@<nop>$$', '@<dummynop>$must_be_replace_nop$')
736
+ content.gsub!('@<nop>||', '@<dummynop>|must_be_replace_nop|')
737
+ content.gsub!('@<nop>{}', '@<dummynop>{must_be_replace_nop}')
738
+
739
+ # Re:VIEW Starter commands
740
+ replace_starter_command(content)
741
+
417
742
  # fixed lack of options
418
743
  content.gsub!(/^\/\/list{/, '//list[][]{')
419
744
  # empty br line to blankline
420
745
  content.gsub!(/^\s*@<br>{}\s*$/, '//blankline')
421
746
 
422
- if Gem::Version.new(ReVIEW::VERSION) >= Gem::Version.new('4.0.0')
747
+ unless ReViewCompat::is_allow_empty_image_caption()
423
748
  # empty caption is not allow
424
749
  content.gsub!(/^\/\/image\[(.*)\]\[\]{/, '//image[\1][ ]{')
425
750
  end
@@ -435,6 +760,7 @@ module ReVIEW
435
760
  replace_block_command_nested_boxed_articles(content)
436
761
 
437
762
  # empty ids
763
+ replace_auto_ids(content, 'table', 2)
438
764
  replace_auto_ids(content, 'list', 2)
439
765
  replace_auto_ids(content, 'listnum', 2)
440
766
 
@@ -450,23 +776,29 @@ module ReVIEW
450
776
  content.gsub!('@<TeX>{}', 'TeX')
451
777
  content.gsub!('@<hearts>{}', '!HEART!')
452
778
 
453
- # nop replace must be last step
454
- content.gsub!('@<nop>$$', '@<b>$$')
455
- content.gsub!('@<nop>||', '@<b>||')
456
- content.gsub!('@<nop>{}', '@<b>{}')
457
-
458
- # expand nested inline command
459
- expand_nested_inline_command(content)
779
+ replace_starter_inline_command(content)
460
780
 
461
781
  # fix deprecated
462
782
  fix_deprecated_list(content)
463
783
 
464
784
  if @ird
465
785
  # br to blankline
466
- content.gsub!(/(.*)@<br>{}$/, "\\1\n\n")
467
- content.gsub!(/(.*)@<br>{}(.*)$/, "\\1\n\n\\2")
786
+ content.gsub!(/(^\/\/footnote\[.*?\]\[.*?)((.*?@<br>({}|\$\$|\|\|)){1,})(.*\])$/) { |m|
787
+ m.gsub(/@<br>({}|\$\$|\|\|)/, '@<fnbr>\1')
788
+ }
789
+
790
+ content.gsub!(/(.*)@<br>({}|\$\$|\|\|)$/, "\\1\n\n")
791
+ content.gsub!(/(.*)@<br>({}|\$\$|\|\|)(.*)$/, "\\1\n\n\\2")
792
+ content.gsub!(/@<fnbr>({}|\$\$|\|\|)/, '@<br>\1')
468
793
  end
469
794
 
795
+ # nop replace must be last step
796
+ # content.gsub!('@<dumynop>$must_be_replace_nop$', '@<b>$$')
797
+ # content.gsub!('@<dumynop>|must_be_replace_nop|', '@<b>||')
798
+ content.gsub!('@<dummynop>$must_be_replace_nop$', '@<b>{}')
799
+ content.gsub!('@<dummynop>|must_be_replace_nop|', '@<b>{}')
800
+ content.gsub!('@<dummynop>{must_be_replace_nop}', '@<b>{}')
801
+
470
802
  File.write(contentfile, content)
471
803
  copy_embedded_contents(outdir, content)
472
804
  end
@@ -497,7 +829,7 @@ module ReVIEW
497
829
  contentdir = abspath
498
830
  info 'replace starter block command'
499
831
  info 'replace starter inline command'
500
- catalog = ReVIEW::Catalog.new(File.open(File.join(abspath, yamlfile)))
832
+ catalog = ReViewCompat::Catalog(File.join(abspath, yamlfile))
501
833
  update_content_files(outdir, contentdir, @catalog_contents)
502
834
  unless options['strict']
503
835
  all_contentsfiles = Pathname.glob(File.join(File.join(@basedir, @srccontentsdir), '*.re')).map(&:basename)
@@ -512,12 +844,10 @@ module ReVIEW
512
844
  contentpath = File.join(contentdir, content)
513
845
  if File.exist?(contentpath)
514
846
  info "preproc #{contentpath}"
515
- buf = StringIO.new
516
847
  pwd = Dir.pwd
517
848
  Dir.chdir(outdir)
518
- File.open(contentpath) { |f| pp.process(f, buf) }
849
+ content = pp.process(contentpath)
519
850
  Dir.chdir(pwd)
520
- content = buf.string
521
851
  content.gsub!(/^#[@]map.*$/, '')
522
852
  content.gsub!(/^#[@]end$/, '')
523
853
  File.write(contentpath, content)
@@ -531,10 +861,10 @@ module ReVIEW
531
861
  contentdir = abspath
532
862
  param = {}
533
863
  param['tabwidth'] = options['tabwidth'].to_i
534
- pp = ReVIEW::Preprocessor.new(ReVIEW::Repository.new(param), param)
864
+ pp = ReViewCompat::Preprocessor(param)
535
865
 
536
866
  if options['strict']
537
- catalog = ReVIEW::Catalog.new(File.open(File.join(abspath, yamlfile)))
867
+ catalog = ReViewCompat::Catalog(File.join(abspath, yamlfile))
538
868
  preproc_content_files(outdir, pp, contentdir, @catalog_contents)
539
869
  else
540
870
  contentsfiles = Pathname.glob(File.join(File.join(@basedir, @srccontentsdir), '*.re')).map(&:basename)
@@ -542,6 +872,29 @@ module ReVIEW
542
872
  end
543
873
  end
544
874
 
875
+ def erb_sty(outdir, filename)
876
+ src = File.join(__dir__, "sty/#{filename}.erb")
877
+ dest = File.join(outdir, "sty/#{filename}")
878
+ erb = ERB.new(File.read(src))
879
+ File.write(dest, erb.result)
880
+ end
881
+
882
+ def update_sty(outdir, options)
883
+ review_custom_sty = File.open(File.join(outdir, 'sty/review-custom.sty'), 'a')
884
+ erb_sty(outdir, 'review-retrovert-custom.sty')
885
+ review_custom_sty.puts('\RequirePackage{review-retrovert-custom}')
886
+ if @ird
887
+ erb_sty(outdir, 'ird.sty')
888
+ review_custom_sty.puts('\RequirePackage{ird}')
889
+ end
890
+ end
891
+
892
+ def update_ext(outdir, options)
893
+ if @ird
894
+ FileUtils.cp(File.join(__dir__, 'ext/review-ext.rb'), File.join(outdir, 'review-ext.rb'))
895
+ end
896
+ end
897
+
545
898
  def clean_initial_project(outdir)
546
899
  FileUtils.rm(File.join(outdir, 'config.yml'))
547
900
  FileUtils.rm(File.join(outdir, 'catalog.yml'))
@@ -560,7 +913,7 @@ module ReVIEW
560
913
  @basedir = @configs.basedir
561
914
  @srccontentsdir = @config['contentdir']
562
915
 
563
- catalog = ReVIEW::Catalog.new(File.open(@configs.catalogfile()))
916
+ catalog = ReViewCompat::Catalog(@configs.catalogfile())
564
917
  add_catalog_contents(catalog.predef())
565
918
  add_catalog_contents(catalog.chaps())
566
919
  add_catalog_contents(catalog.appendix())
@@ -580,12 +933,15 @@ module ReVIEW
580
933
  load_config(yamlfile)
581
934
  store_image_dir = store_out_image(outdir) if options['no-image']
582
935
  create_initial_project(outdir, options)
936
+ @talk_shortcuts = @config['starter']['talk_shortcuts']
583
937
 
584
938
  copy_config(outdir)
585
939
  copy_catalog(outdir)
586
940
  copy_images(outdir, store_image_dir)
587
941
  update_config(outdir)
588
942
  update_contents(outdir, options)
943
+ update_sty(outdir, options)
944
+ update_ext(outdir, options)
589
945
 
590
946
  pwd = Dir.pwd
591
947
  Dir.chdir(outdir)