pbsimply 2.0.1 → 3.0.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 +4 -4
- data/bin/pbsimply +3 -0
- data/bin/pbsimply-testserver +1 -1
- data/lib/pbsimply/accs.rb +110 -0
- data/lib/pbsimply/docdb.rb +83 -0
- data/lib/pbsimply/docengine/base.rb +5 -0
- data/lib/pbsimply/docengine/docutils.rb +60 -0
- data/lib/pbsimply/docengine/misc.rb +84 -0
- data/lib/pbsimply/docengine/pandoc.rb +80 -0
- data/lib/pbsimply/docengine/rdoc.rb +62 -0
- data/lib/pbsimply/frontmatter.rb +204 -0
- data/lib/pbsimply/hooks.rb +85 -0
- data/lib/pbsimply/plugger.rb +77 -0
- data/lib/pbsimply/prayer.rb +107 -0
- data/lib/pbsimply.rb +153 -805
- metadata +15 -4
    
        data/lib/pbsimply.rb
    CHANGED
    
    | @@ -1,11 +1,29 @@ | |
| 1 1 | 
             
            #!/bin/env ruby
         | 
| 2 | 
            +
             | 
| 2 3 | 
             
            require 'yaml'
         | 
| 3 4 | 
             
            require 'erb'
         | 
| 4 5 | 
             
            require 'date'
         | 
| 6 | 
            +
            require 'time'
         | 
| 7 | 
            +
            require 'tmpdir'
         | 
| 5 8 | 
             
            require 'fileutils'
         | 
| 6 9 | 
             
            require 'optparse'
         | 
| 10 | 
            +
            require 'digest/sha1'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            # PureBuilder Simply Components
         | 
| 13 | 
            +
            require 'pbsimply/docdb'
         | 
| 14 | 
            +
            require 'pbsimply/docengine/base'
         | 
| 15 | 
            +
            require 'pbsimply/prayer'
         | 
| 16 | 
            +
            require 'pbsimply/plugger'
         | 
| 17 | 
            +
            require 'pbsimply/hooks'
         | 
| 18 | 
            +
            require 'pbsimply/frontmatter'
         | 
| 19 | 
            +
            require 'pbsimply/accs'
         | 
| 7 20 |  | 
| 8 21 | 
             
            class PBSimply
         | 
| 22 | 
            +
              include Prayer
         | 
| 23 | 
            +
              include Plugger
         | 
| 24 | 
            +
              include Frontmatter
         | 
| 25 | 
            +
              include ACCS
         | 
| 26 | 
            +
             | 
| 9 27 | 
             
              # Use Oj as JSON library for frontmatter passing if possible.
         | 
| 10 28 | 
             
              begin
         | 
| 11 29 | 
             
                require 'oj'
         | 
| @@ -15,141 +33,6 @@ class PBSimply | |
| 15 33 | 
             
                JSON_LIB = JSON
         | 
| 16 34 | 
             
              end
         | 
| 17 35 |  | 
| 18 | 
            -
              # ACCS namespace.
         | 
| 19 | 
            -
              module ACCS
         | 
| 20 | 
            -
                DEFINITIONS = {}
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                # Built-in Accs index eRuby string.
         | 
| 23 | 
            -
                INDEX = <<'EOF'
         | 
| 24 | 
            -
            <%= YAML.dump(
         | 
| 25 | 
            -
              {
         | 
| 26 | 
            -
                "title" => @index["title"],
         | 
| 27 | 
            -
                "date" => @index["date"],
         | 
| 28 | 
            -
                "author" => @index["author"]
         | 
| 29 | 
            -
              }
         | 
| 30 | 
            -
            ) %>
         | 
| 31 | 
            -
            ---
         | 
| 32 | 
            -
             | 
| 33 | 
            -
            <%
         | 
| 34 | 
            -
            articles = Hash.new {|h,k| h[k] = Array.new }
         | 
| 35 | 
            -
             | 
| 36 | 
            -
            if @config["accs_across_category"]
         | 
| 37 | 
            -
              @indexes.each {|filename, index| articles["default"].push index }
         | 
| 38 | 
            -
            else
         | 
| 39 | 
            -
              @indexes.each {|filename, index| articles[(index["category"] || "default")].push index }
         | 
| 40 | 
            -
            end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
            %>
         | 
| 43 | 
            -
             | 
| 44 | 
            -
            % articles.keys.sort.each do |catname|
         | 
| 45 | 
            -
            % cat = articles[catname]
         | 
| 46 | 
            -
             | 
| 47 | 
            -
            % unless articles.length == 1
         | 
| 48 | 
            -
            # <%= catname %>
         | 
| 49 | 
            -
            % end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
            <%
         | 
| 52 | 
            -
              sort_method = case @config["accs_sort_by"]
         | 
| 53 | 
            -
              when "title"
         | 
| 54 | 
            -
                lambda {|i| [i["title"].to_s, i["date"]] }
         | 
| 55 | 
            -
              when "name"
         | 
| 56 | 
            -
                lambda {|i| [i["_filename"].to_s, i["title"].to_s, i["date"]] }
         | 
| 57 | 
            -
              when "serial"
         | 
| 58 | 
            -
                lambda {|i| [i["serial"].to_s, i["date"], i["_filename"].to_s] }
         | 
| 59 | 
            -
              else
         | 
| 60 | 
            -
                lambda {|i| [i["date"], i["title"].to_s, i["_last_update"].to_i] }
         | 
| 61 | 
            -
              end
         | 
| 62 | 
            -
             | 
| 63 | 
            -
              list = if @config["accs_order"] == "desc"
         | 
| 64 | 
            -
                cat.sort_by(&sort_method).reverse
         | 
| 65 | 
            -
              else
         | 
| 66 | 
            -
                cat.sort_by(&sort_method)
         | 
| 67 | 
            -
              end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
              list.each do |i|
         | 
| 70 | 
            -
            %>* [<%= i["title"] %>](<%= i["page_url"] %>)
         | 
| 71 | 
            -
            <% end %>
         | 
| 72 | 
            -
             | 
| 73 | 
            -
            % end
         | 
| 74 | 
            -
            EOF
         | 
| 75 | 
            -
              end
         | 
| 76 | 
            -
             | 
| 77 | 
            -
              # Abstruct super class.
         | 
| 78 | 
            -
              class DocDB
         | 
| 79 | 
            -
                def dump(object)
         | 
| 80 | 
            -
                  File.open(File.join(@dir, ".indexes.#{@ext}"), "w") do |f|
         | 
| 81 | 
            -
                    f.write @store_class.dump(object)
         | 
| 82 | 
            -
                  end
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                def load
         | 
| 86 | 
            -
                  File.open(File.join(@dir, ".indexes.#{@ext}"), "r") do |f|
         | 
| 87 | 
            -
                    next @store_class.load(f)
         | 
| 88 | 
            -
                  end
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                def exist?
         | 
| 92 | 
            -
                  File.exist?(File.join(@dir, ".indexes.#{@ext}"))
         | 
| 93 | 
            -
                end
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                def path
         | 
| 96 | 
            -
                  File.join(@dir, ".indexes.#{@ext}")
         | 
| 97 | 
            -
                end
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                def cmp_obj(frontmatter)
         | 
| 100 | 
            -
                  @store_class.load(@store_class.dump(frontmatter))
         | 
| 101 | 
            -
                end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                class Marshal < DocDB
         | 
| 104 | 
            -
                  def initialize(dir)
         | 
| 105 | 
            -
                    @dir = dir
         | 
| 106 | 
            -
                    @store_class = ::Marshal
         | 
| 107 | 
            -
                    @ext = "rbm"
         | 
| 108 | 
            -
                  end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                  def cmp_obj(frontmatter)
         | 
| 111 | 
            -
                    frontmatter.dup
         | 
| 112 | 
            -
                  end
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                class JSON < DocDB
         | 
| 116 | 
            -
                  def initialize(dir)
         | 
| 117 | 
            -
                    @dir = dir
         | 
| 118 | 
            -
                    @store_class = ::JSON
         | 
| 119 | 
            -
                    @ext = "json"
         | 
| 120 | 
            -
                  end
         | 
| 121 | 
            -
                end
         | 
| 122 | 
            -
             | 
| 123 | 
            -
                class Oj < DocDB::JSON
         | 
| 124 | 
            -
                  def initialize(dir)
         | 
| 125 | 
            -
                    require 'oj'
         | 
| 126 | 
            -
                    @dir = dir
         | 
| 127 | 
            -
                    @ext = "json"
         | 
| 128 | 
            -
                    @store_class = ::Oj
         | 
| 129 | 
            -
                  end
         | 
| 130 | 
            -
                end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                class YAML < DocDB
         | 
| 133 | 
            -
                  def initialize(dir)
         | 
| 134 | 
            -
                    @dir = dir
         | 
