3 | {{ page.title }}
4 |
5 |
6 | {{ content }}
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | inherit_from: .rubocop_todo.yml
2 |
3 | inherit_gem:
4 | jekyll: .rubocop.yml
5 |
6 | AllCops:
7 | TargetRubyVersion: 2.3
8 | Exclude:
9 | - vendor/**/*
10 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: bundler
4 | directory: "/"
5 | schedule:
6 | interval: daily
7 | time: "04:00"
8 | open-pull-requests-limit: 10
9 |
--------------------------------------------------------------------------------
/spec/fixtures/page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: blah "blah" & blah
3 | description: Some description
4 | layout: default
5 | ---
6 |
7 | # Test
8 |
9 | This contains a [link](http://contentlink1.com). And [another link](https://contentlink2.org).
--------------------------------------------------------------------------------
/script/fmt:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo "Rubocop $(bundle exec rubocop --version)"
4 | bundle exec rubocop -S -D -E $@
5 | success=$?
6 | if ((success != 0)); then
7 | echo -e "\nTry running \`script/fmt -a\` to automatically fix errors"
8 | fi
9 | exit $success
10 |
--------------------------------------------------------------------------------
/_release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # https://github.com/svenfuchs/gem-release
3 |
4 | if [ -z "$1" ]; then
5 | echo "Usage: provide the release type (patch, minor, major)."
6 | exit -1
7 | else
8 | release_type="$@"
9 | fi
10 |
11 | gem bump --version "$release_type" --tag --release
12 |
--------------------------------------------------------------------------------
/RELEASES.md:
--------------------------------------------------------------------------------
1 | # Releases
2 |
3 | ## v3.1.0
4 |
5 | - [Supports Jekyll 4](https://github.com/nhoizey/jekyll-postfiles/commit/9dbb9778fb5cc8036aa819a8476a348a72c10e69)
6 |
7 | ## v3.0.0
8 |
9 | - [Rewrite for Jekyll 3.8.0](https://github.com/nhoizey/jekyll-postfiles/pull/12) by [@Birch-san](https://github.com/Birch-san)
10 | - Match jekyll's coding style thanks to [Rubocop](http://rubocop.readthedocs.io/)
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Because this is a gem, ignore Gemfile.lock:
2 |
3 | Gemfile.lock
4 |
5 | # And because this is Ruby, ignore the following
6 | # (source: https://github.com/github/gitignore/blob/master/Ruby.gitignore):
7 |
8 | *.gem
9 | *.rbc
10 | .bundle
11 | .config
12 | coverage
13 | InstalledFiles
14 | lib/bundler/man
15 | pkg
16 | rdoc
17 | spec/reports
18 | test/tmp
19 | test/version_tmp
20 | tmp
21 | spec/fixtures/.jekyll-cache
22 |
--------------------------------------------------------------------------------
/spec/jekyll_postfiles_spec.rb:
--------------------------------------------------------------------------------
1 | require "spec_helper"
2 |
3 | describe Jekyll::PostFiles do
4 | let(:page) { make_page }
5 | let(:site) { make_site }
6 | let(:post) { make_post }
7 | let(:context) { make_context(:page => page, :site => site) }
8 | let(:url) { "" }
9 |
10 | before do
11 | Jekyll.logger.log_level = :error
12 | site.process
13 | end
14 |
15 | it "copies image from global assets folder" do
16 | expect(Pathname.new(File.expand_path('assets/jekyll.png', dest_dir))).to exist
17 | end
18 |
19 | it "copies image from post folder" do
20 | expect(Pathname.new(File.expand_path('2016/06/09/cloudflare.png', dest_dir))).to exist
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/.rubocop_todo.yml:
--------------------------------------------------------------------------------
1 | # This configuration was generated by
2 | # `rubocop --auto-gen-config`
3 | # on 2018-10-31 10:17:53 +0100 using RuboCop version 0.60.0.
4 | # The point is for the user to remove these configuration records
5 | # one by one as the offenses are removed from the code base.
6 | # Note that changes in the inspected code, or installation of new
7 | # versions of RuboCop, may require this file to be generated again.
8 |
9 | # Offense count: 1
10 | Metrics/AbcSize:
11 | Max: 43
12 |
13 | # Offense count: 11
14 | # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
15 | # URISchemes: http, https
16 | Metrics/LineLength:
17 | Max: 135
18 |
19 | # Offense count: 1
20 | # Configuration parameters: CountComments, ExcludedMethods.
21 | Metrics/MethodLength:
22 | Max: 29
23 |
24 | # Offense count: 1
25 | # Configuration parameters: CountKeywordArgs.
26 | Metrics/ParameterLists:
27 | Max: 5
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Nicolas Hoizey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/jekyll-postfiles.gemspec:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | $LOAD_PATH.unshift(File.expand_path("lib", __dir__))
4 | require "jekyll/postfiles/version"
5 |
6 | Gem::Specification.new do |spec|
7 | spec.version = Jekyll::PostFiles::VERSION
8 | spec.homepage = "https://nhoizey.github.io/jekyll-postfiles/"
9 | spec.authors = ["Nicolas Hoizey"]
10 | spec.email = ["nicolas@hoizey.com"]
11 | spec.files = %w(Rakefile Gemfile README.md RELEASES.md LICENSE) + Dir["lib/**/*"]
12 | spec.summary = "A Jekyll plugin to keep posts assets alongside their Markdown files"
13 | spec.name = "jekyll-postfiles"
14 | spec.license = "MIT"
15 | spec.require_paths = ["lib"]
16 | spec.description = <<-DESC
17 | This plugin takes any file that is in posts folders, and copy them to the folder in which the post HTML page will be created.
18 | DESC
19 |
20 | spec.required_ruby_version = ">= 2.3.0"
21 |
22 | spec.add_runtime_dependency "jekyll", ">= 3.8.6", "< 5"
23 |
24 | spec.add_development_dependency "bundler", "~> 2.1.4"
25 | spec.add_development_dependency "rake", "~> 13.0"
26 | spec.add_development_dependency "rubocop", "~> 0.76.0"
27 | spec.add_development_dependency "rspec", "~> 3.5"
28 | spec.add_development_dependency "kramdown-parser-gfm", "~> 1.1.0"
29 | end
30 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
2 | require "jekyll"
3 | require "jekyll-postfiles"
4 |
5 | ENV["JEKYLL_LOG_LEVEL"] = "error"
6 |
7 | def dest_dir
8 | File.expand_path("../tmp/dest", __dir__)
9 | end
10 |
11 | def source_dir
12 | File.expand_path("fixtures", __dir__)
13 | end
14 |
15 | CONFIG_DEFAULTS = {
16 | "source" => source_dir,
17 | "destination" => dest_dir,
18 | "gems" => ["jekyll-postfiles"],
19 | }.freeze
20 |
21 | def make_page(options = {})
22 | page = Jekyll::Page.new site, CONFIG_DEFAULTS["source"], "", "page.md"
23 | page.data = options
24 | page
25 | end
26 |
27 | def make_post(options = {})
28 | filename = File.expand_path("_posts/2016-06-09-cloudflare/2016-06-09-so-long-cloudflare-and-thanks-for-all-the-fissh.md", CONFIG_DEFAULTS["source"])
29 | config = { :site => site, :collection => site.collections["posts"] }
30 | page = Jekyll::Document.new filename, config
31 | page.merge_data!(options)
32 | page
33 | end
34 |
35 | def make_site(options = {})
36 | config = Jekyll.configuration CONFIG_DEFAULTS.merge(options)
37 | Jekyll::Site.new(config)
38 | end
39 |
40 | def make_context(registers = {}, environments = {})
41 | Liquid::Context.new(environments, {}, { :site => site, :page => page }.merge(registers))
42 | end
43 |
--------------------------------------------------------------------------------
/spec/fixtures/_posts/2016-06-09-example/2016-06-09-example.md:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | title: Example
4 | ---
5 |
6 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nec lorem arcu. Duis ac interdum mauris, id ultricies neque. Phasellus sagittis viverra dui, vitae pellentesque libero consequat commodo. Pellentesque sodales augue eu tincidunt lacinia. Mauris ligula leo, dictum non enim nec, efficitur consectetur dui. Donec vitae eros augue. Sed ex ex, scelerisque eget nunc ut, sodales pharetra quam.
7 |
8 | 
9 |
10 | Mauris sed elementum velit, nec suscipit diam. In varius ultricies urna, et ornare lorem consectetur ac. Maecenas sed urna tortor. Sed sed risus laoreet, sodales mi in, condimentum sapien. Etiam consequat fermentum luctus. Duis porttitor mattis euismod. Morbi ullamcorper et sem eu tristique.
11 |
12 | 
13 |
14 | Integer lorem tellus, luctus sed feugiat a, efficitur eu orci. Proin accumsan lorem et hendrerit fermentum. Donec egestas dolor ac rutrum volutpat. Donec quam dolor, mattis at interdum non, convallis at nulla. Integer ultrices turpis ut scelerisque malesuada. Suspendisse quis rutrum lacus. Suspendisse vel eros tempus, bibendum magna a, tincidunt metus. Etiam id ante non nisl rutrum pulvinar. Curabitur turpis lorem, euismod at accumsan nec, aliquet at ligula. Proin iaculis diam bibendum felis ultrices, in accumsan nibh porttitor. Mauris pretium odio purus, ut vestibulum odio sodales vitae. Donec iaculis ex vel consectetur lacinia.
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribute
2 |
3 | ## Introduction
4 |
5 | First, thank you for considering contributing to jekyll-postfiles! It's people like you that make the open source community such a great community! 😊
6 |
7 | We welcome any type of contribution, not only code. You can help with
8 |
9 | * **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)
10 | * **Marketing**: writing blog posts, howto's, printing stickers, ...
11 | * **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...
12 | * **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them.
13 |
14 | ## Your First Contribution
15 |
16 | Working on your first Pull Request? You can learn how from this _free_ series, [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github).
17 |
18 | ## Submitting code
19 |
20 | Any code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests.
21 |
22 | ## Code review process
23 |
24 | The bigger the pull request, the longer it will take to review and merge. Try to [break down large pull requests in smaller chunks](https://oncletom.io/2013/the-55-commits-syndrome/) that are easier to review and merge.
25 |
26 | It is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?
27 |
28 | ## Questions
29 |
30 | If you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).
31 |
32 | ## Credits
33 |
34 | ### Contributors
35 |
36 | Thank you to [all the people who have already contributed](https://github.com/nhoizey/jekyll-postfiles/graphs/contributors) to jekyll-postfiles!
37 |
38 |
39 |
--------------------------------------------------------------------------------
/lib/jekyll/postfiles.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require "jekyll"
4 | require "pathname"
5 |
6 | module Jekyll
7 | module PostFiles
8 |
9 | # there's a bug in the regex Document::DATE_FILENAME_MATCHER:
10 | # %r!^(?:.+/)*(\d{2,4}-\d{1,2}-\d{1,2})-(.*)(\.[^.]+)$!
11 | # used by:
12 | # jekyll/lib/jekyll/readers/post_reader.rb#read_posts
13 | # which ultimately populates:
14 | # site.posts.docs
15 | #
16 | # the original code's intention was to match:
17 | # all files with a date in the name
18 | # but it accidentally matches also:
19 | # all files immediately within a directory whose name contains a date
20 | #
21 | # our plugin changes the regex, to:
22 | # avoid false positive when directory name matches date regex
23 | Hooks.register :site, :after_reset do |_site|
24 | # Suppress warning messages.
25 | original_verbose = $VERBOSE
26 | $VERBOSE = nil
27 | Document.const_set("DATE_FILENAME_MATCHER", PostFileGenerator::FIXED_DATE_FILENAME_MATCHER)
28 | # Activate warning messages again.
29 | $VERBOSE = original_verbose
30 | end
31 |
32 | class PostFile < StaticFile
33 | # Initialize a new PostFile.
34 | #
35 | # site - The Site.
36 | # base - The String path to the - /srv/jekyll
37 | # dir - The String path between and the file - _posts/somedir
38 | # name - The String filename of the file - cool.svg
39 | # dest - The String path to the containing folder of the document which is output - /dist/blog/[:tag/]*:year/:month/:day
40 | def initialize(site, base, dir, name, dest)
41 | super(site, base, dir, name)
42 | @name = name
43 | @dest = dest
44 | end
45 |
46 | # Obtain destination path.
47 | #
48 | # dest - The String path to the destination dir.
49 | #
50 | # Returns destination file path.
51 | def destination(_dest)
52 | File.join(@dest, @name)
53 | end
54 | end
55 |
56 | class PostFileGenerator < Generator
57 | FIXED_DATE_FILENAME_MATCHER = %r!^(?:.+/)*(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)(\.[^.]+)$!.freeze
58 |
59 | # _posts/
60 | # 2018-01-01-whatever.md # there's a date on this filename, so it will be treated as a post
61 | # # it's a direct descendant of _posts, so we do not treat it as an asset root
62 | # somedir/
63 | # 2018-05-01-some-post.md # there's a date on this filename, so it will be treated as a post.
64 | # # moreover, we will treat its dir as an asset root
65 | # cool.svg # there's no date on this filename, so it will be treated as an asset
66 | # undated.md # there's no date on this filename, so it will be treated as an asset
67 | # img/
68 | # cool.png # yes, even deeply-nested files are eligible to be copied.
69 | def generate(site)
70 | site_srcroot = Pathname.new site.source
71 | posts_src_dir = site_srcroot + "_posts"
72 | drafts_src_dir = site_srcroot + "_drafts"
73 |
74 | # Jekyll.logger.warn("[PostFiles]", "_posts: #{posts_src_dir}")
75 | # Jekyll.logger.warn("[PostFiles]", "docs: #{site.posts.docs.map(&:path)}")
76 |
77 | docs_with_dirs = site.posts.docs
78 | .reject do |doc|
79 | Pathname.new(doc.path).dirname.instance_eval do |dirname|
80 | [posts_src_dir, drafts_src_dir].reduce(false) do |acc, dir|
81 | acc || dirname.eql?(dir)
82 | end
83 | end
84 | end
85 |
86 | # Jekyll.logger.warn("[PostFiles]", "postdirs: #{docs_with_dirs.map{|doc| Pathname.new(doc.path).dirname}}")
87 |
88 | assets = docs_with_dirs.map do |doc|
89 | dest_dir = Pathname.new(doc.destination("")).dirname
90 | Pathname.new(doc.path).dirname.instance_eval do |postdir|
91 | Dir[postdir + "**/*"]
92 | .reject { |fname| fname =~ FIXED_DATE_FILENAME_MATCHER }
93 | .reject { |fname| File.directory? fname }
94 | .map do |fname|
95 | asset_abspath = Pathname.new fname
96 | srcroot_to_asset = asset_abspath.relative_path_from(site_srcroot)
97 | srcroot_to_assetdir = srcroot_to_asset.dirname
98 | asset_basename = srcroot_to_asset.basename
99 |
100 | assetdir_abs = site_srcroot + srcroot_to_assetdir
101 | postdir_to_assetdir = assetdir_abs.relative_path_from(postdir)
102 | PostFile.new(site, site_srcroot, srcroot_to_assetdir.to_path, asset_basename, (dest_dir + postdir_to_assetdir).to_path)
103 | end
104 | end
105 | end.flatten
106 |
107 | site.static_files.concat(assets)
108 | end
109 | end
110 | end
111 | end
112 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jekyll-postfiles
2 |
3 | [](https://badge.fury.io/rb/jekyll-postfiles)
4 | [](http://rubygems.org/gems/jekyll-postfiles)
5 | [](https://travis-ci.org/nhoizey/jekyll-postfiles)
6 |
7 |
8 |
9 |
10 |
11 | - [Easing the management of images (and other files) attached to Markdown posts](#easing-the-management-of-images-and-other-files-attached-to-markdown-posts)
12 | - [The pain of Jekyll's recommended posts assets management](#the-pain-of-jekylls-recommended-posts-assets-management)
13 | - [There must be another way](#there-must-be-another-way)
14 | - [Not every assets need this](#not-every-assets-need-this)
15 | - [How does it work?](#how-does-it-work)
16 | - [Installation](#installation)
17 | - [Usage](#usage)
18 | - [Contributing](#contributing)
19 | - [License](#license)
20 | - [Thanks](#thanks)
21 |
22 |
23 |
24 | ## Easing the management of images (and other files) attached to Markdown posts
25 |
26 | ### The pain of Jekyll's recommended posts assets management
27 |
28 | Jekyll's natural way to deal with static files attached to posts, like images or PDFs, is to put them all in a global `assets/` (or `downloads/`) folder at the site root. Read "[Including images and resources](https://jekyllrb.com/docs/posts/#including-images-and-resources)" in Jekyll's documentation.
29 |
30 | You can of course put files in subfolders of `assets/`, but it will be really cumbersome to manage posts' Markdown files in `_posts/` or a subfolder, and images elsewhere, and then use the good hierarchy in all Markdown image tags.
31 |
32 | Imagine you have these files:
33 |
34 | ```
35 | _posts/
36 | 2016-06/
37 | 2016-06-09-so-long-cloudflare-and-thanks-for-all-the-fissh.md
38 | …
39 | assets/
40 | 2016-06-09-cloudflare/
41 | cloudflare-architecture.png
42 | performance-report-sample.pdf
43 | ```
44 |
45 | To use the image and PDF files in the post's Markdown, you will have to write this:
46 |
47 | ```markdown
48 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
49 | tempor incididunt ut labore et dolore magna aliqua.
50 |
51 | 
52 |
53 | Ut enim ad minim veniam,
54 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
55 | consequat.
56 |
57 | Here is [an example of performance report](/assets/2016-06-09-cloudflare/performance-report-sample.pdf).
58 |
59 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
60 | tempor incididunt ut labore et dolore magna aliqua.
61 | ```
62 |
63 | Painful to write.
64 |
65 | Imagine you want to change the post's publication date, or one of the file names?
66 |
67 | Painful to update.
68 |
69 | What if you want to put new WIP Markdown files in `_drafts/`, and the attached assets somewhere in a way they won't be copied to the destination `_site/` folder next time you build the site? You can't put the files in the `assets/` folder, so when you will publish the draft, you will have to change the assets location in the Markdown file.
70 |
71 | Painful, and prone to errors.
72 |
73 | And what about previewing the content while editing? If you use an editor like [MacDown](http://macdown.uranusjr.com/) with live preview, how will it find the actual path to the images? What means `/assets/…` for the editor?
74 |
75 | Painful to preview.
76 |
77 | ### There must be another way
78 |
79 | What if instead, you could have the files stored like that:
80 |
81 | ```
82 | _posts/
83 | 2016-06-09-cloudflare/
84 | 2016-06-09-so-long-cloudflare-and-thanks-for-all-the-fissh.md
85 | cloudflare-architecture.png
86 | performance-report-sample.pdf
87 | ```
88 |
89 | And if you could write your Markdown like this:
90 |
91 | ```markdown
92 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
93 | tempor incididunt ut labore et dolore magna aliqua.
94 |
95 | 
96 |
97 | Ut enim ad minim veniam,
98 | quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
99 | consequat.
100 |
101 | Here is [an example of performance report](performance-report-sample.pdf).
102 |
103 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
104 | tempor incididunt ut labore et dolore magna aliqua.
105 | ```
106 |
107 | Much easier!
108 |
109 | - Easy to store, everything is in one single folder.
110 | - Easy to write, no path to add to file links
111 | - Easy to update
112 | - Easy to move from `_drafts/` to `_posts/`, without anything to change in the Markdown content
113 | - Easy to edit in any editor with live preview
114 |
115 | ### Not every assets need this
116 |
117 | [Some Jekyll users will try to convince you](http://stackoverflow.com/a/10366173/717195) it's a bad idea, because it means the asset is tightly linked to the post.
118 |
119 | In my own experience, 95% of assets, at least, are used in one single post. And this is pretty common to find such requests from users of other static generators, like [Hugo](https://github.com/spf13/hugo/issues/147) ([fixed in May 2015](https://github.com/spf13/hugo/issues/147#issuecomment-104067783)), [Nikola](https://github.com/getnikola/nikola/issues/2266) ([already there, but not obvious or user friendly](https://github.com/getnikola/nikola/issues/2266#issuecomment-189211387)), [Octopress](http://stackoverflow.com/questions/17052468/insert-local-image-into-a-blog-post-with-octopress), etc.
120 |
121 | But it's true this might not be ideal for all assets (the remaining 5%), so you can of course continue using full assets paths with `/assets/…` to have a few assets shared by several posts.
122 |
123 | ## How does it work?
124 |
125 | This plugin takes any file that is in posts folders, and copy them to the folder in which the post HTML page will be created.
126 |
127 | Let's say you have these files:
128 |
129 | ```
130 | _posts/
131 | 2016-06-09-cloudflare/
132 | 2016-06-09-so-long-cloudflare-and-thanks-for-all-the-fissh.md
133 | cloudflare-architecture.png
134 | performance-report-sample.pdf
135 | ```
136 |
137 | And your Jekyll settings for permalinks are these:
138 |
139 | ```yaml
140 | # Permalinks
141 | permalink: /:year/:month/:day/:title/
142 | ```
143 |
144 | Jekyll with this plugin will generate the site content like this:
145 |
146 | ```
147 | 2016/
148 | 06/
149 | 09/
150 | so-long-cloudflare-and-thanks-for-all-the-fissh/
151 | index.html
152 | cloudflare-logo.png
153 | performance-report-sample.pdf
154 | ```
155 |
156 | If you change your Jekyll settings for permalinks like these:
157 |
158 | ```yaml
159 | # Permalinks
160 | permalink: /:year/:month/:day/:title.html
161 | ```
162 |
163 | Jekyll with this plugin will generate the site content like this:
164 |
165 | ```
166 | 2016/
167 | 06/
168 | 09/
169 | so-long-cloudflare-and-thanks-for-all-the-fissh.html
170 | cloudflare-logo.png
171 | performance-report-sample.pdf
172 | ```
173 |
174 | Handy, isn't it?
175 |
176 | ## Installation
177 |
178 | Add `gem 'jekyll-postfiles'` to the `jekyll_plugin` group in your `Gemfile`:
179 |
180 | ```ruby
181 | source 'https://rubygems.org'
182 |
183 | gem 'jekyll'
184 |
185 | group :jekyll_plugins do
186 | gem 'jekyll-postfiles'
187 | end
188 | ```
189 |
190 | Then run `bundle` to install the gem.
191 |
192 | ## Usage
193 |
194 | You don't have anything to do.
195 |
196 | Just put the images (and PDFs, etc.) in the same folder as your Markdown files, or even subfolders, and use the standard Markdown image syntax, with a relative path.
197 |
198 | ## Compatibility
199 |
200 | :warning: This plugin is not supported by Github Pages, host your site on services like https://netlify.com which support third party plugins.
201 |
202 | ## Contributing
203 |
204 | Thanks for your interest in contributing! There are many ways to contribute to this project. [Get started here](https://github.com/nhoizey/jekyll-postfiles/blob/master/CONTRIBUTING.md).
205 |
206 | ## License
207 |
208 | The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
209 |
210 | ## Thanks
211 |
212 | Inspired by [this old Gist](https://gist.github.com/kevinoid/3131752) by [@kevinoid](https://github.com/kevinoid/).
213 |
214 |
--------------------------------------------------------------------------------