Class: PBSimply

Inherits:
Object
  • Object
show all
Includes:
ACCS, Frontmatter, Plugger, Prayer
Defined in:
lib/pbsimply/docengine/pandoc.rb,
lib/pbsimply.rb,
lib/pbsimply/docdb.rb,
lib/pbsimply/docengine/misc.rb,
lib/pbsimply/docengine/rdoc.rb,
lib/pbsimply/docengine/docutils.rb

Overview

DOCUMENT PROCESSORS #

Defined Under Namespace

Modules: ACCS, Frontmatter, Plugger, Prayer, Processor Classes: CustomYAML, DocDB, Hooks

Constant Summary

Constants included from ACCS

ACCS::DEFINITIONS, ACCS::INDEX

Constants included from Plugger

Plugger::POST_PROCESSORS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ACCS

#accsmode, #process_accs, #single_accs

Methods included from Frontmatter

#read_frontmatter

Methods included from Plugger

#post_plugins, #pre_plugins

Methods included from Prayer

#autobless, #bless, #bless_cmd, #bless_ruby

Constructor Details

#initialize(config) ⇒ PBSimply

Returns a new instance of PBSimply.



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/pbsimply.rb', line 96

def initialize(config)
  @config = config
  @docobject = {}
  @this_time_processed = []

  # --metadata-file
  @frontmatter = {}

  @refresh = false # Force generate all documents.
  @skip_index = false # Don't register to index.
  @outfile = nil # Fixed output filename
  @add_meta = nil
  @accs = nil
  @accs_index = {}
  @now = Time.now
  @hooks = PBSimply::Hooks.new(self, @config)
end

Instance Attribute Details

#indexesObject (readonly)

Returns the value of attribute indexes.



156
157
158
# File 'lib/pbsimply.rb', line 156

def indexes
  @indexes
end

Class Method Details

.load_configObject

Load config file.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/pbsimply.rb', line 41

def self.load_config
  config = nil
  begin
    File.open(".pbsimply.yaml") do |f|
      config = Psych.unsafe_load(f)
    end
  rescue
    abort "Failed to load config file (./.pbsimply.yaml)"
  end

  # Required values
  config["outdir"] or abort "Output directory is not set (outdir)."
  config["template"] ||= "./template.html"

  config
end

Instance Method Details

#delete_missingObject

Delete missing source



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/pbsimply.rb', line 280

def delete_missing
  return unless @indexes
  STDERR.puts "Checking missing article..."
  missing_keys = []
  @indexes.each do |k, v|
    next if !v["source_path"] || !v["dest_path"]
    unless File.exist? v["source_path"]
      STDERR.puts "#{k} is missing."
      missing_keys.push k
      @hooks.delete.run({target_file_path: v["dest_path"] ,source_file_path: v["source_path"]})
      File.delete v["dest_path"] if @config["auto_delete"]
    end
  end
  missing_keys.each {|k| @indexes.delete k }
end

#delete_turn_draft(draft_articles) ⇒ Object

Delete turn to draft article.



263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/pbsimply.rb', line 263

def delete_turn_draft draft_articles
  STDERR.puts "Checking turn to draft..."
  draft_articles.each do |dah|
    df = dah[:article_filename]
    [df, (df + ".html"), File.basename(df, ".*"), (File.basename(df, ".*") + ".html")].each do |tfn|
      tfp = File.join(@config["outdir"], @dir, tfn)
      if File.file?(tfp)
        STDERR.puts "#{df} was turn to draft."
        @hooks.delete.run({target_file_path: tfp, source_file_path: dah[:source_file_path]})
        File.delete tfp if @config["auto_delete"]
      end
    end
    @indexes.delete df if @indexes[df]
  end
end

#docObject

Accessor reader.



152
153
154
# File 'lib/pbsimply.rb', line 152

def doc
  @docobject
end

#generate(dir, filename, frontmatter) ⇒ Object



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/pbsimply.rb', line 348