| 135 | 
            -
                    @store_class = ::YAML
         | 
| 136 | 
            -
                    @ext = "yaml"
         | 
| 137 | 
            -
                  end
         | 
| 138 | 
            -
                end
         | 
| 139 | 
            -
              end
         | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
              POST_PROCESSORS = {
         | 
| 143 | 
            -
                ".rb" => "ruby",
         | 
| 144 | 
            -
                ".pl" => "perl",
         | 
| 145 | 
            -
                ".py" => "python",
         | 
| 146 | 
            -
                ".lua" => "lua",
         | 
| 147 | 
            -
                ".bash" => "bash",
         | 
| 148 | 
            -
                ".zsh" => "zsh",
         | 
| 149 | 
            -
                ".php" => "php",
         | 
| 150 | 
            -
                ".sed" => ["sed", ->(script, target) { ["-f", script, target] } ]
         | 
| 151 | 
            -
              }
         | 
| 152 | 
            -
             | 
| 153 36 | 
             
              ###############################################
         | 
| 154 37 | 
             
              #               SETUP FUNCTIONS               #
         | 
| 155 38 | 
             
              ###############################################
         | 
| @@ -183,8 +66,6 @@ EOF | |
| 183 66 | 
             
                  outdir = [@config["outdir"], @dir].join("/")
         | 
| 184 67 | 
             
                end
         | 
| 185 68 |  | 
| 186 | 
            -
                p dir
         | 
| 187 | 
            -
             | 
| 188 69 | 
             
                # Format for Indexes database
         | 
| 189 70 | 
             
                @db = case @config["dbstyle"]
         | 
| 190 71 | 
             
                when "yaml"
         | 
| @@ -225,6 +106,7 @@ EOF | |
| 225 106 | 
             
                @accs = nil
         | 
| 226 107 | 
             
                @accs_index = {}
         | 
| 227 108 | 
             
                @now = Time.now
         | 
| 109 | 
            +
                @hooks = PBSimply::Hooks.new(self)
         | 
| 228 110 | 
             
              end
         | 
| 229 111 |  | 
| 230 112 | 
             
              # Process command-line
         | 
| @@ -234,6 +116,7 @@ EOF | |
| 234 116 | 
             
                opts.on("-f", "--force-refresh") { @refresh = true }
         | 
| 235 117 | 
             
                opts.on("-X", "--ignore-ext") { @ignore_ext = true }
         | 
| 236 118 | 
             
                opts.on("-I", "--skip-index") { @skip_index = true }
         | 
| 119 | 
            +
                opts.on("-A", "--skip-accs") { @skip_accs = true }
         | 
| 237 120 | 
             
                opts.on("-o FILE", "--output") {|v| @outfile = v }
         | 
| 238 121 | 
             
                opts.on("-m FILE", "--additional-metafile") {|v| @add_meta = Psych.unsafe_load(File.read(v))}
         | 
| 239 122 | 
             
                opts.parse!(ARGV)
         | 
| @@ -256,6 +139,7 @@ EOF | |
| 256 139 | 
             
                  @indexes = Hash.new
         | 
| 257 140 | 
             
                end
         | 
| 258 141 | 
             
                @docobject[:indexes] = @indexes
         | 
| 142 | 
            +
                ENV["pbsimply_indexes"] = @db.path
         | 
| 259 143 | 
             
              end
         | 
| 260 144 |  | 
| 261 145 | 
             
              def target_file_extensions
         | 
| @@ -269,7 +153,6 @@ EOF | |
| 269 153 |  | 
| 270 154 | 
             
              attr :indexes
         | 
| 271 155 |  | 
| 272 | 
            -
             | 
| 273 156 | 
             
              ###############################################
         | 
| 274 157 | 
             
              #            PROCESSING FUNCTIONS             #
         | 
| 275 158 | 
             
              ###############################################
         | 
| @@ -284,12 +167,15 @@ EOF | |
| 284 167 |  | 
| 285 168 | 
             
                STDERR.puts "Checking Frontmatter..."
         | 
| 286 169 | 
             
                Dir.foreach(@dir) do |filename|
         | 
| 287 | 
            -
                  next if filename == "." || filename == ".."
         | 
| 170 | 
            +
                  next if filename == "." || filename == ".." || filename == ".index.md"
         | 
| 288 171 | 
             
                  if filename =~ /^\./ || filename =~ /^draft-/
         | 
| 289 | 
            -
                    draft_articles.push | 
| 172 | 
            +
                    draft_articles.push({
         | 
| 173 | 
            +
                      article_filename: filename.sub(/^(?:\.|draft-)/, ""),
         | 
| 174 | 
            +
                      filename: filename,
         | 
| 175 | 
            +
                      source_file_path: File.join(@dir, filename)
         | 
| 176 | 
            +
                    })
         | 
| 290 177 | 
             
                    next
         | 
| 291 178 | 
             
                  end
         | 
| 292 | 
            -
                  next unless File.file?([@dir, filename].join("/"))
         | 
| 293 179 |  | 
| 294 180 | 
             
                  if !@ignore_ext and not target_file_extensions.include? File.extname filename
         | 
| 295 181 | 
             
                    next
         | 
| @@ -301,8 +187,11 @@ EOF | |
| 301 187 | 
             
                  frontmatter.merge!(@add_meta) if @add_meta
         | 
| 302 188 |  | 
| 303 189 | 
             
                  if frontmatter["draft"]
         | 
| 304 | 
            -
                     | 
| 305 | 
            -
             | 
| 190 | 
            +
                    draft_articles.push({
         | 
| 191 | 
            +
                      article_filename: filename,
         | 
| 192 | 
            +
                      filename: filename,
         | 
| 193 | 
            +
                      source_file_path: File.join(@dir, filename)
         | 
| 194 | 
            +
                    })
         | 
| 306 195 | 
             
                    next
         | 
| 307 196 | 
             
                  end
         | 
| 308 197 |  | 
| @@ -313,33 +202,35 @@ EOF | |
| 313 202 | 
             
                  target_docs.push([filename, frontmatter, pos])
         | 
| 314 203 | 
             
                end
         | 
| 315 204 |  | 
| 316 | 
            -
                 | 
| 317 | 
            -
             | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
                    File.delete tfp if File.file?(tfp)
         | 
| 322 | 
            -
                  end
         | 
| 323 | 
            -
                end
         | 
| 205 | 
            +
                delete_turn_draft draft_articles
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                proc_docs target_docs
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                delete_missing
         | 
| 324 210 |  | 
| 325 211 | 
             
                # Save index.
         | 
| 326 212 | 
             
                @db.dump(@indexes) unless @skip_index
         | 
| 327 213 |  | 
| 328 | 
            -
                 | 
| 329 | 
            -
             | 
| 330 | 
            -
             | 
| 331 | 
            -
                target_docs.each do |filename, frontmatter, pos|
         | 
| 332 | 
            -
                  if @config["bless_style"] == "cmd"
         | 
| 333 | 
            -
                    bless_cmd(frontmatter)
         | 
| 334 | 
            -
                  else
         | 
| 335 | 
            -
                    bless_ruby(frontmatter)
         | 
| 336 | 
            -
                  end
         | 
| 214 | 
            +
                # ACCS processing
         | 
| 215 | 
            +
                if @accs && !target_docs.empty?
         | 
| 216 | 
            +
                  process_accs
         | 
| 337 217 | 
             
                end
         | 
| 218 | 
            +
              end
         | 
| 338 219 |  | 
| 339 | 
            -
             | 
| 220 | 
            +
              def proc_docs target_docs
         | 
| 221 | 
            +
                # Exclude unchanged documents.
         | 
| 222 | 
            +
                if @indexes && @indexes_orig
         | 
| 223 | 
            +
                  STDERR.puts "Checking modification..."
         | 
| 224 | 
            +
                  target_docs.delete_if {|filename, frontmatter, pos| !check_modify([@dir, filename], frontmatter)}
         | 
| 225 | 
            +
                end
         | 
| 340 226 |  | 
| 341 | 
            -
                 | 
| 227 | 
            +
                # Modify frontmatter `BLESSING'
         | 
| 228 | 
            +
                target_docs.each do |filename, frontmatter, pos|
         | 
| 229 | 
            +
                  STDERR.puts "Blessing #{filename}..."
         | 
| 230 | 
            +
                  bless frontmatter
         | 
| 231 | 
            +
                end
         | 
| 342 232 |  | 
| 233 | 
            +
                # Ready.
         | 
| 343 234 | 
             
                STDERR.puts "Okay, Now ready. Process documents..."
         | 
| 344 235 |  | 
| 345 236 | 
             
                # Proccess documents
         | 
| @@ -348,135 +239,107 @@ EOF | |
| 348 239 | 
             
                  @index = frontmatter
         | 
