pbsimply 3.4.1 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b3583d8259481a06d6ac35e90619841a2b3dedda0689db267c61679c06ceed2
4
- data.tar.gz: 69160342826f79285f050b9358b315267376337bd03ccf80d4808d2e38be992d
3
+ metadata.gz: 2f75e4f4e81729dbe5a291d473f1f2dc83bd51d52076179bd1a5517cf6bde380
4
+ data.tar.gz: df909fb121e61744b056e0d934e07acd43d88d1630873c78910cc92a6462c390
5
5
  SHA512:
6
- metadata.gz: a0f0112820966f4d03e5ae46210eee0dfeac73faa81534ea1dadd40c55f08723026352ce882721f92bdb3285d28edfb8ee852b3d8bae966bd857b8c4227aaa0d
7
- data.tar.gz: 584cbb371bceb868d89ba6265dbef0029eab4598e5db3d575888c8b8af37070f8e48bc677f1c3d183212cfbdbb5b09a2d70478cc60d1c3432428c39ffe8a432a
6
+ metadata.gz: 06417d28977298a737faee844340700128d9d047d938ea16737ede93d1d8609e6844d0f3b49c138b4129b9c658f9a1444f38eb89e80848aa3362e1d04b47b720
7
+ data.tar.gz: da761d0166bc05e276296b449393f2914ea6b462ebe28d6d96ea1f392323bfa919864c3d655e1279029f57773cbdd7d89464cb33f0f74be28032455ddd275ac2
data/README.md CHANGED
@@ -34,7 +34,11 @@ PB Simply ACCS make `index.md` with indexes build by PureBuilder.
34
34
  ## Dependency
35
35
 
36
36
  * Ruby >= 3.0
37
- * Pandoc >= 2.8
37
+ * Pandoc >= 2.8 (Optional)
38
+ * Docutils (Optional)
39
+ * redcarpet Gem (Optional)
40
+ * kramdown Gem (Optional)
41
+ * commonmarker Gem (Optional)
38
42
 
39
43
  ## Usage
40
44
 
data/bin/pbsimply CHANGED
@@ -25,6 +25,12 @@ end
25
25
  # Alias for compatibility.
26
26
  PureBuilder = pbs_class
27
27
 
28
- pbs = pbs_class.new(config)
29
- pbs.treat_cmdline
30
- pbs.main
28
+ begin
29
+ pbs = pbs_class.new(config)
30
+ pbs.treat_cmdline
31
+
32
+ pbs.main
33
+ rescue PBSimply::CommandLineError => e
34
+ $stderr.puts e.to_s
35
+ exit 1
36
+ end
@@ -85,7 +85,6 @@ class PBSimply
85
85
  end
86
86
 
87
87
  def target_file_extensions
88
- p [".md", ".rst"] + @pandoc_input_extmap.keys
89
88
  [".md", ".rst"] + @pandoc_input_extmap.keys
90
89
  end
91
90
  end
