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,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