Merge branch 'upstream' into 'upstream'
New upstream version 3.8.6+dfsg
See merge request ruby-team/jekyll!4
Daniel Leidert
4 years ago
1 | 1 | script: script/cibuild |
2 | 2 | cache: bundler |
3 | 3 | language: ruby |
4 | sudo: false | |
5 | 4 | |
6 | 5 | rvm: |
7 | 6 | - &ruby1 2.5.1 |
30 | 29 | only: |
31 | 30 | - master |
32 | 31 | - themes |
33 | - /*-stable/ | |
32 | - /.*-stable/ | |
34 | 33 | |
35 | 34 | notifications: |
36 | 35 | slack: |
53 | 52 | - bundle exec codeclimate-test-reporter |
54 | 53 | |
55 | 54 | before_install: |
56 | - gem update --system | |
57 | - gem install bundler | |
55 | - gem update --system || true |
26 | 26 | gem "httpclient" |
27 | 27 | gem "jekyll_test_plugin" |
28 | 28 | gem "jekyll_test_plugin_malicious" |
29 | # nokogiri v1.8 does not work with ruby 2.1 and below | |
30 | gem "nokogiri", RUBY_VERSION >= "2.2" ? "~> 1.7" : "~> 1.7.0" | |
29 | # nokogiri v1.10 does not work with ruby 2.2 and below | |
30 | gem "nokogiri", RUBY_VERSION >= "2.3" ? "~> 1.9" : "~> 1.9.0" | |
31 | 31 | gem "rspec" |
32 | 32 | gem "rspec-mocks" |
33 | 33 | gem "rubocop", "~> 0.56.0" |
34 | 34 | gem "test-dependency-theme", :path => File.expand_path("test/fixtures/test-dependency-theme", __dir__) |
35 | 35 | gem "test-theme", :path => File.expand_path("test/fixtures/test-theme", __dir__) |
36 | gem "test-theme-skinny", :path => File.expand_path("test/fixtures/test-theme-skinny", __dir__) | |
37 | gem "test-theme-symlink", :path => File.expand_path("test/fixtures/test-theme-symlink", __dir__) | |
36 | 38 | |
37 | gem "jruby-openssl" if RUBY_ENGINE == "jruby" | |
39 | gem "jruby-openssl", "0.10.1" if RUBY_ENGINE == "jruby" | |
38 | 40 | end |
39 | 41 | |
40 | 42 | # |
0 | ## 3.8.6 / 2019-07-02 | |
1 | ||
2 | ### Bug Fixes | |
3 | ||
4 | * Update log output for an invalid theme directory (#7734) | |
5 | * Memoize `SiteDrop#documents` to reduce allocations (#7722) | |
6 | * Excerpt handling of custom and intermediate tags (#7467) | |
7 | * Escape valid special chars in a site's path name (#7573) | |
8 | * Revert memoizing `Site#docs_to_write` and refactor `#documents` (#7689) | |
9 | * Fix broken `include_relative` usage in excerpt (#7690) | |
10 | * Install platform-specific gems as required (3c06609406) | |
11 | ||
12 | ### Security Fixes | |
13 | ||
14 | * Theme gems: ensure directories aren't symlinks (#7424) | |
15 | ||
16 | ## 3.8.5 / 2018-11-04 | |
17 | ||
18 | ### Bug Fixes | |
19 | ||
20 | * Re-implement handling Liquid blocks in excerpts (#7250) | |
21 | ||
22 | ## 3.8.4 / 2018-09-18 | |
23 | ||
24 | ### Bug Fixes | |
25 | ||
26 | * security: fix `include` bypass of `EntryFilter#filter` symlink check (#7228) | |
27 | ||
0 | 28 | ## 3.8.3 / 2018-06-05 |
1 | 29 | |
2 | 30 | ### Bug Fixes |
0 | 0 | --- |
1 | version: 3.8.3 | |
1 | version: 3.8.6 | |
2 | 2 | name: Jekyll • Simple, blog-aware, static sites |
3 | 3 | description: Transform your plain text into static websites and blogs |
4 | 4 | url: https://jekyllrb.com |
2 | 2 | permalink: "/docs/history/" |
3 | 3 | note: This file is autogenerated. Edit /History.markdown instead. |
4 | 4 | --- |
5 | ||
6 | ## 3.8.6 / 2019-07-02 | |
7 | {: #v3-8-6} | |
8 | ||
9 | ### Bug Fixes | |
10 | {: #bug-fixes-v3-8-6} | |
11 | ||
12 | - Update log output for an invalid theme directory ([#7734]({{ site.repository }}/issues/7734)) | |
13 | - Memoize `SiteDrop#documents` to reduce allocations ([#7722]({{ site.repository }}/issues/7722)) | |
14 | - Excerpt handling of custom and intermediate tags ([#7467]({{ site.repository }}/issues/7467)) | |
15 | - Escape valid special chars in a site's path name ([#7573]({{ site.repository }}/issues/7573)) | |
16 | - Revert memoizing `Site#docs_to_write` and refactor `#documents` ([#7689]({{ site.repository }}/issues/7689)) | |
17 | - Fix broken `include_relative` usage in excerpt ([#7690]({{ site.repository }}/issues/7690)) | |
18 | - Install platform-specific gems as required (3c06609406) | |
19 | ||
20 | ### Security Fixes | |
21 | {: #security-fixes-v3-8-6} | |
22 | ||
23 | - Theme gems: ensure directories aren't symlinks ([#7424]({{ site.repository }}/issues/7424)) | |
24 | ||
25 | ||
26 | ## 3.8.5 / 2018-11-04 | |
27 | {: #v3-8-5} | |
28 | ||
29 | ### Bug Fixes | |
30 | {: #bug-fixes-v3-8-5} | |
31 | ||
32 | - Re-implement handling Liquid blocks in excerpts ([#7250]({{ site.repository }}/issues/7250)) | |
33 | ||
34 | ||
35 | ## 3.8.4 / 2018-09-18 | |
36 | {: #v3-8-4} | |
37 | ||
38 | ### Bug Fixes | |
39 | {: #bug-fixes-v3-8-4} | |
40 | ||
41 | - security: fix `include` bypass of `EntryFilter#filter` symlink check ([#7228]({{ site.repository }}/issues/7228)) | |
42 | ||
5 | 43 | |
6 | 44 | ## 3.8.3 / 2018-06-05 |
7 | 45 | {: #v3-8-3} |
0 | --- | |
1 | title: 'Jekyll 3.8.6 Released' | |
2 | date: 2019-07-02 11:21:02 -0400 | |
3 | author: parkr | |
4 | version: 3.8.6 | |
5 | categories: [release] | |
6 | --- | |
7 | ||
8 | We have another patch release in the 3.8 series! This time, we have one security patch | |
9 | and a handful of bug patches, including: | |
10 | ||
11 | - Filter symlinks from theme gems | |
12 | - Fix excerpt handling of some Liquid tags | |
13 | - Handle case where a theme directory doesn't exist | |
14 | - A few internal optimizations to reduce memory overhead | |
15 | ||
16 | ... and a few more! You can check out the patches and see all the details in [the release notes](/docs/history/#v3-8-6) | |
17 | ||
18 | Happy Jekylling! |
0 | Feature: include_relative Tag | |
1 | In order to share content across several closely related pages | |
2 | As a hacker who likes to blog | |
3 | I want to be able to include snippets in my site's pages and documents relative to current file | |
4 | ||
5 | Scenario: Include a file relative to a post | |
6 | Given I have a _posts directory | |
7 | And I have a _posts/snippets directory | |
8 | And I have the following post: | |
9 | | title | date | content | | |
10 | | Star Wars | 2018-09-02 | {% include_relative snippets/welcome_para.md %} | | |
11 | And I have an "_posts/snippets/welcome_para.md" file that contains "Welcome back Dear Reader!" | |
12 | When I run jekyll build | |
13 | Then I should get a zero exit status | |
14 | And the _site directory should exist | |
15 | And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" | |
16 | ||
17 | Scenario: Include a nested file relative to a post | |
18 | Given I have a _posts directory | |
19 | And I have a _posts/snippets directory | |
20 | And I have a _posts/snippets/welcome_para directory | |
21 | And I have the following post: | |
22 | | title | date | content | | |
23 | | Star Wars | 2018-09-02 | {% include_relative snippets/welcome_para.md %} | | |
24 | And I have an "_posts/snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" | |
25 | And I have an "_posts/snippets/welcome_para/greeting.md" file that contains "Welcome back" | |
26 | When I run jekyll build | |
27 | Then I should get a zero exit status | |
28 | And the _site directory should exist | |
29 | And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" | |
30 | ||
31 | Scenario: Include a nested file relative to a post as an excerpt | |
32 | Given I have a _posts directory | |
33 | And I have a _posts/snippets directory | |
34 | And I have a _posts/snippets/welcome_para directory | |
35 | And I have a "_posts/2018-09-02-star-wars.md" file with content: | |
36 | """ | |
37 | {% include_relative snippets/welcome_para.md %} | |
38 | ||
39 | Hello World | |
40 | """ | |
41 | And I have an "_posts/snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" | |
42 | And I have an "_posts/snippets/welcome_para/greeting.md" file that contains "Welcome back" | |
43 | And I have an "index.md" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" | |
44 | When I run jekyll build | |
45 | Then I should get a zero exit status | |
46 | And the _site directory should exist | |
47 | And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" | |
48 | And I should see "Welcome back Dear Reader!" in "_site/index.html" | |
49 | ||
50 | Scenario: Include a nested file relative to a page at root | |
51 | Given I have a snippets directory | |
52 | And I have a snippets/welcome_para directory | |
53 | And I have a "index.md" page that contains "{% include_relative snippets/welcome_para.md %}" | |
54 | And I have a "snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" | |
55 | And I have a "snippets/welcome_para/greeting.md" file that contains "Welcome back" | |
56 | When I run jekyll build | |
57 | Then I should get a zero exit status | |
58 | And the _site directory should exist | |
59 | And I should see "Welcome back Dear Reader!" in "_site/index.html" |
3 | 3 | In order to share my awesome ideas with the interwebs |
4 | 4 | But I want to make it as simply as possible |
5 | 5 | So render with Liquid and place in Layouts |
6 | ||
7 | Scenario: Rendering a site with parentheses in its path name | |
8 | Given I have a blank site in "omega(beta)" | |
9 | And I have an "omega(beta)/test.md" page with layout "simple" that contains "Hello World" | |
10 | And I have an omega(beta)/_includes directory | |
11 | And I have an "omega(beta)/_includes/head.html" file that contains "Snippet" | |
12 | And I have a configuration file with "source" set to "omega(beta)" | |
13 | And I have an omega(beta)/_layouts directory | |
14 | And I have an "omega(beta)/_layouts/simple.html" file that contains "{% include head.html %}: {{ content }}" | |
15 | When I run jekyll build --profile | |
16 | Then I should get a zero exit status | |
17 | And I should see "Snippet: <p>Hello World</p>" in "_site/test.html" | |
18 | And I should see "_layouts/simple.html" in the build output | |
6 | 19 | |
7 | 20 | Scenario: When receiving bad Liquid |
8 | 21 | Given I have a "index.html" page with layout "simple" that contains "{% include invalid.html %}" |
56 | 56 | And I should see "From your site." in "_site/assets/application.coffee" |
57 | 57 | And I should see "From your site." in "_site/assets/base.js" |
58 | 58 | |
59 | Scenario: A theme with *just* layouts | |
60 | Given I have a configuration file with "theme" set to "test-theme-skinny" | |
61 | And I have an "index.html" page with layout "home" that contains "The quick brown fox." | |
62 | When I run jekyll build | |
63 | Then I should get a zero exit status | |
64 | And the _site directory should exist | |
65 | And I should see "Message: The quick brown fox." in "_site/index.html" | |
66 | But I should not see "_includes" in the build output | |
67 | And I should not see "_sass" in the build output | |
68 | And I should not see "assets" in the build output | |
69 | ||
59 | 70 | Scenario: Requiring dependencies of a theme |
60 | 71 | Given I have a configuration file with "theme" set to "test-dependency-theme" |
61 | 72 | When I run jekyll build |
87 | 87 | end |
88 | 88 | |
89 | 89 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem |
90 | gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] | |
90 | # and associated library. | |
91 | install_if -> { RUBY_PLATFORM =~ %r!mingw|mswin|java! } do | |
92 | gem "tzinfo", "~> 1.2" | |
93 | gem "tzinfo-data" | |
94 | end | |
91 | 95 | |
92 | 96 | # Performance-booster for watching directories on Windows |
93 | gem "wdm", "~> 0.1.0" if Gem.win_platform? | |
97 | gem "wdm", "~> 0.1.0", :install_if => Gem.win_platform? | |
94 | 98 | |
95 | 99 | RUBY |
96 | 100 | end |
7 | 7 | mutable false |
8 | 8 | |
9 | 9 | def_delegator :@obj, :site_data, :data |
10 | def_delegators :@obj, :time, :pages, :static_files, :documents, | |
11 | :tags, :categories | |
10 | def_delegators :@obj, :time, :pages, :static_files, :tags, :categories | |
12 | 11 | |
13 | 12 | private def_delegator :@obj, :config, :fallback_data |
14 | 13 | |
38 | 37 | @site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid) |
39 | 38 | end |
40 | 39 | |
40 | # `Site#documents` cannot be memoized so that `Site#docs_to_write` can access the | |
41 | # latest state of the attribute. | |
42 | # | |
43 | # Since this method will be called after `Site#pre_render` hook, | |
44 | # the `Site#documents` array shouldn't thereafter change and can therefore be | |
45 | # safely memoized to prevent additional computation of `Site#documents`. | |
46 | def documents | |
47 | @documents ||= @obj.documents | |
48 | end | |
49 | ||
41 | 50 | # `{{ site.related_posts }}` is how posts can get posts related to |
42 | 51 | # them, either through LSI if it's enabled, or through the most |
43 | 52 | # recent posts. |
30 | 30 | |
31 | 31 | def filter(entries) |
32 | 32 | entries.reject do |e| |
33 | unless included?(e) | |
34 | special?(e) || backup?(e) || excluded?(e) || symlink?(e) | |
35 | end | |
33 | # Reject this entry if it is a symlink. | |
34 | next true if symlink?(e) | |
35 | # Do not reject this entry if it is included. | |
36 | next false if included?(e) | |
37 | # Reject this entry if it is special, a backup file, or excluded. | |
38 | special?(e) || backup?(e) || excluded?(e) | |
36 | 39 | end |
37 | 40 | end |
38 | 41 |
127 | 127 | # |
128 | 128 | # Returns excerpt String |
129 | 129 | |
130 | LIQUID_TAG_REGEX = %r!{%-?\s*(\w+).+\s*-?%}!m | |
130 | LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m | |
131 | 131 | MKDWN_LINK_REF_REGEX = %r!^ {0,3}\[[^\]]+\]:.+$! |
132 | 132 | |
133 | 133 | def extract_excerpt(doc_content) |
134 | 134 | head, _, tail = doc_content.to_s.partition(doc.excerpt_separator) |
135 | 135 | |
136 | # append appropriate closing tag (to a Liquid block), to the "head" if the | |
137 | # partitioning resulted in leaving the closing tag somewhere in the "tail" | |
138 | # partition. | |
136 | # append appropriate closing tag(s) (for each Liquid block), to the `head` | |
137 | # if the partitioning resulted in leaving the closing tag somewhere | |
138 | # in the `tail` partition. | |
139 | ||
139 | 140 | if head.include?("{%") |
140 | head =~ LIQUID_TAG_REGEX | |
141 | tag_name = Regexp.last_match(1) | |
141 | modified = false | |
142 | tag_names = head.scan(LIQUID_TAG_REGEX) | |
143 | tag_names.flatten! | |
144 | tag_names.reverse_each do |tag_name| | |
145 | next unless liquid_block?(tag_name) | |
146 | next if head =~ endtag_regex_stash(tag_name) | |
142 | 147 | |
143 | if liquid_block?(tag_name) && head.match(%r!{%-?\s*end#{tag_name}\s*-?%}!).nil? | |
144 | print_build_warning | |
148 | modified = true | |
145 | 149 | head << "\n{% end#{tag_name} %}" |
146 | 150 | end |
151 | print_build_warning if modified | |
147 | 152 | end |
148 | 153 | |
149 | if tail.empty? | |
150 | head | |
151 | else | |
152 | head.to_s.dup << "\n\n" << tail.scan(MKDWN_LINK_REF_REGEX).join("\n") | |
153 | end | |
154 | return head if tail.empty? | |
155 | ||
156 | head << "\n\n" << tail.scan(MKDWN_LINK_REF_REGEX).join("\n") | |
154 | 157 | end |
155 | 158 | |
156 | 159 | private |
157 | 160 | |
161 | def endtag_regex_stash(tag_name) | |
162 | @endtag_regex_stash ||= {} | |
163 | @endtag_regex_stash[tag_name] ||= %r!{%-?\s*end#{tag_name}.*?\s*-?%}!m | |
164 | end | |
165 | ||
158 | 166 | def liquid_block?(tag_name) |
159 | Liquid::Template.tags[tag_name].superclass == Liquid::Block | |
167 | return false unless tag_name.is_a?(String) | |
168 | return false unless Liquid::Template.tags[tag_name] | |
169 | ||
170 | Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block) | |
160 | 171 | rescue NoMethodError |
161 | 172 | Jekyll.logger.error "Error:", |
162 | 173 | "A Liquid tag in the excerpt of #{doc.relative_path} couldn't be " \ |
166 | 177 | |
167 | 178 | def print_build_warning |
168 | 179 | Jekyll.logger.warn "Warning:", "Excerpt modified in #{doc.relative_path}!" |
169 | Jekyll.logger.warn "", | |
170 | "Found a Liquid block containing separator '#{doc.excerpt_separator}' and has " \ | |
171 | "been modified with the appropriate closing tag." | |
172 | Jekyll.logger.warn "", | |
173 | "Feel free to define a custom excerpt or excerpt_separator in the document's " \ | |
174 | "Front Matter if the generated excerpt is unsatisfactory." | |
180 | Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator" \ | |
181 | " #{doc.excerpt_separator.inspect}. " | |
182 | Jekyll.logger.warn "", "The block has been modified with the appropriate" \ | |
183 | " closing tag." | |
184 | Jekyll.logger.warn "", "Feel free to define a custom excerpt or" \ | |
185 | " excerpt_separator in the document's front matter" \ | |
186 | " if the generated excerpt is unsatisfactory." | |
175 | 187 | end |
176 | 188 | end |
177 | 189 | end |
52 | 52 | private |
53 | 53 | |
54 | 54 | def filename_regex |
55 | @filename_regex ||= %r!\A(#{source_dir}/|#{theme_dir}/|\W*)(.*)!i | |
55 | @filename_regex ||= begin | |
56 | %r!\A(#{Regexp.escape(source_dir)}/|#{Regexp.escape(theme_dir.to_s)}/|/*)(.*)!i | |
57 | end | |
56 | 58 | end |
57 | 59 | |
58 | 60 | def new_profile_hash |
313 | 313 | # |
314 | 314 | # Returns an Array of Documents which should be written |
315 | 315 | def docs_to_write |
316 | @docs_to_write ||= documents.select(&:write?) | |
316 | documents.select(&:write?) | |
317 | 317 | end |
318 | 318 | |
319 | 319 | # Get all the documents |
320 | 320 | # |
321 | 321 | # Returns an Array of all Documents |
322 | 322 | def documents |
323 | collections.reduce(Set.new) do |docs, (_, collection)| | |
324 | docs + collection.docs + collection.files | |
323 | collections.each_with_object(Set.new) do |(_, collection), set| | |
324 | set.merge(collection.docs).merge(collection.files) | |
325 | 325 | end.to_a |
326 | 326 | end |
327 | 327 |
223 | 223 | else |
224 | 224 | File.join(site.config["collections_dir"], page_payload["path"]) |
225 | 225 | end |
226 | resource_path.sub!(%r!/#excerpt\z!, "") | |
226 | 227 | site.in_source_dir File.dirname(resource_path) |
227 | 228 | end |
228 | 229 | end |
55 | 55 | end |
56 | 56 | |
57 | 57 | def realpath_for(folder) |
58 | File.realpath(Jekyll.sanitized_path(root, folder.to_s)) | |
59 | rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP | |
60 | Jekyll.logger.warn "Invalid theme folder:", folder | |
58 | # This resolves all symlinks for the theme subfolder and then ensures | |
59 | # that the directory remains inside the theme root. This prevents the | |
60 | # use of symlinks for theme subfolders to escape the theme root. | |
61 | # However, symlinks are allowed to point to other directories within the theme. | |
62 | Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s))) | |
63 | rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP => e | |
64 | log_realpath_exception(e, folder) | |
61 | 65 | nil |
66 | end | |
67 | ||
68 | def log_realpath_exception(err, folder) | |
69 | return if err.is_a?(Errno::ENOENT) | |
70 | ||
71 | case err | |
72 | when Errno::EACCES | |
73 | Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible." | |
74 | when Errno::ELOOP | |
75 | Jekyll.logger.error "Theme error:", | |
76 | "Directory '#{folder}' includes a symbolic link loop." | |
77 | end | |
62 | 78 | end |
63 | 79 | |
64 | 80 | def gemspec |
0 | 0 | # frozen_string_literal: true |
1 | 1 | |
2 | 2 | module Jekyll |
3 | VERSION = "3.8.3".freeze | |
3 | VERSION = "3.8.6".freeze | |
4 | 4 | end |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <meta charset="UTF-8"> | |
4 | <title>Skinny</title> | |
5 | </head> | |
6 | <body> | |
7 | <h1>Hello World</h1> | |
8 | {{ content }} | |
9 | </body> | |
10 | </html> |
0 | # frozen_string_literal: true | |
1 | ||
2 | Gem::Specification.new do |s| | |
3 | s.name = "test-theme-skinny" | |
4 | s.version = "0.1.0" | |
5 | s.licenses = ["MIT"] | |
6 | s.summary = "This is a theme with just layouts used to test Jekyll" | |
7 | s.authors = ["Jekyll"] | |
8 | s.files = ["lib/example.rb"] | |
9 | s.homepage = "https://github.com/jekyll/jekyll" | |
10 | end |
0 | # frozen_string_literal: true | |
1 | ||
2 | Gem::Specification.new do |s| | |
3 | s.name = "test-theme-symlink" | |
4 | s.version = "0.1.0" | |
5 | s.licenses = ["MIT"] | |
6 | s.summary = "This is a theme with a symlink used to test Jekyll" | |
7 | s.authors = ["Jekyll"] | |
8 | s.files = ["lib/example.rb"] | |
9 | s.homepage = "https://github.com/jekyll/jekyll" | |
10 | end |
194 | 194 | skip msg.to_s.magenta |
195 | 195 | end |
196 | 196 | end |
197 | ||
198 | def symlink_if_allowed(target, sym_file) | |
199 | FileUtils.ln_sf(target, sym_file) | |
200 | rescue Errno::EACCES | |
201 | skip "Permission denied for creating a symlink to #{target.inspect} " \ | |
202 | "on this machine".magenta | |
203 | rescue NotImplementedError => error | |
204 | skip error.to_s.magenta | |
205 | end | |
197 | 206 | end |
198 | 207 | |
199 | 208 | class FakeLogger |
0 | # frozen_string_literal: true | |
1 | ||
2 | # For testing excerpt handling of custom tags | |
3 | ||
4 | module Jekyll | |
5 | class DoNothingBlock < Liquid::Block | |
6 | end | |
7 | ||
8 | class DoNothingOther < Liquid::Tag | |
9 | end | |
10 | end | |
11 | ||
12 | Liquid::Template.register_tag("do_nothing", Jekyll::DoNothingBlock) | |
13 | Liquid::Template.register_tag("do_nothing_other", Jekyll::DoNothingOther) |
1 | 1 | layout: post |
2 | 2 | --- |
3 | 3 | |
4 | {% if | |
5 | page.layout == "post" %} | |
6 | You’ll find this post in your `_posts` directory. | |
7 | To add new posts, simply add a file in the `_posts` directory. | |
8 | {% endif %} | |
4 | {% | |
5 | highlight | |
6 | ruby | |
7 | %} | |
8 | {% assign foo = 'foobar' %} | |
9 | {% raw | |
10 | %} | |
11 | def print_hi(name) | |
12 | puts "Hi, #{name}" | |
13 | end | |
14 | print_hi('Tom') | |
15 | #=> prints 'Hi, Tom' to STDOUT. | |
16 | {% | |
17 | endraw | |
18 | %} | |
19 | {% | |
20 | endhighlight | |
21 | %} | |
9 | 22 | |
10 | 23 | So let's talk business. |
1 | 1 | layout: post |
2 | 2 | --- |
3 | 3 | |
4 | {% if page.layout == "post" %} | |
5 | You’ll find this post in your `_posts` directory. | |
4 | {% | |
5 | highlight | |
6 | ruby | |
7 | %} | |
8 | {% assign foo = 'foobar' %} | |
9 | {% raw | |
10 | %} | |
11 | def print_hi(name) | |
12 | puts "Hi, #{name}" | |
13 | end | |
6 | 14 | |
7 | {% else %} | |
15 | print_hi('Tom') | |
16 | #=> prints 'Hi, Tom' to STDOUT. | |
17 | {% endraw %} | |
18 | {% endhighlight %} | |
8 | 19 | |
9 | To add new posts, simply add a file in the `_posts` directory. | |
10 | {% endif %} | |
20 | So let's talk business. |
0 | --- | |
1 | title: liquid_block excerpt test with open tags in excerpt | |
2 | layout: post | |
3 | --- | |
4 | ||
5 | {% assign company = "Yoyodyne" %} | |
6 | {% do_nothing_other %} | |
7 | {% do_nothing %} | |
8 | {% unless false %} | |
9 | {% for i in (1..10) %} | |
10 | {% if true %} | |
11 | {% raw %} | |
12 | EVIL! PURE AND SIMPLE FROM THE EIGHTH DIMENSION! | |
13 | {% endraw %} | |
14 | {% elsif false %} | |
15 | No matter where you go, there you are. | |
16 | {% break %} | |
17 | {% else %} | |
18 | {% case company %} | |
19 | {% when "Yoyodyne" %} | |
20 | Buckaroo Banzai | |
21 | {% else %} | |
22 | {% continue %} | |
23 | ||
24 | {% endcase %} | |
25 | {% endif %} | |
26 | {% endfor %} | |
27 | {% endunless %} | |
28 | {% enddo_nothing %} |
0 | /etc/passwd⏎ |
4 | 4 | class TestEntryFilter < JekyllUnitTest |
5 | 5 | context "Filtering entries" do |
6 | 6 | setup do |
7 | @site = Site.new(site_configuration) | |
7 | @site = fixture_site | |
8 | 8 | end |
9 | 9 | |
10 | 10 | should "filter entries" do |
86 | 86 | # no support for symlinks on Windows |
87 | 87 | skip_if_windows "Jekyll does not currently support symlinks on Windows." |
88 | 88 | |
89 | site = Site.new(site_configuration("safe" => true)) | |
89 | site = fixture_site("safe" => true) | |
90 | 90 | site.reader.read_directories("symlink-test") |
91 | 91 | |
92 | 92 | assert_equal %w(main.scss symlinked-file).length, site.pages.length |
98 | 98 | # no support for symlinks on Windows |
99 | 99 | skip_if_windows "Jekyll does not currently support symlinks on Windows." |
100 | 100 | |
101 | site = Site.new(site_configuration) | |
101 | @site.reader.read_directories("symlink-test") | |
102 | refute_equal [], @site.pages | |
103 | refute_equal [], @site.static_files | |
104 | end | |
102 | 105 | |
106 | should "include only safe symlinks in safe mode even when included" do | |
107 | # no support for symlinks on Windows | |
108 | skip_if_windows "Jekyll does not currently support symlinks on Windows." | |
109 | ||
110 | site = fixture_site("safe" => true, "include" => ["symlinked-file-outside-source"]) | |
103 | 111 | site.reader.read_directories("symlink-test") |
104 | refute_equal [], site.pages | |
105 | refute_equal [], site.static_files | |
112 | ||
113 | # rubocop:disable Performance/FixedSize | |
114 | assert_equal %w(main.scss symlinked-file).length, site.pages.length | |
115 | refute_includes site.static_files.map(&:name), "symlinked-file-outside-source" | |
116 | # rubocop:enable Performance/FixedSize | |
106 | 117 | end |
107 | 118 | end |
108 | 119 |
184 | 184 | @post = setup_post("2018-01-28-open-liquid-block-excerpt.markdown") |
185 | 185 | @excerpt = @post.data["excerpt"] |
186 | 186 | |
187 | assert_includes @post.content, "{% if" | |
188 | refute_includes @post.content.split("\n\n")[0], "{% endif %}" | |
187 | head = @post.content.split("\n\n")[0] | |
188 | ||
189 | assert_includes @post.content, "{%\n highlight\n" | |
190 | assert_includes @post.content, "{% raw" | |
191 | refute_includes head, "{% endraw %}" | |
192 | refute_includes head, "{% endhighlight %}" | |
189 | 193 | end |
190 | 194 | |
191 | 195 | should "be appended to as necessary and generated" do |
192 | assert_includes @excerpt.content, "{% endif %}" | |
196 | assert_includes @excerpt.content, "{% endraw %}" | |
197 | assert_includes @excerpt.content, "{% endhighlight %}" | |
193 | 198 | assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) |
194 | 199 | end |
195 | 200 | end |
201 | 206 | @post = setup_post("2018-01-28-closed-liquid-block-excerpt.markdown") |
202 | 207 | @excerpt = @post.data["excerpt"] |
203 | 208 | |
204 | assert_includes @post.content, "{% if" | |
205 | assert_includes @post.content.split("\n\n")[0], "{% endif %}" | |
209 | head = @post.content.split("\n\n")[0] | |
210 | ||
211 | assert_includes @post.content, "{%\n highlight\n" | |
212 | assert_includes @post.content, "{% raw" | |
213 | assert_includes head, "{%\n endraw\n%}" | |
214 | assert_includes head, "{%\n endhighlight\n%}" | |
206 | 215 | end |
207 | 216 | |
208 | 217 | should "not be appended to but generated as is" do |
209 | assert_includes @excerpt.content, "{% endif %}" | |
210 | refute_includes @excerpt.content, "{% endif %}\n\n{% endif %}" | |
218 | assert_includes @excerpt.content, "{%\n endraw\n%}" | |
219 | assert_includes @excerpt.content, "{%\n endhighlight\n%}" | |
220 | refute_includes @excerpt.content, "{%\n endraw\n%}\n\n{% endraw %}" | |
221 | refute_includes @excerpt.content, "{%\n endhighlight\n%}\n\n{% endhighlight %}" | |
211 | 222 | assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) |
212 | 223 | end |
213 | 224 | end |
263 | 274 | assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) |
264 | 275 | end |
265 | 276 | end |
277 | ||
278 | context "An excerpt with Liquid tags" do | |
279 | setup do | |
280 | clear_dest | |
281 | @site = fixture_site | |
282 | @post = setup_post("2018-11-15-excerpt-liquid-block.md") | |
283 | @excerpt = @post.data["excerpt"] | |
284 | ||
285 | assert_includes @post.content.split("\n\n")[0].strip, "{% continue %}" | |
286 | assert_equal true, Jekyll::DoNothingBlock.ancestors.include?(Liquid::Block) | |
287 | assert_equal false, Jekyll::DoNothingOther.ancestors.include?(Liquid::Block) | |
288 | assert_match "Jekyll::DoNothingBlock", Liquid::Template.tags["do_nothing"].name | |
289 | assert_match "Jekyll::DoNothingOther", Liquid::Template.tags["do_nothing_other"].name | |
290 | end | |
291 | ||
292 | should "close open block tags, including custom tags, and ignore others" do | |
293 | assert_includes @excerpt.content, "{% endcase %}" | |
294 | assert_includes @excerpt.content, "{% endif %}" | |
295 | assert_includes @excerpt.content, "{% endfor %}" | |
296 | assert_includes @excerpt.content, "{% endunless %}" | |
297 | assert_includes @excerpt.content, "{% enddo_nothing %}" | |
298 | refute_includes @excerpt.content, "{% enddo_nothing_other %}" | |
299 | assert_equal true, @excerpt.is_a?(Jekyll::Excerpt) | |
300 | end | |
301 | end | |
266 | 302 | end |
15 | 15 | end |
16 | 16 | |
17 | 17 | should "ensure post count is as expected" do |
18 | assert_equal 57, @site.posts.size | |
18 | assert_equal 58, @site.posts.size | |
19 | 19 | end |
20 | 20 | |
21 | 21 | should "insert site.posts into the index" do |
30 | 30 | assert_equal LayoutReader.new(@site).layout_directory, source_dir("blah/_layouts") |
31 | 31 | end |
32 | 32 | end |
33 | ||
34 | context "when a layout is a symlink" do | |
35 | setup do | |
36 | symlink_if_allowed("/etc/passwd", source_dir("_layouts", "symlink.html")) | |
37 | ||
38 | @site = fixture_site( | |
39 | "safe" => true, | |
40 | "include" => ["symlink.html"] | |
41 | ) | |
42 | end | |
43 | ||
44 | teardown do | |
45 | FileUtils.rm_f(source_dir("_layouts", "symlink.html")) | |
46 | end | |
47 | ||
48 | should "only read the layouts which are in the site" do | |
49 | skip_if_windows "Jekyll does not currently support symlinks on Windows." | |
50 | ||
51 | layouts = LayoutReader.new(@site).read | |
52 | ||
53 | refute layouts.key?("symlink"), "Should not read the symlinked layout" | |
54 | end | |
55 | end | |
56 | ||
57 | context "with a theme" do | |
58 | setup do | |
59 | symlink_if_allowed("/etc/passwd", theme_dir("_layouts", "theme-symlink.html")) | |
60 | @site = fixture_site( | |
61 | "include" => ["theme-symlink.html"], | |
62 | "theme" => "test-theme", | |
63 | "safe" => true | |
64 | ) | |
65 | end | |
66 | ||
67 | teardown do | |
68 | FileUtils.rm_f(theme_dir("_layouts", "theme-symlink.html")) | |
69 | end | |
70 | ||
71 | should "not read a symlink'd theme" do | |
72 | skip_if_windows "Jekyll does not currently support symlinks on Windows." | |
73 | ||
74 | layouts = LayoutReader.new(@site).read | |
75 | ||
76 | refute layouts.key?("theme-symlink"), \ | |
77 | "Should not read symlinked layout from theme" | |
78 | end | |
79 | end | |
33 | 80 | end |
34 | 81 | end |
328 | 328 | %(<table class="rouge-table"><tbody>) + |
329 | 329 | %(<tr><td class="gutter gl">) + |
330 | 330 | %(<pre class="lineno">1\n</pre></td>) + |
331 | %(<td class="code"><pre>test</pre></td></tr>) + | |
331 | %(<td class="code"><pre>test\n</pre></td></tr>) + | |
332 | 332 | %(</tbody></table>), |
333 | 333 | @result |
334 | 334 | ) |
475 | 475 | expected = <<-EOS |
476 | 476 | <p>This is not yet highlighted</p>\n |
477 | 477 | <figure class="highlight"><pre><code class="language-php" data-lang="php"><table class="rouge-table"><tbody><tr><td class="gutter gl"><pre class="lineno">1 |
478 | </pre></td><td class="code"><pre><span class="nx">test</span></pre></td></tr></tbody></table></code></pre></figure>\n | |
478 | </pre></td><td class="code"><pre><span class="nx">test</span>\n</pre></td></tr></tbody></table></code></pre></figure>\n | |
479 | 479 | <p>This should not be highlighted, right?</p> |
480 | 480 | EOS |
481 | 481 | assert_match(expected, @result) |
74 | 74 | refute_file_with_relative_path site.pages, "assets/style.scss" |
75 | 75 | end |
76 | 76 | end |
77 | ||
78 | context "symlinked theme" do | |
79 | should "not read assets from symlinked theme" do | |
80 | skip_if_windows "Jekyll does not currently support symlinks on Windows." | |
81 | ||
82 | begin | |
83 | tmp_dir = Dir.mktmpdir("jekyll-theme-test") | |
84 | File.open(File.join(tmp_dir, "test.txt"), "wb") { |f| f.write "content" } | |
85 | ||
86 | theme_dir = File.join(__dir__, "fixtures", "test-theme-symlink") | |
87 | File.symlink(tmp_dir, File.join(theme_dir, "assets")) | |
88 | ||
89 | site = fixture_site( | |
90 | "theme" => "test-theme-symlink", | |
91 | "theme-color" => "black" | |
92 | ) | |
93 | ThemeAssetsReader.new(site).read | |
94 | ||
95 | assert_empty site.static_files, "static file should not have been picked up" | |
96 | ensure | |
97 | FileUtils.rm_rf(tmp_dir) | |
98 | FileUtils.rm_rf(File.join(theme_dir, "assets")) | |
99 | end | |
100 | end | |
101 | end | |
77 | 102 | end |