@@ -0,0 +1,110 @@
1
+ require 'pbsimply/frontmatter'
2
+
3
+ class PBSimply
4
+ class Document
5
+ include Frontmatter
6
+
7
+ def initialize(config, dir, filename, base_frontmatter, now)
8
+ @config = config
9
+ @dir = dir
10
+ @filename = filename
11
+ @ext = File.extname filename
12
+ @orig_filepath = File.join(dir, filename)
13
+ @now = now
14
+ frontmatter, @pos = read_frontmatter(dir, filename)
15
+ @frontmatter = base_frontmatter.merge frontmatter
16
+ @modified = true
17
+ @proc_doc_path = nil
18
+ end
19
+
20
+ attr_reader :frontmatter, :filename, :pos, :ext, :proc_doc_path, :orig_filepath
21
+ attr_accessor :orig_frontmatter, :now
22
+
23
+ def add_meta(additional_meta)
24
+ frontmatter.merge!(additional_meta)
25
+ end
26
+
27
+ def read_document(workdir: "")
28
+ File.open(File.join(@dir, @filename)) do |f|
29
+ f.seek(@pos)
30
+ doc_content = f.read
31
+ if @config["unicode_normalize"] && !@frontmatter["skip_normalize"]
32
+ doc_content.unicode_normalize!(@config["unicode_normalize"].to_sym)
33
+ end
34
+ File.open(File.join(workdir, "current_document#{@ext}"), "w") do |fo|
35
+ fo.write doc_content
36
+ end
37
+ end
38
+
39
+ @proc_doc_path = File.join(workdir, "current_document#{@ext}")
40
+ end
41
+
42
+ def draft?
43
+ frontmatter["draft"]
44
+ end
45
+
46
+ def to_a
47
+ [@dir, @filename, @frontmatter]
48
+ end
49
+
50
+ # Check is the article modified? (or force update?)
51
+ def modified?
52
+ index = @orig_frontmatter ||= {}
53
+
54
+ case @config["detect_modification"]
55
+ when "changes"
56
+ # Use "changes"
57
+ @modified = false if @frontmatter["changes"] == index["changes"]
58
+ when "mtimesize"
59
+ # Use mtime and file size.
60
+ @modified = false if @frontmatter["_mtime"] <= (index["_last_proced"] || 0) && @frontmatter["_size"] == index["_size"]
61
+ else
62
+ # Default method, use mtime.
63
+ @modified = false if @frontmatter["_mtime"] <= (index["_last_proced"] || 0)
64
+ end
65
+
66
+ if @modified
67
+ $stderr.puts "#{@filename} last modified at #{@frontmatter["_mtime"]}, last processed at #{index["_last_proced"] || 0}"
68
+ else
69
+ $stderr.puts "#{@filename} is not modified."
70
+ end
71
+
72
+ set_timestamp
73
+
74
+ if @frontmatter["skip_update"]
75
+ # Document specific skip update
76
+ @modified = false
77
+ elsif index["_modified"]
78
+ @modified = true
79
+ else
80
+ @modified
81
+ end
82
+ end
83
+
84
+ def mark_meta_modified
85
+ # Frontmatter used as a reference for metadata update detection.
86
+ # Keys that are always updated during processing should be removed.
87
+ ex_keys = ["_last_proced", "last_update"] + (@config["compr_ex_keys"] || [])
88
+ @orig_frontmatter ||= {}
89
+ compr_frontmatter = @orig_frontmatter.except(*ex_keys) # Hash#except from Ruby 2.0
90
+
91
+ if compr_frontmatter == frontmatter
92
+ @modified = false
93
+ else
94
+ @frontmatter["_modified"] = true
95
+ @frontmatter.merge!(@orig_frontmatter.slice(*ex_keys))
96
+ end
97
+ end
98
+
99
+ def effective_forntmatter
100
+ @modified ? @frontmatter : @orig_frontmatter
101
+ end
102
+
103
+ private
104
+
105
+ def set_timestamp
106
+ @frontmatter["_last_proced"] = @now.to_i
107
+ @frontmatter["last_update"] = @now.strftime("%Y-%m-%d %H:%M:%S")
108
+ end
109
+ end
110
+ end
@@ -211,6 +211,8 @@ module PBSimply::Frontmatter
211
211
  return frontmatter, pos
212
212
  end
213
213
 
214
+ private
215
+
214
216
  def outext frontmatter
215
217
  return frontmatter["force_ext"] if frontmatter["force_ext"]
216
218
 
@@ -107,11 +107,5 @@ class PBSimply::Hooks
107
107
  end
108
108
  end
109
109
 
110
- attr :pre
111
- attr :process
112
- attr :delete
113
- attr :post
114
- attr :accs
115
-
116
- attr :config
110
+ attr_reader :pre, :process, :delete, :post, :accs, :config
117
111
  end
data/lib/pbsimply.rb CHANGED
@@ -8,6 +8,7 @@ require 'tmpdir'
8
8
  require 'fileutils'
9
9
  require 'optparse'
10
10
  require 'digest/sha1'
11
+ require 'set' # It's not needed since Ruby 3.2
11
12
 
12
13
  # PureBuilder Simply Components
13
14
  require 'pbsimply/docdb'
@@ -15,16 +16,19 @@ require 'pbsimply/docengine/base'
15
16
  require 'pbsimply/prayer'
16
17
  require 'pbsimply/plugger'
17
18
  require 'pbsimply/hooks'