| 349 240 | 
             
                  File.open(File.join(@dir, filename)) do |f|
         | 
| 350 241 | 
             
                    f.seek(pos)
         | 
| 351 | 
            -
                    File.open(" | 
| 242 | 
            +
                    File.open(File.join(@workdir, "current_document#{ext}"), "w") {|fo| fo.write f.read}
         | 
| 352 243 | 
             
                  end
         | 
| 353 244 |  | 
| 354 245 | 
             
                  STDERR.puts "Processing #{filename}"
         | 
| 355 246 | 
             
                  generate(@dir, filename, frontmatter)
         | 
| 356 247 | 
             
                end
         | 
| 357 | 
            -
             | 
| 358 | 
            -
                 | 
| 359 | 
            -
             | 
| 248 | 
            +
                
         | 
| 249 | 
            +
                # Call post plugins
         | 
| 360 250 | 
             
                post_plugins
         | 
| 361 251 |  | 
| 362 | 
            -
                #  | 
| 363 | 
            -
                 | 
| 364 | 
            -
                  process_accs
         | 
| 365 | 
            -
                end
         | 
| 252 | 
            +
                # Call hooks
         | 
| 253 | 
            +
                @hooks.post.run({this_time_processed: @this_time_processed})
         | 
| 366 254 | 
             
              end
         | 
| 367 255 |  | 
| 368 | 
            -
              #  | 
| 369 | 
            -
              def  | 
| 370 | 
            -
                 | 
| 371 | 
            -
                 | 
| 372 | 
            -
             | 
| 373 | 
            -
             | 
| 374 | 
            -
             | 
| 375 | 
            -
             | 
| 376 | 
            -
             | 
| 377 | 
            -
             | 
| 378 | 
            -
             | 
| 379 | 
            -
             | 
| 380 | 
            -
                    dir = "."
         | 
| 381 | 
            -
                    filename = @dir
         | 
| 256 | 
            +
              # Delete turn to draft article.
         | 
| 257 | 
            +
              def delete_turn_draft draft_articles
         | 
| 258 | 
            +
                STDERR.puts "Checking turn to draft..."
         | 
| 259 | 
            +
                draft_articles.each do |dah|
         | 
| 260 | 
            +
                  df = dah[:article_filename]
         | 
| 261 | 
            +
                  [df, (df + ".html"), File.basename(df, ".*"), (File.basename(df, ".*") + ".html")].each do |tfn|
         | 
| 262 | 
            +
                    tfp = File.join(@config["outdir"], @dir, tfn)
         | 
| 263 | 
            +
                    if File.file?(tfp)
         | 
| 264 | 
            +
                      STDERR.puts "#{df} was turn to draft."
         | 
| 265 | 
            +
                      @hooks.delete.run({target_file_path: tfp, source_file_path: dah[:source_file_path]})
         | 
| 266 | 
            +
                      File.delete tfp if @config["auto_delete"]
         | 
| 267 | 
            +
                    end
         | 
| 382 268 | 
             
                  end
         | 
| 383 | 
            -
                  @ | 
| 384 | 
            -
             | 
| 269 | 
            +
                  @indexes.delete df if @indexes[df]
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
              end
         | 
| 385 272 |  | 
| 386 | 
            -
             | 
| 273 | 
            +
              # Delete missing source
         | 
| 274 | 
            +
              def delete_missing
         | 
| 275 | 
            +
                return unless @indexes
         | 
| 276 | 
            +
                STDERR.puts "Checking missing article..."
         | 
| 277 | 
            +
                missing_keys = []
         | 
| 278 | 
            +
                @indexes.each do |k, v|
         | 
| 279 | 
            +
                  next if !v["source_path"] || !v["dest_path"]
         | 
| 280 | 
            +
                  unless File.exist? v["source_path"]
         | 
| 281 | 
            +
                    STDERR.puts "#{k} is missing."
         | 
| 282 | 
            +
                    missing_keys.push k
         | 
| 283 | 
            +
                    @hooks.delete.run({target_file_path: v["dest_path"] ,source_file_path: v["source_path"]})
         | 
| 284 | 
            +
                    File.delete v["dest_path"] if @config["auto_delete"]
         | 
| 285 | 
            +
                  end
         | 
| 286 | 
            +
                end
         | 
| 287 | 
            +
                missing_keys.each {|k| @indexes.delete k }
         | 
| 288 | 
            +
              end
         | 
| 387 289 |  | 
| 388 | 
            -
             | 
| 389 | 
            -
             | 
| 390 | 
            -
             | 
| 290 | 
            +
              # Run PureBuilder Simply.
         | 
| 291 | 
            +
              def main
         | 
| 292 | 
            +
                @hooks.load
         | 
| 293 | 
            +
                Dir.mktmpdir("pbsimply") do |dir|
         | 
| 294 | 
            +
                  ENV["pbsimply_working_dir"] = dir
         | 
| 295 | 
            +
                  @workdir ||= dir
         | 
| 296 | 
            +
                  @workfile_frontmatter ||= File.join(@workdir, "pbsimply-frontmatter.json")
         | 
| 297 | 
            +
                  ENV["pbsimply_frontmatter"] = @workfile_frontmatter
         | 
| 298 | 
            +
                  @workfile_pandoc_defaultfiles ||= File.join(@workdir, "pbsimply-defaultfiles.yaml")
         | 
| 299 | 
            +
                  # If target file is regular file, run as single mode.
         | 
| 300 | 
            +
                  @singlemode = true if File.file?(@dir)
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                  # Check single file mode.
         | 
| 303 | 
            +
                  if @singlemode
         | 
| 304 | 
            +
                    # Single file mode
         | 
| 305 | 
            +
                    if @dir =~ %r:(.*)/([^/]+):
         | 
| 306 | 
            +
                      dir = $1
         | 
| 307 | 
            +
                      filename = $2
         | 
| 308 | 
            +
                    else
         | 
| 309 | 
            +
                      dir = "."
         | 
| 310 | 
            +
                      filename = @dir
         | 
| 311 | 
            +
                    end
         | 
| 312 | 
            +
                    @dir = dir
         | 
| 313 | 
            +
                    setup_config(dir)
         | 
| 391 314 |  | 
| 392 | 
            -
             | 
| 393 | 
            -
                  File.open(File.join(dir, filename)) do |f|
         | 
| 394 | 
            -
                    f.seek(pos)
         | 
| 395 | 
            -
                    File.open(".current_document#{ext}", "w") {|fo| fo.write f.read}
         | 
| 396 | 
            -
                  end
         | 
| 315 | 
            +
                    load_index
         | 
| 397 316 |  | 
| 398 | 
            -
             | 
| 317 | 
            +
                    frontmatter, pos = read_frontmatter(dir, filename)
         | 
| 318 | 
            +
                    frontmatter = @frontmatter.merge frontmatter
         | 
| 319 | 
            +
                    @index = frontmatter
         | 
| 399 320 |  | 
| 400 | 
            -
             | 
| 321 | 
            +
                    proc_docs([[filename, frontmatter, pos]])
         | 
| 401 322 |  | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 404 | 
            -
             | 
| 405 | 
            -
                   | 
| 323 | 
            +
                    if File.exist?(File.join(@dir, ".accs.yaml")) && !@accs_processing && !@skip_accs
         | 
| 324 | 
            +
                      single_accs filename, frontmatter
         | 
| 325 | 
            +
                    end
         | 
| 326 | 
            +
                  else
         | 
| 327 | 
            +
                    # Normal (directory) mode.
         | 
| 328 | 
            +
                    setup_config(@dir)
         | 
| 329 | 
            +
                    load_index
         | 
| 406 330 |  | 
| 407 | 
            -
             | 
| 331 | 
            +
                    @accs = true if File.exist?(File.join(@dir, ".accs.yaml"))
         | 
| 408 332 |  | 
| 409 | 
            -
             | 
| 410 | 
            -
             | 
| 333 | 
            +
                    # Check existing in indexes.
         | 
| 334 | 
            +
                    @indexes.delete_if {|k,v| ! File.exist?([@dir, k].join("/")) }
         | 
| 411 335 |  | 
| 412 | 
            -
             | 
| 413 | 
            -
                end
         | 
| 414 | 
            -
              ensure
         | 
| 415 | 
            -
                # Clean up temporary files.
         | 
| 416 | 
            -
                Dir.children(".").each do |fn|
         | 
| 417 | 
            -
                  if fn[0, 22] == ".pbsimply-defaultfiles.yaml" or
         | 
| 418 | 
            -
                     fn[0, 21] == ".pbsimply-frontmatter" or
         | 
| 419 | 
            -
                     fn[0, 17] == ".current_document"
         | 
| 420 | 
            -
                    File.delete fn
         | 
| 421 | 
            -
                  end
         | 
| 422 | 
            -
                end
         | 
| 423 | 
            -
              end
         | 
| 424 | 
            -
             | 
| 425 | 
            -
              def pre_plugins(procdoc, frontmatter)
         | 
| 426 | 
            -
                if File.directory?(".pre_generate")
         | 
| 427 | 
            -
                  STDERR.puts("Processing with pre plugins")
         | 
| 428 | 
            -
                  script_file = File.join(".pre_generate", script_file)
         | 
| 429 | 
            -
                  Dir.entries(".pre_generate").sort.each do |script_file|
         | 
| 430 | 
            -
                    next if script_file =~ /^\./
         | 
| 431 | 
            -
                    STDERR.puts "Running script: #{File.basename script_file}"
         | 
| 432 | 
            -
                    pre_script_result = nil
         | 
| 433 | 
            -
                    script_cmdline = case
         | 
| 434 | 
            -
                    when File.executable?(script_file)
         | 
| 435 | 
            -
                      [script_file, procdoc]
         | 
| 436 | 
            -
                    when POST_PROCESSORS[File.extname(script_file)]
         | 
| 437 | 
            -
                      [POST_PROCESSORS[File.extname(script_file)], script_file, procdoc]
         | 
| 438 | 
            -
                    else
         | 
| 439 | 
            -
                      ["perl", script_file, procdoc]
         | 
| 440 | 
            -
                    end
         | 
| 441 | 
            -
                    IO.popen({"pbsimply_doc_frontmatter" => YAML.dump(frontmatter)}, script_cmdline) do |io|
         | 
| 442 | 
            -
                      pre_script_result = io.read
         | 
| 443 | 
            -
                    end
         | 
| 444 | 
            -
                    File.open(procdoc, "w") {|f| f.write pre_script_result}
         | 
| 445 | 
            -
                  end
         | 
| 446 | 
            -
                end
         | 
| 447 | 
            -
              end
         | 
| 448 | 
            -
             | 
| 449 | 
            -
              def post_plugins(frontmatter=nil)
         | 
| 450 | 
            -
                if File.directory?(".post_generate")
         | 
| 451 | 
            -
             | 
| 452 | 
            -
                  STDERR.puts("Processing with post plugins")
         | 
| 453 | 
            -
             | 
| 454 | 
            -
                  @this_time_processed.each do |v|
         | 
| 455 | 
            -
                    STDERR.puts "Processing #{v[:dest]} (from #{v[:source]})"
         | 
| 456 | 
            -
                    procdoc = v[:dest]
         | 
| 457 | 
            -
                    frontmatter ||= @indexes[File.basename v[:source]]
         | 
| 458 | 
            -
                    File.open(".pbsimply-frontmatter.json", "w") {|f| f.write JSON_LIB.dump(frontmatter)}
         | 
| 459 | 
            -
                    Dir.entries(".post_generate").sort.each do |script_file|
         | 
| 460 | 
            -
                      next if script_file =~ /^\./
         | 
| 461 | 
            -
                      STDERR.puts "Running script: #{script_file}"
         | 
| 462 | 
            -
                      script_file = File.join(".post_generate", script_file)
         | 
| 463 | 
            -
                      post_script_result = nil
         | 
| 464 | 
            -
                      script_cmdline = case
         | 
| 465 | 
            -
                      when File.executable?(script_file)
         | 
| 466 | 
            -
                        [script_file, procdoc]
         | 
| 467 | 
            -
                      when POST_PROCESSORS[File.extname(script_file)]
         | 
| 468 | 
            -
                        [POST_PROCESSORS[File.extname(script_file)], script_file, procdoc]
         | 
| 469 | 
            -
                      else
         | 
| 470 | 
            -
                        ["perl", script_file, procdoc]
         | 
| 471 | 
            -
                      end
         | 
| 472 | 
            -
                      IO.popen({"pbsimply_frontmatter" => ".pbsimply-frontmatter.json", "pbsimply_indexes" => @db.path}, script_cmdline) do |io|
         | 
| 473 | 
            -
                        post_script_result = io.read
         | 
| 474 | 
            -
                      end
         | 
| 475 | 
            -
             | 
| 476 | 
            -
                      File.open(procdoc, "w") {|f| f.write post_script_result}
         | 
| 477 | 
            -
                    end
         | 
| 336 | 
            +
                    proc_dir
         | 
| 478 337 | 
             
                  end
         | 
| 479 338 | 
             
                end
         | 
| 339 | 
            +
              ensure
         | 
| 340 | 
            +
                @workdir = nil
         | 
| 341 | 
            +
                @workfile_frontmatter = nil
         | 
| 342 | 
            +
                @workfile_pandoc_defaultfiles = nil
         | 
| 480 343 | 
             
              end
         | 
| 481 344 |  | 
| 482 345 | 
             
              def generate(dir, filename, frontmatter)
         | 
| @@ -485,8 +348,10 @@ EOF | |
| 485 348 | 
             
                # Preparing and pre script.
         | 
| 486 349 | 
             
                orig_filepath = [dir, filename].join("/")
         | 
| 487 350 | 
             
                ext = File.extname(filename)
         | 
| 488 | 
            -
                procdoc =  | 
| 351 | 
            +
                procdoc = File.join(@workdir, "current_document#{ext}")
         | 
| 352 | 
            +
             | 
| 489 353 | 
             
                pre_plugins(procdoc, frontmatter)
         | 
| 354 | 
            +
                @hooks.pre.run({procdoc: procdoc, frontmatter: frontmatter})
         | 
| 490 355 |  | 
| 491 356 | 
             
                doc = process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc) # at sub-class
         | 