def generate(dir, filename, frontmatter)
  print_fileproc_msg(filename) # at sub-class

  # Preparing and pre script.
  orig_filepath = [dir, filename].join("/")
  ext = File.extname(filename)
  procdoc = File.join(@workdir, "current_document#{ext}")

  pre_plugins(procdoc, frontmatter)
  @hooks.pre.run({procdoc: procdoc, frontmatter: frontmatter})

  doc = process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc) # at sub-class

  ##### Post eRuby
  if @config["post_eruby"]
    STDERR.puts "Porcessing with eRuby."
    doc = ERB.new(doc, nil, "%<>").result(binding)
  end

  # Write out
  outpath = frontmatter["dest_path"]

  File.open(outpath, "w") do |f|
    f.write(doc)
  end

  # Hooks for processed document.
  @hooks.process.run({
    outpath: outpath,
    frontmatter: frontmatter,
    procdoc: procdoc
  })

  # Mark processed
  @this_time_processed.push({source: orig_filepath, dest: outpath, frontmatter: frontmatter})
end

#load_indexObject

Load document index database (.indexes.$ext).



137
138
139
140
141
142
143
144
145
# File 'lib/pbsimply.rb', line 137

def load_index
  if @db.exist?
    @indexes = @db.load
  else
    @indexes = Hash.new
  end
  @docobject[:indexes] = @indexes
  ENV["pbsimply_indexes"] = @db.path
end

#mainObject

Run PureBuilder Simply.



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/pbsimply.rb', line 297

def main
  @hooks.load
  Dir.mktmpdir("pbsimply") do |dir|
    ENV["pbsimply_working_dir"] = dir
    @workdir ||= dir
    @workfile_frontmatter ||= File.join(@workdir, "pbsimply-frontmatter.json")
    ENV["pbsimply_frontmatter"] = @workfile_frontmatter
    @workfile_pandoc_defaultfiles ||= File.join(@workdir, "pbsimply-defaultfiles.yaml")
    # If target file is regular file, run as single mode.
    @singlemode = true if File.file?(@dir)

    # Check single file mode.
    if @singlemode
      # Single file mode
      if @dir =~ %r:(.*)/([^/]+):
        dir = $1
        filename = $2
      else
        dir = "."
        filename = @dir
      end
      @dir = dir
      setup_config(dir)

      load_index

      frontmatter, pos = read_frontmatter(dir, filename)
      frontmatter = @frontmatter.merge frontmatter
      @index = frontmatter

      proc_docs([[filename, frontmatter, pos]])

      if File.exist?(File.join(@dir, ".accs.yaml")) && !@accs_processing && !@skip_accs
        single_accs filename, frontmatter
      end
    else
      # Normal (directory) mode.
      setup_config(@dir)
      load_index

      @accs = true if File.exist?(File.join(@dir, ".accs.yaml"))

      proc_dir
    end
  end
ensure
  @workdir = nil
  @workfile_frontmatter = nil
  @workfile_pandoc_defaultfiles = nil
end

#proc_dirObject

Directory mode’s main function. Read Frontmatters from all documents and proc each documents.



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/pbsimply.rb', line 164

def proc_dir
  draft_articles = []
  target_docs = []
  @indexes_orig = {}
  STDERR.puts "in #{@dir}..."

  STDERR.puts "Checking Frontmatter..."
  Dir.foreach(@dir) do |filename|
    next if filename == "." || filename == ".." || filename == ".index.md"
    if filename =~ /^\./ || filename =~ /^draft-/
      draft_articles.push({
        article_filename: filename.sub(/^(?:\.|draft-)/, ""),
        filename: filename,
        source_file_path: File.join(@dir, filename)
      })
      next
    end

    if !@ignore_ext and not target_file_extensions.include? File.extname filename
      next
    end

    STDERR.puts "Checking frontmatter in #{filename}"
    frontmatter, pos = read_frontmatter(@dir, filename)
    frontmatter = @frontmatter.merge frontmatter
    frontmatter.merge!(@add_meta) if @add_meta

    if frontmatter["draft"]
      draft_articles.push({
        article_filename: filename,
        filename: filename,
        source_file_path: File.join(@dir, filename)
      })
      next
    end

    @indexes_orig[filename] = @indexes[filename]
    @indexes[filename] = frontmatter

    # Push to target documents without checking modification.
    target_docs.push([filename, frontmatter, pos])
  end
  ENV.delete("pbsimply_currentdoc")
  ENV.delete("pbsimply_filename")

  delete_turn_draft draft_articles

  proc_docs target_docs

  delete_missing

  # Save index.
  @db.dump(@indexes) unless @skip_index

  # ACCS processing
  if @accs && !target_docs.empty?
    process_accs
  end
