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.
Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/lib/jekyll.rb +195 -0
  3. data/lib/jekyll/cleaner.rb +110 -0
  4. data/lib/jekyll/collection.rb +230 -0
  5. data/lib/jekyll/command.rb +78 -0
  6. data/lib/jekyll/commands/build.rb +102 -0
  7. data/lib/jekyll/commands/clean.rb +43 -0
  8. data/lib/jekyll/commands/doctor.rb +153 -0
  9. data/lib/jekyll/commands/help.rb +34 -0
  10. data/lib/jekyll/commands/new.rb +156 -0
  11. data/lib/jekyll/commands/new_theme.rb +40 -0
  12. data/lib/jekyll/commands/serve.rb +245 -0
  13. data/lib/jekyll/commands/serve/servlet.rb +62 -0
  14. data/lib/jekyll/configuration.rb +410 -0
  15. data/lib/jekyll/converter.rb +54 -0
  16. data/lib/jekyll/converters/identity.rb +23 -0
  17. data/lib/jekyll/converters/markdown.rb +104 -0
  18. data/lib/jekyll/converters/markdown/kramdown_parser.rb +123 -0
  19. data/lib/jekyll/converters/markdown/rdiscount_parser.rb +35 -0
  20. data/lib/jekyll/converters/markdown/redcarpet_parser.rb +108 -0
  21. data/lib/jekyll/converters/smartypants.rb +36 -0
  22. data/lib/jekyll/convertible.rb +251 -0
  23. data/lib/jekyll/deprecator.rb +52 -0
  24. data/lib/jekyll/document.rb +507 -0
  25. data/lib/jekyll/drops/collection_drop.rb +22 -0
  26. data/lib/jekyll/drops/document_drop.rb +69 -0
  27. data/lib/jekyll/drops/drop.rb +214 -0
  28. data/lib/jekyll/drops/excerpt_drop.rb +15 -0
  29. data/lib/jekyll/drops/jekyll_drop.rb +33 -0
  30. data/lib/jekyll/drops/site_drop.rb +47 -0
  31. data/lib/jekyll/drops/static_file_drop.rb +13 -0
  32. data/lib/jekyll/drops/unified_payload_drop.rb +25 -0
  33. data/lib/jekyll/drops/url_drop.rb +88 -0
  34. data/lib/jekyll/entry_filter.rb +123 -0
  35. data/lib/jekyll/errors.rb +20 -0
  36. data/lib/jekyll/excerpt.rb +126 -0
  37. data/lib/jekyll/external.rb +74 -0
  38. data/lib/jekyll/filters.rb +430 -0
  39. data/lib/jekyll/filters/grouping_filters.rb +65 -0
  40. data/lib/jekyll/filters/url_filters.rb +60 -0
  41. data/lib/jekyll/frontmatter_defaults.rb +197 -0
  42. data/lib/jekyll/generator.rb +5 -0
  43. data/lib/jekyll/hooks.rb +104 -0
  44. data/lib/jekyll/layout.rb +62 -0
  45. data/lib/jekyll/liquid_extensions.rb +24 -0
  46. data/lib/jekyll/liquid_renderer.rb +49 -0
  47. data/lib/jekyll/liquid_renderer/file.rb +56 -0
  48. data/lib/jekyll/liquid_renderer/table.rb +96 -0
  49. data/lib/jekyll/log_adapter.rb +147 -0
  50. data/lib/jekyll/mime.types +825 -0
  51. data/lib/jekyll/page.rb +187 -0
  52. data/lib/jekyll/plugin.rb +98 -0
  53. data/lib/jekyll/plugin_manager.rb +113 -0
  54. data/lib/jekyll/publisher.rb +23 -0
  55. data/lib/jekyll/reader.rb +134 -0
  56. data/lib/jekyll/readers/collection_reader.rb +22 -0
  57. data/lib/jekyll/readers/data_reader.rb +77 -0
  58. data/lib/jekyll/readers/layout_reader.rb +71 -0
  59. data/lib/jekyll/readers/page_reader.rb +25 -0
  60. data/lib/jekyll/readers/post_reader.rb +72 -0
  61. data/lib/jekyll/readers/static_file_reader.rb +25 -0
  62. data/lib/jekyll/readers/theme_assets_reader.rb +49 -0
  63. data/lib/jekyll/regenerator.rb +201 -0
  64. data/lib/jekyll/related_posts.rb +52 -0
  65. data/lib/jekyll/renderer.rb +269 -0
  66. data/lib/jekyll/site.rb +471 -0
  67. data/lib/jekyll/static_file.rb +162 -0
  68. data/lib/jekyll/stevenson.rb +61 -0
  69. data/lib/jekyll/tags/highlight.rb +141 -0
  70. data/lib/jekyll/tags/include.rb +215 -0
  71. data/lib/jekyll/tags/link.rb +37 -0
  72. data/lib/jekyll/tags/post_url.rb +103 -0
  73. data/lib/jekyll/theme.rb +68 -0
  74. data/lib/jekyll/theme_builder.rb +119 -0
  75. data/lib/jekyll/url.rb +161 -0
  76. data/lib/jekyll/utils.rb +337 -0
  77. data/lib/jekyll/utils/ansi.rb +59 -0
  78. data/lib/jekyll/utils/exec.rb +27 -0
  79. data/lib/jekyll/utils/platforms.rb +82 -0
  80. data/lib/jekyll/utils/rouge.rb +21 -0
  81. data/lib/jekyll/utils/win_tz.rb +75 -0
  82. data/lib/jekyll/version.rb +5 -0
  83. data/lib/site_template/404.html +24 -0
  84. data/lib/site_template/_config.yml +43 -0
  85. data/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +25 -0
  86. data/lib/site_template/about.md +18 -0
  87. data/lib/site_template/index.md +6 -0
  88. data/lib/theme_template/CODE_OF_CONDUCT.md.erb +74 -0
  89. data/lib/theme_template/Gemfile +4 -0
  90. data/lib/theme_template/LICENSE.txt.erb +21 -0
  91. data/lib/theme_template/README.md.erb +52 -0
  92. data/lib/theme_template/_layouts/default.html +1 -0
  93. data/lib/theme_template/_layouts/page.html +5 -0
  94. data/lib/theme_template/_layouts/post.html +5 -0
  95. data/lib/theme_template/example/_config.yml.erb +1 -0
  96. data/lib/theme_template/example/_post.md +12 -0
  97. data/lib/theme_template/example/index.html +14 -0
  98. data/lib/theme_template/example/style.scss +7 -0
  99. data/lib/theme_template/gitignore.erb +5 -0
  100. data/lib/theme_template/theme.gemspec.erb +19 -0
  101. metadata +103 -156
  102. data/lib/jekyll-docs.rb +0 -31
  103. data/site/404.html +0 -153
  104. data/site/CNAME +0 -1
  105. data/site/community/index.html +0 -299
  106. data/site/conduct/index.html +0 -10
  107. data/site/css/screen.css +0 -1
  108. data/site/docs/assets/index.html +0 -724
  109. data/site/docs/code_of_conduct/index.html +0 -730
  110. data/site/docs/collections/index.html +0 -1097
  111. data/site/docs/conduct/index.html +0 -744
  112. data/site/docs/configuration/index.html +0 -1403
  113. data/site/docs/continuous-integration/buddyworks/index.html +0 -726
  114. data/site/docs/continuous-integration/circleci/index.html +0 -757
  115. data/site/docs/continuous-integration/index.html +0 -681
  116. data/site/docs/continuous-integration/travis-ci/index.html +0 -891
  117. data/site/docs/contributing/index.html +0 -863
  118. data/site/docs/datafiles/index.html +0 -780
  119. data/site/docs/deployment-methods/index.html +0 -875
  120. data/site/docs/drafts/index.html +0 -636
  121. data/site/docs/extras/index.html +0 -689
  122. data/site/docs/frontmatter/index.html +0 -807
  123. data/site/docs/github-pages/index.html +0 -819
  124. data/site/docs/history/index.html +0 -3955
  125. data/site/docs/home/index.html +0 -644
  126. data/site/docs/includes/index.html +0 -800
  127. data/site/docs/index.html +0 -10
  128. data/site/docs/installation/index.html +0 -732
  129. data/site/docs/maintaining/affinity-team-captain/index.html +0 -706
  130. data/site/docs/maintaining/avoiding-burnout/index.html +0 -709
  131. data/site/docs/maintaining/becoming-a-maintainer/index.html +0 -717
  132. data/site/docs/maintaining/index.html +0 -713
  133. data/site/docs/maintaining/merging-a-pull-request/index.html +0 -747
  134. data/site/docs/maintaining/reviewing-a-pull-request/index.html +0 -725
  135. data/site/docs/maintaining/special-labels/index.html +0 -705
  136. data/site/docs/maintaining/triaging-an-issue/index.html +0 -735
  137. data/site/docs/migrations/index.html +0 -647
  138. data/site/docs/pages/index.html +0 -695
  139. data/site/docs/pagination/index.html +0 -870
  140. data/site/docs/permalinks/index.html +0 -1027
  141. data/site/docs/plugins/index.html +0 -1800
  142. data/site/docs/posts/index.html +0 -858
  143. data/site/docs/quickstart/index.html +0 -650
  144. data/site/docs/resources/index.html +0 -769
  145. data/site/docs/sites/index.html +0 -702
  146. data/site/docs/static-files/index.html +0 -720
  147. data/site/docs/structure/index.html +0 -822
  148. data/site/docs/templates/index.html +0 -1208
  149. data/site/docs/themes/index.html +0 -935
  150. data/site/docs/troubleshooting/index.html +0 -893
  151. data/site/docs/upgrading/0-to-2/index.html +0 -826
  152. data/site/docs/upgrading/2-to-3/index.html +0 -824
  153. data/site/docs/upgrading/index.html +0 -693
  154. data/site/docs/usage/index.html +0 -705
  155. data/site/docs/variables/index.html +0 -1048
  156. data/site/docs/windows/index.html +0 -799
  157. data/site/favicon.ico +0 -0
  158. data/site/feed.xml +0 -372
  159. data/site/fonts/FontAwesome.eot +0 -0
  160. data/site/fonts/FontAwesome.svg +0 -12
  161. data/site/fonts/FontAwesome.ttf +0 -0
  162. data/site/fonts/FontAwesome.woff +0 -0
  163. data/site/github.html +0 -10
  164. data/site/help/index.html +0 -244
  165. data/site/icomoon-selection.json +0 -96
  166. data/site/img/article-footer.png +0 -0
  167. data/site/img/footer-arrow.png +0 -0
  168. data/site/img/footer-logo.png +0 -0
  169. data/site/img/jekyll-sticker.jpg +0 -0
  170. data/site/img/jekylllayoutconcept.png +0 -0
  171. data/site/img/logo-2x.png +0 -0
  172. data/site/img/logo-rss.png +0 -0
  173. data/site/img/octojekyll.png +0 -0
  174. data/site/index.html +0 -267
  175. data/site/issues.html +0 -10
  176. data/site/js/html5shiv.min.js +0 -4
  177. data/site/js/respond.min.js +0 -5
  178. data/site/latest_version.txt +0 -1
  179. data/site/news/2013/05/05/jekyll-1-0-0-released/index.html +0 -570
  180. data/site/news/2013/05/08/jekyll-1-0-1-released/index.html +0 -570
  181. data/site/news/2013/05/12/jekyll-1-0-2-released/index.html +0 -571
  182. data/site/news/2013/06/07/jekyll-1-0-3-released/index.html +0 -568
  183. data/site/news/2013/07/14/jekyll-1-1-0-released/index.html +0 -570
  184. data/site/news/2013/07/24/jekyll-1-1-1-released/index.html +0 -569
  185. data/site/news/2013/07/25/jekyll-1-0-4-released/index.html +0 -565
  186. data/site/news/2013/07/25/jekyll-1-1-2-released/index.html +0 -565
  187. data/site/news/2013/09/06/jekyll-1-2-0-released/index.html +0 -572
  188. data/site/news/2013/09/14/jekyll-1-2-1-released/index.html +0 -566
  189. data/site/news/2013/10/28/jekyll-1-3-0-rc1-released/index.html +0 -564
  190. data/site/news/2013/11/04/jekyll-1-3-0-released/index.html +0 -599
  191. data/site/news/2013/11/26/jekyll-1-3-1-released/index.html +0 -568
  192. data/site/news/2013/12/07/jekyll-1-4-0-released/index.html +0 -583
  193. data/site/news/2013/12/09/jekyll-1-4-1-released/index.html +0 -565
  194. data/site/news/2013/12/16/jekyll-1-4-2-released/index.html +0 -564
  195. data/site/news/2014/01/13/jekyll-1-4-3-released/index.html +0 -573
  196. data/site/news/2014/03/24/jekyll-1-5-0-released/index.html +0 -564
  197. data/site/news/2014/03/27/jekyll-1-5-1-released/index.html +0 -569
  198. data/site/news/2014/05/06/jekyll-turns-2-0-0/index.html +0 -585
  199. data/site/news/2014/05/08/jekyll-2-0-3-released/index.html +0 -565
  200. data/site/news/2014/06/04/jekyll-stickers-1-dollar-stickermule/index.html +0 -567
  201. data/site/news/2014/06/28/jekyll-turns-21-i-mean-2-1-0/index.html +0 -582
  202. data/site/news/2014/07/01/jekyll-2-1-1-released/index.html +0 -579
  203. data/site/news/2014/07/29/jekyll-2-2-0-released/index.html +0 -568
  204. data/site/news/2014/08/10/jekyll-2-3-0-released/index.html +0 -588
  205. data/site/news/2014/09/09/jekyll-2-4-0-released/index.html +0 -574
  206. data/site/news/2014/11/05/jekylls-midlife-crisis-jekyll-turns-2-5-0/index.html +0 -597
  207. data/site/news/2014/11/09/jekyll-2-5-1-released/index.html +0 -575
  208. data/site/news/2014/11/12/jekyll-2-5-2-released/index.html +0 -565
  209. data/site/news/2014/12/17/alfredxing-welcome-to-jekyll-core/index.html +0 -572
  210. data/site/news/2014/12/22/jekyll-2-5-3-released/index.html +0 -567
  211. data/site/news/2015/01/20/jekyll-meet-and-greet/index.html +0 -568
  212. data/site/news/2015/01/24/jekyll-3-0-0-beta1-released/index.html +0 -588
  213. data/site/news/2015/02/26/introducing-jekyll-talk/index.html +0 -563
  214. data/site/news/2015/10/26/jekyll-3-0-released/index.html +0 -592
  215. data/site/news/2015/11/17/jekyll-3-0-1-released/index.html +0 -576
  216. data/site/news/2016/01/20/jekyll-3-0-2-released/index.html +0 -566
  217. data/site/news/2016/01/24/jekyll-3-1-0-released/index.html +0 -599
  218. data/site/news/2016/01/28/jekyll-3-1-1-released/index.html +0 -583
  219. data/site/news/2016/02/08/jekyll-3-0-3-released/index.html +0 -578
  220. data/site/news/2016/02/19/jekyll-3-1-2-released/index.html +0 -569
  221. data/site/news/2016/03/10/making-it-easier-to-contribute-to-jekyll/index.html +0 -565
  222. data/site/news/2016/04/19/jekyll-3-0-4-released/index.html +0 -571
  223. data/site/news/2016/04/19/jekyll-3-1-3-released/index.html +0 -566
  224. data/site/news/2016/04/26/jekyll-3-0-5-released/index.html +0 -572
  225. data/site/news/2016/05/18/jekyll-3-1-4-released/index.html +0 -576
  226. data/site/news/2016/05/18/jekyll-3-1-5-released/index.html +0 -564
  227. data/site/news/2016/05/19/jekyll-3-1-6-released/index.html +0 -566
  228. data/site/news/2016/06/03/update-on-jekyll-s-google-summer-of-code-projects/index.html +0 -567
  229. data/site/news/2016/07/26/jekyll-3-2-0-released/index.html +0 -676
  230. data/site/news/2016/08/02/jekyll-3-2-1-released/index.html +0 -571
  231. data/site/news/2016/08/24/jekyll-admin-initial-release/index.html +0 -566
  232. data/site/news/2016/10/06/jekyll-3-3-is-here/index.html +0 -645
  233. data/site/news/2016/11/14/jekyll-3-3-1-released/index.html +0 -569
  234. data/site/news/2017/01/18/jekyll-3-4-0-released/index.html +0 -592
  235. data/site/news/2017/03/02/jekyll-3-4-1-released/index.html +0 -649
  236. data/site/news/2017/03/09/jekyll-3-4-2-released/index.html +0 -598
  237. data/site/news/2017/03/21/jekyll-3-4-3-released/index.html +0 -594
  238. data/site/news/2017/06/15/jekyll-3-5-0-released/index.html +0 -589
  239. data/site/news/2017/07/17/jekyll-3-5-1-released/index.html +0 -569
  240. data/site/news/2017/08/12/jekyll-3-5-2-released/index.html +0 -573
  241. data/site/news/2017/09/21/jekyll-3-6-0-released/index.html +0 -565
  242. data/site/news/index.html +0 -3609
  243. data/site/news/releases/index.html +0 -3344
  244. data/site/philosophy.html +0 -46
  245. data/site/readme.md +0 -23
  246. data/site/robots.txt +0 -1
  247. data/site/sitemap.xml +0 -485
  248. data/site/tutorials/convert-site-to-jekyll/index.html +0 -793
  249. data/site/tutorials/custom-404-page/index.html +0 -358
  250. data/site/tutorials/home/index.html +0 -323
  251. data/site/tutorials/index.html +0 -10
  252. data/site/tutorials/navigation/index.html +0 -872
  253. data/site/tutorials/orderofinterpretation/index.html +0 -441
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Kramdown::Parser::SmartyPants < Kramdown::Parser::Kramdown
4
+ def initialize(source, options)
5
+ super
6
+ @block_parsers = [:block_html]
7
+ @span_parsers = [:smart_quotes, :html_entity, :typographic_syms, :span_html]
8
+ end
9
+ end
10
+
11
+ module Jekyll
12
+ module Converters
13
+ class SmartyPants < Converter
14
+ safe true
15
+ priority :low
16
+
17
+ def initialize(config)
18
+ Jekyll::External.require_with_graceful_fail "kramdown"
19
+ @config = config["kramdown"].dup || {}
20
+ @config[:input] = :SmartyPants
21
+ end
22
+
23
+ def matches(_)
24
+ false
25
+ end
26
+
27
+ def output_ext(_)
28
+ nil
29
+ end
30
+
31
+ def convert(content)
32
+ Kramdown::Document.new(content, @config).to_html.chomp
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,251 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ # Convertible provides methods for converting a pagelike item
6
+ # from a certain type of markup into actual content
7
+ #
8
+ # Requires
9
+ # self.site -> Jekyll::Site
10
+ # self.content
11
+ # self.content=
12
+ # self.data=
13
+ # self.ext=
14
+ # self.output=
15
+ # self.name
16
+ # self.path
17
+ # self.type -> :page, :post or :draft
18
+
19
+ module Jekyll
20
+ module Convertible
21
+ # Returns the contents as a String.
22
+ def to_s
23
+ content || ""
24
+ end
25
+
26
+ # Whether the file is published or not, as indicated in YAML front-matter
27
+ def published?
28
+ !(data.key?("published") && data["published"] == false)
29
+ end
30
+
31
+ # Read the YAML frontmatter.
32
+ #
33
+ # base - The String path to the dir containing the file.
34
+ # name - The String filename of the file.
35
+ # opts - optional parameter to File.read, default at site configs
36
+ #
37
+ # Returns nothing.
38
+ # rubocop:disable Metrics/AbcSize
39
+ def read_yaml(base, name, opts = {})
40
+ filename = File.join(base, name)
41
+
42
+ begin
43
+ self.content = File.read(@path || site.in_source_dir(base, name),
44
+ Utils.merged_file_read_opts(site, opts))
45
+ if content =~ Document::YAML_FRONT_MATTER_REGEXP
46
+ self.content = $POSTMATCH
47
+ self.data = SafeYAML.load(Regexp.last_match(1))
48
+ end
49
+ rescue SyntaxError => e
50
+ Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
51
+ raise e if self.site.config["strict_front_matter"]
52
+ rescue => e
53
+ Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
54
+ raise e if self.site.config["strict_front_matter"]
55
+ end
56
+
57
+ self.data ||= {}
58
+
59
+ validate_data! filename
60
+ validate_permalink! filename
61
+
62
+ self.data
63
+ end
64
+ # rubocop:enable Metrics/AbcSize
65
+
66
+ def validate_data!(filename)
67
+ unless self.data.is_a?(Hash)
68
+ raise Errors::InvalidYAMLFrontMatterError,
69
+ "Invalid YAML front matter in #{filename}"
70
+ end
71
+ end
72
+
73
+ def validate_permalink!(filename)
74
+ if self.data["permalink"] && self.data["permalink"].to_s.empty?
75
+ raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
76
+ end
77
+ end
78
+
79
+ # Transform the contents based on the content type.
80
+ #
81
+ # Returns the transformed contents.
82
+ def transform
83
+ _renderer.convert(content)
84
+ end
85
+
86
+ # Determine the extension depending on content_type.
87
+ #
88
+ # Returns the String extension for the output file.
89
+ # e.g. ".html" for an HTML output file.
90
+ def output_ext
91
+ _renderer.output_ext
92
+ end
93
+
94
+ # Determine which converter to use based on this convertible's
95
+ # extension.
96
+ #
97
+ # Returns the Converter instance.
98
+ def converters
99
+ _renderer.converters
100
+ end
101
+
102
+ # Render Liquid in the content
103
+ #
104
+ # content - the raw Liquid content to render
105
+ # payload - the payload for Liquid
106
+ # info - the info for Liquid
107
+ #
108
+ # Returns the converted content
109
+ def render_liquid(content, payload, info, path)
110
+ _renderer.render_liquid(content, payload, info, path)
111
+ end
112
+ # rubocop: enable RescueException
113
+
114
+ # Convert this Convertible's data to a Hash suitable for use by Liquid.
115
+ #
116
+ # Returns the Hash representation of this Convertible.
117
+ def to_liquid(attrs = nil)
118
+ further_data = Hash[(attrs || self.class::ATTRIBUTES_FOR_LIQUID).map do |attribute|
119
+ [attribute, send(attribute)]
120
+ end]
121
+
122
+ defaults = site.frontmatter_defaults.all(relative_path, type)
123
+ Utils.deep_merge_hashes defaults, Utils.deep_merge_hashes(data, further_data)
124
+ end
125
+
126
+ # The type of a document,
127
+ # i.e., its classname downcase'd and to_sym'd.
128
+ #
129
+ # Returns the type of self.
130
+ def type
131
+ if is_a?(Page)
132
+ :pages
133
+ end
134
+ end
135
+
136
+ # returns the owner symbol for hook triggering
137
+ def hook_owner
138
+ if is_a?(Page)
139
+ :pages
140
+ end
141
+ end
142
+
143
+ # Determine whether the document is an asset file.
144
+ # Asset files include CoffeeScript files and Sass/SCSS files.
145
+ #
146
+ # Returns true if the extname belongs to the set of extensions
147
+ # that asset files use.
148
+ def asset_file?
149
+ sass_file? || coffeescript_file?
150
+ end
151
+
152
+ # Determine whether the document is a Sass file.
153
+ #
154
+ # Returns true if extname == .sass or .scss, false otherwise.
155
+ def sass_file?
156
+ %w(.sass .scss).include?(ext)
157
+ end
158
+
159
+ # Determine whether the document is a CoffeeScript file.
160
+ #
161
+ # Returns true if extname == .coffee, false otherwise.
162
+ def coffeescript_file?
163
+ ext == ".coffee"
164
+ end
165
+
166
+ # Determine whether the file should be rendered with Liquid.
167
+ #
168
+ # Always returns true.
169
+ def render_with_liquid?
170
+ true
171
+ end
172
+
173
+ # Determine whether the file should be placed into layouts.
174
+ #
175
+ # Returns false if the document is an asset file.
176
+ def place_in_layout?
177
+ !asset_file?
178
+ end
179
+
180
+ # Checks if the layout specified in the document actually exists
181
+ #
182
+ # layout - the layout to check
183
+ #
184
+ # Returns true if the layout is invalid, false if otherwise
185
+ def invalid_layout?(layout)
186
+ !data["layout"].nil? && layout.nil? && !(self.is_a? Jekyll::Excerpt)
187
+ end
188
+
189
+ # Recursively render layouts
190
+ #
191
+ # layouts - a list of the layouts
192
+ # payload - the payload for Liquid
193
+ # info - the info for Liquid
194
+ #
195
+ # Returns nothing
196
+ def render_all_layouts(layouts, payload, info)
197
+ _renderer.layouts = layouts
198
+ self.output = _renderer.place_in_layouts(output, payload, info)
199
+ ensure
200
+ @_renderer = nil # this will allow the modifications above to disappear
201
+ end
202
+
203
+ # Add any necessary layouts to this convertible document.
204
+ #
205
+ # payload - The site payload Drop or Hash.
206
+ # layouts - A Hash of {"name" => "layout"}.
207
+ #
208
+ # Returns nothing.
209
+ def do_layout(payload, layouts)
210
+ self.output = _renderer.tap do |renderer|
211
+ renderer.layouts = layouts
212
+ renderer.payload = payload
213
+ end.run
214
+
215
+ Jekyll.logger.debug "Post-Render Hooks:", self.relative_path
216
+ Jekyll::Hooks.trigger hook_owner, :post_render, self
217
+ ensure
218
+ @_renderer = nil # this will allow the modifications above to disappear
219
+ end
220
+
221
+ # Write the generated page file to the destination directory.
222
+ #
223
+ # dest - The String path to the destination dir.
224
+ #
225
+ # Returns nothing.
226
+ def write(dest)
227
+ path = destination(dest)
228
+ FileUtils.mkdir_p(File.dirname(path))
229
+ File.write(path, output, :mode => "wb")
230
+ Jekyll::Hooks.trigger hook_owner, :post_write, self
231
+ end
232
+
233
+ # Accessor for data properties by Liquid.
234
+ #
235
+ # property - The String name of the property to retrieve.
236
+ #
237
+ # Returns the String value or nil if the property isn't included.
238
+ def [](property)
239
+ if self.class::ATTRIBUTES_FOR_LIQUID.include?(property)
240
+ send(property)
241
+ else
242
+ data[property]
243
+ end
244
+ end
245
+
246
+ private
247
+ def _renderer
248
+ @_renderer ||= Jekyll::Renderer.new(site, self)
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ module Deprecator
5
+ extend self
6
+
7
+ def process(args)
8
+ arg_is_present? args, "--server", "The --server command has been replaced by the \
9
+ 'serve' subcommand."
10
+ arg_is_present? args, "--serve", "The --serve command has been replaced by the \
11
+ 'serve' subcommand."
12
+ arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \
13
+ use the 'build' subcommand."
14
+ arg_is_present? args, "--auto", "The switch '--auto' has been replaced with \
15
+ '--watch'."
16
+ arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \
17
+ the '--watch' switch."
18
+ arg_is_present? args, "--pygments", "The 'pygments'settings has been removed in \
19
+ favour of 'highlighter'."
20
+ arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in \
21
+ your config files."
22
+ arg_is_present? args, "--url", "The 'url' setting can only be set in your \
23
+ config files."
24
+ no_subcommand(args)
25
+ end
26
+
27
+ def no_subcommand(args)
28
+ unless args.empty? ||
29
+ args.first !~ %r(!/^--/!) || %w(--help --version).include?(args.first)
30
+ deprecation_message "Jekyll now uses subcommands instead of just switches. \
31
+ Run `jekyll help` to find out more."
32
+ abort
33
+ end
34
+ end
35
+
36
+ def arg_is_present?(args, deprecated_argument, message)
37
+ if args.include?(deprecated_argument)
38
+ deprecation_message(message)
39
+ end
40
+ end
41
+
42
+ def deprecation_message(message)
43
+ Jekyll.logger.warn "Deprecation:", message
44
+ end
45
+
46
+ def defaults_deprecate_type(old, current)
47
+ Jekyll.logger.warn "Defaults:", "The '#{old}' type has become '#{current}'."
48
+ Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use \
49
+ 'type: #{current}'."
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,507 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Document
5
+ include Comparable
6
+ extend Forwardable
7
+
8
+ attr_reader :path, :site, :extname, :collection
9
+ attr_accessor :content, :output
10
+
11
+ def_delegator :self, :read_post_data, :post_read
12
+
13
+ YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
14
+ DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!
15
+ DATE_FILENAME_MATCHER = %r!^(?:.+/)*(\d{2,4}-\d{1,2}-\d{1,2})-(.*)(\.[^.]+)$!
16
+
17
+ # Create a new Document.
18
+ #
19
+ # path - the path to the file
20
+ # relations - a hash with keys :site and :collection, the values of which
21
+ # are the Jekyll::Site and Jekyll::Collection to which this
22
+ # Document belong.
23
+ #
24
+ # Returns nothing.
25
+ def initialize(path, relations = {})
26
+ @site = relations[:site]
27
+ @path = path
28
+ @extname = File.extname(path)
29
+ @collection = relations[:collection]
30
+ @has_yaml_header = nil
31
+
32
+ if draft?
33
+ categories_from_path("_drafts")
34
+ else
35
+ categories_from_path(collection.relative_directory)
36
+ end
37
+
38
+ data.default_proc = proc do |_, key|
39
+ site.frontmatter_defaults.find(relative_path, collection.label, key)
40
+ end
41
+
42
+ trigger_hooks(:post_init)
43
+ end
44
+
45
+ # Fetch the Document's data.
46
+ #
47
+ # Returns a Hash containing the data. An empty hash is returned if
48
+ # no data was read.
49
+ def data
50
+ @data ||= {}
51
+ end
52
+
53
+ # Merge some data in with this document's data.
54
+ #
55
+ # Returns the merged data.
56
+ def merge_data!(other, source: "YAML front matter")
57
+ merge_categories!(other)
58
+ Utils.deep_merge_hashes!(data, other)
59
+ merge_date!(source)
60
+ data
61
+ end
62
+
63
+ def date
64
+ data["date"] ||= (draft? ? source_file_mtime : site.time)
65
+ end
66
+
67
+ def source_file_mtime
68
+ @source_file_mtime ||= File.mtime(path)
69
+ end
70
+
71
+ # Returns whether the document is a draft. This is only the case if
72
+ # the document is in the 'posts' collection but in a different
73
+ # directory than '_posts'.
74
+ #
75
+ # Returns whether the document is a draft.
76
+ def draft?
77
+ data["draft"] ||= relative_path.index(collection.relative_directory).nil? &&
78
+ collection.label == "posts"
79
+ end
80
+
81
+ # The path to the document, relative to the site source.
82
+ #
83
+ # Returns a String path which represents the relative path
84
+ # from the site source to this document
85
+ def relative_path
86
+ @relative_path ||= Pathutil.new(path).relative_path_from(site.source).to_s
87
+ end
88
+
89
+ # The output extension of the document.
90
+ #
91
+ # Returns the output extension
92
+ def output_ext
93
+ Jekyll::Renderer.new(site, self).output_ext
94
+ end
95
+
96
+ # The base filename of the document, without the file extname.
97
+ #
98
+ # Returns the basename without the file extname.
99
+ def basename_without_ext
100
+ @basename_without_ext ||= File.basename(path, ".*")
101
+ end
102
+
103
+ # The base filename of the document.
104
+ #
105
+ # Returns the base filename of the document.
106
+ def basename
107
+ @basename ||= File.basename(path)
108
+ end
109
+
110
+ # Produces a "cleaned" relative path.
111
+ # The "cleaned" relative path is the relative path without the extname
112
+ # and with the collection's directory removed as well.
113
+ # This method is useful when building the URL of the document.
114
+ #
115
+ # Examples:
116
+ # When relative_path is "_methods/site/generate.md":
117
+ # cleaned_relative_path
118
+ # # => "/site/generate"
119
+ #
120
+ # Returns the cleaned relative path of the document.
121
+ def cleaned_relative_path
122
+ @cleaned_relative_path ||=
123
+ relative_path[0..-extname.length - 1].sub(collection.relative_directory, "")
124
+ end
125
+
126
+ # Determine whether the document is a YAML file.
127
+ #
128
+ # Returns true if the extname is either .yml or .yaml, false otherwise.
129
+ def yaml_file?
130
+ %w(.yaml .yml).include?(extname)
131
+ end
132
+
133
+ # Determine whether the document is an asset file.
134
+ # Asset files include CoffeeScript files and Sass/SCSS files.
135
+ #
136
+ # Returns true if the extname belongs to the set of extensions
137
+ # that asset files use.
138
+ def asset_file?
139
+ sass_file? || coffeescript_file?
140
+ end
141
+
142
+ # Determine whether the document is a Sass file.
143
+ #
144
+ # Returns true if extname == .sass or .scss, false otherwise.
145
+ def sass_file?
146
+ %w(.sass .scss).include?(extname)
147
+ end
148
+
149
+ # Determine whether the document is a CoffeeScript file.
150
+ #
151
+ # Returns true if extname == .coffee, false otherwise.
152
+ def coffeescript_file?
153
+ extname == ".coffee"
154
+ end
155
+
156
+ # Determine whether the file should be rendered with Liquid.
157
+ #
158
+ # Returns false if the document is either an asset file or a yaml file,
159
+ # true otherwise.
160
+ def render_with_liquid?
161
+ !(coffeescript_file? || yaml_file?)
162
+ end
163
+
164
+ # Determine whether the file should be rendered with a layout.
165
+ #
166
+ # Returns true if the Front Matter specifies that `layout` is set to `none`.
167
+ def no_layout?
168
+ data["layout"] == "none"
169
+ end
170
+
171
+ # Determine whether the file should be placed into layouts.
172
+ #
173
+ # Returns false if the document is set to `layouts: none`, or is either an
174
+ # asset file or a yaml file. Returns true otherwise.
175
+ def place_in_layout?
176
+ !(asset_file? || yaml_file? || no_layout?)
177
+ end
178
+
179
+ # The URL template where the document would be accessible.
180
+ #
181
+ # Returns the URL template for the document.
182
+ def url_template
183
+ collection.url_template
184
+ end
185
+
186
+ # Construct a Hash of key-value pairs which contain a mapping between
187
+ # a key in the URL template and the corresponding value for this document.
188
+ #
189
+ # Returns the Hash of key-value pairs for replacement in the URL.
190
+ def url_placeholders
191
+ @url_placeholders ||= Drops::UrlDrop.new(self)
192
+ end
193
+
194
+ # The permalink for this Document.
195
+ # Permalink is set via the data Hash.
196
+ #
197
+ # Returns the permalink or nil if no permalink was set in the data.
198
+ def permalink
199
+ data && data.is_a?(Hash) && data["permalink"]
200
+ end
201
+
202
+ # The computed URL for the document. See `Jekyll::URL#to_s` for more details.
203
+ #
204
+ # Returns the computed URL for the document.
205
+ def url
206
+ @url ||= URL.new({
207
+ :template => url_template,
208
+ :placeholders => url_placeholders,
209
+ :permalink => permalink,
210
+ }).to_s
211
+ end
212
+
213
+ def [](key)
214
+ data[key]
215
+ end
216
+
217
+ # The full path to the output file.
218
+ #
219
+ # base_directory - the base path of the output directory
220
+ #
221
+ # Returns the full path to the output file of this document.
222
+ def destination(base_directory)
223
+ dest = site.in_dest_dir(base_directory)
224
+ path = site.in_dest_dir(dest, URL.unescape_path(url))
225
+ if url.end_with? "/"
226
+ path = File.join(path, "index.html")
227
+ else
228
+ path << output_ext unless path.end_with? output_ext
229
+ end
230
+ path
231
+ end
232
+
233
+ # Write the generated Document file to the destination directory.
234
+ #
235
+ # dest - The String path to the destination dir.
236
+ #
237
+ # Returns nothing.
238
+ def write(dest)
239
+ path = destination(dest)
240
+ FileUtils.mkdir_p(File.dirname(path))
241
+ File.write(path, output, :mode => "wb")
242
+
243
+ trigger_hooks(:post_write)
244
+ end
245
+
246
+ # Whether the file is published or not, as indicated in YAML front-matter
247
+ #
248
+ # Returns 'false' if the 'published' key is specified in the
249
+ # YAML front-matter and is 'false'. Otherwise returns 'true'.
250
+ def published?
251
+ !(data.key?("published") && data["published"] == false)
252
+ end
253
+
254
+ # Read in the file and assign the content and data based on the file contents.
255
+ # Merge the frontmatter of the file with the frontmatter default
256
+ # values
257
+ #
258
+ # Returns nothing.
259
+ def read(opts = {})
260
+ Jekyll.logger.debug "Reading:", relative_path
261
+
262
+ if yaml_file?
263
+ @data = SafeYAML.load_file(path)
264
+ else
265
+ begin
266
+ merge_defaults
267
+ read_content(opts)
268
+ read_post_data
269
+ rescue => e
270
+ handle_read_error(e)
271
+ end
272
+ end
273
+ end
274
+
275
+ # Create a Liquid-understandable version of this Document.
276
+ #
277
+ # Returns a Hash representing this Document's data.
278
+ def to_liquid
279
+ @to_liquid ||= Drops::DocumentDrop.new(self)
280
+ end
281
+
282
+ # The inspect string for this document.
283
+ # Includes the relative path and the collection label.
284
+ #
285
+ # Returns the inspect string for this document.
286
+ def inspect
287
+ "#<Jekyll::Document #{relative_path} collection=#{collection.label}>"
288
+ end
289
+
290
+ # The string representation for this document.
291
+ #
292
+ # Returns the content of the document
293
+ def to_s
294
+ output || content || "NO CONTENT"
295
+ end
296
+
297
+ # Compare this document against another document.
298
+ # Comparison is a comparison between the 2 paths of the documents.
299
+ #
300
+ # Returns -1, 0, +1 or nil depending on whether this doc's path is less than,
301
+ # equal or greater than the other doc's path. See String#<=> for more details.
302
+ def <=>(other)
303
+ return nil unless other.respond_to?(:data)
304
+ cmp = data["date"] <=> other.data["date"]
305
+ cmp = path <=> other.path if cmp.nil? || cmp.zero?
306
+ cmp
307
+ end
308
+
309
+ # Determine whether this document should be written.
310
+ # Based on the Collection to which it belongs.
311
+ #
312
+ # True if the document has a collection and if that collection's #write?
313
+ # method returns true, otherwise false.
314
+ def write?
315
+ collection && collection.write?
316
+ end
317
+
318
+ # The Document excerpt_separator, from the YAML Front-Matter or site
319
+ # default excerpt_separator value
320
+ #
321
+ # Returns the document excerpt_separator
322
+ def excerpt_separator
323
+ (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
324
+ end
325
+
326
+ # Whether to generate an excerpt
327
+ #
328
+ # Returns true if the excerpt separator is configured.
329
+ def generate_excerpt?
330
+ !excerpt_separator.empty?
331
+ end
332
+
333
+ def next_doc
334
+ pos = collection.docs.index { |post| post.equal?(self) }
335
+ if pos && pos < collection.docs.length - 1
336
+ collection.docs[pos + 1]
337
+ end
338
+ end
339
+
340
+ def previous_doc
341
+ pos = collection.docs.index { |post| post.equal?(self) }
342
+ if pos && pos > 0
343
+ collection.docs[pos - 1]
344
+ end
345
+ end
346
+
347
+ def trigger_hooks(hook_name, *args)
348
+ Jekyll::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection
349
+ Jekyll::Hooks.trigger :documents, hook_name, self, *args
350
+ end
351
+
352
+ def id
353
+ @id ||= File.join(File.dirname(url), (data["slug"] || basename_without_ext).to_s)
354
+ end
355
+
356
+ # Calculate related posts.
357
+ #
358
+ # Returns an Array of related Posts.
359
+ def related_posts
360
+ Jekyll::RelatedPosts.new(self).build
361
+ end
362
+
363
+ # Override of normal respond_to? to match method_missing's logic for
364
+ # looking in @data.
365
+ def respond_to?(method, include_private = false)
366
+ data.key?(method.to_s) || super
367
+ end
368
+
369
+ # Override of method_missing to check in @data for the key.
370
+ def method_missing(method, *args, &blck)
371
+ if data.key?(method.to_s)
372
+ Jekyll::Deprecator.deprecation_message "Document##{method} is now a key "\
373
+ "in the #data hash."
374
+ Jekyll::Deprecator.deprecation_message "Called by #{caller(0..0)}."
375
+ data[method.to_s]
376
+ else
377
+ super
378
+ end
379
+ end
380
+
381
+ def respond_to_missing?(method, *)
382
+ data.key?(method.to_s) || super
383
+ end
384
+
385
+ # Add superdirectories of the special_dir to categories.
386
+ # In the case of es/_posts, 'es' is added as a category.
387
+ # In the case of _posts/es, 'es' is NOT added as a category.
388
+ #
389
+ # Returns nothing.
390
+ def categories_from_path(special_dir)
391
+ superdirs = relative_path.sub(%r!#{special_dir}(.*)!, "")
392
+ .split(File::SEPARATOR)
393
+ .reject do |c|
394
+ c.empty? || c == special_dir || c == basename
395
+ end
396
+ merge_data!({ "categories" => superdirs }, :source => "file path")
397
+ end
398
+
399
+ def populate_categories
400
+ merge_data!({
401
+ "categories" => (
402
+ Array(data["categories"]) + Utils.pluralized_array_from_hash(
403
+ data,
404
+ "category",
405
+ "categories"
406
+ )
407
+ ).map(&:to_s).flatten.uniq,
408
+ })
409
+ end
410
+
411
+ def populate_tags
412
+ merge_data!({
413
+ "tags" => Utils.pluralized_array_from_hash(data, "tag", "tags").flatten,
414
+ })
415
+ end
416
+
417
+ private
418
+ def merge_categories!(other)
419
+ if other.key?("categories") && !other["categories"].nil?
420
+ if other["categories"].is_a?(String)
421
+ other["categories"] = other["categories"].split(%r!\s+!).map(&:strip)
422
+ end
423
+ other["categories"] = (data["categories"] || []) | other["categories"]
424
+ end
425
+ end
426
+
427
+ private
428
+ def merge_date!(source)
429
+ if data.key?("date") && !data["date"].is_a?(Time)
430
+ data["date"] = Utils.parse_date(
431
+ data["date"].to_s,
432
+ "Document '#{relative_path}' does not have a valid date in the #{source}."
433
+ )
434
+ end
435
+ end
436
+
437
+ private
438
+ def merge_defaults
439
+ defaults = @site.frontmatter_defaults.all(
440
+ relative_path,
441
+ collection.label.to_sym
442
+ )
443
+ merge_data!(defaults, :source => "front matter defaults") unless defaults.empty?
444
+ end
445
+
446
+ private
447
+ def read_content(opts)
448
+ self.content = File.read(path, Utils.merged_file_read_opts(site, opts))
449
+ if content =~ YAML_FRONT_MATTER_REGEXP
450
+ self.content = $POSTMATCH
451
+ data_file = SafeYAML.load(Regexp.last_match(1))
452
+ merge_data!(data_file, :source => "YAML front matter") if data_file
453
+ end
454
+ end
455
+
456
+ private
457
+ def read_post_data
458
+ populate_title
459
+ populate_categories
460
+ populate_tags
461
+ generate_excerpt
462
+ end
463
+
464
+ private
465
+ def handle_read_error(error)
466
+ if error.is_a? SyntaxError
467
+ Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{error.message}"
468
+ else
469
+ Jekyll.logger.error "Error:", "could not read file #{path}: #{error.message}"
470
+ end
471
+
472
+ if site.config["strict_front_matter"] || error.is_a?(Jekyll::Errors::FatalException)
473
+ raise error
474
+ end
475
+ end
476
+
477
+ private
478
+ def populate_title
479
+ if relative_path =~ DATE_FILENAME_MATCHER
480
+ date, slug, ext = Regexp.last_match.captures
481
+ modify_date(date)
482
+ elsif relative_path =~ DATELESS_FILENAME_MATCHER
483
+ slug, ext = Regexp.last_match.captures
484
+ end
485
+
486
+ # Try to ensure the user gets a title.
487
+ data["title"] ||= Utils.titleize_slug(slug)
488
+ # Only overwrite slug & ext if they aren't specified.
489
+ data["slug"] ||= slug
490
+ data["ext"] ||= ext
491
+ end
492
+
493
+ private
494
+ def modify_date(date)
495
+ if !data["date"] || data["date"].to_i == site.time.to_i
496
+ merge_data!({ "date" => date }, :source => "filename")
497
+ end
498
+ end
499
+
500
+ private
501
+ def generate_excerpt
502
+ if generate_excerpt?
503
+ data["excerpt"] ||= Jekyll::Excerpt.new(self)
504
+ end
505
+ end
506
+ end
507
+ end