| 492 357 |  | 
| @@ -497,54 +362,21 @@ EOF | |
| 497 362 | 
             
                end
         | 
| 498 363 |  | 
| 499 364 | 
             
                # Write out
         | 
| 500 | 
            -
                 | 
| 501 | 
            -
                outpath = case
         | 
| 502 | 
            -
                when @outfile
         | 
| 503 | 
            -
                  @outfile
         | 
| 504 | 
            -
                when @accs_processing
         | 
| 505 | 
            -
                  File.join(@config["outdir"], @dir, "index") + outext
         | 
| 506 | 
            -
                else
         | 
| 507 | 
            -
                  File.join(@config["outdir"], @dir, File.basename(filename, ".*")) + outext
         | 
| 508 | 
            -
                end
         | 
| 365 | 
            +
                outpath = frontmatter["dest_path"]
         | 
| 509 366 |  | 
| 510 367 | 
             
                File.open(outpath, "w") do |f|
         | 
| 511 368 | 
             
                  f.write(doc)
         | 
| 512 369 | 
             
                end
         | 
| 513 370 |  | 
| 514 | 
            -
                #  | 
| 515 | 
            -
                @ | 
| 516 | 
            -
             | 
| 517 | 
            -
             | 
| 518 | 
            -
             | 
| 519 | 
            -
             | 
| 520 | 
            -
              # This method called on the assumption that processed all documents and run as directory mode.
         | 
| 521 | 
            -
              def process_accs
         | 
| 522 | 
            -
                STDERR.puts "Processing ACCS index..."
         | 
| 523 | 
            -
                if File.exist?(File.join(@dir, ".accsindex.erb"))
         | 
| 524 | 
            -
                  erbtemplate = File.read(File.join(@dir, ".accsindex.erb"))
         | 
| 525 | 
            -
                elsif File.exist?(".accsindex.erb")
         | 
| 526 | 
            -
                  erbtemplate = File.read(".accsindex.erb")
         | 
| 527 | 
            -
                else
         | 
| 528 | 
            -
                  erbtemplate = ACCS::INDEX
         | 
| 529 | 
            -
                end
         | 
| 530 | 
            -
             | 
| 531 | 
            -
                # Get infomation
         | 
| 532 | 
            -
                @accs_index = Psych.unsafe_load(File.read([@dir, ".accs.yaml"].join("/")))
         | 
| 533 | 
            -
             | 
| 534 | 
            -
                @accs_index["title"] ||= (@config["accs_index_title"] || "Index")
         | 
| 535 | 
            -
                @accs_index["date"] ||= Time.now.strftime("%Y-%m-%d")
         | 
| 536 | 
            -
                @accs_index["pagetype"] = "accs_index"
         | 
| 537 | 
            -
             | 
| 538 | 
            -
                @index = @frontmatter.merge @accs_index
         | 
| 539 | 
            -
             | 
| 540 | 
            -
                doc = ERB.new(erbtemplate, trim_mode: "%<>").result(binding)
         | 
| 541 | 
            -
                File.open(File.join(@dir, ".index.md"), "w") do |f|
         | 
| 542 | 
            -
                  f.write doc
         | 
| 543 | 
            -
                end
         | 
| 371 | 
            +
                # Hooks for processed document.
         | 