18
- require 'pbsimply/frontmatter'
19
19
  require 'pbsimply/accs'
20
20
  require 'pbsimply/config-checker.rb'
21
+ require 'pbsimply/document'
21
22
 
22
23
  class PBSimply
23
24
  include Prayer
24
25
  include Plugger
25
- include Frontmatter
26
26
  include ACCS
27
27
 
28
+ # Custom exception
29
+ class CommandLineError < StandardError
30
+ end
31
+
28
32
  # Use Oj as JSON library for frontmatter passing if possible.
29
33
  begin
30
34
  require 'oj'
@@ -118,6 +122,7 @@ class PBSimply
118
122
 
119
123
  @refresh = false # Force generate all documents.
120
124
  @skip_index = false # Don't register to index.
125
+ @preflight = false # Don't generate output document.
121
126
  @outfile = nil # Fixed output filename
122
127
  @add_meta = nil
123
128
  @accs = nil
@@ -136,8 +141,10 @@ class PBSimply
136
141
  opts.on("-X", "--ignore-ext") { @ignore_ext = true }
137
142
  opts.on("-I", "--skip-index") { @skip_index = true }
138
143
  opts.on("-A", "--skip-accs") { @skip_accs = true }
144
+ opts.on("-p", "--preflight") { @preflight = true }
139
145
  opts.on("-o FILE", "--output") {|v| @outfile = v }
140
146
  opts.on("-m FILE", "--additional-metafile") {|v| @add_meta = Psych.unsafe_load(File.read(v))}
147
+ opts.on("-a", "--only-accs") { @accs_only = true }
141
148
  opts.parse!(ARGV)
142
149
 
143
150
  if File.exist?(".pbsimply-bless.rb")
@@ -170,7 +177,7 @@ class PBSimply
170
177
  @docobject
171
178
  end
172
179
 
173
- attr :indexes
180
+ attr_reader :indexes
174
181
 
175
182
  ###############################################
176
183
  # PROCESSING FUNCTIONS #
@@ -181,7 +188,6 @@ class PBSimply
181
188
  def proc_dir
182
189
  draft_articles = []
183
190
  target_docs = []
184
- @indexes_orig = {}
185
191
  $stderr.puts "in #{@dir}..."
186
192
 
187
193
  $stderr.puts "Checking Frontmatter..."
@@ -201,11 +207,9 @@ class PBSimply
201
207
  end
202
208
 
203
209
  $stderr.puts "Checking frontmatter in #{filename}"
204
- frontmatter, pos = read_frontmatter(@dir, filename)
205
- frontmatter = @frontmatter.merge frontmatter
206
- frontmatter.merge!(@add_meta) if @add_meta
210
+ doc = Document.new(@config, @dir, filename, @frontmatter, @now)
207
211
 