end

#proc_docs(target_docs) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/pbsimply.rb', line 224

def proc_docs target_docs
  # Exclude unchanged documents.
  if @indexes && @indexes_orig
    STDERR.puts "Checking modification..."
    target_docs.delete_if {|filename, frontmatter, pos| !check_modify(filename, frontmatter)}
  end

  # Modify frontmatter `BLESSING'
  target_docs.each do |filename, frontmatter, pos|
    STDERR.puts "Blessing #{filename}..."
    bless frontmatter
  end

  # Ready.
  STDERR.puts "Okay, Now ready. Process documents..."

  # Proccess documents
  target_docs.each do |filename, frontmatter, pos|
    ext = File.extname filename
    ENV["pbsimply_currentdoc"] = File.join(@workdir, "current_document#{ext}")
    ENV["pbsimply_filename"] = filename
    @index = frontmatter
    File.open(File.join(@dir, filename)) do |f|
      f.seek(pos)
      File.open(File.join(@workdir, "current_document#{ext}"), "w") {|fo| fo.write f.read}
    end

    STDERR.puts "Processing #{filename}"
    generate(@dir, filename, frontmatter)
  end
  
  # Call post plugins
  post_plugins

  # Call hooks
  @hooks.post.run({this_time_processed: @this_time_processed})
end

#setup_config(dir) ⇒ Object

initialize phase,



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/pbsimply.rb', line 59

def setup_config(dir)
  ENV["pbsimply_outdir"] = @config["outdir"]
  @docobject[:config] = @config

  if @singlemode
    outdir = [@config["outdir"], @dir.sub(%r:/[^/]*$:, "")].join("/")
  else
    outdir = [@config["outdir"], @dir].join("/")
  end

  # Format for Indexes database
  @db = case @config["dbstyle"]
  when "yaml"
    DocDB::YAML.new(dir)
  when "json"
    DocDB::JSON.new(dir)
  when "oj"
    DocDB::Oj.new(dir)
  when "marshal"
    DocDB::Marshal.new(dir)
  else
    DocDB::Marshal.new(dir)
  end

  @frontmatter.merge!(@config["default_meta"]) if @config["default_meta"]

  # Merge ACCS Frontmatter
  if @accs_processing && @config["alt_frontmatter"]
    @frontmatter.merge!(@config["alt_frontmatter"])
  end

  unless File.exist? outdir
    STDERR.puts "destination directory is not exist. creating (only one step.)"
    FileUtils.mkdir_p outdir
  end
end

#target_file_extensionsObject



147
148
149
# File 'lib/pbsimply.rb', line 147

def target_file_extensions
  [".md"]
end

#treat_cmdline(dir = nil) ⇒ Object

Process command-line



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/pbsimply.rb', line 115

def treat_cmdline(dir=nil)
  # Options definition.
  opts = OptionParser.new
  opts.on("-f", "--force-refresh") { @refresh = true }
  opts.on("-X", "--ignore-ext") { @ignore_ext = true }
  opts.on("-I", "--skip-index") { @skip_index = true }
  opts.on("-A", "--skip-accs") { @skip_accs = true }
  opts.on("-o FILE", "--output") {|v| @outfile = v }
  opts.on("-m FILE", "--additional-metafile") {|v| @add_meta = Psych.unsafe_load(File.read(v))}
  opts.parse!(ARGV)

  if File.exist?(".pbsimply-bless.rb")
    require "./.pbsimply-bless.rb"
  end

  # Set target directory.
  @dir = ARGV.shift unless dir
  @dir ||= "."
  ENV["pbsimply_subdir"] = @dir
end