| 372 | 
            +
                @hooks.process.run({
         | 
| 373 | 
            +
                  outpath: outpath,
         | 
| 374 | 
            +
                  frontmatter: frontmatter,
         | 
| 375 | 
            +
                  procdoc: procdoc
         | 
| 376 | 
            +
                })
         | 
| 544 377 |  | 
| 545 | 
            -
                 | 
| 546 | 
            -
                @ | 
| 547 | 
            -
                main
         | 
| 378 | 
            +
                # Mark processed
         | 
| 379 | 
            +
                @this_time_processed.push({source: orig_filepath, dest: outpath, frontmatter: frontmatter})
         | 
| 548 380 | 
             
              end
         | 
| 549 381 |  | 
| 550 382 | 
             
              ###############################################
         | 
| @@ -553,198 +385,21 @@ EOF | |
| 553 385 |  | 
| 554 386 | 
             
              private
         | 
| 555 387 |  | 
| 556 | 
            -
              # Turn on ACCS processing mode.
         | 
| 557 | 
            -
              def accsmode
         | 
| 558 | 
            -
                @accs_processing = true
         | 
| 559 | 
            -
                @singlemode = true
         | 
| 560 | 
            -
                @skip_index = true
         | 
| 561 | 
            -
              end
         | 
| 562 | 
            -
             | 
| 563 | 
            -
              # Read Frontmatter from the document.
         | 
| 564 | 
            -
              # This method returns frontmatter, pos.
         | 
| 565 | 
            -
              # pos means position at end of Frontmatter on the file.
         | 
| 566 | 
            -
              def read_frontmatter(dir, filename)
         | 
| 567 | 
            -
                frontmatter = nil
         | 
| 568 | 
            -
                pos = nil
         | 
| 569 | 
            -
             | 
| 570 | 
            -
                if File.exist? File.join(dir, ".meta." + filename)
         | 
| 571 | 
            -
                  # Load standalone metadata YAML.
         | 
| 572 | 
            -
                  frontmatter = Psych.unsafe_load(File.read(File.join(dir, (".meta." + filename))))
         | 
| 573 | 
            -
                  pos = 0
         | 
| 574 | 
            -
                else
         | 
| 575 | 
            -
             | 
| 576 | 
            -
                  case File.extname filename
         | 
| 577 | 
            -
                  when ".md"
         | 
| 578 | 
            -
             | 
| 579 | 
            -
                    # Load Markdown's YAML frontmatter.
         | 
| 580 | 
            -
                    File.open(File.join(dir, filename)) do |f|
         | 
| 581 | 
            -
                      l = f.gets
         | 
| 582 | 
            -
                      next unless l && l.chomp == "---"
         | 
| 583 | 
            -
             | 
| 584 | 
            -
                      lines = []
         | 
| 585 | 
            -
             | 
| 586 | 
            -
                      while l = f.gets
         | 
| 587 | 
            -
                        break if l.nil?
         | 
| 588 | 
            -
             | 
| 589 | 
            -
                        break if  l.chomp == "---"
         | 
| 590 | 
            -
                        lines.push l
         | 
| 591 | 
            -
                      end
         | 
| 592 | 
            -
             | 
| 593 | 
            -
                      next if f.eof?
         | 
| 594 | 
            -
             | 
| 595 | 
            -
                      begin
         | 
| 596 | 
            -
                        frontmatter = Psych.unsafe_load(lines.join)
         | 
| 597 | 
            -
                      rescue => e
         | 
| 598 | 
            -
                        STDERR.puts "!CRITICAL: Cannot parse frontmatter."
         | 
| 599 | 
            -
                        raise e
         | 
| 600 | 
            -
                      end
         | 
| 601 | 
            -
             | 
| 602 | 
            -
                      pos = f.pos
         | 
| 603 | 
            -
                    end
         | 
| 604 | 
            -
             | 
| 605 | 
            -
                  when ".rst"
         | 
| 606 | 
            -
                    # ReSTRUCTURED Text
         | 
| 607 | 
            -
             | 
| 608 | 
            -
                    File.open(File.join(dir, filename)) do |f|
         | 
| 609 | 
            -
                      l = f.gets
         | 
| 610 | 
            -
                      if l =~ /:([A-Za-z_-]+): (.*)/ #docinfo
         | 
| 611 | 
            -
                        frontmatter = { $1 => [$2.chomp] }
         | 
| 612 | 
            -
                        last_key = $1
         | 
| 613 | 
            -
             | 
| 614 | 
            -
                        # Read docinfo
         | 
| 615 | 
            -
                        while(l = f.gets)
         | 
| 616 | 
            -
                          break if l =~ /^\s*$/ # End of docinfo
         | 
| 617 | 
            -
                          if l =~ /^\s+/ # Continuous line
         | 