208
- if frontmatter["draft"]
212
+ if doc.draft?
209
213
  draft_articles.push({
210
214
  article_filename: filename,
211
215
  filename: filename,
@@ -214,31 +218,31 @@ class PBSimply
214
218
  next
215
219
  end
216
220
 
217
- @indexes_orig[filename] = @indexes[filename]
218
- @indexes[filename] = frontmatter
221
+ doc.orig_frontmatter = @indexes[filename]
219
222
 
220
223
  # Push to target documents without checking modification.
221
- target_docs.push([filename, frontmatter, pos])
224
+ target_docs.push(doc)
222
225
  end
223
226
  ENV.delete("pbsimply_currentdoc")
224
227
  ENV.delete("pbsimply_filename")
225
228
 
226
229
  delete_turn_draft draft_articles
227
230
 
228
- # #proc_docs destructs target_docs
229
- processed_docs = proc_docs target_docs.dup
231
+ proc_docs target_docs
230
232
 
231
233
  delete_missing
232
-
233
- # Restore skipped doc's frontmatter
234
- orig_filelist = Set.new(target_docs.map {|i| i[0]})
235
- proc_filelist = Set.new(processed_docs.map {|i| i[0]})
236
- recov_filelist = orig_filelist - proc_filelist
237
- pp recov_filelist
238
- recov_filelist.each do |filename|
239
- @indexes[filename] = @indexes_orig[filename]
240
- end
241
234
 
235
+ # Update modified doc's frontmatter
236
+ if @preflight
237
+ target_docs.each do |doc|
238
+ @indexes[doc.filename] = doc.effective_forntmatter
239
+ end
240
+ else
241
+ target_docs.each do |doc|
242
+ @indexes[doc.filename] = doc.frontmatter
243
+ end
244
+ end
245
+
242
246
  # Save index.
243
247
  @db.dump(@indexes) unless @skip_index
244
248
 
@@ -250,37 +254,41 @@ class PBSimply
250
254
 
251
255
  def proc_docs target_docs
252
256
  # Exclude unchanged documents.
253
- if @indexes && @indexes_orig
257
+ unless @singlemode
254
258
  $stderr.puts "Checking modification..."
255
- target_docs.delete_if {|filename, frontmatter, pos| !check_modify(filename, frontmatter)}
259
+ if !@preflight
260
+ target_docs.delete_if do |doc|
261
+ next false if @refresh # Force refresh mode
262
+ !doc.modified?
263
+ end
264
+ # target_docs.delete_if {|filename, frontmatter, pos| !check_modify(filename, frontmatter)}
265
+ end
256
266
  end
257
267
 
258
268
  # Modify frontmatter `BLESSING'
259
- target_docs.each do |filename, frontmatter, pos|
260
- $stderr.puts "Blessing #{filename}..."
261
- bless frontmatter
269
+ target_docs.each do |doc|
270
+ $stderr.puts "Blessing #{doc.filename}..."
271
+ bless doc.frontmatter
272
+ end
273
+
274
+ if !@singlemode && @preflight
275
+ $stderr.puts "Checking metadata modification..."
276
+ target_docs.each {|doc| doc.mark_meta_modified }
277
+ return # Resign processing document in preflight mode.
262
278
  end
263
279
 
264
280
  # Ready.
265
281
  $stderr.puts "Okay, Now ready. Process documents..."
266
282
 
267
283
  # Proccess documents
268
- target_docs.each do |filename, frontmatter, pos|
269
- ext = File.extname filename
270
- ENV["pbsimply_currentdoc"] = File.join(@workdir, "current_document#{ext}")
271
- ENV["pbsimply_filename"] = filename
272
- @index = frontmatter
273
- File.open(File.join(@dir, filename)) do |f|
274
- f.seek(pos)
275
- doc_content = f.read
276
- if @config["unicode_normalize"] && !frontmatter["skip_normalize"]
277
- doc_content.unicode_normalize!(@config["unicode_normalize"].to_sym)
278
- end
279
- File.open(File.join(@workdir, "current_document#{ext}"), "w") {|fo| fo.write doc_content }
280
- end
281
-
282
- $stderr.puts "Processing #{filename}"
283
- generate(@dir, filename, frontmatter)
284
+ target_docs.each do |doc|
285
+ ENV["pbsimply_currentdoc"] = File.join(@workdir, "current_document#{doc.ext}")
286
+ ENV["pbsimply_filename"] = doc.filename
287
+ @index = doc.frontmatter
288
+ doc.read_document(workdir: @workdir)
289
+
290
+ $stderr.puts "Processing #{doc.filename}"
291
+ generate(doc)
284
292
  end
285
293
 
286
294
  # Call post plugins
@@ -337,11 +345,20 @@ class PBSimply
337
345
  ENV["pbsimply_frontmatter"] = @workfile_frontmatter
338
346
  @workfile_pandoc_defaultfiles ||= File.join(@workdir, "pbsimply-defaultfiles.yaml")
339
347
  # If target file is regular file, run as single mode.
340
- @singlemode = true if File.file?(@dir)
348
+ @singlemode = File.file?(@dir)
349
+
350
+ if @accs_only && !@accs_processing
351
+ accs_only_mode_check
341
352
 
342
- # Check single file mode.
343
- if @singlemode
353
+ # Process ACCS without regular generating document
354
+ setup_config(@dir)
355
+ load_index
356
+
357
+ process_accs
358
+ elsif @singlemode # Check single file mode.
344
359
  # Single file mode
360
+ return if @preflight
361
+
345
362
  if @dir =~ %r:(.*)/([^/]+):
346
363
  dir = $1
347
364
  filename = $2
@@ -354,14 +371,13 @@ class PBSimply
354
371
 
355
372
  load_index
356
373
 
357
- frontmatter, pos = read_frontmatter(dir, filename)
358
- frontmatter = @frontmatter.merge frontmatter
359
- @index = frontmatter
374
+ doc = Document.new(@config, dir, filename, @frontmatter, @now)
375
+ @index = doc.frontmatter
360
376
 
361
- proc_docs([[filename, frontmatter, pos]])
377
+ proc_docs([doc])
362
378
 
363
379
  if File.exist?(File.join(@dir, ".accs.yaml")) && !@accs_processing && !@skip_accs
364
- single_accs filename, frontmatter
380
+ single_accs doc.filename, doc.frontmatter
365
381
  end
366
382
  else
367
383
  # Normal (directory) mode.
@@ -379,13 +395,14 @@ class PBSimply
379
395
  @workfile_pandoc_defaultfiles = nil
380
396
  end
381
397
 
382
- def generate(dir, filename, frontmatter)
398
+ def generate(doc)
399
+ dir, filename, frontmatter = *doc.to_a
383
400
  print_fileproc_msg(filename) # at sub-class
384
401
 
385
402
  # Preparing and pre script.
386
- orig_filepath = [dir, filename].join("/")
387
- ext = File.extname(filename)
388
- procdoc = File.join(@workdir, "current_document#{ext}")
403
+ orig_filepath = doc.orig_filepath
404
+ ext = doc.ext
405
+ procdoc = doc.proc_doc_path
389
406
 
390
407
  pre_plugins(procdoc, frontmatter)
391
408
  @hooks.pre.run({procdoc: procdoc, frontmatter: frontmatter})
@@ -454,41 +471,12 @@ class PBSimply
454
471
  end
455
472
  end
456
473
 
457
- # Check is the article modified? (or force update?)
458
- def check_modify(filename, frontmatter)
459
- modify = true
460
- index = @indexes_orig[filename]&.dup || {}
461
-
462
- case @config["detect_modification"]
463
- when "changes"
464
- # Use "changes"
465
- modify = false if frontmatter["changes"] == index["changes"]
466
- when "mtimesize"
467
- # Use mtime and file size.
468
- modify = false if frontmatter["_mtime"] <= (index["_last_proced"] || 0) && frontmatter["_size"] == index["_size"]
469
- else
470
- # Default method, use mtime.
471
- modify = false if frontmatter["_mtime"] <= (index["_last_proced"] || 0)
472
- end
473
-
474
-
475
- if modify
476
- $stderr.puts "#{filename} last modified at #{frontmatter["_mtime"]}, last processed at #{@indexes_orig[filename]&.[]("_last_proced") || 0}"
477
- else
478
- $stderr.puts "#{filename} is not modified."
474
+ def accs_only_mode_check
475
+ unless File.exist?(File.join(@dir, ".accs.yaml"))
476
+ raise CommandLineError.new "ACCS-only processing mode can only be performed on the ACCS directory."
479
477
  end
480
-
481
- frontmatter["_last_proced"] = @now.to_i
482
- frontmatter["last_update"] = @now.strftime("%Y-%m-%d %H:%M:%S")
483
-
484
- if frontmatter["skip_update"]
485
- # Document specific skip update
486
- false
487
- elsif @refresh
488
- # Refresh (force update) mode.
489
- true
490
- else
491
- modify
478
+ unless File.directory?(@dir)
479
+ raise CommandLineError.new "ACCS-only processing needs ACCS directory as an argument."
492
480
  end
493
481
  end
494
482
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pbsimply
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.1
4
+ version: 3.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Haruka
@@ -36,6 +36,7 @@ files:
36
36
  - lib/pbsimply/docengine/misc.rb
37
37
  - lib/pbsimply/docengine/pandoc.rb
38
38
  - lib/pbsimply/docengine/rdoc.rb
39
+ - lib/pbsimply/document.rb
39
40
  - lib/pbsimply/frontmatter.rb
40
41
  - lib/pbsimply/hooks.rb
41
42
  - lib/pbsimply/plugger.rb