pbsimply 2.0.1 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +203 -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 +163 -813
- metadata +15 -4
@@ -0,0 +1,203 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require 'erb'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module PBSimply::Frontmatter
|
6
|
+
# Read Frontmatter from the document.
|
7
|
+
# This method returns frontmatter, pos.
|
8
|
+
# pos means position at end of Frontmatter on the file.
|
9
|
+
def read_frontmatter(dir, filename)
|
10
|
+
frontmatter = nil
|
11
|
+
pos = nil
|
12
|
+
|
13
|
+
source_path = File.join(dir, filename)
|
14
|
+
|
15
|
+
if File.exist? File.join(dir, ".meta." + filename)
|
16
|
+
# Load standalone metadata YAML.
|
17
|
+
frontmatter = Psych.unsafe_load(File.read(File.join(dir, (".meta." + filename))))
|
18
|
+
pos = 0
|
19
|
+
else
|
20
|
+
|
21
|
+
case File.extname filename
|
22
|
+
when ".md"
|
23
|
+
|
24
|
+
# Load Markdown's YAML frontmatter.
|
25
|
+
File.open(source_path) do |f|
|
26
|
+
l = f.gets
|
27
|
+
next unless l && l.chomp == "---"
|
28
|
+
|
29
|
+
lines = []
|
30
|
+
|
31
|
+
while l = f.gets
|
32
|
+
break if l.nil?
|
33
|
+
|
34
|
+
break if l.chomp == "---"
|
35
|
+
lines.push l
|
36
|
+
end
|
37
|
+
|
38
|
+
next if f.eof?
|
39
|
+
|
40
|
+
begin
|
41
|
+
frontmatter = Psych.unsafe_load(lines.join)
|
42
|
+
rescue => e
|
43
|
+
STDERR.puts "!CRITICAL: Cannot parse frontmatter."
|
44
|
+
raise e
|
45
|
+
end
|
46
|
+
|
47
|
+
pos = f.pos
|
48
|
+
end
|
49
|
+
|
50
|
+
when ".rst"
|
51
|
+
# ReSTRUCTURED Text
|
52
|
+
|
53
|
+
File.open(source_path) do |f|
|
54
|
+
l = f.gets
|
55
|
+
if l =~ /:([A-Za-z_-]+): (.*)/ #docinfo
|
56
|
+
frontmatter = { $1 => [$2.chomp] }
|
57
|
+
last_key = $1
|
58
|
+
|
59
|
+
# Read docinfo
|
60
|
+
while(l = f.gets)
|
61
|
+
break if l =~ /^\s*$/ # End of docinfo
|
62
|
+
if l =~ /^\s+/ # Continuous line
|
63
|
+
docinfo_lines.last.push($'.chomp)
|
64
|
+
elsif l =~ /:([A-Za-z_-]+): (.*)/
|
65
|
+
frontmatter[$1] = [$2.chomp]
|
66
|
+
last_key = $1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Treat docinfo lines
|
71
|
+
frontmatter.each do |k,v|
|
72
|
+
v = v.join(" ")
|
73
|
+
#if((k == "author" || k == "authors") && v.include?(";")) # Multiple authors.
|
74
|
+
if(v.include?(";")) # Multiple element.
|
75
|
+
v = v.split(/\s*;\s*/)
|
76
|
+
|
77
|
+
elsif k == "date" # Date?
|
78
|
+
# Datetime?
|
79
|
+
if v =~ /[0-2][0-9]:[0-6][0-9]/
|
80
|
+
v = Time.parse(v)
|
81
|
+
else
|
82
|
+
v = Date.parse(v)
|
83
|
+
end
|
84
|
+
elsif v == "yes" || v == "true"
|
85
|
+
v = true
|
86
|
+
else # Simple String.
|
87
|
+
nil # keep v
|
88
|
+
end
|
89
|
+
|
90
|
+
frontmatter[k] = v
|
91
|
+
end
|
92
|
+
|
93
|
+
elsif l && l.chomp == ".." #YAML
|
94
|
+
# Load ReST YAML that document begins comment and block is yaml.
|
95
|
+
lines = []
|
96
|
+
|
97
|
+
while(l = f.gets)
|
98
|
+
if(l !~ /^\s*$/ .. l =~ /^\s*$/)
|
99
|
+
if l=~ /^\s*$/
|
100
|
+
break
|
101
|
+
else
|
102
|
+
lines.push l
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
next if f.eof?
|
107
|
+
|
108
|
+
|
109
|
+
# Rescue for failed to read YAML.
|
110
|
+
begin
|
111
|
+
frontmatter = Psych.unsafe_load(lines.map {|i| i.sub(/^\s*/, "") }.join)
|
112
|
+
rescue
|
113
|
+
STDERR.puts "Error in parsing ReST YAML frontmatter (#{$!})"
|
114
|
+
next
|
115
|
+
end
|
116
|
+
else
|
117
|
+
next
|
118
|
+
end
|
119
|
+
|
120
|
+
pos = f.pos
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
abort "This document has no frontmatter" unless frontmatter
|
127
|
+
abort "This document has no title." unless frontmatter["title"]
|
128
|
+
|
129
|
+
outext = frontmatter["force_ext"] || ".html"
|
130
|
+
outpath = case
|
131
|
+
when @outfile
|
132
|
+
@outfile
|
133
|
+
when @accs_processing
|
134
|
+
File.join(@config["outdir"], @dir, "index") + outext
|
135
|
+
else
|
136
|
+
File.join(@config["outdir"], @dir, File.basename(filename, ".*")) + outext
|
137
|
+
end
|
138
|
+
|
139
|
+
absolute_current = File.absolute_path Dir.pwd
|
140
|
+
absolute_docdir = File.absolute_path dir
|
141
|
+
absolute_docpath = File.absolute_path source_path
|
142
|
+
pwd_length = absolute_current.length
|
143
|
+
|
144
|
+
### Additional meta values. ###
|
145
|
+
frontmatter["source_directory"] = dir # Source Directory
|
146
|
+
frontmatter["source_filename"] = filename # Source Filename
|
147
|
+
frontmatter["source_path"] = source_path # Source Path
|
148
|
+
frontmatter["dest_path"] = outpath
|
149
|
+
frontmatter["normalized_docdir"] = absolute_docdir[pwd_length..]
|
150
|
+
frontmatter["normalized_docpath"] = absolute_docpath[pwd_length..]
|
151
|
+
# URL in site.
|
152
|
+
this_url = (source_path).sub(/^[\.\/]*/) { @config["self_url_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html")
|
153
|
+
frontmatter["page_url"] = this_url
|
154
|
+
# URL in site with URI encode.
|
155
|
+
frontmatter["page_url_encoded"] = ERB::Util.url_encode(this_url)
|
156
|
+
frontmatter["page_url_encoded_external"] = ERB::Util.url_encode((source_path).sub(/^[\.\/]*/) { @config["self_url_external_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html"))
|
157
|
+
frontmatter["page_html_escaped"] = ERB::Util.html_escape(this_url)
|
158
|
+
frontmatter["page_html_escaped_external"] = ERB::Util.html_escape((source_path).sub(/^[\.\/]*/) { @config["self_url_external_prefix"] || "/" }.sub(/\.[a-zA-Z0-9]+$/, ".html"))
|
159
|
+
# Title with URL Encoded.
|
160
|
+
frontmatter["title_encoded"] = ERB::Util.url_encode(frontmatter["title"])
|
161
|
+
frontmatter["title_html_escaped"] = ERB::Util.html_escape(frontmatter["title"])
|
162
|
+
fts = frontmatter["timestamp"]
|
163
|
+
fts = fts.to_datetime if Time === fts
|
164
|
+
if DateTime === fts
|
165
|
+
frontmatter["timestamp_xmlschema"] = fts.xmlschema
|
166
|
+
frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日 %H時%M分%S秒')
|
167
|
+
frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d %H:%M:%S %Z %Y')
|
168
|
+
frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d %H:%M:%S %Z")
|
169
|
+
elsif Date === fts
|
170
|
+
frontmatter["timestamp_xmlschema"] = fts.xmlschema
|
171
|
+
frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日')
|
172
|
+
frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d')
|
173
|
+
frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d")
|
174
|
+
elsif Date === frontmatter["Date"]
|
175
|
+
fts = frontmatter["Date"]
|
176
|
+
frontmatter["timestamp_xmlschema"] = fts.xmlschema
|
177
|
+
frontmatter["timestamp_jplocal"] = fts.strftime('%Y年%m月%d日')
|
178
|
+
frontmatter["timestamp_rubytimestr"] = fts.strftime('%a %b %d')
|
179
|
+
frontmatter["timestamp_str"] = fts.strftime("%Y-%m-%d")
|
180
|
+
end
|
181
|
+
|
182
|
+
fsize = FileTest.size(source_path)
|
183
|
+
mtime = File.mtime(source_path).to_i
|
184
|
+
|
185
|
+
frontmatter["_filename"] ||= filename
|
186
|
+
frontmatter["pagetype"] ||= "post"
|
187
|
+
|
188
|
+
frontmatter["_size"] = fsize
|
189
|
+
frontmatter["_mtime"] = mtime
|
190
|
+
|
191
|
+
if File.extname(filename) == ".md"
|
192
|
+
frontmatter["_docformat"] = "Markdown"
|
193
|
+
elsif File.extname(filename) == ".rst" || File.extname(filename) == ".rest"
|
194
|
+
frontmatter["_docformat"] = "ReST"
|
195
|
+
elsif File.extname(filename) == ".rdoc"
|
196
|
+
frontmatter["_docformat"] = "RDoc"
|
197
|
+
end
|
198
|
+
|
199
|
+
frontmatter["date"] ||= @now.strftime("%Y-%m-%d %H:%M:%S")
|
200
|
+
|
201
|
+
return frontmatter, pos
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# Hooks is new in PureBuilder Simply 2.2.
|
4
|
+
# Hooks object has instance variables for each timing.
|
5
|
+
#
|
6
|
+
class PBSimply::Hooks
|
7
|
+
|
8
|
+
# Timing object class.
|
9
|
+
class HooksHolder
|
10
|
+
def initialize name
|
11
|
+
@name = name
|
12
|
+
@hooks = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(proc)
|
16
|
+
@hooks << proc
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :add :<<
|
20
|
+
|
21
|
+
def run(arg)
|
22
|
+
STDERR.puts "Hooks processing (#{@name})"
|
23
|
+
@hooks.each_with_index do |proc, index|
|
24
|
+
STDERR.puts "Hooks[#{index}]"
|
25
|
+
begin
|
26
|
+
proc.(arg)
|
27
|
+
rescue
|
28
|
+
STDERR.puts "*** HOOKS PROC ERROR ***"
|
29
|
+
raise
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(pbsimply)
|
36
|
+
@pbsimply = pbsimply
|
37
|
+
|
38
|
+
# Called first phase before generate. This hooks called before blessing.
|
39
|
+
#
|
40
|
+
# Argument: frontmatter, procdoc.
|
41
|
+
# procdoc is processing source document path.
|
42
|
+
@pre = HooksHolder.new "pre"
|
43
|
+
|
44
|
+
# Called after document was generated.
|
45
|
+
#
|
46
|
+
# Argument: outpath, frontmatter, procdoc.
|
47
|
+
# outpath is generated final document path. You can read output result.
|
48
|
+
# procdoc is source document path before generate.
|
49
|
+
@process = HooksHolder.new "process"
|
50
|
+
|
51
|
+
# Called each deleted document on ACCS final phase, before deletion.
|
52
|
+
#
|
53
|
+
# Argument: target_file_path, source_file_path.
|
54
|
+
# target_file_path is output file path (existing or non-existing.)
|
55
|
+
@delete = HooksHolder.new "delete"
|
56
|
+
|
57
|
+
# Called after all document were generated.
|
58
|
+
#
|
59
|
+
# Argument: this_time_processed([{source, dest, frontmatter}...])
|
60
|
+
# this_time_processed has actually processed documents.
|
61
|
+
# source is source file path, dest is generated file path.
|
62
|
+
@post = HooksHolder.new "post"
|
63
|
+
|
64
|
+
# Called before generating ACCS index.
|
65
|
+
#
|
66
|
+
# Argument: index, indexes.
|
67
|
+
#
|
68
|
+
# index is @index (frontmatter for ACCS index),
|
69
|
+
# indexes is @indexes.
|
70
|
+
@accs = HooksHolder.new "accs"
|
71
|
+
end
|
72
|
+
|
73
|
+
def load
|
74
|
+
if File.file?("./.pbsimply-hooks.rb")
|
75
|
+
require './.pbsimply-hooks.rb'
|
76
|
+
PBSimply::Hooks.load_hooks(self)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
attr :pre
|
81
|
+
attr :process
|
82
|
+
attr :delete
|
83
|
+
attr :post
|
84
|
+
attr :accs
|
85
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Document tweaking module.
|
2
|
+
# Provides deprected Pre-plugins and Post-plugins.
|
3
|
+
module PBSimply::Plugger
|
4
|
+
POST_PROCESSORS = {
|
5
|
+
".rb" => "ruby",
|
6
|
+
".pl" => "perl",
|
7
|
+
".py" => "python",
|
8
|
+
".lua" => "lua",
|
9
|
+
".bash" => "bash",
|
10
|
+
".zsh" => "zsh",
|
11
|
+
".php" => "php",
|
12
|
+
".sed" => ["sed", ->(script, target) { ["-f", script, target] } ]
|
13
|
+
}
|
14
|
+
|
15
|
+
# Deprecated filter command feature.
|
16
|
+
#
|
17
|
+
# Pre plugins invoke each command on .pre_generate directory as filter command before process document.
|
18
|
+
# Porcessing document (same content as source document) path given as first argument.
|
19
|
+
def pre_plugins(procdoc, frontmatter)
|
20
|
+
if File.directory?(".pre_generate")
|
21
|
+
STDERR.puts("Processing with pre plugins")
|
22
|
+
script_file = File.join(".pre_generate", script_file)
|
23
|
+
Dir.entries(".pre_generate").sort.each do |script_file|
|
24
|
+
next if script_file =~ /^\./
|
25
|
+
STDERR.puts "Running script: #{File.basename script_file}"
|
26
|
+
pre_script_result = nil
|
27
|
+
script_cmdline = case
|
28
|
+
when File.executable?(script_file)
|
29
|
+
[script_file, procdoc]
|
30
|
+
when POST_PROCESSORS[File.extname(script_file)]
|
31
|
+
[POST_PROCESSORS[File.extname(script_file)], script_file, procdoc]
|
32
|
+
else
|
33
|
+
["perl", script_file, procdoc]
|
34
|
+
end
|
35
|
+
IO.popen({"pbsimply_doc_frontmatter" => YAML.dump(frontmatter)}, script_cmdline) do |io|
|
36
|
+
pre_script_result = io.read
|
37
|
+
end
|
38
|
+
File.open(procdoc, "w") {|f| f.write pre_script_result}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Post plugins invoke each command on .post_generate directory as filter command after processed.
|
44
|
+
# Generated document (typically HTML) path given as first argument.
|
45
|
+
def post_plugins(frontmatter=nil)
|
46
|
+
if File.directory?(".post_generate")
|
47
|
+
|
48
|
+
STDERR.puts("Processing with post plugins")
|
49
|
+
|
50
|
+
@this_time_processed.each do |v|
|
51
|
+
STDERR.puts "Processing #{v[:dest]} (from #{v[:source]})"
|
52
|
+
procdoc = v[:dest]
|
53
|
+
frontmatter ||= @indexes[File.basename v[:source]]
|
54
|
+
File.open(@workfile_frontmatter, "w") {|f| f.write JSON_LIB.dump(frontmatter)}
|
55
|
+
Dir.entries(".post_generate").sort.each do |script_file|
|
56
|
+
next if script_file =~ /^\./
|
57
|
+
STDERR.puts "Running script: #{script_file}"
|
58
|
+
script_file = File.join(".post_generate", script_file)
|
59
|
+
post_script_result = nil
|
60
|
+
script_cmdline = case
|
61
|
+
when File.executable?(script_file)
|
62
|
+
[script_file, procdoc]
|
63
|
+
when POST_PROCESSORS[File.extname(script_file)]
|
64
|
+
[POST_PROCESSORS[File.extname(script_file)], script_file, procdoc]
|
65
|
+
else
|
66
|
+
["perl", script_file, procdoc]
|
67
|
+
end
|
68
|
+
IO.popen({"pbsimply_workdir" => @workdir,"pbsimply_frontmatter" => @workfile_frontmatter, "pbsimply_indexes" => @db.path}, script_cmdline) do |io|
|
69
|
+
post_script_result = io.read
|
70
|
+
end
|
71
|
+
|
72
|
+
File.open(procdoc, "w") {|f| f.write post_script_result}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# Module for BLESSING feature.
|
4
|
+
module PBSimply::Prayer
|
5
|
+
def bless frontmatter
|
6
|
+
if @config["bless_style"] == "cmd"
|
7
|
+
bless_cmd frontmatter
|
8
|
+
else
|
9
|
+
bless_ruby frontmatter
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def bless_ruby(frontmatter)
|
14
|
+
# BLESSING (Always)
|
15
|
+
if PureBuilder.const_defined?(:BLESS) && Proc === PureBuilder::BLESS
|
16
|
+
begin
|
17
|
+
PureBuilder::BLESS.(frontmatter, self)
|
18
|
+
rescue
|
19
|
+
STDERR.puts "*** BLESSING PROC ERROR ***"
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# BLESSING (ACCS)
|
25
|
+
if @accs && PureBuilder::ACCS.const_defined?(:BLESS) && Proc === PureBuilder::ACCS::BLESS
|
26
|
+
begin
|
27
|
+
PureBuilder::ACCS::BLESS.(frontmatter, self)
|
28
|
+
rescue
|
29
|
+
STDERR.puts "*** ACCS BLESSING PROC ERROR ***"
|
30
|
+
raise
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# ACCS DEFINITIONS
|
35
|
+
if @accs
|
36
|
+
if Proc === PureBuilder::ACCS::DEFINITIONS[:next]
|
37
|
+
i = PureBuilder::ACCS::DEFINITIONS[:next].call(frontmatter, self)
|
38
|
+
frontmatter["next_article"] = i if i
|
39
|
+
end
|
40
|
+
if Proc === PureBuilder::ACCS::DEFINITIONS[:prev]
|
41
|
+
i = PureBuilder::ACCS::DEFINITIONS[:prev].call(frontmatter, self)
|
42
|
+
frontmatter["prev_article"] = i if i
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
autobless(frontmatter)
|
47
|
+
end
|
48
|
+
|
49
|
+
def bless_cmd(frontmatter)
|
50
|
+
File.open(@workfile_frontmatter, "w") {|f| f.write JSON_LIB.dump(frontmatter) }
|
51
|
+
# BLESSING (Always)
|
52
|
+
if @config["bless_cmd"]
|
53
|
+
(Array === @config["bless_cmd"] ? system(*@config["bless_cmd"]) : system(@config["bless_cmd"]) ) or abort "*** BLESS COMMAND RETURNS NON-ZERO STATUS"
|
54
|
+
end
|
55
|
+
# BLESSING (ACCS)
|
56
|
+
if @config["bless_accscmd"]
|
57
|
+
(Array === @config["bless_accscmd"] ? system({"pbsimply_workdir" => @workdir, "pbsimply_frontmatter" => @workfile_frontmatter, "pbsimply_indexes" => @db.path}, *@config["bless_accscmd"]) : system({"pbsimply_workdir" => @workdir, "pbsimply_frontmatter" => @workfile_frontmatter, "pbsimply_indexes" => @db.path}, @config["bless_accscmd"]) ) or abort "*** BLESS COMMAND RETURNS NON-ZERO STATUS"
|
58
|
+
end
|
59
|
+
mod_frontmatter = JSON.load(File.read(@workfile_frontmatter))
|
60
|
+
frontmatter.replace(mod_frontmatter)
|
61
|
+
|
62
|
+
autobless(frontmatter)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Blessing automatic method with configuration.
|
66
|
+
def autobless(frontmatter)
|
67
|
+
catch(:accs_rel) do
|
68
|
+
# find Next/Prev page on accs
|
69
|
+
if @accs && @config["blessmethod_accs_rel"]
|
70
|
+
# Preparing. Run at once.
|
71
|
+
if !@article_order
|
72
|
+
@rev_article_order_index = {}
|
73
|
+
|
74
|
+
case @config["blessmethod_accs_rel"]
|
75
|
+
when "numbering"
|
76
|
+
@article_order = @indexes.to_a.sort_by {|i| i[1]["_filename"].to_i }
|
77
|
+
when "date"
|
78
|
+
begin
|
79
|
+
@article_order = @indexes.to_a.sort_by {|i| i[1]["date"]}
|
80
|
+
rescue
|
81
|
+
abort "*** Automatic Blessing Method Error: Maybe some article have no date."
|
82
|
+
end
|
83
|
+
when "timestamp"
|
84
|
+
begin
|
85
|
+
@article_order = @indexes.to_a.sort_by {|i| i[1]["timestamp"]}
|
86
|
+
rescue
|
87
|
+
abort "*** Automatic Blessing Method Error: Maybe some article have no timetsamp."
|
88
|
+
end
|
89
|
+
when "lexical"
|
90
|
+
@article_order = @indexes.to_a.sort_by {|i| i[1]["_filename"]}
|
91
|
+
end
|
92
|
+
@article_order.each_with_index {|x,i| @rev_article_order_index[x[0]] = i }
|
93
|
+
end
|
94
|
+
|
95
|
+
throw(:accs_rel) unless index = @rev_article_order_index[frontmatter["_filename"]]
|
96
|
+
if @article_order[index + 1]
|
97
|
+
frontmatter["next_article"] = {"url" => @article_order[index + 1][1]["page_url"],
|
98
|
+
"title" => @article_order[index + 1][1]["title"]}
|
99
|
+
end
|
100
|
+
if index > 0
|
101
|
+
frontmatter["prev_article"] = {"url" => @article_order[index - 1][1]["page_url"],
|
102
|
+
"title" => @article_order[index - 1][1]["title"]}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|