| 618 | 
            -
                            docinfo_lines.last.push($'.chomp)
         | 
| 619 | 
            -
                          elsif l =~ /:([A-Za-z_-]+): (.*)/
         | 
| 620 | 
            -
                            frontmatter[$1] = [$2.chomp]
         | 
| 621 | 
            -
                            last_key = $1
         | 
| 622 | 
            -
                          end
         | 
| 623 | 
            -
                        end
         | 
| 624 | 
            -
             | 
| 625 | 
            -
                        # Treat docinfo lines
         | 
| 626 | 
            -
                        frontmatter.each do |k,v|
         | 
| 627 | 
            -
                          v = v.join(" ")
         | 
| 628 | 
            -
                          #if((k == "author" || k == "authors") && v.include?(";")) # Multiple authors.
         | 
| 629 | 
            -
                          if(v.include?(";")) # Multiple element.
         | 
| 630 | 
            -
                            v = v.split(/\s*;\s*/)
         | 
| 631 | 
            -
             | 
| 632 | 
            -
                          elsif k == "date" # Date?
         | 
| 633 | 
            -
                            # Datetime?
         | 
| 634 | 
            -
                            if v =~ /[0-2][0-9]:[0-6][0-9]/
         | 
| 635 | 
            -
                              v = DateTime.parse(v)
         | 
| 636 | 
            -
                            else
         | 
| 637 | 
            -
                              v = Date.parse(v)
         | 
| 638 | 
            -
                            end
         | 
| 639 | 
            -
                          elsif v == "yes" || v == "true"
         | 
| 640 | 
            -
                            v = true
         | 
| 641 | 
            -
                          else # Simple String.
         | 
| 642 | 
            -
                            nil # keep v
         | 
| 643 | 
            -
                          end
         | 
| 644 | 
            -
             | 
| 645 | 
            -
                          frontmatter[k] = v
         | 
| 646 | 
            -
                        end
         | 
| 647 | 
            -
             | 
| 648 | 
            -
                      elsif l && l.chomp == ".." #YAML
         | 
| 649 | 
            -
                        # Load ReST YAML that document begins comment and block is yaml.
         | 
| 650 | 
            -
                        lines = []
         | 
| 651 | 
            -
             | 
| 652 | 
            -
                        while(l = f.gets)
         | 
| 653 | 
            -
                          if(l !~ /^\s*$/ .. l =~ /^\s*$/)
         | 
| 654 | 
            -
                            if l=~ /^\s*$/
         | 
| 655 | 
            -
                              break
         | 
| 656 | 
            -
                            else
         | 
| 657 | 
            -
                              lines.push l
         | 
| 658 | 
            -
                            end
         | 
| 659 | 
            -
                          end
         | 
| 660 | 
            -
                        end
         | 
| 661 | 
            -
                        next if f.eof?
         | 
| 662 | 
            -
             | 
| 663 | 
            -
             | 
| 664 | 
            -
                        # Rescue for failed to read YAML.
         | 
| 665 | 
            -
                        begin
         | 
| 666 | 
            -
                          frontmatter = Psych.unsafe_load(lines.map {|i| i.sub(/^\s*/, "") }.join)
         | 
| 667 | 
            -
                        rescue
         | 
| 668 | 
            -
                          STDERR.puts "Error in parsing ReST YAML frontmatter (#{$!})"
         | 
| 669 | 
            -
                          next
         | 
| 670 | 
            -
                        end
         | 
| 671 | 
            -
                      else
         | 
| 672 | 
            -
                        next
         | 
| 673 | 
            -
                      end
         | 
| 674 | 
            -
             | 
| 675 | 
            -
                      pos = f.pos
         | 
| 676 | 
            -
             | 
| 677 | 
            -
                    end
         | 
| 678 | 
            -
                  end
         | 
| 679 | 
            -
                end
         | 
| 680 | 
            -
             | 
| 681 | 
            -
                abort "This document has no frontmatter" unless frontmatter
         | 
| 682 | 
            -
                abort "This document has no title." unless frontmatter["title"]
         | 
| 683 | 
            -
             | 
| 684 | 
            -
             | 
| 685 | 
            -
                ### Additional meta values. ###
         | 
| 686 | 
            -
                frontmatter["source_directory"] = dir # Source Directory
         | 
| 687 | 
            -
                frontmatter["source_filename"] = filename # Source Filename
         | 
| 688 | 
            -
                frontmatter["source_path"] = File.join(dir, filename) # Source Path
         | 
| 689 | 
            -
                # URL in site.
         | 
| 690 | 
            -
                this_url = (File.join(dir, filename)).sub(/^[\.\/]*/) { @config["self_url_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html")
         | 
| 691 | 
            -
                frontmatter["page_url"] = this_url
         | 
| 692 | 
            -
                # URL in site with URI encode.
         | 
| 693 | 
            -
                frontmatter["page_url_encoded"] = ERB::Util.url_encode(this_url)
         | 
| 694 | 
            -
                frontmatter["page_url_encoded_external"] = ERB::Util.url_encode((File.join(dir, filename)).sub(/^[\.\/]*/) { @config["self_url_external_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html"))
         | 
| 695 | 
            -
                frontmatter["page_html_escaped"] = ERB::Util.html_escape(this_url)
         | 
| 696 | 
            -
                frontmatter["page_html_escaped_external"] = ERB::Util.html_escape((File.join(dir, filename)).sub(/^[\.\/]*/) { @config["self_url_external_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html"))
         | 
| 697 | 
            -
                # Title with URL Encoded.
         | 
| 698 | 
            -
                frontmatter["title_encoded"] = ERB::Util.url_encode(frontmatter["title"])
         | 
| 699 | 
            -
                frontmatter["title_html_escaped"] = ERB::Util.html_escape(frontmatter["title"])
         | 
| 700 | 
            -
                fts = frontmatter["timestamp"]
         | 
| 701 | 
            -
                fts = fts.to_datetime if Time === fts
         | 
| 702 | 
            -
                if DateTime === fts
         | 
| 703 | 
            -
                  frontmatter["timestamp_xmlschema"] = fts.xmlschema
         | 
| 704 | 
            -
                  frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日 %H時%M分%S秒')
         | 
| 705 | 
            -
                  frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d %H:%M:%S %Z %Y')
         | 
| 706 | 
            -
                  frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d %H:%M:%S %Z")
         | 
| 707 | 
            -
                elsif Date === fts
         | 
| 708 | 
            -
                  frontmatter["timestamp_xmlschema"] = fts.xmlschema
         | 
| 709 | 
            -
                  frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日')
         | 
| 710 | 
            -
                  frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d')
         | 
| 711 | 
            -
                  frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d")
         | 
| 712 | 
            -
                elsif Date === frontmatter["Date"]
         | 
| 713 | 
            -
                  fts = frontmatter["Date"]
         | 
| 714 | 
            -
                  frontmatter["timestamp_xmlschema"] = fts.xmlschema
         | 
| 715 | 
            -
                  frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日')
         | 
| 716 | 
            -
                  frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d')
         | 
| 717 | 
            -
                  frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d")
         | 
| 718 | 
            -
                end
         | 
| 719 | 
            -
             | 
| 720 | 
            -
                fsize = FileTest.size(File.join(dir, filename))
         | 
| 721 | 
            -
                mtime = File.mtime(File.join(dir, filename)).to_i
         | 
| 722 | 
            -
             | 
| 723 | 
            -
                frontmatter["_filename"] ||= filename
         | 
| 724 | 
            -
                frontmatter["pagetype"] ||= "post"
         | 
| 725 | 
            -
             | 
| 726 | 
            -
                frontmatter["_size"] = fsize
         | 
| 727 | 
            -
                frontmatter["_mtime"] = mtime
         | 
| 728 | 
            -
                frontmatter["_last_proced"] = @now.to_i
         | 
| 729 | 
            -
             | 
| 730 | 
            -
                if File.extname(filename) == ".md"
         | 
| 731 | 
            -
                  frontmatter["_docformat"] = "Markdown"
         | 
| 732 | 
            -
                elsif File.extname(filename) == ".rst" || File.extname(filename) == ".rest"
         | 
| 733 | 
            -
                  frontmatter["_docformat"] = "ReST"
         | 
| 734 | 
            -
                end
         | 
| 735 | 
            -
             | 
| 736 | 
            -
                frontmatter["date"] ||= @now.strftime("%Y-%m-%d %H:%M:%S")
         | 
| 737 | 
            -
             | 
| 738 | 
            -
                return frontmatter, pos
         | 
| 739 | 
            -
              end
         | 
| 740 | 
            -
             | 
| 741 388 | 
             
              # Check is the article modified? (or force update?)
         | 
| 742 389 | 
             
              def check_modify(path, frontmatter)
         | 
| 743 390 | 
             
                modify = true
         | 
| 744 391 | 
             
                index = @indexes_orig[path[1]].dup || {}
         | 
| 745 392 | 
             
                frontmatter = @db.cmp_obj(frontmatter)
         | 
| 393 | 
            +
             | 
| 394 | 
            +
                # Remove unstable metadata for compartion.
         | 
| 746 395 | 
             
                index.delete("_last_proced")
         | 
| 396 | 
            +
                index.delete("source_path")
         | 
| 397 | 
            +
                index.delete("source_directory")
         | 
| 398 | 
            +
                index.delete("dest_path")
         | 
| 747 399 | 
             
                frontmatter.delete("_last_proced")
         | 
| 400 | 
            +
                frontmatter.delete("source_path")
         | 
| 401 | 
            +
                frontmatter.delete("source_directory")
         | 
| 402 | 
            +
                frontmatter.delete("dest_path")
         | 
| 748 403 |  | 
| 749 404 | 
             
                if index == frontmatter
         | 
| 750 405 | 
             
                  STDERR.puts "#{path[1]} is not modified."
         | 
| @@ -761,311 +416,4 @@ EOF | |
| 761 416 | 
             
                  modify
         | 
| 762 417 | 
             
                end
         | 
| 763 418 | 
             
              end
         | 
| 764 | 
            -
             | 
| 765 | 
            -
              def bless_ruby(frontmatter)
         | 
| 766 | 
            -
                # BLESSING (Always)
         | 
| 767 | 
            -
                if PureBuilder.const_defined?(:BLESS) && Proc === PureBuilder::BLESS
         | 
| 768 | 
            -
                  begin
         | 
| 769 | 
            -
                    PureBuilder::BLESS.(frontmatter, self)
         | 
| 770 | 
            -
                  rescue
         | 
| 771 | 
            -
                    STDERR.puts "*** BLESSING PROC ERROR ***"
         | 
| 772 | 
            -
                    raise
         | 
| 773 | 
            -
                  end
         | 
| 774 | 
            -
                end
         | 
| 775 | 
            -
             | 
| 776 | 
            -
                # BLESSING (ACCS)
         | 
| 777 | 
            -
                if @accs && PureBuilder::ACCS.const_defined?(:BLESS) && Proc === PureBuilder::ACCS::BLESS
         | 
| 778 | 
            -
                  begin
         | 
| 779 | 
            -
                    PureBuilder::ACCS::BLESS.(frontmatter, self)
         | 
| 780 | 
            -
                  rescue
         | 
| 781 | 
            -
                    STDERR.puts "*** ACCS BLESSING PROC ERROR ***"
         | 
| 782 | 
            -
                    raise
         | 
| 783 | 
            -
                  end
         | 
| 784 | 
            -
                end
         | 
| 785 | 
            -
             | 
| 786 | 
            -
                # ACCS DEFINITIONS
         | 
| 787 | 
            -
                if @accs
         | 
| 788 | 
            -
                  if Proc === PureBuilder::ACCS::DEFINITIONS[:next]
         | 
| 789 | 
            -
                    i = PureBuilder::ACCS::DEFINITIONS[:next].call(frontmatter, self)
         | 
| 790 | 
            -
                    frontmatter["next_article"] = i if i
         | 
| 791 | 
            -
                  end
         | 
| 792 | 
            -
                  if Proc === PureBuilder::ACCS::DEFINITIONS[:prev]
         | 
| 793 | 
            -
                    i = PureBuilder::ACCS::DEFINITIONS[:prev].call(frontmatter, self)
         | 
| 794 | 
            -
                    frontmatter["prev_article"] = i if i
         | 
| 795 | 
            -
                  end
         | 
| 796 | 
            -
                end
         | 
| 797 | 
            -
             | 
| 798 | 
            -
                autobless(frontmatter)
         | 
| 799 | 
            -
              end
         | 
| 800 | 
            -
             | 
| 801 | 
            -
              def bless_cmd(frontmatter)
         | 
| 802 | 
            -
                File.open(".pbsimply-frontmatter.json", "w") {|f| f.write JSON_LIB.dump(frontmatter) }
         | 
| 803 | 
            -
                # BLESSING (Always)
         | 
| 804 | 
            -
                if @config["bless_cmd"]
         | 
| 805 | 
            -
                  (Array === @config["bless_cmd"] ? system(*@config["bless_cmd"]) : system(@config["bless_cmd"]) ) or abort "*** BLESS COMMAND RETURNS NON-ZERO STATUS"
         | 
| 806 | 
            -
                end
         | 
| 807 | 
            -
                # BLESSING (ACCS)
         | 
| 808 | 
            -
                if @config["bless_accscmd"]
         | 
| 809 | 
            -
                  (Array === @config["bless_accscmd"] ? system({"pbsimply_frontmatter" => ".pbsimply-frontmatter.json", "pbsimply_indexes" => @db.path}, *@config["bless_accscmd"]) : system({"pbsimply_frontmatter" => ".pbsimply-frontmatter.json", "pbsimply_indexes" => @db.path}, @config["bless_accscmd"]) ) or abort "*** BLESS COMMAND RETURNS NON-ZERO STATUS"
         | 
| 810 | 
            -
                end
         | 
| 811 | 
            -
                mod_frontmatter = JSON.load(File.read(".pbsimply-frontmatter.json"))
         | 
| 812 | 
            -
                frontmatter.replace(mod_frontmatter)
         | 
| 813 | 
            -
             | 
| 814 | 
            -
                autobless(frontmatter)
         | 
| 815 | 
            -
              end
         | 
| 816 | 
            -
             | 
| 817 | 
            -
              # Blessing automatic method with configuration.
         | 
| 818 | 
            -
              def autobless(frontmatter)
         | 
| 819 | 
            -
                catch(:accs_rel) do
         | 
| 820 | 
            -
                  # find Next/Prev page on accs
         | 
| 821 | 
            -
                  if @accs && @config["blessmethod_accs_rel"]
         | 
| 822 | 
            -
                    # Preparing. Run at once.
         | 
| 823 | 
            -
                    if !@article_order
         | 
| 824 | 
            -
                      @rev_article_order_index = {}
         | 
| 825 | 
            -
             | 
| 826 | 
            -
                      case @config["blessmethod_accs_rel"]
         | 
| 827 | 
            -
                      when "numbering"
         | 
| 828 | 
            -
                        @article_order = @indexes.to_a.sort_by {|i| i[1]["_filename"].to_i }
         | 
| 829 | 
            -
                      when "date"
         | 
| 830 | 
            -
                        begin
         | 
| 831 | 
            -
                          @article_order = @indexes.to_a.sort_by {|i| i[1]["date"]}
         | 
| 832 | 
            -
                        rescue
         | 
| 833 | 
            -
                          abort "*** Automatic Blessing Method Error: Maybe some article have no date."
         | 
| 834 | 
            -
                        end
         | 
| 835 | 
            -
                      when "timestamp"
         | 
| 836 | 
            -
                        begin
         | 
| 837 | 
            -
                          @article_order = @indexes.to_a.sort_by {|i| i[1]["timestamp"]}
         | 
| 838 | 
            -
                        rescue
         | 
| 839 | 
            -
                          abort "*** Automatic Blessing Method Error: Maybe some article have no timetsamp."
         | 
| 840 | 
            -
                        end
         | 
| 841 | 
            -
                      when "lexical"
         | 
| 842 | 
            -
                        @article_order = @indexes.to_a.sort_by {|i| i[1]["_filename"]}
         | 
| 843 | 
            -
                      end
         | 
| 844 | 
            -
                      @article_order.each_with_index {|x,i| @rev_article_order_index[x[0]] = i }
         | 
| 845 | 
            -
                    end
         | 
| 846 | 
            -
             | 
| 847 | 
            -
                    throw(:accs_rel) unless index = @rev_article_order_index[frontmatter["_filename"]]
         | 
| 848 | 
            -
                    if @article_order[index + 1]
         | 
| 849 | 
            -
                      frontmatter["next_article"] = {"url" => @article_order[index + 1][1]["page_url"],
         | 
| 850 | 
            -
                                                     "title" => @article_order[index + 1][1]["title"]}
         | 
| 851 | 
            -
                    end
         | 
| 852 | 
            -
                    if index > 0
         | 
| 853 | 
            -
                      frontmatter["prev_article"] = {"url" => @article_order[index - 1][1]["page_url"],
         | 
| 854 | 
            -
                                                     "title" => @article_order[index - 1][1]["title"]}
         | 
| 855 | 
            -
                    end
         | 
| 856 | 
            -
                  end
         | 
| 857 | 
            -
                end
         | 
| 858 | 
            -
              end
         | 
| 859 | 
            -
             | 
| 860 | 
            -
              ###############################################
         | 
| 861 | 
            -
              #           DOCUMENT PROCESSORS               #
         | 
| 862 | 
            -
              ###############################################
         | 
| 863 | 
            -
             | 
| 864 | 
            -
             | 
| 865 | 
            -
              module Processor
         | 
| 866 | 
            -
             | 
| 867 | 
            -
                # Pandoc processor
         | 
| 868 | 
            -
                class Pandoc < PBSimply
         | 
| 869 | 
            -
                  def initialize(config)
         | 
| 870 | 
            -
                    @pandoc_default_file = {}
         | 
| 871 | 
            -
             | 
| 872 | 
            -
                    # -d
         | 
| 873 | 
            -
                    @pandoc_default_file = {
         | 
| 874 | 
            -
                      "to" => "html5",
         | 
| 875 | 
            -
                      "standalone" => true
         | 
| 876 | 
            -
                    }
         | 
| 877 | 
            -
                    super
         | 
| 878 | 
            -
                  end
         | 
| 879 | 
            -
             | 
| 880 | 
            -
                  def setup_config(dir)
         | 
| 881 | 
            -
                    super
         | 
| 882 | 
            -
                    @pandoc_default_file["template"] = @config["template"]
         | 
| 883 | 
            -
             | 
| 884 | 
            -
                    if @config["css"]
         | 
| 885 | 
            -
                      if @config["css"].kind_of?(String)
         | 
| 886 | 
            -
                        @pandoc_default_file["css"] = [@config["css"]]
         | 
| 887 | 
            -
                      elsif @config["css"].kind_of?(Array)
         | 
| 888 | 
            -
                        @pandoc_default_file["css"] = @config["css"]
         | 
| 889 | 
            -
                      else
         | 
| 890 | 
            -
                        abort "css in Config should be a String or an Array."
         | 
| 891 | 
            -
                      end
         | 
| 892 | 
            -
                    end
         | 
| 893 | 
            -
             | 
| 894 | 
            -
                    if @config["toc"]
         | 
| 895 | 
            -
                      @pandoc_default_file["toc"] = true
         | 
| 896 | 
            -
                    end
         | 
| 897 | 
            -
             | 
| 898 | 
            -
                    if Hash === @config["pandoc_additional_options"]
         | 
| 899 | 
            -
                      @pandoc_default_file.merge! @config["pandoc_additional_options"]
         | 
| 900 | 
            -
                    end
         | 
| 901 | 
            -
             | 
| 902 | 
            -
                  end
         | 
| 903 | 
            -
             | 
| 904 | 
            -
                  # Invoke pandoc, parse and format and write out.
         | 
| 905 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 906 | 
            -
                    STDERR.puts "#{filename} is going Pandoc."
         | 
| 907 | 
            -
                  end
         | 
| 908 | 
            -
             | 
| 909 | 
            -
                  def process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc)
         | 
| 910 | 
            -
                    doc = nil
         | 
| 911 | 
            -
             | 
| 912 | 
            -
                    File.open(".pbsimply-defaultfiles.yaml", "w") {|f| YAML.dump(@pandoc_default_file, f)}
         | 
| 913 | 
            -
                    File.open(".pbsimply-frontmatter.yaml", "w") {|f| YAML.dump(frontmatter, f)}
         | 
| 914 | 
            -
             | 
| 915 | 
            -
                    # Go Pandoc
         | 
| 916 | 
            -
                    pandoc_cmdline = ["pandoc"]
         | 
| 917 | 
            -
                    pandoc_cmdline += ["-d", ".pbsimply-defaultfiles.yaml", "--metadata-file", ".pbsimply-frontmatter.yaml", "-M", "title:#{frontmatter["title"]}"]
         | 
| 918 | 
            -
                    pandoc_cmdline += ["-f", frontmatter["input_format"]] if frontmatter["input_format"]
         | 
| 919 | 
            -
                    pandoc_cmdline += [ procdoc ]
         | 
| 920 | 
            -
                    IO.popen((pandoc_cmdline)) do |io|
         | 
| 921 | 
            -
                      doc = io.read
         | 
| 922 | 
            -
                    end
         | 
| 923 | 
            -
             | 
| 924 | 
            -
                    # Abort if pandoc returns non-zero status
         | 
| 925 | 
            -
                    if $?.exitstatus != 0
         | 
| 926 | 
            -
                      abort "Pandoc returns exit code #{$?.exitstatus}"
         | 
| 927 | 
            -
                    end
         | 
| 928 | 
            -
             | 
| 929 | 
            -
                    doc
         | 
| 930 | 
            -
                  end
         | 
| 931 | 
            -
             | 
| 932 | 
            -
                  def target_file_extensions
         | 
| 933 | 
            -
                    [".md", ".rst"]
         | 
| 934 | 
            -
                  end
         | 
| 935 | 
            -
                end
         | 
| 936 | 
            -
             | 
| 937 | 
            -
                # RDoc family Base
         | 
| 938 | 
            -
                class PbsRBase < PBSimply
         | 
| 939 | 
            -
                  def initialize(config)
         | 
| 940 | 
            -
                    require 'rdoc'
         | 
| 941 | 
            -
                    require 'rdoc/markup/to_html'
         | 
| 942 | 
            -
             | 
| 943 | 
            -
                    @rdoc_options = RDoc::Options.new
         | 
| 944 | 
            -
                    @rdoc_markup = RDoc::Markup.new
         | 
| 945 | 
            -
             | 
| 946 | 
            -
                    super
         | 
| 947 | 
            -
                  end
         | 
| 948 | 
            -
             | 
| 949 | 
            -
                  def process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc)
         | 
| 950 | 
            -
                    # Getting HTML string.
         | 
| 951 | 
            -
                    rdoc = RDoc::Markup::ToHtml.new(@rdoc_options, @rdoc_markup)
         | 
| 952 | 
            -
                    article_body = rdoc.convert(get_markup_document(procdoc))
         | 
| 953 | 
            -
             | 
| 954 | 
            -
                    # Process with eRuby temaplte.
         | 
| 955 | 
            -
                    erb_template = ERB.new(File.read(@config["template"]), trim_mode: '%<>')
         | 
| 956 | 
            -
                    doc = erb_template.result(binding)
         | 
| 957 | 
            -
             | 
| 958 | 
            -
                    doc
         | 
| 959 | 
            -
                  end
         | 
| 960 | 
            -
                end
         | 
| 961 | 
            -
             | 
| 962 | 
            -
                # RDoc/Markdown processor
         | 
| 963 | 
            -
                class PbsRMakrdown < PbsRBase
         | 
| 964 | 
            -
                  def initialize(config)
         | 
| 965 | 
            -
                    require 'rdoc'
         | 
| 966 | 
            -
                    require 'rdoc/markdown'
         | 
| 967 | 
            -
                    super
         | 
| 968 | 
            -
                  end
         | 
| 969 | 
            -
             | 
| 970 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 971 | 
            -
                    STDERR.puts "#{filename} generate with RDoc/Markdown"
         | 
| 972 | 
            -
                  end
         | 
| 973 | 
            -
             | 
| 974 | 
            -
                  def get_markup_document procdoc
         | 
| 975 | 
            -
                    RDoc::Markdown.parse(File.read procdoc)
         | 
| 976 | 
            -
                  end
         | 
| 977 | 
            -
                end
         | 
| 978 | 
            -
             | 
| 979 | 
            -
                # RDoc processor
         | 
| 980 | 
            -
                class PbsRDoc < PbsRBase
         | 
| 981 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 982 | 
            -
                    STDERR.puts "#{filename} generate with RDoc"
         | 
| 983 | 
            -
                  end
         | 
| 984 | 
            -
             | 
| 985 | 
            -
                  def get_markup_document procdoc
         | 
| 986 | 
            -
                    File.read procdoc
         | 
| 987 | 
            -
                  end
         | 
| 988 | 
            -
             | 
| 989 | 
            -
                  def target_file_extensions
         | 
| 990 | 
            -
                    [".rdoc"]
         | 
| 991 | 
            -
                  end
         | 
| 992 | 
            -
                end
         | 
| 993 | 
            -
             | 
| 994 | 
            -
                class PbsRedCarpet < PBSimply
         | 
| 995 | 
            -
                  def initialize(config)
         | 
| 996 | 
            -
                    require 'redcarpet'
         | 
| 997 | 
            -
                    super
         | 
| 998 | 
            -
                  end
         | 
| 999 | 
            -
             | 
| 1000 | 
            -
                  def setup_config(dir)
         | 
| 1001 | 
            -
                    super
         | 
| 1002 | 
            -
                    @rc_extension = @config["redcarpet_extensions"] || {}
         | 
| 1003 | 
            -
                  end
         | 
| 1004 | 
            -
             | 
| 1005 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 1006 | 
            -
                    STDERR.puts "#{filename} generate with Redcarpet Markdown"
         | 
| 1007 | 
            -
                  end
         | 
| 1008 | 
            -
             | 
| 1009 | 
            -
                  def process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc)
         | 
| 1010 | 
            -
                    # Getting HTML string.
         | 
| 1011 | 
            -
                    markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, **@rc_extension)
         | 
