jekyll-docs 3.6.0 → 3.6.1

Sign up to get free protection for your applications and to get access to all the features.
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,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class RelatedPosts
5
+ class << self
6
+ attr_accessor :lsi
7
+ end
8
+
9
+ attr_reader :post, :site
10
+
11
+ def initialize(post)
12
+ @post = post
13
+ @site = post.site
14
+ Jekyll::External.require_with_graceful_fail("classifier-reborn") if site.lsi
15
+ end
16
+
17
+ def build
18
+ return [] unless site.posts.docs.size > 1
19
+
20
+ if site.lsi
21
+ build_index
22
+ lsi_related_posts
23
+ else
24
+ most_recent_posts
25
+ end
26
+ end
27
+
28
+ def build_index
29
+ self.class.lsi ||= begin
30
+ lsi = ClassifierReborn::LSI.new(:auto_rebuild => false)
31
+ Jekyll.logger.info("Populating LSI...")
32
+
33
+ site.posts.docs.each do |x|
34
+ lsi.add_item(x)
35
+ end
36
+
37
+ Jekyll.logger.info("Rebuilding index...")
38
+ lsi.build_index
39
+ Jekyll.logger.info("")
40
+ lsi
41
+ end
42
+ end
43
+
44
+ def lsi_related_posts
45
+ self.class.lsi.find_related(post, 11)
46
+ end
47
+
48
+ def most_recent_posts
49
+ @most_recent_posts ||= (site.posts.docs.reverse - [post]).first(10)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Jekyll
4
+ class Renderer
5
+ attr_reader :document, :site
6
+ attr_writer :layouts, :payload
7
+
8
+ def initialize(site, document, site_payload = nil)
9
+ @site = site
10
+ @document = document
11
+ @payload = site_payload
12
+ end
13
+
14
+ # Fetches the payload used in Liquid rendering.
15
+ # It can be written with #payload=(new_payload)
16
+ # Falls back to site.site_payload if no payload is set.
17
+ #
18
+ # Returns a Jekyll::Drops::UnifiedPayloadDrop
19
+ def payload
20
+ @payload ||= site.site_payload
21
+ end
22
+
23
+ # The list of layouts registered for this Renderer.
24
+ # It can be written with #layouts=(new_layouts)
25
+ # Falls back to site.layouts if no layouts are registered.
26
+ #
27
+ # Returns a Hash of String => Jekyll::Layout identified
28
+ # as basename without the extension name.
29
+ def layouts
30
+ @layouts || site.layouts
31
+ end
32
+
33
+ # Determine which converters to use based on this document's
34
+ # extension.
35
+ #
36
+ # Returns Array of Converter instances.
37
+ def converters
38
+ @converters ||= site.converters.select { |c| c.matches(document.extname) }.sort
39
+ end
40
+
41
+ # Determine the extname the outputted file should have
42
+ #
43
+ # Returns String the output extname including the leading period.
44
+ def output_ext
45
+ @output_ext ||= (permalink_ext || converter_output_ext)
46
+ end
47
+
48
+ # Prepare payload and render the document
49
+ #
50
+ # Returns String rendered document output
51
+ def run
52
+ Jekyll.logger.debug "Rendering:", document.relative_path
53
+
54
+ assign_pages!
55
+ assign_related_posts!
56
+ assign_highlighter_options!
57
+ assign_layout_data!
58
+
59
+ Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
60
+ document.trigger_hooks(:pre_render, payload)
61
+
62
+ render_document
63
+ end
64
+
65
+ # Render the document.
66
+ #
67
+ # Returns String rendered document output
68
+ # rubocop: disable AbcSize
69
+ def render_document
70
+ info = {
71
+ :registers => { :site => site, :page => payload["page"] },
72
+ }
73
+ output = document.content
74
+ if document.render_with_liquid?
75
+ Jekyll.logger.debug "Rendering Liquid:", document.relative_path
76
+ output = render_liquid(output, payload, info, document.path)
77
+ end
78
+
79
+ Jekyll.logger.debug "Rendering Markup:", document.relative_path
80
+ output = convert(output)
81
+ document.content = output
82
+
83
+ if document.place_in_layout?
84
+ Jekyll.logger.debug "Rendering Layout:", document.relative_path
85
+ output = place_in_layouts(output, payload, info)
86
+ end
87
+
88
+ output
89
+ end
90
+ # rubocop: enable AbcSize
91
+
92
+ # Convert the document using the converters which match this renderer's document.
93
+ #
94
+ # Returns String the converted content.
95
+ def convert(content)
96
+ converters.reduce(content) do |output, converter|
97
+ begin
98
+ converter.convert output
99
+ rescue => e
100
+ Jekyll.logger.error "Conversion error:",
101
+ "#{converter.class} encountered an error while "\
102
+ "converting '#{document.relative_path}':"
103
+ Jekyll.logger.error("", e.to_s)
104
+ raise e
105
+ end
106
+ end
107
+ end
108
+
109
+ # Render the given content with the payload and info
110
+ #
111
+ # content -
112
+ # payload -
113
+ # info -
114
+ # path - (optional) the path to the file, for use in ex
115
+ #
116
+ # Returns String the content, rendered by Liquid.
117
+ def render_liquid(content, payload, info, path = nil)
118
+ template = site.liquid_renderer.file(path).parse(content)
119
+ template.warnings.each do |e|
120
+ Jekyll.logger.warn "Liquid Warning:",
121
+ LiquidRenderer.format_error(e, path || document.relative_path)
122
+ end
123
+ template.render!(payload, info)
124
+ # rubocop: disable RescueException
125
+ rescue Exception => e
126
+ Jekyll.logger.error "Liquid Exception:",
127
+ LiquidRenderer.format_error(e, path || document.relative_path)
128
+ raise e
129
+ end
130
+ # rubocop: enable RescueException
131
+
132
+ # Checks if the layout specified in the document actually exists
133
+ #
134
+ # layout - the layout to check
135
+ #
136
+ # Returns Boolean true if the layout is invalid, false if otherwise
137
+ def invalid_layout?(layout)
138
+ !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt)
139
+ end
140
+
141
+ # Render layouts and place document content inside.
142
+ #
143
+ # Returns String rendered content
144
+ def place_in_layouts(content, payload, info)
145
+ output = content.dup
146
+ layout = layouts[document.data["layout"]]
147
+ validate_layout(layout)
148
+
149
+ used = Set.new([layout])
150
+
151
+ # Reset the payload layout data to ensure it starts fresh for each page.
152
+ payload["layout"] = nil
153
+
154
+ while layout
155
+ output = render_layout(output, layout, info)
156
+ add_regenerator_dependencies(layout)
157
+
158
+ if (layout = site.layouts[layout.data["layout"]])
159
+ break if used.include?(layout)
160
+ used << layout
161
+ end
162
+ end
163
+ output
164
+ end
165
+
166
+ # Checks if the layout specified in the document actually exists
167
+ #
168
+ # layout - the layout to check
169
+ # Returns nothing
170
+ private
171
+ def validate_layout(layout)
172
+ return unless invalid_layout?(layout)
173
+ Jekyll.logger.warn(
174
+ "Build Warning:",
175
+ "Layout '#{document.data["layout"]}' requested "\
176
+ "in #{document.relative_path} does not exist."
177
+ )
178
+ end
179
+
180
+ # Render layout content into document.output
181
+ #
182
+ # Returns String rendered content
183
+ private
184
+ def render_layout(output, layout, info)
185
+ payload["content"] = output
186
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
187
+
188
+ render_liquid(
189
+ layout.content,
190
+ payload,
191
+ info,
192
+ layout.relative_path
193
+ )
194
+ end
195
+
196
+ private
197
+ def add_regenerator_dependencies(layout)
198
+ return unless document.write?
199
+ site.regenerator.add_dependency(
200
+ site.in_source_dir(document.path),
201
+ site.in_source_dir(layout.path)
202
+ )
203
+ end
204
+
205
+ # Set page content to payload and assign pager if document has one.
206
+ #
207
+ # Returns nothing
208
+ private
209
+ def assign_pages!
210
+ payload["page"] = document.to_liquid
211
+ payload["paginator"] = if document.respond_to?(:pager)
212
+ document.pager.to_liquid
213
+ end
214
+ end
215
+
216
+ # Set related posts to payload if document is a post.
217
+ #
218
+ # Returns nothing
219
+ private
220
+ def assign_related_posts!
221
+ if document.is_a?(Document) && document.collection.label == "posts"
222
+ payload["site"]["related_posts"] = document.related_posts
223
+ else
224
+ payload["site"]["related_posts"] = nil
225
+ end
226
+ end
227
+
228
+ # Set highlighter prefix and suffix
229
+ #
230
+ # Returns nothing
231
+ private
232
+ def assign_highlighter_options!
233
+ payload["highlighter_prefix"] = converters.first.highlighter_prefix
234
+ payload["highlighter_suffix"] = converters.first.highlighter_suffix
235
+ end
236
+
237
+ private
238
+ def assign_layout_data!
239
+ layout = layouts[document.data["layout"]]
240
+ if layout
241
+ payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
242
+ end
243
+ end
244
+
245
+ private
246
+ def permalink_ext
247
+ if document.permalink && !document.permalink.end_with?("/")
248
+ permalink_ext = File.extname(document.permalink)
249
+ permalink_ext unless permalink_ext.empty?
250
+ end
251
+ end
252
+
253
+ private
254
+ def converter_output_ext
255
+ if output_exts.size == 1
256
+ output_exts.last
257
+ else
258
+ output_exts[-2]
259
+ end
260
+ end
261
+
262
+ private
263
+ def output_exts
264
+ @output_exts ||= converters.map do |c|
265
+ c.output_ext(document.extname)
266
+ end.compact
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,471 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Jekyll
6
+ class Site
7
+ attr_reader :source, :dest, :config
8
+ attr_accessor :layouts, :pages, :static_files, :drafts,
9
+ :exclude, :include, :lsi, :highlighter, :permalink_style,
10
+ :time, :future, :unpublished, :safe, :plugins, :limit_posts,
11
+ :show_drafts, :keep_files, :baseurl, :data, :file_read_opts,
12
+ :gems, :plugin_manager, :theme
13
+
14
+ attr_accessor :converters, :generators, :reader
15
+ attr_reader :regenerator, :liquid_renderer, :includes_load_paths
16
+
17
+ # Public: Initialize a new Site.
18
+ #
19
+ # config - A Hash containing site configuration details.
20
+ def initialize(config)
21
+ # Source and destination may not be changed after the site has been created.
22
+ @source = File.expand_path(config["source"]).freeze
23
+ @dest = File.expand_path(config["destination"]).freeze
24
+
25
+ self.config = config
26
+
27
+ @reader = Reader.new(self)
28
+ @regenerator = Regenerator.new(self)
29
+ @liquid_renderer = LiquidRenderer.new(self)
30
+
31
+ Jekyll.sites << self
32
+
33
+ reset
34
+ setup
35
+
36
+ Jekyll::Hooks.trigger :site, :after_init, self
37
+ end
38
+
39
+ # Public: Set the site's configuration. This handles side-effects caused by
40
+ # changing values in the configuration.
41
+ #
42
+ # config - a Jekyll::Configuration, containing the new configuration.
43
+ #
44
+ # Returns the new configuration.
45
+ def config=(config)
46
+ @config = config.clone
47
+
48
+ %w(safe lsi highlighter baseurl exclude include future unpublished
49
+ show_drafts limit_posts keep_files).each do |opt|
50
+ self.send("#{opt}=", config[opt])
51
+ end
52
+
53
+ # keep using `gems` to avoid breaking change
54
+ self.gems = config["plugins"]
55
+
56
+ configure_plugins
57
+ configure_theme
58
+ configure_include_paths
59
+ configure_file_read_opts
60
+
61
+ self.permalink_style = config["permalink"].to_sym
62
+
63
+ @config
64
+ end
65
+
66
+ # Public: Read, process, and write this Site to output.
67
+ #
68
+ # Returns nothing.
69
+ def process
70
+ reset
71
+ read
72
+ generate
73
+ render
74
+ cleanup
75
+ write
76
+ print_stats if config["profile"]
77
+ end
78
+
79
+ def print_stats
80
+ puts @liquid_renderer.stats_table
81
+ end
82
+
83
+ # Reset Site details.
84
+ #
85
+ # Returns nothing
86
+ def reset
87
+ self.time = if config["time"]
88
+ Utils.parse_date(config["time"].to_s, "Invalid time in _config.yml.")
89
+ else
90
+ Time.now
91
+ end
92
+ self.layouts = {}
93
+ self.pages = []
94
+ self.static_files = []
95
+ self.data = {}
96
+ @collections = nil
97
+ @regenerator.clear_cache
98
+ @liquid_renderer.reset
99
+
100
+ if limit_posts < 0
101
+ raise ArgumentError, "limit_posts must be a non-negative number"
102
+ end
103
+
104
+ Jekyll::Hooks.trigger :site, :after_reset, self
105
+ end
106
+
107
+ # Load necessary libraries, plugins, converters, and generators.
108
+ #
109
+ # Returns nothing.
110
+ def setup
111
+ ensure_not_in_dest
112
+
113
+ plugin_manager.conscientious_require
114
+
115
+ self.converters = instantiate_subclasses(Jekyll::Converter)
116
+ self.generators = instantiate_subclasses(Jekyll::Generator)
117
+ end
118
+
119
+ # Check that the destination dir isn't the source dir or a directory
120
+ # parent to the source dir.
121
+ def ensure_not_in_dest
122
+ dest_pathname = Pathname.new(dest)
123
+ Pathname.new(source).ascend do |path|
124
+ if path == dest_pathname
125
+ raise(
126
+ Errors::FatalException,
127
+ "Destination directory cannot be or contain the Source directory."
128
+ )
129
+ end
130
+ end
131
+ end
132
+
133
+ # The list of collections and their corresponding Jekyll::Collection instances.
134
+ # If config['collections'] is set, a new instance is created
135
+ # for each item in the collection, a new hash is returned otherwise.
136
+ #
137
+ # Returns a Hash containing collection name-to-instance pairs.
138
+ def collections
139
+ @collections ||= Hash[collection_names.map do |coll|
140
+ [coll, Jekyll::Collection.new(self, coll)]
141
+ end]
142
+ end
143
+
144
+ # The list of collection names.
145
+ #
146
+ # Returns an array of collection names from the configuration,
147
+ # or an empty array if the `collections` key is not set.
148
+ def collection_names
149
+ case config["collections"]
150
+ when Hash
151
+ config["collections"].keys
152
+ when Array
153
+ config["collections"]
154
+ when nil
155
+ []
156
+ else
157
+ raise ArgumentError, "Your `collections` key must be a hash or an array."
158
+ end
159
+ end
160
+
161
+ # Read Site data from disk and load it into internal data structures.
162
+ #
163
+ # Returns nothing.
164
+ def read
165
+ reader.read
166
+ limit_posts!
167
+ Jekyll::Hooks.trigger :site, :post_read, self
168
+ end
169
+
170
+ # Run each of the Generators.
171
+ #
172
+ # Returns nothing.
173
+ def generate
174
+ generators.each do |generator|
175
+ start = Time.now
176
+ generator.generate(self)
177
+ Jekyll.logger.debug "Generating:",
178
+ "#{generator.class} finished in #{Time.now - start} seconds."
179
+ end
180
+ end
181
+
182
+ # Render the site to the destination.
183
+ #
184
+ # Returns nothing.
185
+ def render
186
+ relative_permalinks_are_deprecated
187
+
188
+ payload = site_payload
189
+
190
+ Jekyll::Hooks.trigger :site, :pre_render, self, payload
191
+
192
+ render_docs(payload)
193
+ render_pages(payload)
194
+
195
+ Jekyll::Hooks.trigger :site, :post_render, self, payload
196
+ end
197
+
198
+ # Remove orphaned files and empty directories in destination.
199
+ #
200
+ # Returns nothing.
201
+ def cleanup
202
+ site_cleaner.cleanup!
203
+ end
204
+
205
+ # Write static files, pages, and posts.
206
+ #
207
+ # Returns nothing.
208
+ def write
209
+ each_site_file do |item|
210
+ item.write(dest) if regenerator.regenerate?(item)
211
+ end
212
+ regenerator.write_metadata
213
+ Jekyll::Hooks.trigger :site, :post_write, self
214
+ end
215
+
216
+ def posts
217
+ collections["posts"] ||= Collection.new(self, "posts")
218
+ end
219
+
220
+ # Construct a Hash of Posts indexed by the specified Post attribute.
221
+ #
222
+ # post_attr - The String name of the Post attribute.
223
+ #
224
+ # Examples
225
+ #
226
+ # post_attr_hash('categories')
227
+ # # => { 'tech' => [<Post A>, <Post B>],
228
+ # # 'ruby' => [<Post B>] }
229
+ #
230
+ # Returns the Hash: { attr => posts } where
231
+ # attr - One of the values for the requested attribute.
232
+ # posts - The Array of Posts with the given attr value.
233
+ def post_attr_hash(post_attr)
234
+ # Build a hash map based on the specified post attribute ( post attr =>
235
+ # array of posts ) then sort each array in reverse order.
236
+ hash = Hash.new { |h, key| h[key] = [] }
237
+ posts.docs.each do |p|
238
+ p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr]
239
+ end
240
+ hash.each_value { |posts| posts.sort!.reverse! }
241
+ hash
242
+ end
243
+
244
+ def tags
245
+ post_attr_hash("tags")
246
+ end
247
+
248
+ def categories
249
+ post_attr_hash("categories")
250
+ end
251
+
252
+ # Prepare site data for site payload. The method maintains backward compatibility
253
+ # if the key 'data' is already used in _config.yml.
254
+ #
255
+ # Returns the Hash to be hooked to site.data.
256
+ def site_data
257
+ config["data"] || data
258
+ end
259
+
260
+ # The Hash payload containing site-wide data.
261
+ #
262
+ # Returns the Hash: { "site" => data } where data is a Hash with keys:
263
+ # "time" - The Time as specified in the configuration or the
264
+ # current time if none was specified.
265
+ # "posts" - The Array of Posts, sorted chronologically by post date
266
+ # and then title.
267
+ # "pages" - The Array of all Pages.
268
+ # "html_pages" - The Array of HTML Pages.
269
+ # "categories" - The Hash of category values and Posts.
270
+ # See Site#post_attr_hash for type info.
271
+ # "tags" - The Hash of tag values and Posts.
272
+ # See Site#post_attr_hash for type info.
273
+ def site_payload
274
+ Drops::UnifiedPayloadDrop.new self
275
+ end
276
+ alias_method :to_liquid, :site_payload
277
+
278
+ # Get the implementation class for the given Converter.
279
+ # Returns the Converter instance implementing the given Converter.
280
+ # klass - The Class of the Converter to fetch.
281
+
282
+ def find_converter_instance(klass)
283
+ converters.find { |klass_| klass_.instance_of?(klass) } || \
284
+ raise("No Converters found for #{klass}")
285
+ end
286
+
287
+ # klass - class or module containing the subclasses.
288
+ # Returns array of instances of subclasses of parameter.
289
+ # Create array of instances of the subclasses of the class or module
290
+ # passed in as argument.
291
+
292
+ def instantiate_subclasses(klass)
293
+ klass.descendants.select { |c| !safe || c.safe }.sort.map do |c|
294
+ c.new(config)
295
+ end
296
+ end
297
+
298
+ # Warns the user if permanent links are relative to the parent
299
+ # directory. As this is a deprecated function of Jekyll.
300
+ #
301
+ # Returns
302
+ def relative_permalinks_are_deprecated
303
+ if config["relative_permalinks"]
304
+ Jekyll.logger.abort_with "Since v3.0, permalinks for pages" \
305
+ " in subfolders must be relative to the" \
306
+ " site source directory, not the parent" \
307
+ " directory. Check https://jekyllrb.com/docs/upgrading/"\
308
+ " for more info."
309
+ end
310
+ end
311
+
312
+ # Get the to be written documents
313
+ #
314
+ # Returns an Array of Documents which should be written
315
+ def docs_to_write
316
+ documents.select(&:write?)
317
+ end
318
+
319
+ # Get all the documents
320
+ #
321
+ # Returns an Array of all Documents
322
+ def documents
323
+ collections.reduce(Set.new) do |docs, (_, collection)|
324
+ docs + collection.docs + collection.files
325
+ end.to_a
326
+ end
327
+
328
+ def each_site_file
329
+ %w(pages static_files docs_to_write).each do |type|
330
+ send(type).each do |item|
331
+ yield item
332
+ end
333
+ end
334
+ end
335
+
336
+ # Returns the FrontmatterDefaults or creates a new FrontmatterDefaults
337
+ # if it doesn't already exist.
338
+ #
339
+ # Returns The FrontmatterDefaults
340
+ def frontmatter_defaults
341
+ @frontmatter_defaults ||= FrontmatterDefaults.new(self)
342
+ end
343
+
344
+ # Whether to perform a full rebuild without incremental regeneration
345
+ #
346
+ # Returns a Boolean: true for a full rebuild, false for normal build
347
+ def incremental?(override = {})
348
+ override["incremental"] || config["incremental"]
349
+ end
350
+
351
+ # Returns the publisher or creates a new publisher if it doesn't
352
+ # already exist.
353
+ #
354
+ # Returns The Publisher
355
+ def publisher
356
+ @publisher ||= Publisher.new(self)
357
+ end
358
+
359
+ # Public: Prefix a given path with the source directory.
360
+ #
361
+ # paths - (optional) path elements to a file or directory within the
362
+ # source directory
363
+ #
364
+ # Returns a path which is prefixed with the source directory.
365
+ def in_source_dir(*paths)
366
+ paths.reduce(source) do |base, path|
367
+ Jekyll.sanitized_path(base, path)
368
+ end
369
+ end
370
+
371
+ # Public: Prefix a given path with the theme directory.
372
+ #
373
+ # paths - (optional) path elements to a file or directory within the
374
+ # theme directory
375
+ #
376
+ # Returns a path which is prefixed with the theme root directory.
377
+ def in_theme_dir(*paths)
378
+ return nil unless theme
379
+ paths.reduce(theme.root) do |base, path|
380
+ Jekyll.sanitized_path(base, path)
381
+ end
382
+ end
383
+
384
+ # Public: Prefix a given path with the destination directory.
385
+ #
386
+ # paths - (optional) path elements to a file or directory within the
387
+ # destination directory
388
+ #
389
+ # Returns a path which is prefixed with the destination directory.
390
+ def in_dest_dir(*paths)
391
+ paths.reduce(dest) do |base, path|
392
+ Jekyll.sanitized_path(base, path)
393
+ end
394
+ end
395
+
396
+ # Limits the current posts; removes the posts which exceed the limit_posts
397
+ #
398
+ # Returns nothing
399
+ private
400
+ def limit_posts!
401
+ if limit_posts > 0
402
+ limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
403
+ self.posts.docs = posts.docs[-limit, limit]
404
+ end
405
+ end
406
+
407
+ # Returns the Cleaner or creates a new Cleaner if it doesn't
408
+ # already exist.
409
+ #
410
+ # Returns The Cleaner
411
+ private
412
+ def site_cleaner
413
+ @site_cleaner ||= Cleaner.new(self)
414
+ end
415
+
416
+ private
417
+ def configure_plugins
418
+ self.plugin_manager = Jekyll::PluginManager.new(self)
419
+ self.plugins = plugin_manager.plugins_path
420
+ end
421
+
422
+ private
423
+ def configure_theme
424
+ self.theme = nil
425
+ return if config["theme"].nil?
426
+
427
+ self.theme =
428
+ if config["theme"].is_a?(String)
429
+ Jekyll::Theme.new(config["theme"])
430
+ else
431
+ Jekyll.logger.warn "Theme:", "value of 'theme' in config should be " \
432
+ "String to use gem-based themes, but got #{config["theme"].class}"
433
+ nil
434
+ end
435
+ end
436
+
437
+ private
438
+ def configure_include_paths
439
+ @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
440
+ @includes_load_paths << theme.includes_path if theme && theme.includes_path
441
+ end
442
+
443
+ private
444
+ def configure_file_read_opts
445
+ self.file_read_opts = {}
446
+ self.file_read_opts[:encoding] = config["encoding"] if config["encoding"]
447
+ end
448
+
449
+ private
450
+ def render_docs(payload)
451
+ collections.each_value do |collection|
452
+ collection.docs.each do |document|
453
+ if regenerator.regenerate?(document)
454
+ document.output = Jekyll::Renderer.new(self, document, payload).run
455
+ document.trigger_hooks(:post_render)
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ private
462
+ def render_pages(payload)
463
+ pages.flatten.each do |page|
464
+ if regenerator.regenerate?(page)
465
+ page.output = Jekyll::Renderer.new(self, page, payload).run
466
+ page.trigger_hooks(:post_render)
467
+ end
468
+ end
469
+ end
470
+ end
471
+ end