jekyll-docs 3.6.0 → 3.6.1
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/jekyll.rb +195 -0
- data/lib/jekyll/cleaner.rb +110 -0
- data/lib/jekyll/collection.rb +230 -0
- data/lib/jekyll/command.rb +78 -0
- data/lib/jekyll/commands/build.rb +102 -0
- data/lib/jekyll/commands/clean.rb +43 -0
- data/lib/jekyll/commands/doctor.rb +153 -0
- data/lib/jekyll/commands/help.rb +34 -0
- data/lib/jekyll/commands/new.rb +156 -0
- data/lib/jekyll/commands/new_theme.rb +40 -0
- data/lib/jekyll/commands/serve.rb +245 -0
- data/lib/jekyll/commands/serve/servlet.rb +62 -0
- data/lib/jekyll/configuration.rb +410 -0
- data/lib/jekyll/converter.rb +54 -0
- data/lib/jekyll/converters/identity.rb +23 -0
- data/lib/jekyll/converters/markdown.rb +104 -0
- data/lib/jekyll/converters/markdown/kramdown_parser.rb +123 -0
- data/lib/jekyll/converters/markdown/rdiscount_parser.rb +35 -0
- data/lib/jekyll/converters/markdown/redcarpet_parser.rb +108 -0
- data/lib/jekyll/converters/smartypants.rb +36 -0
- data/lib/jekyll/convertible.rb +251 -0
- data/lib/jekyll/deprecator.rb +52 -0
- data/lib/jekyll/document.rb +507 -0
- data/lib/jekyll/drops/collection_drop.rb +22 -0
- data/lib/jekyll/drops/document_drop.rb +69 -0
- data/lib/jekyll/drops/drop.rb +214 -0
- data/lib/jekyll/drops/excerpt_drop.rb +15 -0
- data/lib/jekyll/drops/jekyll_drop.rb +33 -0
- data/lib/jekyll/drops/site_drop.rb +47 -0
- data/lib/jekyll/drops/static_file_drop.rb +13 -0
- data/lib/jekyll/drops/unified_payload_drop.rb +25 -0
- data/lib/jekyll/drops/url_drop.rb +88 -0
- data/lib/jekyll/entry_filter.rb +123 -0
- data/lib/jekyll/errors.rb +20 -0
- data/lib/jekyll/excerpt.rb +126 -0
- data/lib/jekyll/external.rb +74 -0
- data/lib/jekyll/filters.rb +430 -0
- data/lib/jekyll/filters/grouping_filters.rb +65 -0
- data/lib/jekyll/filters/url_filters.rb +60 -0
- data/lib/jekyll/frontmatter_defaults.rb +197 -0
- data/lib/jekyll/generator.rb +5 -0
- data/lib/jekyll/hooks.rb +104 -0
- data/lib/jekyll/layout.rb +62 -0
- data/lib/jekyll/liquid_extensions.rb +24 -0
- data/lib/jekyll/liquid_renderer.rb +49 -0
- data/lib/jekyll/liquid_renderer/file.rb +56 -0
- data/lib/jekyll/liquid_renderer/table.rb +96 -0
- data/lib/jekyll/log_adapter.rb +147 -0
- data/lib/jekyll/mime.types +825 -0
- data/lib/jekyll/page.rb +187 -0
- data/lib/jekyll/plugin.rb +98 -0
- data/lib/jekyll/plugin_manager.rb +113 -0
- data/lib/jekyll/publisher.rb +23 -0
- data/lib/jekyll/reader.rb +134 -0
- data/lib/jekyll/readers/collection_reader.rb +22 -0
- data/lib/jekyll/readers/data_reader.rb +77 -0
- data/lib/jekyll/readers/layout_reader.rb +71 -0
- data/lib/jekyll/readers/page_reader.rb +25 -0
- data/lib/jekyll/readers/post_reader.rb +72 -0
- data/lib/jekyll/readers/static_file_reader.rb +25 -0
- data/lib/jekyll/readers/theme_assets_reader.rb +49 -0
- data/lib/jekyll/regenerator.rb +201 -0
- data/lib/jekyll/related_posts.rb +52 -0
- data/lib/jekyll/renderer.rb +269 -0
- data/lib/jekyll/site.rb +471 -0
- data/lib/jekyll/static_file.rb +162 -0
- data/lib/jekyll/stevenson.rb +61 -0
- data/lib/jekyll/tags/highlight.rb +141 -0
- data/lib/jekyll/tags/include.rb +215 -0
- data/lib/jekyll/tags/link.rb +37 -0
- data/lib/jekyll/tags/post_url.rb +103 -0
- data/lib/jekyll/theme.rb +68 -0
- data/lib/jekyll/theme_builder.rb +119 -0
- data/lib/jekyll/url.rb +161 -0
- data/lib/jekyll/utils.rb +337 -0
- data/lib/jekyll/utils/ansi.rb +59 -0
- data/lib/jekyll/utils/exec.rb +27 -0
- data/lib/jekyll/utils/platforms.rb +82 -0
- data/lib/jekyll/utils/rouge.rb +21 -0
- data/lib/jekyll/utils/win_tz.rb +75 -0
- data/lib/jekyll/version.rb +5 -0
- data/lib/site_template/404.html +24 -0
- data/lib/site_template/_config.yml +43 -0
- data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +25 -0
- data/lib/site_template/about.md +18 -0
- data/lib/site_template/index.md +6 -0
- data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
- data/lib/theme_template/Gemfile +4 -0
- data/lib/theme_template/LICENSE.txt.erb +21 -0
- data/lib/theme_template/README.md.erb +52 -0
- data/lib/theme_template/_layouts/default.html +1 -0
- data/lib/theme_template/_layouts/page.html +5 -0
- data/lib/theme_template/_layouts/post.html +5 -0
- data/lib/theme_template/example/_config.yml.erb +1 -0
- data/lib/theme_template/example/_post.md +12 -0
- data/lib/theme_template/example/index.html +14 -0
- data/lib/theme_template/example/style.scss +7 -0
- data/lib/theme_template/gitignore.erb +5 -0
- data/lib/theme_template/theme.gemspec.erb +19 -0
- metadata +103 -156
- data/lib/jekyll-docs.rb +0 -31
- data/site/404.html +0 -153
- data/site/CNAME +0 -1
- data/site/community/index.html +0 -299
- data/site/conduct/index.html +0 -10
- data/site/css/screen.css +0 -1
- data/site/docs/assets/index.html +0 -724
- data/site/docs/code_of_conduct/index.html +0 -730
- data/site/docs/collections/index.html +0 -1097
- data/site/docs/conduct/index.html +0 -744
- data/site/docs/configuration/index.html +0 -1403
- data/site/docs/continuous-integration/buddyworks/index.html +0 -726
- data/site/docs/continuous-integration/circleci/index.html +0 -757
- data/site/docs/continuous-integration/index.html +0 -681
- data/site/docs/continuous-integration/travis-ci/index.html +0 -891
- data/site/docs/contributing/index.html +0 -863
- data/site/docs/datafiles/index.html +0 -780
- data/site/docs/deployment-methods/index.html +0 -875
- data/site/docs/drafts/index.html +0 -636
- data/site/docs/extras/index.html +0 -689
- data/site/docs/frontmatter/index.html +0 -807
- data/site/docs/github-pages/index.html +0 -819
- data/site/docs/history/index.html +0 -3955
- data/site/docs/home/index.html +0 -644
- data/site/docs/includes/index.html +0 -800
- data/site/docs/index.html +0 -10
- data/site/docs/installation/index.html +0 -732
- data/site/docs/maintaining/affinity-team-captain/index.html +0 -706
- data/site/docs/maintaining/avoiding-burnout/index.html +0 -709
- data/site/docs/maintaining/becoming-a-maintainer/index.html +0 -717
- data/site/docs/maintaining/index.html +0 -713
- data/site/docs/maintaining/merging-a-pull-request/index.html +0 -747
- data/site/docs/maintaining/reviewing-a-pull-request/index.html +0 -725
- data/site/docs/maintaining/special-labels/index.html +0 -705
- data/site/docs/maintaining/triaging-an-issue/index.html +0 -735
- data/site/docs/migrations/index.html +0 -647
- data/site/docs/pages/index.html +0 -695
- data/site/docs/pagination/index.html +0 -870
- data/site/docs/permalinks/index.html +0 -1027
- data/site/docs/plugins/index.html +0 -1800
- data/site/docs/posts/index.html +0 -858
- data/site/docs/quickstart/index.html +0 -650
- data/site/docs/resources/index.html +0 -769
- data/site/docs/sites/index.html +0 -702
- data/site/docs/static-files/index.html +0 -720
- data/site/docs/structure/index.html +0 -822
- data/site/docs/templates/index.html +0 -1208
- data/site/docs/themes/index.html +0 -935
- data/site/docs/troubleshooting/index.html +0 -893
- data/site/docs/upgrading/0-to-2/index.html +0 -826
- data/site/docs/upgrading/2-to-3/index.html +0 -824
- data/site/docs/upgrading/index.html +0 -693
- data/site/docs/usage/index.html +0 -705
- data/site/docs/variables/index.html +0 -1048
- data/site/docs/windows/index.html +0 -799
- data/site/favicon.ico +0 -0
- data/site/feed.xml +0 -372
- data/site/fonts/FontAwesome.eot +0 -0
- data/site/fonts/FontAwesome.svg +0 -12
- data/site/fonts/FontAwesome.ttf +0 -0
- data/site/fonts/FontAwesome.woff +0 -0
- data/site/github.html +0 -10
- data/site/help/index.html +0 -244
- data/site/icomoon-selection.json +0 -96
- data/site/img/article-footer.png +0 -0
- data/site/img/footer-arrow.png +0 -0
- data/site/img/footer-logo.png +0 -0
- data/site/img/jekyll-sticker.jpg +0 -0
- data/site/img/jekylllayoutconcept.png +0 -0
- data/site/img/logo-2x.png +0 -0
- data/site/img/logo-rss.png +0 -0
- data/site/img/octojekyll.png +0 -0
- data/site/index.html +0 -267
- data/site/issues.html +0 -10
- data/site/js/html5shiv.min.js +0 -4
- data/site/js/respond.min.js +0 -5
- data/site/latest_version.txt +0 -1
- data/site/news/2013/05/05/jekyll-1-0-0-released/index.html +0 -570
- data/site/news/2013/05/08/jekyll-1-0-1-released/index.html +0 -570
- data/site/news/2013/05/12/jekyll-1-0-2-released/index.html +0 -571
- data/site/news/2013/06/07/jekyll-1-0-3-released/index.html +0 -568
- data/site/news/2013/07/14/jekyll-1-1-0-released/index.html +0 -570
- data/site/news/2013/07/24/jekyll-1-1-1-released/index.html +0 -569
- data/site/news/2013/07/25/jekyll-1-0-4-released/index.html +0 -565
- data/site/news/2013/07/25/jekyll-1-1-2-released/index.html +0 -565
- data/site/news/2013/09/06/jekyll-1-2-0-released/index.html +0 -572
- data/site/news/2013/09/14/jekyll-1-2-1-released/index.html +0 -566
- data/site/news/2013/10/28/jekyll-1-3-0-rc1-released/index.html +0 -564
- data/site/news/2013/11/04/jekyll-1-3-0-released/index.html +0 -599
- data/site/news/2013/11/26/jekyll-1-3-1-released/index.html +0 -568
- data/site/news/2013/12/07/jekyll-1-4-0-released/index.html +0 -583
- data/site/news/2013/12/09/jekyll-1-4-1-released/index.html +0 -565
- data/site/news/2013/12/16/jekyll-1-4-2-released/index.html +0 -564
- data/site/news/2014/01/13/jekyll-1-4-3-released/index.html +0 -573
- data/site/news/2014/03/24/jekyll-1-5-0-released/index.html +0 -564
- data/site/news/2014/03/27/jekyll-1-5-1-released/index.html +0 -569
- data/site/news/2014/05/06/jekyll-turns-2-0-0/index.html +0 -585
- data/site/news/2014/05/08/jekyll-2-0-3-released/index.html +0 -565
- data/site/news/2014/06/04/jekyll-stickers-1-dollar-stickermule/index.html +0 -567
- data/site/news/2014/06/28/jekyll-turns-21-i-mean-2-1-0/index.html +0 -582
- data/site/news/2014/07/01/jekyll-2-1-1-released/index.html +0 -579
- data/site/news/2014/07/29/jekyll-2-2-0-released/index.html +0 -568
- data/site/news/2014/08/10/jekyll-2-3-0-released/index.html +0 -588
- data/site/news/2014/09/09/jekyll-2-4-0-released/index.html +0 -574
- data/site/news/2014/11/05/jekylls-midlife-crisis-jekyll-turns-2-5-0/index.html +0 -597
- data/site/news/2014/11/09/jekyll-2-5-1-released/index.html +0 -575
- data/site/news/2014/11/12/jekyll-2-5-2-released/index.html +0 -565
- data/site/news/2014/12/17/alfredxing-welcome-to-jekyll-core/index.html +0 -572
- data/site/news/2014/12/22/jekyll-2-5-3-released/index.html +0 -567
- data/site/news/2015/01/20/jekyll-meet-and-greet/index.html +0 -568
- data/site/news/2015/01/24/jekyll-3-0-0-beta1-released/index.html +0 -588
- data/site/news/2015/02/26/introducing-jekyll-talk/index.html +0 -563
- data/site/news/2015/10/26/jekyll-3-0-released/index.html +0 -592
- data/site/news/2015/11/17/jekyll-3-0-1-released/index.html +0 -576
- data/site/news/2016/01/20/jekyll-3-0-2-released/index.html +0 -566
- data/site/news/2016/01/24/jekyll-3-1-0-released/index.html +0 -599
- data/site/news/2016/01/28/jekyll-3-1-1-released/index.html +0 -583
- data/site/news/2016/02/08/jekyll-3-0-3-released/index.html +0 -578
- data/site/news/2016/02/19/jekyll-3-1-2-released/index.html +0 -569
- data/site/news/2016/03/10/making-it-easier-to-contribute-to-jekyll/index.html +0 -565
- data/site/news/2016/04/19/jekyll-3-0-4-released/index.html +0 -571
- data/site/news/2016/04/19/jekyll-3-1-3-released/index.html +0 -566
- data/site/news/2016/04/26/jekyll-3-0-5-released/index.html +0 -572
- data/site/news/2016/05/18/jekyll-3-1-4-released/index.html +0 -576
- data/site/news/2016/05/18/jekyll-3-1-5-released/index.html +0 -564
- data/site/news/2016/05/19/jekyll-3-1-6-released/index.html +0 -566
- data/site/news/2016/06/03/update-on-jekyll-s-google-summer-of-code-projects/index.html +0 -567
- data/site/news/2016/07/26/jekyll-3-2-0-released/index.html +0 -676
- data/site/news/2016/08/02/jekyll-3-2-1-released/index.html +0 -571
- data/site/news/2016/08/24/jekyll-admin-initial-release/index.html +0 -566
- data/site/news/2016/10/06/jekyll-3-3-is-here/index.html +0 -645
- data/site/news/2016/11/14/jekyll-3-3-1-released/index.html +0 -569
- data/site/news/2017/01/18/jekyll-3-4-0-released/index.html +0 -592
- data/site/news/2017/03/02/jekyll-3-4-1-released/index.html +0 -649
- data/site/news/2017/03/09/jekyll-3-4-2-released/index.html +0 -598
- data/site/news/2017/03/21/jekyll-3-4-3-released/index.html +0 -594
- data/site/news/2017/06/15/jekyll-3-5-0-released/index.html +0 -589
- data/site/news/2017/07/17/jekyll-3-5-1-released/index.html +0 -569
- data/site/news/2017/08/12/jekyll-3-5-2-released/index.html +0 -573
- data/site/news/2017/09/21/jekyll-3-6-0-released/index.html +0 -565
- data/site/news/index.html +0 -3609
- data/site/news/releases/index.html +0 -3344
- data/site/philosophy.html +0 -46
- data/site/readme.md +0 -23
- data/site/robots.txt +0 -1
- data/site/sitemap.xml +0 -485
- data/site/tutorials/convert-site-to-jekyll/index.html +0 -793
- data/site/tutorials/custom-404-page/index.html +0 -358
- data/site/tutorials/home/index.html +0 -323
- data/site/tutorials/index.html +0 -10
- data/site/tutorials/navigation/index.html +0 -872
- data/site/tutorials/orderofinterpretation/index.html +0 -441
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Drops
|
|
5
|
+
class UrlDrop < Drop
|
|
6
|
+
extend Forwardable
|
|
7
|
+
|
|
8
|
+
mutable false
|
|
9
|
+
|
|
10
|
+
def_delegator :@obj, :cleaned_relative_path, :path
|
|
11
|
+
def_delegator :@obj, :output_ext, :output_ext
|
|
12
|
+
|
|
13
|
+
def collection
|
|
14
|
+
@obj.collection.label
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def name
|
|
18
|
+
Utils.slugify(@obj.basename_without_ext)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def title
|
|
22
|
+
Utils.slugify(@obj.data["slug"], :mode => "pretty", :cased => true) ||
|
|
23
|
+
Utils.slugify(@obj.basename_without_ext, :mode => "pretty", :cased => true)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def slug
|
|
27
|
+
Utils.slugify(@obj.data["slug"]) || Utils.slugify(@obj.basename_without_ext)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def categories
|
|
31
|
+
category_set = Set.new
|
|
32
|
+
Array(@obj.data["categories"]).each do |category|
|
|
33
|
+
category_set << category.to_s.downcase
|
|
34
|
+
end
|
|
35
|
+
category_set.to_a.join("/")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def year
|
|
39
|
+
@obj.date.strftime("%Y")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def month
|
|
43
|
+
@obj.date.strftime("%m")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def day
|
|
47
|
+
@obj.date.strftime("%d")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def hour
|
|
51
|
+
@obj.date.strftime("%H")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def minute
|
|
55
|
+
@obj.date.strftime("%M")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def second
|
|
59
|
+
@obj.date.strftime("%S")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def i_day
|
|
63
|
+
@obj.date.strftime("%-d")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def i_month
|
|
67
|
+
@obj.date.strftime("%-m")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def short_month
|
|
71
|
+
@obj.date.strftime("%b")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def short_year
|
|
75
|
+
@obj.date.strftime("%y")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def y_day
|
|
79
|
+
@obj.date.strftime("%j")
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private
|
|
83
|
+
def fallback_data
|
|
84
|
+
{}
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
class EntryFilter
|
|
5
|
+
attr_reader :site
|
|
6
|
+
SPECIAL_LEADING_CHARACTERS = [
|
|
7
|
+
".", "_", "#", "~",
|
|
8
|
+
].freeze
|
|
9
|
+
|
|
10
|
+
def initialize(site, base_directory = nil)
|
|
11
|
+
@site = site
|
|
12
|
+
@base_directory = derive_base_directory(
|
|
13
|
+
@site, base_directory.to_s.dup
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def base_directory
|
|
18
|
+
@base_directory.to_s
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def derive_base_directory(site, base_dir)
|
|
22
|
+
base_dir[site.source] = "" if base_dir.start_with?(site.source)
|
|
23
|
+
base_dir
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def relative_to_source(entry)
|
|
27
|
+
File.join(
|
|
28
|
+
base_directory, entry
|
|
29
|
+
)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def filter(entries)
|
|
33
|
+
entries.reject do |e|
|
|
34
|
+
unless included?(e)
|
|
35
|
+
special?(e) || backup?(e) || excluded?(e) || symlink?(e)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def included?(entry)
|
|
41
|
+
glob_include?(site.include, entry) ||
|
|
42
|
+
glob_include?(site.include, File.basename(entry))
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def special?(entry)
|
|
46
|
+
SPECIAL_LEADING_CHARACTERS.include?(entry[0..0]) ||
|
|
47
|
+
SPECIAL_LEADING_CHARACTERS.include?(File.basename(entry)[0..0])
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def backup?(entry)
|
|
51
|
+
entry[-1..-1] == "~"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def excluded?(entry)
|
|
55
|
+
glob_include?(site.exclude, relative_to_source(entry)).tap do |excluded|
|
|
56
|
+
if excluded
|
|
57
|
+
Jekyll.logger.debug(
|
|
58
|
+
"EntryFilter:",
|
|
59
|
+
"excluded #{relative_to_source(entry)}"
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# --
|
|
66
|
+
# Check if a file is a symlink.
|
|
67
|
+
# NOTE: This can be converted to allowing even in safe,
|
|
68
|
+
# since we use Pathutil#in_path? now.
|
|
69
|
+
# --
|
|
70
|
+
def symlink?(entry)
|
|
71
|
+
site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# --
|
|
75
|
+
# NOTE: Pathutil#in_path? gets the realpath.
|
|
76
|
+
# @param [<Anything>] entry the entry you want to validate.
|
|
77
|
+
# Check if a path is outside of our given root.
|
|
78
|
+
# --
|
|
79
|
+
def symlink_outside_site_source?(entry)
|
|
80
|
+
!Pathutil.new(entry).in_path?(
|
|
81
|
+
site.in_source_dir
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# --
|
|
86
|
+
# Check if an entry matches a specific pattern and return true,false.
|
|
87
|
+
# Returns true if path matches against any glob pattern.
|
|
88
|
+
# --
|
|
89
|
+
def glob_include?(enum, e)
|
|
90
|
+
entry = Pathutil.new(site.in_source_dir).join(e)
|
|
91
|
+
enum.any? do |exp|
|
|
92
|
+
# Users who send a Regexp knows what they want to
|
|
93
|
+
# exclude, so let them send a Regexp to exclude files,
|
|
94
|
+
# we will not bother caring if it works or not, it's
|
|
95
|
+
# on them at this point.
|
|
96
|
+
|
|
97
|
+
if exp.is_a?(Regexp)
|
|
98
|
+
entry =~ exp
|
|
99
|
+
|
|
100
|
+
else
|
|
101
|
+
item = Pathutil.new(site.in_source_dir).join(exp)
|
|
102
|
+
|
|
103
|
+
# If it's a directory they want to exclude, AKA
|
|
104
|
+
# ends with a "/" then we will go on to check and
|
|
105
|
+
# see if the entry falls within that path and
|
|
106
|
+
# exclude it if that's the case.
|
|
107
|
+
|
|
108
|
+
if e.end_with?("/")
|
|
109
|
+
entry.in_path?(
|
|
110
|
+
item
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
else
|
|
114
|
+
File.fnmatch?(item, entry) ||
|
|
115
|
+
entry.to_path.start_with?(
|
|
116
|
+
item
|
|
117
|
+
)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module Errors
|
|
5
|
+
FatalException = Class.new(::RuntimeError)
|
|
6
|
+
|
|
7
|
+
InvalidThemeName = Class.new(FatalException)
|
|
8
|
+
|
|
9
|
+
DropMutationException = Class.new(FatalException)
|
|
10
|
+
InvalidPermalinkError = Class.new(FatalException)
|
|
11
|
+
InvalidYAMLFrontMatterError = Class.new(FatalException)
|
|
12
|
+
MissingDependencyException = Class.new(FatalException)
|
|
13
|
+
|
|
14
|
+
InvalidDateError = Class.new(FatalException)
|
|
15
|
+
InvalidPostNameError = Class.new(FatalException)
|
|
16
|
+
PostURLError = Class.new(FatalException)
|
|
17
|
+
InvalidURLError = Class.new(FatalException)
|
|
18
|
+
InvalidConfigurationError = Class.new(FatalException)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
class Excerpt
|
|
5
|
+
extend Forwardable
|
|
6
|
+
|
|
7
|
+
attr_accessor :doc
|
|
8
|
+
attr_accessor :content, :ext
|
|
9
|
+
attr_writer :output
|
|
10
|
+
|
|
11
|
+
def_delegators :@doc, :site, :name, :ext, :relative_path, :extname,
|
|
12
|
+
:render_with_liquid?, :collection, :related_posts,
|
|
13
|
+
:url, :next_doc, :previous_doc
|
|
14
|
+
|
|
15
|
+
# Initialize this Excerpt instance.
|
|
16
|
+
#
|
|
17
|
+
# doc - The Document.
|
|
18
|
+
#
|
|
19
|
+
# Returns the new Excerpt.
|
|
20
|
+
def initialize(doc)
|
|
21
|
+
self.doc = doc
|
|
22
|
+
self.content = extract_excerpt(doc.content)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Fetch YAML front-matter data from related doc, without layout key
|
|
26
|
+
#
|
|
27
|
+
# Returns Hash of doc data
|
|
28
|
+
def data
|
|
29
|
+
@data ||= doc.data.dup
|
|
30
|
+
@data.delete("layout")
|
|
31
|
+
@data.delete("excerpt")
|
|
32
|
+
@data
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def trigger_hooks(*); end
|
|
36
|
+
|
|
37
|
+
# 'Path' of the excerpt.
|
|
38
|
+
#
|
|
39
|
+
# Returns the path for the doc this excerpt belongs to with #excerpt appended
|
|
40
|
+
def path
|
|
41
|
+
File.join(doc.path, "#excerpt")
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Check if excerpt includes a string
|
|
45
|
+
#
|
|
46
|
+
# Returns true if the string passed in
|
|
47
|
+
def include?(something)
|
|
48
|
+
(output && output.include?(something)) || content.include?(something)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The UID for this doc (useful in feeds).
|
|
52
|
+
# e.g. /2008/11/05/my-awesome-doc
|
|
53
|
+
#
|
|
54
|
+
# Returns the String UID.
|
|
55
|
+
def id
|
|
56
|
+
"#{doc.id}#excerpt"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def to_s
|
|
60
|
+
output || content
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def to_liquid
|
|
64
|
+
Jekyll::Drops::ExcerptDrop.new(self)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Returns the shorthand String identifier of this doc.
|
|
68
|
+
def inspect
|
|
69
|
+
"<Excerpt: #{self.id}>"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def output
|
|
73
|
+
@output ||= Renderer.new(doc.site, self, site.site_payload).run
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def place_in_layout?
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
|
|
82
|
+
# Internal: Extract excerpt from the content
|
|
83
|
+
#
|
|
84
|
+
# By default excerpt is your first paragraph of a doc: everything before
|
|
85
|
+
# the first two new lines:
|
|
86
|
+
#
|
|
87
|
+
# ---
|
|
88
|
+
# title: Example
|
|
89
|
+
# ---
|
|
90
|
+
#
|
|
91
|
+
# First paragraph with [link][1].
|
|
92
|
+
#
|
|
93
|
+
# Second paragraph.
|
|
94
|
+
#
|
|
95
|
+
# [1]: http://example.com/
|
|
96
|
+
#
|
|
97
|
+
# This is fairly good option for Markdown and Textile files. But might cause
|
|
98
|
+
# problems for HTML docs (which is quite unusual for Jekyll). If default
|
|
99
|
+
# excerpt delimiter is not good for you, you might want to set your own via
|
|
100
|
+
# configuration option `excerpt_separator`. For example, following is a good
|
|
101
|
+
# alternative for HTML docs:
|
|
102
|
+
#
|
|
103
|
+
# # file: _config.yml
|
|
104
|
+
# excerpt_separator: "<!-- more -->"
|
|
105
|
+
#
|
|
106
|
+
# Notice that all markdown-style link references will be appended to the
|
|
107
|
+
# excerpt. So the example doc above will have this excerpt source:
|
|
108
|
+
#
|
|
109
|
+
# First paragraph with [link][1].
|
|
110
|
+
#
|
|
111
|
+
# [1]: http://example.com/
|
|
112
|
+
#
|
|
113
|
+
# Excerpts are rendered same time as content is rendered.
|
|
114
|
+
#
|
|
115
|
+
# Returns excerpt String
|
|
116
|
+
def extract_excerpt(doc_content)
|
|
117
|
+
head, _, tail = doc_content.to_s.partition(doc.excerpt_separator)
|
|
118
|
+
|
|
119
|
+
if tail.empty?
|
|
120
|
+
head
|
|
121
|
+
else
|
|
122
|
+
head.to_s.dup << "\n\n" << tail.scan(%r!^ {0,3}\[[^\]]+\]:.+$!).join("\n")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Jekyll
|
|
4
|
+
module External
|
|
5
|
+
class << self
|
|
6
|
+
#
|
|
7
|
+
# Gems that, if installed, should be loaded.
|
|
8
|
+
# Usually contain subcommands.
|
|
9
|
+
#
|
|
10
|
+
def blessed_gems
|
|
11
|
+
%w(
|
|
12
|
+
jekyll-docs
|
|
13
|
+
jekyll-import
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#
|
|
18
|
+
# Require a gem or file if it's present, otherwise silently fail.
|
|
19
|
+
#
|
|
20
|
+
# names - a string gem name or array of gem names
|
|
21
|
+
#
|
|
22
|
+
def require_if_present(names)
|
|
23
|
+
Array(names).each do |name|
|
|
24
|
+
begin
|
|
25
|
+
require name
|
|
26
|
+
rescue LoadError
|
|
27
|
+
Jekyll.logger.debug "Couldn't load #{name}. Skipping."
|
|
28
|
+
yield(name, version_constraint(name)) if block_given?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# The version constraint required to activate a given gem.
|
|
36
|
+
# Usually the gem version requirement is "> 0," because any version
|
|
37
|
+
# will do. In the case of jekyll-docs, however, we require the exact
|
|
38
|
+
# same version as Jekyll.
|
|
39
|
+
#
|
|
40
|
+
# Returns a String version constraint in a parseable form for
|
|
41
|
+
# RubyGems.
|
|
42
|
+
def version_constraint(gem_name)
|
|
43
|
+
return "= #{Jekyll::VERSION}" if gem_name.to_s.eql?("jekyll-docs")
|
|
44
|
+
"> 0"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
#
|
|
48
|
+
# Require a gem or gems. If it's not present, show a very nice error
|
|
49
|
+
# message that explains everything and is much more helpful than the
|
|
50
|
+
# normal LoadError.
|
|
51
|
+
#
|
|
52
|
+
# names - a string gem name or array of gem names
|
|
53
|
+
#
|
|
54
|
+
def require_with_graceful_fail(names)
|
|
55
|
+
Array(names).each do |name|
|
|
56
|
+
begin
|
|
57
|
+
Jekyll.logger.debug "Requiring:", name.to_s
|
|
58
|
+
require name
|
|
59
|
+
rescue LoadError => e
|
|
60
|
+
Jekyll.logger.error "Dependency Error:", <<-MSG
|
|
61
|
+
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
|
|
62
|
+
In order to use Jekyll as currently configured, you'll need to install this gem.
|
|
63
|
+
|
|
64
|
+
The full error message from Ruby is: '#{e.message}'
|
|
65
|
+
|
|
66
|
+
If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/!
|
|
67
|
+
MSG
|
|
68
|
+
raise Jekyll::Errors::MissingDependencyException, name
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "addressable/uri"
|
|
4
|
+
require "json"
|
|
5
|
+
require "date"
|
|
6
|
+
require "liquid"
|
|
7
|
+
|
|
8
|
+
require_all "jekyll/filters"
|
|
9
|
+
|
|
10
|
+
module Jekyll
|
|
11
|
+
module Filters
|
|
12
|
+
include URLFilters
|
|
13
|
+
include GroupingFilters
|
|
14
|
+
|
|
15
|
+
# Convert a Markdown string into HTML output.
|
|
16
|
+
#
|
|
17
|
+
# input - The Markdown String to convert.
|
|
18
|
+
#
|
|
19
|
+
# Returns the HTML formatted String.
|
|
20
|
+
def markdownify(input)
|
|
21
|
+
site = @context.registers[:site]
|
|
22
|
+
converter = site.find_converter_instance(Jekyll::Converters::Markdown)
|
|
23
|
+
converter.convert(input.to_s)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Convert quotes into smart quotes.
|
|
27
|
+
#
|
|
28
|
+
# input - The String to convert.
|
|
29
|
+
#
|
|
30
|
+
# Returns the smart-quotified String.
|
|
31
|
+
def smartify(input)
|
|
32
|
+
site = @context.registers[:site]
|
|
33
|
+
converter = site.find_converter_instance(Jekyll::Converters::SmartyPants)
|
|
34
|
+
converter.convert(input.to_s)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Convert a Sass string into CSS output.
|
|
38
|
+
#
|
|
39
|
+
# input - The Sass String to convert.
|
|
40
|
+
#
|
|
41
|
+
# Returns the CSS formatted String.
|
|
42
|
+
def sassify(input)
|
|
43
|
+
site = @context.registers[:site]
|
|
44
|
+
converter = site.find_converter_instance(Jekyll::Converters::Sass)
|
|
45
|
+
converter.convert(input)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Convert a Scss string into CSS output.
|
|
49
|
+
#
|
|
50
|
+
# input - The Scss String to convert.
|
|
51
|
+
#
|
|
52
|
+
# Returns the CSS formatted String.
|
|
53
|
+
def scssify(input)
|
|
54
|
+
site = @context.registers[:site]
|
|
55
|
+
converter = site.find_converter_instance(Jekyll::Converters::Scss)
|
|
56
|
+
converter.convert(input)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Slugify a filename or title.
|
|
60
|
+
#
|
|
61
|
+
# input - The filename or title to slugify.
|
|
62
|
+
# mode - how string is slugified
|
|
63
|
+
#
|
|
64
|
+
# Returns the given filename or title as a lowercase URL String.
|
|
65
|
+
# See Utils.slugify for more detail.
|
|
66
|
+
def slugify(input, mode = nil)
|
|
67
|
+
Utils.slugify(input, :mode => mode)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Format a date in short format e.g. "27 Jan 2011".
|
|
71
|
+
#
|
|
72
|
+
# date - the Time to format.
|
|
73
|
+
#
|
|
74
|
+
# Returns the formatting String.
|
|
75
|
+
def date_to_string(date)
|
|
76
|
+
time(date).strftime("%d %b %Y")
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Format a date in long format e.g. "27 January 2011".
|
|
80
|
+
#
|
|
81
|
+
# date - The Time to format.
|
|
82
|
+
#
|
|
83
|
+
# Returns the formatted String.
|
|
84
|
+
def date_to_long_string(date)
|
|
85
|
+
return date if date.to_s.empty?
|
|
86
|
+
time(date).strftime("%d %B %Y")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Format a date for use in XML.
|
|
90
|
+
#
|
|
91
|
+
# date - The Time to format.
|
|
92
|
+
#
|
|
93
|
+
# Examples
|
|
94
|
+
#
|
|
95
|
+
# date_to_xmlschema(Time.now)
|
|
96
|
+
# # => "2011-04-24T20:34:46+08:00"
|
|
97
|
+
#
|
|
98
|
+
# Returns the formatted String.
|
|
99
|
+
def date_to_xmlschema(date)
|
|
100
|
+
return date if date.to_s.empty?
|
|
101
|
+
time(date).xmlschema
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Format a date according to RFC-822
|
|
105
|
+
#
|
|
106
|
+
# date - The Time to format.
|
|
107
|
+
#
|
|
108
|
+
# Examples
|
|
109
|
+
#
|
|
110
|
+
# date_to_rfc822(Time.now)
|
|
111
|
+
# # => "Sun, 24 Apr 2011 12:34:46 +0000"
|
|
112
|
+
#
|
|
113
|
+
# Returns the formatted String.
|
|
114
|
+
def date_to_rfc822(date)
|
|
115
|
+
return date if date.to_s.empty?
|
|
116
|
+
time(date).rfc822
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# XML escape a string for use. Replaces any special characters with
|
|
120
|
+
# appropriate HTML entity replacements.
|
|
121
|
+
#
|
|
122
|
+
# input - The String to escape.
|
|
123
|
+
#
|
|
124
|
+
# Examples
|
|
125
|
+
#
|
|
126
|
+
# xml_escape('foo "bar" <baz>')
|
|
127
|
+
# # => "foo "bar" <baz>"
|
|
128
|
+
#
|
|
129
|
+
# Returns the escaped String.
|
|
130
|
+
def xml_escape(input)
|
|
131
|
+
input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# CGI escape a string for use in a URL. Replaces any special characters
|
|
135
|
+
# with appropriate %XX replacements.
|
|
136
|
+
#
|
|
137
|
+
# input - The String to escape.
|
|
138
|
+
#
|
|
139
|
+
# Examples
|
|
140
|
+
#
|
|
141
|
+
# cgi_escape('foo,bar;baz?')
|
|
142
|
+
# # => "foo%2Cbar%3Bbaz%3F"
|
|
143
|
+
#
|
|
144
|
+
# Returns the escaped String.
|
|
145
|
+
def cgi_escape(input)
|
|
146
|
+
CGI.escape(input)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# URI escape a string.
|
|
150
|
+
#
|
|
151
|
+
# input - The String to escape.
|
|
152
|
+
#
|
|
153
|
+
# Examples
|
|
154
|
+
#
|
|
155
|
+
# uri_escape('foo, bar \\baz?')
|
|
156
|
+
# # => "foo,%20bar%20%5Cbaz?"
|
|
157
|
+
#
|
|
158
|
+
# Returns the escaped String.
|
|
159
|
+
def uri_escape(input)
|
|
160
|
+
Addressable::URI.normalize_component(input)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Replace any whitespace in the input string with a single space
|
|
164
|
+
#
|
|
165
|
+
# input - The String on which to operate.
|
|
166
|
+
#
|
|
167
|
+
# Returns the formatted String
|
|
168
|
+
def normalize_whitespace(input)
|
|
169
|
+
input.to_s.gsub(%r!\s+!, " ").strip
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Count the number of words in the input string.
|
|
173
|
+
#
|
|
174
|
+
# input - The String on which to operate.
|
|
175
|
+
#
|
|
176
|
+
# Returns the Integer word count.
|
|
177
|
+
def number_of_words(input)
|
|
178
|
+
input.split.length
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Join an array of things into a string by separating with commas and the
|
|
182
|
+
# word "and" for the last one.
|
|
183
|
+
#
|
|
184
|
+
# array - The Array of Strings to join.
|
|
185
|
+
# connector - Word used to connect the last 2 items in the array
|
|
186
|
+
#
|
|
187
|
+
# Examples
|
|
188
|
+
#
|
|
189
|
+
# array_to_sentence_string(["apples", "oranges", "grapes"])
|
|
190
|
+
# # => "apples, oranges, and grapes"
|
|
191
|
+
#
|
|
192
|
+
# Returns the formatted String.
|
|
193
|
+
def array_to_sentence_string(array, connector = "and")
|
|
194
|
+
case array.length
|
|
195
|
+
when 0
|
|
196
|
+
""
|
|
197
|
+
when 1
|
|
198
|
+
array[0].to_s
|
|
199
|
+
when 2
|
|
200
|
+
"#{array[0]} #{connector} #{array[1]}"
|
|
201
|
+
else
|
|
202
|
+
"#{array[0...-1].join(", ")}, #{connector} #{array[-1]}"
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
# Convert the input into json string
|
|
207
|
+
#
|
|
208
|
+
# input - The Array or Hash to be converted
|
|
209
|
+
#
|
|
210
|
+
# Returns the converted json string
|
|
211
|
+
def jsonify(input)
|
|
212
|
+
as_liquid(input).to_json
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Filter an array of objects
|
|
216
|
+
#
|
|
217
|
+
# input - the object array
|
|
218
|
+
# property - property within each object to filter by
|
|
219
|
+
# value - desired value
|
|
220
|
+
#
|
|
221
|
+
# Returns the filtered array of objects
|
|
222
|
+
def where(input, property, value)
|
|
223
|
+
return input unless input.respond_to?(:select)
|
|
224
|
+
input = input.values if input.is_a?(Hash)
|
|
225
|
+
input.select do |object|
|
|
226
|
+
Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
|
|
227
|
+
end || []
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# Filters an array of objects against an expression
|
|
231
|
+
#
|
|
232
|
+
# input - the object array
|
|
233
|
+
# variable - the variable to assign each item to in the expression
|
|
234
|
+
# expression - a Liquid comparison expression passed in as a string
|
|
235
|
+
#
|
|
236
|
+
# Returns the filtered array of objects
|
|
237
|
+
def where_exp(input, variable, expression)
|
|
238
|
+
return input unless input.respond_to?(:select)
|
|
239
|
+
input = input.values if input.is_a?(Hash) # FIXME
|
|
240
|
+
|
|
241
|
+
condition = parse_condition(expression)
|
|
242
|
+
@context.stack do
|
|
243
|
+
input.select do |object|
|
|
244
|
+
@context[variable] = object
|
|
245
|
+
condition.evaluate(@context)
|
|
246
|
+
end
|
|
247
|
+
end || []
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Convert the input into integer
|
|
251
|
+
#
|
|
252
|
+
# input - the object string
|
|
253
|
+
#
|
|
254
|
+
# Returns the integer value
|
|
255
|
+
def to_integer(input)
|
|
256
|
+
return 1 if input == true
|
|
257
|
+
return 0 if input == false
|
|
258
|
+
input.to_i
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# Sort an array of objects
|
|
262
|
+
#
|
|
263
|
+
# input - the object array
|
|
264
|
+
# property - property within each object to filter by
|
|
265
|
+
# nils ('first' | 'last') - nils appear before or after non-nil values
|
|
266
|
+
#
|
|
267
|
+
# Returns the filtered array of objects
|
|
268
|
+
def sort(input, property = nil, nils = "first")
|
|
269
|
+
if input.nil?
|
|
270
|
+
raise ArgumentError, "Cannot sort a null object."
|
|
271
|
+
end
|
|
272
|
+
if property.nil?
|
|
273
|
+
input.sort
|
|
274
|
+
else
|
|
275
|
+
if nils == "first"
|
|
276
|
+
order = - 1
|
|
277
|
+
elsif nils == "last"
|
|
278
|
+
order = + 1
|
|
279
|
+
else
|
|
280
|
+
raise ArgumentError, "Invalid nils order: " \
|
|
281
|
+
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
sort_input(input, property, order)
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def pop(array, num = 1)
|
|
289
|
+
return array unless array.is_a?(Array)
|
|
290
|
+
num = Liquid::Utils.to_integer(num)
|
|
291
|
+
new_ary = array.dup
|
|
292
|
+
new_ary.pop(num)
|
|
293
|
+
new_ary
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
def push(array, input)
|
|
297
|
+
return array unless array.is_a?(Array)
|
|
298
|
+
new_ary = array.dup
|
|
299
|
+
new_ary.push(input)
|
|
300
|
+
new_ary
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def shift(array, num = 1)
|
|
304
|
+
return array unless array.is_a?(Array)
|
|
305
|
+
num = Liquid::Utils.to_integer(num)
|
|
306
|
+
new_ary = array.dup
|
|
307
|
+
new_ary.shift(num)
|
|
308
|
+
new_ary
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
def unshift(array, input)
|
|
312
|
+
return array unless array.is_a?(Array)
|
|
313
|
+
new_ary = array.dup
|
|
314
|
+
new_ary.unshift(input)
|
|
315
|
+
new_ary
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def sample(input, num = 1)
|
|
319
|
+
return input unless input.respond_to?(:sample)
|
|
320
|
+
num = Liquid::Utils.to_integer(num) rescue 1
|
|
321
|
+
if num == 1
|
|
322
|
+
input.sample
|
|
323
|
+
else
|
|
324
|
+
input.sample(num)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Convert an object into its String representation for debugging
|
|
329
|
+
#
|
|
330
|
+
# input - The Object to be converted
|
|
331
|
+
#
|
|
332
|
+
# Returns a String representation of the object.
|
|
333
|
+
def inspect(input)
|
|
334
|
+
xml_escape(input.inspect)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
private
|
|
338
|
+
|
|
339
|
+
# Sort the input Enumerable by the given property.
|
|
340
|
+
# If the property doesn't exist, return the sort order respective of
|
|
341
|
+
# which item doesn't have the property.
|
|
342
|
+
# We also utilize the Schwartzian transform to make this more efficient.
|
|
343
|
+
def sort_input(input, property, order)
|
|
344
|
+
input.map { |item| [item_property(item, property), item] }
|
|
345
|
+
.sort! do |apple_info, orange_info|
|
|
346
|
+
apple_property = apple_info.first
|
|
347
|
+
orange_property = orange_info.first
|
|
348
|
+
|
|
349
|
+
if !apple_property.nil? && orange_property.nil?
|
|
350
|
+
- order
|
|
351
|
+
elsif apple_property.nil? && !orange_property.nil?
|
|
352
|
+
+ order
|
|
353
|
+
else
|
|
354
|
+
apple_property <=> orange_property
|
|
355
|
+
end
|
|
356
|
+
end
|
|
357
|
+
.map!(&:last)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
private
|
|
361
|
+
def time(input)
|
|
362
|
+
date = Liquid::Utils.to_date(input)
|
|
363
|
+
unless date.respond_to?(:to_time)
|
|
364
|
+
raise Errors::InvalidDateError,
|
|
365
|
+
"Invalid Date: '#{input.inspect}' is not a valid datetime."
|
|
366
|
+
end
|
|
367
|
+
date.to_time.dup.localtime
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
private
|
|
371
|
+
def item_property(item, property)
|
|
372
|
+
if item.respond_to?(:to_liquid)
|
|
373
|
+
property.to_s.split(".").reduce(item.to_liquid) do |subvalue, attribute|
|
|
374
|
+
subvalue[attribute]
|
|
375
|
+
end
|
|
376
|
+
elsif item.respond_to?(:data)
|
|
377
|
+
item.data[property.to_s]
|
|
378
|
+
else
|
|
379
|
+
item[property.to_s]
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
private
|
|
384
|
+
def as_liquid(item)
|
|
385
|
+
case item
|
|
386
|
+
when Hash
|
|
387
|
+
pairs = item.map { |k, v| as_liquid([k, v]) }
|
|
388
|
+
Hash[pairs]
|
|
389
|
+
when Array
|
|
390
|
+
item.map { |i| as_liquid(i) }
|
|
391
|
+
else
|
|
392
|
+
if item.respond_to?(:to_liquid)
|
|
393
|
+
liquidated = item.to_liquid
|
|
394
|
+
# prevent infinite recursion for simple types (which return `self`)
|
|
395
|
+
if liquidated == item
|
|
396
|
+
item
|
|
397
|
+
else
|
|
398
|
+
as_liquid(liquidated)
|
|
399
|
+
end
|
|
400
|
+
else
|
|
401
|
+
item
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Parse a string to a Liquid Condition
|
|
407
|
+
private
|
|
408
|
+
def parse_condition(exp)
|
|
409
|
+
parser = Liquid::Parser.new(exp)
|
|
410
|
+
left_expr = parser.expression
|
|
411
|
+
operator = parser.consume?(:comparison)
|
|
412
|
+
condition =
|
|
413
|
+
if operator
|
|
414
|
+
Liquid::Condition.new(Liquid::Expression.parse(left_expr),
|
|
415
|
+
operator,
|
|
416
|
+
Liquid::Expression.parse(parser.expression))
|
|
417
|
+
else
|
|
418
|
+
Liquid::Condition.new(Liquid::Expression.parse(left_expr))
|
|
419
|
+
end
|
|
420
|
+
parser.consume(:end_of_string)
|
|
421
|
+
|
|
422
|
+
condition
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
end
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
Liquid::Template.register_filter(
|
|
429
|
+
Jekyll::Filters
|
|
430
|
+
)
|