| 1012 | 
            -
                    article_body = markdown.render(File.read procdoc)
         | 
| 1013 | 
            -
             | 
| 1014 | 
            -
                    # Process with eRuby temaplte.
         | 
| 1015 | 
            -
                    erb_template = ERB.new(File.read(@config["template"]), trim_mode: '%<>')
         | 
| 1016 | 
            -
                    doc = erb_template.result(binding)
         | 
| 1017 | 
            -
             | 
| 1018 | 
            -
                    doc
         | 
| 1019 | 
            -
                  end
         | 
| 1020 | 
            -
                end
         | 
| 1021 | 
            -
             | 
| 1022 | 
            -
                class PbsKramdown < PBSimply
         | 
| 1023 | 
            -
                  def initialize(config)
         | 
| 1024 | 
            -
                    require 'kramdown'
         | 
| 1025 | 
            -
                    super
         | 
| 1026 | 
            -
                  end
         | 
| 1027 | 
            -
             | 
| 1028 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 1029 | 
            -
                    STDERR.puts "#{filename} generate with Kramdown"
         | 
| 1030 | 
            -
                  end
         | 
| 1031 | 
            -
             | 
| 1032 | 
            -
                  def process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc)
         | 
| 1033 | 
            -
                    # Set feature options
         | 
