liquidoc 0.12.0.pre.rc5 → 0.12.0.pre.rc6
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/lib/liquid/filters/date_filters.rb +107 -0
- data/lib/liquid/filters/grouping_filters.rb +65 -0
- data/lib/liquid/filters/jekyll.rb +488 -0
- data/lib/liquid/filters/url_filters.rb +63 -0
- data/lib/liquid/tags/highlight.rb +131 -0
- data/lib/liquid/tags/jekyll.rb +219 -0
- data/lib/liquid/tags/link.rb +37 -0
- data/lib/liquid/tags/post_url.rb +103 -0
- data/lib/liquidoc/version.rb +1 -1
- data/lib/liquidoc.rb +378 -101
- metadata +38 -2
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Filters
|
5
|
+
module URLFilters
|
6
|
+
# Produces an absolute URL based on site.url and site.baseurl.
|
7
|
+
#
|
8
|
+
# input - the URL to make absolute.
|
9
|
+
#
|
10
|
+
# Returns the absolute URL as a String.
|
11
|
+
def absolute_url(input)
|
12
|
+
return if input.nil?
|
13
|
+
input = input.url if input.respond_to?(:url)
|
14
|
+
return input if Addressable::URI.parse(input.to_s).absolute?
|
15
|
+
site = @context.registers[:site]
|
16
|
+
return relative_url(input) if site.config["url"].nil?
|
17
|
+
Addressable::URI.parse(
|
18
|
+
site.config["url"].to_s + relative_url(input)
|
19
|
+
).normalize.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
# Produces a URL relative to the domain root based on site.baseurl
|
23
|
+
# unless it is already an absolute url with an authority (host).
|
24
|
+
#
|
25
|
+
# input - the URL to make relative to the domain root
|
26
|
+
#
|
27
|
+
# Returns a URL relative to the domain root as a String.
|
28
|
+
def relative_url(input)
|
29
|
+
return if input.nil?
|
30
|
+
input = input.url if input.respond_to?(:url)
|
31
|
+
return input if Addressable::URI.parse(input.to_s).absolute?
|
32
|
+
|
33
|
+
parts = [sanitized_baseurl, input]
|
34
|
+
Addressable::URI.parse(
|
35
|
+
parts.compact.map { |part| ensure_leading_slash(part.to_s) }.join
|
36
|
+
).normalize.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
# Strips trailing `/index.html` from URLs to create pretty permalinks
|
40
|
+
#
|
41
|
+
# input - the URL with a possible `/index.html`
|
42
|
+
#
|
43
|
+
# Returns a URL with the trailing `/index.html` removed
|
44
|
+
def strip_index(input)
|
45
|
+
return if input.nil? || input.to_s.empty?
|
46
|
+
input.sub(%r!/index\.html?$!, "/")
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def sanitized_baseurl
|
52
|
+
site = @context.registers[:site]
|
53
|
+
site.config["baseurl"].to_s.chomp("/")
|
54
|
+
end
|
55
|
+
|
56
|
+
def ensure_leading_slash(input)
|
57
|
+
return input if input.nil? || input.empty? || input.start_with?("/")
|
58
|
+
"/#{input}"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Tags
|
5
|
+
class HighlightBlock < Liquid::Block
|
6
|
+
include Liquid::StandardFilters
|
7
|
+
|
8
|
+
# The regular expression syntax checker. Start with the language specifier.
|
9
|
+
# Follow that by zero or more space separated options that take one of three
|
10
|
+
# forms: name, name=value, or name="<quoted list>"
|
11
|
+
#
|
12
|
+
# <quoted list> is a space-separated list of numbers
|
13
|
+
SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!
|
14
|
+
|
15
|
+
def initialize(tag_name, markup, tokens)
|
16
|
+
super
|
17
|
+
"WORKS!"
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(context)
|
21
|
+
prefix = context["highlighter_prefix"] || ""
|
22
|
+
suffix = context["highlighter_suffix"] || ""
|
23
|
+
code = super.to_s.gsub(%r!\A(\n|\r)+|(\n|\r)+\z!, "")
|
24
|
+
|
25
|
+
is_safe = !!context.registers[:site].safe
|
26
|
+
|
27
|
+
output =
|
28
|
+
case context.registers[:site].highlighter
|
29
|
+
when "pygments"
|
30
|
+
render_pygments(code, is_safe)
|
31
|
+
when "rouge"
|
32
|
+
render_rouge(code)
|
33
|
+
else
|
34
|
+
render_codehighlighter(code)
|
35
|
+
end
|
36
|
+
|
37
|
+
rendered_output = add_code_tag(output)
|
38
|
+
prefix + rendered_output + suffix
|
39
|
+
end
|
40
|
+
|
41
|
+
def sanitized_opts(opts, is_safe)
|
42
|
+
if is_safe
|
43
|
+
Hash[[
|
44
|
+
[:startinline, opts.fetch(:startinline, nil)],
|
45
|
+
[:hl_lines, opts.fetch(:hl_lines, nil)],
|
46
|
+
[:linenos, opts.fetch(:linenos, nil)],
|
47
|
+
[:encoding, opts.fetch(:encoding, "utf-8")],
|
48
|
+
[:cssclass, opts.fetch(:cssclass, nil)],
|
49
|
+
].reject { |f| f.last.nil? }]
|
50
|
+
else
|
51
|
+
opts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)+!
|
58
|
+
|
59
|
+
def parse_options(input)
|
60
|
+
options = {}
|
61
|
+
return options if input.empty?
|
62
|
+
|
63
|
+
# Split along 3 possible forms -- key="<quoted list>", key=value, or key
|
64
|
+
input.scan(OPTIONS_REGEX) do |opt|
|
65
|
+
key, value = opt.split("=")
|
66
|
+
# If a quoted list, convert to array
|
67
|
+
if value && value.include?('"')
|
68
|
+
value.delete!('"')
|
69
|
+
value = value.split
|
70
|
+
end
|
71
|
+
options[key.to_sym] = value || true
|
72
|
+
end
|
73
|
+
|
74
|
+
options[:linenos] = "inline" if options[:linenos] == true
|
75
|
+
options
|
76
|
+
end
|
77
|
+
|
78
|
+
def render_pygments(code, is_safe)
|
79
|
+
Jekyll::External.require_with_graceful_fail("pygments") unless defined?(Pygments)
|
80
|
+
|
81
|
+
highlighted_code = Pygments.highlight(
|
82
|
+
code,
|
83
|
+
:lexer => @lang,
|
84
|
+
:options => sanitized_opts(@highlight_options, is_safe)
|
85
|
+
)
|
86
|
+
|
87
|
+
if highlighted_code.nil?
|
88
|
+
Jekyll.logger.error <<-MSG
|
89
|
+
There was an error highlighting your code:
|
90
|
+
|
91
|
+
#{code}
|
92
|
+
|
93
|
+
While attempting to convert the above code, Pygments.rb returned an unacceptable value.
|
94
|
+
This is usually a timeout problem solved by running `jekyll build` again.
|
95
|
+
MSG
|
96
|
+
raise ArgumentError, "Pygments.rb returned an unacceptable value "\
|
97
|
+
"when attempting to highlight some code."
|
98
|
+
end
|
99
|
+
|
100
|
+
highlighted_code.sub('<div class="highlight"><pre>', "").sub("</pre></div>", "")
|
101
|
+
end
|
102
|
+
|
103
|
+
def render_rouge(code)
|
104
|
+
formatter = Jekyll::Utils::Rouge.html_formatter(
|
105
|
+
:line_numbers => @highlight_options[:linenos],
|
106
|
+
:wrap => false,
|
107
|
+
:css_class => "highlight",
|
108
|
+
:gutter_class => "gutter",
|
109
|
+
:code_class => "code"
|
110
|
+
)
|
111
|
+
lexer = ::Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
112
|
+
formatter.format(lexer.lex(code))
|
113
|
+
end
|
114
|
+
|
115
|
+
def render_codehighlighter(code)
|
116
|
+
h(code).strip
|
117
|
+
end
|
118
|
+
|
119
|
+
def add_code_tag(code)
|
120
|
+
code_attributes = [
|
121
|
+
"class=\"language-#{@lang.to_s.tr("+", "-")}\"",
|
122
|
+
"data-lang=\"#{@lang}\"",
|
123
|
+
].join(" ")
|
124
|
+
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
125
|
+
"#{code.chomp}</code></pre></figure>"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
Liquid::Template.register_tag("highlight", Jekyll::Tags::HighlightBlock)
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# (C) Jekyll, this file contains some of Jekyll's custom Liquid filters
|
2
|
+
# It is placed in lib/liquid/jekyll for this reason, even though the module/class
|
3
|
+
# path is Jekyll::Tags::, so as not to conflict with the Liquid:: path.
|
4
|
+
|
5
|
+
# frozen_string_literal: true
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
module Tags
|
9
|
+
class IncludeTagError < StandardError
|
10
|
+
attr_accessor :path
|
11
|
+
|
12
|
+
def initialize(msg, path)
|
13
|
+
super(msg)
|
14
|
+
@path = path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class IncludeTag < Liquid::Tag
|
19
|
+
# matches proper params format only
|
20
|
+
# 1(key-formatted str) = (2(double-quoted str) or 3(single-quoted str) 4(var-formatted str))
|
21
|
+
VALID_SYNTAX = %r!
|
22
|
+
([\w-]+)\s*=\s*
|
23
|
+
(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([a-z][\w'"\[\]\.-]*))
|
24
|
+
!x
|
25
|
+
# extracts filename as #{variable} and k/v pairs as #{params}
|
26
|
+
VARIABLE_SYNTAX = %r!
|
27
|
+
(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)
|
28
|
+
(?<params>.*)
|
29
|
+
!mx
|
30
|
+
|
31
|
+
FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!
|
32
|
+
VALID_FILENAME_CHARS = %r!^[\w/\.-]+$!
|
33
|
+
INVALID_SEQUENCES = %r![./]{2,}!
|
34
|
+
|
35
|
+
def initialize(tag_name, markup, tokens)
|
36
|
+
super
|
37
|
+
matched = markup.strip.match(VARIABLE_SYNTAX)
|
38
|
+
if matched # include passes filename as variable
|
39
|
+
@file = matched["variable"].strip # The file to include (as a var)
|
40
|
+
@params = matched["params"].strip # The paired vars to load
|
41
|
+
else # if the filename isn't a variable, just grab the first arg as filename and rest as params
|
42
|
+
@file, @params = markup.strip.split(%r!\s+!, 2)
|
43
|
+
end
|
44
|
+
validate_params if @params
|
45
|
+
@tag_name = tag_name
|
46
|
+
end
|
47
|
+
|
48
|
+
def syntax_example
|
49
|
+
"{% #{@tag_name} file.ext param='value' param2='value' %}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_params(context)
|
53
|
+
params = {}
|
54
|
+
markup = @params
|
55
|
+
while (match = VALID_SYNTAX.match(markup))
|
56
|
+
# run until syntax no longer matches parameters
|
57
|
+
markup = markup[match.end(0)..-1]
|
58
|
+
# set val by which group matched in VALID_SYNTAX
|
59
|
+
# either a quoted string (2,3) or a variable (4)
|
60
|
+
value = if match[2]
|
61
|
+
match[2].gsub(%r!\\"!, '"')
|
62
|
+
elsif match[3]
|
63
|
+
match[3].gsub(%r!\\'!, "'")
|
64
|
+
elsif match[4] # val is resolved context var
|
65
|
+
context[match[4]]
|
66
|
+
end
|
67
|
+
params[match[1]] = value # inserts param
|
68
|
+
end
|
69
|
+
params # returns hash for the include scope
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_file_name(file)
|
73
|
+
if file =~ INVALID_SEQUENCES || file !~ VALID_FILENAME_CHARS
|
74
|
+
raise ArgumentError, <<-MSG
|
75
|
+
Invalid syntax for include tag. File contains invalid characters or sequences:
|
76
|
+
|
77
|
+
#{file}
|
78
|
+
|
79
|
+
Valid syntax:
|
80
|
+
|
81
|
+
#{syntax_example}
|
82
|
+
|
83
|
+
MSG
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def validate_params
|
88
|
+
unless @params =~ FULL_VALID_SYNTAX
|
89
|
+
raise ArgumentError, <<-MSG
|
90
|
+
Invalid syntax for include tag:
|
91
|
+
|
92
|
+
#{@params}
|
93
|
+
|
94
|
+
Valid syntax:
|
95
|
+
|
96
|
+
#{syntax_example}
|
97
|
+
|
98
|
+
MSG
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# # Grab file read opts in the context
|
103
|
+
# def file_read_opts(context)
|
104
|
+
# context.registers[:site].file_read_opts
|
105
|
+
# end
|
106
|
+
|
107
|
+
# Express the filename from the variable
|
108
|
+
# Passes along the context in which it was called, from the parent file
|
109
|
+
def render_variable(context)
|
110
|
+
Liquid::Template.parse(@file).render(context) if @file =~ VARIABLE_SYNTAX
|
111
|
+
end
|
112
|
+
|
113
|
+
# Array of directories where includes are stored
|
114
|
+
def tag_includes_dirs(context)
|
115
|
+
# context[:includes_dirs]
|
116
|
+
['_templates','_templates/liquid','_templates/liquid/ops','theme/_includes','_theme/layouts']
|
117
|
+
end
|
118
|
+
|
119
|
+
# Traverse includes dirs, setting paths for includes
|
120
|
+
def locate_include_file(context, file, safe)
|
121
|
+
includes_dirs = ['_templates','_templates/liquid','_templates/liquid/ops','_templates/ops','theme/_includes','theme/_layouts']
|
122
|
+
includes_dirs.each do |dir|
|
123
|
+
path = File.join(dir.to_s, file.to_s)
|
124
|
+
return path if File.exist?(path)
|
125
|
+
end
|
126
|
+
raise IOError, could_not_locate_message(file, includes_dirs, safe)
|
127
|
+
end
|
128
|
+
|
129
|
+
# recall/render the included partial and place it in the parent doc
|
130
|
+
def render(context)
|
131
|
+
file = render_variable(context) || @file # use parsed variable filename unless passed explicit filename
|
132
|
+
validate_file_name(file)
|
133
|
+
path = locate_include_file(context, file, true) # ensure file exists in safe path
|
134
|
+
return unless path
|
135
|
+
# # ???????
|
136
|
+
# add_include_to_dependency(site, path, context)
|
137
|
+
#
|
138
|
+
# Load the partial if it's identical to one we've already loaded ???
|
139
|
+
partial = File.read(path) # reads the template file
|
140
|
+
partial = Liquid::Template.parse(partial) # compiles template
|
141
|
+
# setup and perform render
|
142
|
+
context.stack do
|
143
|
+
# create a hash object for any passed k/v pair args
|
144
|
+
# by parsing passed parameters using the parent file's scope
|
145
|
+
context["include"] = parse_params(context) if @params
|
146
|
+
begin # render the include for output
|
147
|
+
partial.render!(context)
|
148
|
+
rescue Liquid::Error => e
|
149
|
+
e.template_name = path
|
150
|
+
e.markup_context = "included " if e.markup_context.nil?
|
151
|
+
raise e
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# #
|
157
|
+
# def add_include_to_dependency(site, path, context)
|
158
|
+
# if context.registers[:page] && context.registers[:page].key?("path")
|
159
|
+
# site.regenerator.add_dependency(
|
160
|
+
# site.in_source_dir(context.registers[:page]["path"]),
|
161
|
+
# path
|
162
|
+
# )
|
163
|
+
# end
|
164
|
+
# end
|
165
|
+
|
166
|
+
def load_cached_partial(path, context)
|
167
|
+
context.registers[:cached_partials] ||= {}
|
168
|
+
cached_partial = context.registers[:cached_partials]
|
169
|
+
|
170
|
+
if cached_partial.key?(path)
|
171
|
+
cached_partial[path]
|
172
|
+
else
|
173
|
+
unparsed_file = context.registers[:globals]
|
174
|
+
.liquid_renderer
|
175
|
+
.file(path)
|
176
|
+
begin
|
177
|
+
# Cache a version of the
|
178
|
+
cached_partial[path] = unparsed_file.parse(read_file(path, context))
|
179
|
+
rescue Liquid::Error => e
|
180
|
+
e.template_name = path
|
181
|
+
e.markup_context = "included " if e.markup_context.nil?
|
182
|
+
raise e
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def outside_site_source?(path, dir, safe)
|
188
|
+
safe && !realpath_prefixed_with?(path, dir)
|
189
|
+
end
|
190
|
+
|
191
|
+
def realpath_prefixed_with?(path, dir)
|
192
|
+
File.exist?(path) && File.realpath(path).start_with?(dir)
|
193
|
+
rescue StandardError
|
194
|
+
false
|
195
|
+
end
|
196
|
+
|
197
|
+
# This method allows to modify the file content by inheriting from the class.
|
198
|
+
def read_file(file, context)
|
199
|
+
File.read(file)
|
200
|
+
end
|
201
|
+
|
202
|
+
private
|
203
|
+
|
204
|
+
def could_not_locate_message(file, includes_dirs, safe)
|
205
|
+
message = "Could not locate the included file '#{file}' in any of "\
|
206
|
+
"#{includes_dirs}. Ensure it exists in one of those directories and"
|
207
|
+
message + if safe
|
208
|
+
" is not a symlink as those are not allowed in safe mode."
|
209
|
+
else
|
210
|
+
", if it is a symlink, does not point outside your site source."
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
end # Tags
|
216
|
+
|
217
|
+
end
|
218
|
+
|
219
|
+
Liquid::Template.register_tag("include", Jekyll::Tags::IncludeTag)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Tags
|
5
|
+
class Link < Liquid::Tag
|
6
|
+
class << self
|
7
|
+
def tag_name
|
8
|
+
self.name.split("::").last.downcase
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(tag_name, relative_path, tokens)
|
13
|
+
super
|
14
|
+
|
15
|
+
@relative_path = relative_path.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
def render(context)
|
19
|
+
site = context.registers[:site]
|
20
|
+
|
21
|
+
site.each_site_file do |item|
|
22
|
+
return item.url if item.relative_path == @relative_path
|
23
|
+
# This takes care of the case for static files that have a leading /
|
24
|
+
return item.url if item.relative_path == "/#{@relative_path}"
|
25
|
+
end
|
26
|
+
|
27
|
+
raise ArgumentError, <<-MSG
|
28
|
+
Could not find document '#{@relative_path}' in tag '#{self.class.tag_name}'.
|
29
|
+
|
30
|
+
Make sure the document exists and the path is correct.
|
31
|
+
MSG
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
Liquid::Template.register_tag(Jekyll::Tags::Link.tag_name, Jekyll::Tags::Link)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jekyll
|
4
|
+
module Tags
|
5
|
+
class PostComparer
|
6
|
+
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!
|
7
|
+
|
8
|
+
attr_reader :path, :date, :slug, :name
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@name = name
|
12
|
+
|
13
|
+
all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
|
14
|
+
unless all
|
15
|
+
raise Jekyll::Errors::InvalidPostNameError,
|
16
|
+
"'#{name}' does not contain valid date and/or title."
|
17
|
+
end
|
18
|
+
|
19
|
+
escaped_slug = Regexp.escape(slug)
|
20
|
+
@name_regex = %r!^_posts/#{path}#{date}-#{escaped_slug}\.[^.]+|
|
21
|
+
^#{path}_posts/?#{date}-#{escaped_slug}\.[^.]+!x
|
22
|
+
end
|
23
|
+
|
24
|
+
def post_date
|
25
|
+
@post_date ||= Utils.parse_date(date,
|
26
|
+
"\"#{date}\" does not contain valid date and/or title.")
|
27
|
+
end
|
28
|
+
|
29
|
+
def ==(other)
|
30
|
+
other.relative_path.match(@name_regex)
|
31
|
+
end
|
32
|
+
|
33
|
+
def deprecated_equality(other)
|
34
|
+
slug == post_slug(other) &&
|
35
|
+
post_date.year == other.date.year &&
|
36
|
+
post_date.month == other.date.month &&
|
37
|
+
post_date.day == other.date.day
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
# Construct the directory-aware post slug for a Jekyll::Post
|
42
|
+
#
|
43
|
+
# other - the Jekyll::Post
|
44
|
+
#
|
45
|
+
# Returns the post slug with the subdirectory (relative to _posts)
|
46
|
+
def post_slug(other)
|
47
|
+
path = other.basename.split("/")[0...-1].join("/")
|
48
|
+
if path.nil? || path == ""
|
49
|
+
other.data["slug"]
|
50
|
+
else
|
51
|
+
path + "/" + other.data["slug"]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class PostUrl < Liquid::Tag
|
57
|
+
def initialize(tag_name, post, tokens)
|
58
|
+
super
|
59
|
+
@orig_post = post.strip
|
60
|
+
begin
|
61
|
+
@post = PostComparer.new(@orig_post)
|
62
|
+
rescue StandardError => e
|
63
|
+
raise Jekyll::Errors::PostURLError, <<-MSG
|
64
|
+
Could not parse name of post "#{@orig_post}" in tag 'post_url'.
|
65
|
+
|
66
|
+
Make sure the post exists and the name is correct.
|
67
|
+
|
68
|
+
#{e.class}: #{e.message}
|
69
|
+
MSG
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def render(context)
|
74
|
+
site = context.registers[:site]
|
75
|
+
|
76
|
+
site.posts.docs.each do |p|
|
77
|
+
return p.url if @post == p
|
78
|
+
end
|
79
|
+
|
80
|
+
# New matching method did not match, fall back to old method
|
81
|
+
# with deprecation warning if this matches
|
82
|
+
|
83
|
+
site.posts.docs.each do |p|
|
84
|
+
next unless @post.deprecated_equality p
|
85
|
+
Jekyll::Deprecator.deprecation_message "A call to "\
|
86
|
+
"'{% post_url #{@post.name} %}' did not match " \
|
87
|
+
"a post using the new matching method of checking name " \
|
88
|
+
"(path-date-slug) equality. Please make sure that you " \
|
89
|
+
"change this tag to match the post's name exactly."
|
90
|
+
return p.url
|
91
|
+
end
|
92
|
+
|
93
|
+
raise Jekyll::Errors::PostURLError, <<-MSG
|
94
|
+
Could not find post "#{@orig_post}" in tag 'post_url'.
|
95
|
+
|
96
|
+
Make sure the post exists and the name is correct.
|
97
|
+
MSG
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Liquid::Template.register_tag("post_url", Jekyll::Tags::PostUrl)
|
data/lib/liquidoc/version.rb
CHANGED