├── .gitignore
├── LICENSE
├── README.md
├── asset_path_tag.rb
├── icon.png
└── test_site
├── Gemfile
├── Gemfile.lock
├── _another_collection
└── Another.markdown
├── _config.yml
├── _plugins
└── asset_path_tag.rb
├── _posts
├── 2000-01-02-Another_page.markdown
└── 2017-01-14-tests.markdown
├── _test_collection
└── Test_collection_item.markdown
├── assets
├── another_collection
│ └── Another
│ │ ├── another with space.png
│ │ └── another.png
├── error.png
├── nonpost_tests
│ ├── nonpost with space.png
│ └── nonpost.png
├── posts
│ ├── Another_page
│ │ ├── another page with space.png
│ │ └── another-page.png
│ └── tests
│ │ ├── this page with space.png
│ │ └── this-page.png
└── test_collection
│ └── Test_collection_item
│ ├── this collection item with space.png
│ └── this-collection-item.png
├── index.html
└── nonpost_tests.markdown
/.gitignore:
--------------------------------------------------------------------------------
1 | test_site/_site
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Sam Rayner
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | 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, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Jekyll Asset Path Tag
2 | =====================
3 |
4 |
5 |
6 | A liquid tag to output a relative URL for assets based on the post or page, allowing you to organise your assets into subdirectories.
7 |
8 | Syntax:
9 | ```
10 | {% asset_path filename %}
11 | {% asset_path filename post_id %}
12 | {% asset_path "filename with whitespace" post_id %}
13 | {% asset_path filename /collection_label/post_id %}
14 | ```
15 |
16 | ## Installation
17 | Copy asset_path_tag.rb into */_plugins* ([Jekyll][j]) or */plugins* ([Octopress][o])
18 |
19 | ## Examples
20 |
21 | ### Asset of this post
22 |
23 | ```
24 | {% asset_path my-image.png %}
25 | ```
26 | in post 2013-01-01-post-title would output:
27 | ```
28 | /assets/posts/post-title/my-image.png
29 | ```
30 | in page my-first-page would output:
31 | ```
32 | /assets/my-first-page/my-image.png
33 | ```
34 |
35 | ### Asset of another post
36 |
37 | ```
38 | {% asset_path document.pdf /2012/05/25/another-post-title %}
39 | ```
40 | would output:
41 | ```
42 | /assets/posts/another-post-title/document.pdf
43 | ```
44 |
45 | ### Asset of document in a collection
46 |
47 | ```
48 | {% asset_path image.jpg /my_collection/document_in_collection %}
49 | ```
50 | would output:
51 | ```
52 | /assets/my_collection/document_in_collection/image.jpg
53 | ```
54 |
55 | ## Uses
56 |
57 | Useful for images and links in Markdown or HTML:
58 | ```
59 | [Download script]({% asset_path my-script.js %})
60 |
61 | ```
62 |
63 | Given file _data/image.csv contains:
64 | ```csv
65 | file
66 | image_one.png
67 | image_two.png
68 | ```
69 | and post 2015-03-21-another-post-title contains:
70 | ```liquid
71 | {% for image in site.data.images %}
72 | {% asset_path {{ image.file }} %}
73 | {% endfor %}
74 | ```
75 | then the tag will output:
76 | ```text
77 | /assets/posts/another-post-title/image_one.png
78 | /assets/posts/another-post-title/image_two.png
79 | ```
80 |
81 | When used with `post_id` parameter, the tag is useful for showing asset from each page. Given the site contains pages:
82 | ```
83 | post-title
84 | another-post-title
85 | ```
86 | then
87 | ```
88 | {% for post in site.posts %}{% asset_path cover.jpg {{post.id}} %}{% endfor %}
89 | ```
90 | on index.html will output:
91 | ```
92 | /assets/posts/post-title/cover.jpg
93 | /assets/posts/another-post-title/cover.jpg
94 | ```
95 |
96 | [j]: http://jekyllrb.com/
97 | [o]: http://octopress.org/
98 |
99 | ## Testing
100 | The plugin can be tested by using the Jekyll test site in `test_site` directory. Generate the site with
101 | ```
102 | bundle exec jekyll serve
103 | ```
104 | then check the test results by browsing to [http://localhost:4000][test_site].
105 |
106 | [test_site]: http://localhost:4000
107 |
--------------------------------------------------------------------------------
/asset_path_tag.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | # rubocop: disable Metrics/LineLength
4 |
5 | # Title: Asset path tag for Jekyll
6 | # Authors:
7 | # Sam Rayner http://samrayner.com
8 | # Otto Urpelainen http://koti.kapsi.fi/oturpe/projects/
9 | #
10 | # Description: Output a relative URL for assets based on the post or page
11 | #
12 | # Syntax
13 | # {% asset_path filename post_id %}
14 | # {% asset_path "filename with whitespace" post_id %}
15 | #
16 | # Examples:
17 | # {% asset_path kitten.png %} on post 2013-01-01-post-title
18 | # {% asset_path pirate.mov %} on page page-title
19 | # {% asset_path document.pdf /2012/05/25/another-post-title %}
20 | # {% asset_path "document with spaces in name.pdf" /2012/05/25/another-post-title %}
21 | # {% asset_path image.jpg /my_collection/document_in_collection %}
22 | #
23 | # Output:
24 | # /assets/posts/post-title/kitten.png
25 | # /assets/page-title/pirate.mov
26 | # /assets/posts/another-post-title/document.pdf
27 | # /assets/posts/another-post-title/document with spaces in name.pdf
28 | # /assets/my_collection/document_in_collection/image.jpg
29 | #
30 | # Looping example using a variable for the pathname:
31 | #
32 | # File _data/image.csv contains:
33 | # file
34 | # image_one.png
35 | # image_two.png
36 | #
37 | # {% for image in site.data.images %}{% asset_path {{ image.file }} %}{% endfor %} on post 2015-03-21-post-title
38 | #
39 | # Output:
40 | # /assets/posts/post-title/image_one.png
41 | # /assets/posts/post-title/image_two.png
42 | #
43 | # Looping example over posts:
44 | #
45 | # Site contains posts:
46 | # post-title
47 | # another-post-title
48 | #
49 | # {% for post in site.posts %}{% asset_path cover.jpg {{post.id}} %}{% endfor %} on index.html
50 | #
51 | # Output:
52 | # /assets/posts/post-title/cover.jpg
53 | # /assets/posts/another-post-title/cover.jpg
54 |
55 | # rubocop: enable Metrics/LineLength
56 |
57 | # Jekyll plugin.
58 | module Jekyll
59 | def self.get_post_path(page_id, collections)
60 | #loop through all collections to find the matching document and get its slug
61 | collections.each do |collection|
62 | doc = collection.docs.find { |doc| doc.id == page_id }
63 | if doc != nil
64 | slug = Jekyll::VERSION >= '3.0.0' ? doc.data["slug"] : doc.slug
65 | return "#{collection.label}/#{slug}"
66 | end
67 | end
68 |
69 | ''
70 | end
71 |
72 | # Returns the path to the specified asset.
73 | class AssetPathTag < Liquid::Tag
74 | @markup = nil
75 |
76 | def initialize(tag_name, markup, tokens)
77 | # strip leading and trailing spaces
78 | @markup = markup.strip
79 | super
80 | end
81 |
82 | def render(context)
83 | if @markup.empty?
84 | return 'Error processing input, expected syntax: ' \
85 | '{% asset_path filename post_id %}'
86 | end
87 |
88 | # render the markup
89 | filename, post_id = parse_parameters context
90 | path = post_path context, post_id
91 |
92 | # strip filename
93 | path = File.dirname(path) if path =~ /\.\w+$/
94 |
95 | # fix double slashes
96 | "#{context.registers[:site].config['baseurl']}/assets/#{path}/#{filename}"
97 | .gsub(%r{/{2,}}, '/')
98 | end
99 |
100 | private
101 |
102 | def parse_parameters(context)
103 | parameters = Liquid::Template.parse(@markup).render context
104 | parameters.strip!
105 |
106 | if ['"', "'"].include? parameters[0]
107 | # Quoted filename, possibly followed by post id
108 | last_quote_index = parameters.rindex(parameters[0])
109 | filename = parameters[1...last_quote_index]
110 | post_id = parameters[(last_quote_index + 1)..-1].strip
111 | return filename, post_id
112 | end
113 | # Unquoted filename, possibly followed by post id
114 | parameters.split(/\s+/)
115 | end
116 |
117 | def post_path(context, post_id)
118 | page = context.environments.first['page']
119 |
120 | post_id = page['id'] if post_id.nil? || post_id.empty?
121 | if post_id
122 | # Posts as well as documents in other collections have a post_id
123 | collections = context.registers[:site].collections.map { |c| c[1] }
124 | Jekyll.get_post_path(post_id, collections)
125 | else
126 | page['url']
127 | end
128 | end
129 | end
130 | end
131 |
132 | Liquid::Template.register_tag('asset_path', Jekyll::AssetPathTag)
133 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/icon.png
--------------------------------------------------------------------------------
/test_site/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'jekyll', '~> 3.8.6'
4 | gem 'json'
5 | gem 'stringex'
6 | gem 'rmagick', '~>4.0.0'
7 |
--------------------------------------------------------------------------------
/test_site/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: https://rubygems.org/
3 | specs:
4 | addressable (2.6.0)
5 | public_suffix (>= 2.0.2, < 4.0)
6 | colorator (1.1.0)
7 | concurrent-ruby (1.1.5)
8 | em-websocket (0.5.1)
9 | eventmachine (>= 0.12.9)
10 | http_parser.rb (~> 0.6.0)
11 | eventmachine (1.2.7)
12 | ffi (1.11.1)
13 | forwardable-extended (2.6.0)
14 | http_parser.rb (0.6.0)
15 | i18n (0.9.5)
16 | concurrent-ruby (~> 1.0)
17 | jekyll (3.8.6)
18 | addressable (~> 2.4)
19 | colorator (~> 1.0)
20 | em-websocket (~> 0.5)
21 | i18n (~> 0.7)
22 | jekyll-sass-converter (~> 1.0)
23 | jekyll-watch (~> 2.0)
24 | kramdown (~> 1.14)
25 | liquid (~> 4.0)
26 | mercenary (~> 0.3.3)
27 | pathutil (~> 0.9)
28 | rouge (>= 1.7, < 4)
29 | safe_yaml (~> 1.0)
30 | jekyll-sass-converter (1.5.2)
31 | sass (~> 3.4)
32 | jekyll-watch (2.2.1)
33 | listen (~> 3.0)
34 | json (2.2.0)
35 | kramdown (1.17.0)
36 | liquid (4.0.3)
37 | listen (3.1.5)
38 | rb-fsevent (~> 0.9, >= 0.9.4)
39 | rb-inotify (~> 0.9, >= 0.9.7)
40 | ruby_dep (~> 1.2)
41 | mercenary (0.3.6)
42 | pathutil (0.16.2)
43 | forwardable-extended (~> 2.6)
44 | public_suffix (3.1.1)
45 | rb-fsevent (0.10.3)
46 | rb-inotify (0.10.0)
47 | ffi (~> 1.0)
48 | rmagick (4.0.0)
49 | rouge (3.5.1)
50 | ruby_dep (1.5.0)
51 | safe_yaml (1.0.5)
52 | sass (3.7.4)
53 | sass-listen (~> 4.0.0)
54 | sass-listen (4.0.0)
55 | rb-fsevent (~> 0.9, >= 0.9.4)
56 | rb-inotify (~> 0.9, >= 0.9.7)
57 | stringex (2.8.5)
58 |
59 | PLATFORMS
60 | ruby
61 |
62 | DEPENDENCIES
63 | jekyll (~> 3.8.6)
64 | json
65 | rmagick (~> 4.0.0)
66 | stringex
67 |
68 | BUNDLED WITH
69 | 2.0.2
70 |
--------------------------------------------------------------------------------
/test_site/_another_collection/Another.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Another document in collection"
3 | ---
4 | Another item in test collection to refer to.
5 |
--------------------------------------------------------------------------------
/test_site/_config.yml:
--------------------------------------------------------------------------------
1 | # Welcome to Jekyll!
2 | #
3 | # This config file is meant for settings that affect your whole blog, values
4 | # which you are expected to set up once and rarely edit after that. If you find
5 | # yourself editing these this file very often, consider using Jekyll's data files
6 | # feature for the data you need to update frequently.
7 | #
8 | # For technical reasons, this file is *NOT* reloaded automatically when you use
9 | # 'jekyll serve'. If you change this file, please restart the server process.
10 |
11 | # Site settings
12 | # These are used to personalize your new site. If you look in the HTML files,
13 | # you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
14 | # You can create any custom variable you would like, and they will be accessible
15 | # in the templates via {{ site.myvariable }}.
16 | title: jekyll-asset-path-plugin test site
17 | email: otto.urpelainen@iki.fi
18 | description: > # this means to ignore newlines until "baseurl:"
19 | Test site for jekyll-asset-path-plugin
20 | baseurl: "" # the subpath of your site, e.g. /blog
21 | url: "http://example.com" # the base hostname & protocol for your site
22 |
23 | collections:
24 | test_collection:
25 | output: true
26 | another_collection:
27 | output: true
28 |
29 | # Build settings
30 | markdown: kramdown
31 |
--------------------------------------------------------------------------------
/test_site/_plugins/asset_path_tag.rb:
--------------------------------------------------------------------------------
1 | ../../asset_path_tag.rb
--------------------------------------------------------------------------------
/test_site/_posts/2000-01-02-Another_page.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Another page"
3 | date: 2000-01-02 10:50:12 +0200
4 | ---
5 | Another page to reference to.
6 |
--------------------------------------------------------------------------------
/test_site/_posts/2017-01-14-tests.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: "jekyll-thumbnail-generator tests"
3 | date: 2017-01-14 10:50:12 +0200
4 | ---
5 | Page tests.
6 |
7 | ## This page
8 |
9 | ### Unquoted: this-page.png
10 | 
11 |
12 | ### Double quotes: "this-page.png"
13 | 
14 |
15 | ### Single quotes: 'this-page.png'
16 | 
17 |
18 | ### Quoted with spaces: "this page with space.png"
19 | 
20 |
21 | ### Single quotes with spaces: 'this page with space.png'
22 | 
23 |
24 | ## Other page
25 |
26 | ### Unquoted: another-page.png /2000/01/02/Another_page
27 | 
28 |
29 | ### Double quotes: "another-page.png" /2000/01/02/Another_page
30 | 
31 |
32 | ### Single quotes: 'another-page.png' /2000/01/02/Another_page
33 | 
34 |
35 | ### Double quotes with space: "another page with space.png" /2000/01/02/Another_page
36 | 
37 |
38 | ### Single quotes with space: 'another page with space.png' /2000/01/02/Another_page
39 | 
40 |
41 |
42 |
--------------------------------------------------------------------------------
/test_site/_test_collection/Test_collection_item.markdown:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Test collection item"
3 | ---
4 |
5 | Test collection document.
6 |
7 | ## This document
8 |
9 | ### Unquoted: this-collection-item.png
10 | 
11 |
12 | ### Double quotes: "this-collection-item.png"
13 | 
14 |
15 | ### Single quotes: 'this-collection-item.png'
16 | 
17 |
18 | ### Quoted with spaces: "this collection item with space.png"
19 | 
20 |
21 | ### Single quotes with spaces: 'this collection item with space.png'
22 | 
23 |
24 | ## Document in default collection 'posts'
25 |
26 | ### Unquoted: another-page.png /2000/01/02/Another_page
27 | 
28 |
29 | ### Double quotes: "another-page.png" /2000/01/02/Another_page
30 | 
31 |
32 | ### Single quotes: 'another-page.png' /2000/01/02/Another_page
33 | 
34 |
35 | ### Double quotes with space: "another page with space.png" /2000/01/02/Another_page
36 | 
37 |
38 | ### Single quotes with space: 'another page with space.png' /2000/01/02/Another_page
39 | 
40 |
41 | ## Document in another collection
42 |
43 | ### Unquoted: another.png /another_collection/Another
44 | 
45 |
46 | ### Double quotes: "another.png" /another_collection/Another
47 | 
48 |
49 | ### Single quotes: 'another.png' /another_collection/Another
50 | 
51 |
52 | ### Double quotes with space: "another with space.png" /another_collection/Another
53 | 
54 |
55 | ### Single quotes with space: 'another with space.png' /another_collection/Another
56 | 
57 |
--------------------------------------------------------------------------------
/test_site/assets/another_collection/Another/another with space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/another_collection/Another/another with space.png
--------------------------------------------------------------------------------
/test_site/assets/another_collection/Another/another.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/another_collection/Another/another.png
--------------------------------------------------------------------------------
/test_site/assets/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/error.png
--------------------------------------------------------------------------------
/test_site/assets/nonpost_tests/nonpost with space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/nonpost_tests/nonpost with space.png
--------------------------------------------------------------------------------
/test_site/assets/nonpost_tests/nonpost.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/nonpost_tests/nonpost.png
--------------------------------------------------------------------------------
/test_site/assets/posts/Another_page/another page with space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/posts/Another_page/another page with space.png
--------------------------------------------------------------------------------
/test_site/assets/posts/Another_page/another-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/posts/Another_page/another-page.png
--------------------------------------------------------------------------------
/test_site/assets/posts/tests/this page with space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/posts/tests/this page with space.png
--------------------------------------------------------------------------------
/test_site/assets/posts/tests/this-page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/posts/tests/this-page.png
--------------------------------------------------------------------------------
/test_site/assets/test_collection/Test_collection_item/this collection item with space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/test_collection/Test_collection_item/this collection item with space.png
--------------------------------------------------------------------------------
/test_site/assets/test_collection/Test_collection_item/this-collection-item.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/samrayner/jekyll-asset-path-plugin/aa25a7c96ae69657cac8b3ea2c9e04254a2ea630/test_site/assets/test_collection/Test_collection_item/this-collection-item.png
--------------------------------------------------------------------------------
/test_site/index.html:
--------------------------------------------------------------------------------
1 | ---
2 | ---
3 |
4 |
12 | Non-post tests 13 |
14 | Post tests 15 |
16 | Collection tests 17 |