| 1034 | 
            -
                    features = @config["kramdown_features"] || {}
         | 
| 1035 | 
            -
             | 
| 1036 | 
            -
                    # Getting HTML string.
         | 
| 1037 | 
            -
                    markdown = Kramdown::Document.new(File.read(procdoc), **features)
         | 
| 1038 | 
            -
                    article_body = markdown.to_html
         | 
| 1039 | 
            -
             | 
| 1040 | 
            -
                    # Process with eRuby temaplte.
         | 
| 1041 | 
            -
                    erb_template = ERB.new(File.read(@config["template"]), trim_mode: '%<>')
         | 
| 1042 | 
            -
                    doc = erb_template.result(binding)
         | 
| 1043 | 
            -
             | 
| 1044 | 
            -
                    doc
         | 
| 1045 | 
            -
                  end
         | 
| 1046 | 
            -
                end
         | 
| 1047 | 
            -
             | 
| 1048 | 
            -
                class PbsCommonMark < PBSimply
         | 
| 1049 | 
            -
                  def initialize(config)
         | 
| 1050 | 
            -
                    require 'commonmarker'
         | 
| 1051 | 
            -
                    super
         | 
| 1052 | 
            -
                  end
         | 
| 1053 | 
            -
             | 
| 1054 | 
            -
                  def print_fileproc_msg(filename)
         | 
| 1055 | 
            -
                    STDERR.puts "#{filename} generate with CommonMarker (cmark-gfm)"
         | 
| 1056 | 
            -
                  end
         | 
| 1057 | 
            -
             | 
| 1058 | 
            -
                  def process_document(dir, filename, frontmatter, orig_filepath, ext, procdoc)
         | 
| 1059 | 
            -
                    # Getting HTML string.
         | 
| 1060 | 
            -
                    article_body = CommonMarker.render_doc(File.read(procdoc), :DEFAULT, [:table, :strikethrough]).to_html
         | 
| 1061 | 
            -
             | 
| 1062 | 
            -
                    # Process with eRuby temaplte.
         | 
| 1063 | 
            -
                    erb_template = ERB.new(File.read(@config["template"]), trim_mode: '%<>')
         | 
| 1064 | 
            -
                    doc = erb_template.result(binding)
         | 
| 1065 | 
            -
             | 
| 1066 | 
            -
                    doc
         | 
| 1067 | 
            -
                  end
         | 
| 1068 | 
            -
                end
         | 
| 1069 | 
            -
             | 
| 1070 | 
            -
              end
         | 
| 1071 419 | 
             
            end
         |