├── _layouts └── category_archive.html ├── README.md └── _plugins └── category_archive_plugin.rb /_layouts/category_archive.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 |
5 |
6 | Category archive for {{ page.category }} 7 |
8 |
9 | 12 |
13 |
14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Category archive plugin for Jekyll 2 | 3 | Generate a category archive like MovableType does. 4 | 5 | This code is based on following hacks: 6 | 7 | - https://gist.github.com/ilkka/707909 8 | - https://gist.github.com/ilkka/707020 9 | - https://gist.github.com/nlindley/6409459 10 | 11 | 12 | # Installation 13 | 14 | To use this plugin, 15 | 16 | - Place the file `category_archive_plugin.rb` into `_plugins` 17 | directory of Jekyll site working directory. 18 | 19 | - Copy `_layouts/category_archive.html` into `_layouts` directory of 20 | Jekyll site working directory, then edit it appropriately. 21 | 22 | 23 | # Parameter configuration 24 | 25 | Archive layout can be specified by `layout` key in the `category_archive` 26 | site configuration. Default is `category_archive`. 27 | 28 | Archive generation directory prefix can be specified by `path` key in the `category_archive` 29 | site configuration. If specified, archive will be generated in 30 | `PATH/CATEGORY/index.html`, where `PATH` is substituted by `path`, `CATEGORY` is the category 31 | the archive for. Default is null string. 32 | 33 | If the `slugify` key is set to `true`, then category URLs will be slugified. 34 | ie: the url for "My Category" will be 'categories/my-category' not 35 | 'categories/My%20Category' 36 | 37 | # Liquid variables for template 38 | 39 | `page.category` contains the category name. 40 | 41 | # Linking to a category archive 42 | 43 | This plugin provides the custom liquid block tag, `categorylink`, which can be used to render a 44 | link to a category's archive. For example: 45 | 46 | ``` 47 | {% categorylink foo %}This is a link to foo{% endcategorylink %} 48 | ``` 49 | 50 | Would create a link to the category archive of `foo` with the content "This is a link to foo". In 51 | addition, if the name of a variable is specified instead of a category, the variable will be 52 | expanded every time the tag block is rendered. 53 | 54 | 55 | # Copyright 56 | 57 | The MIT License (MIT) 58 | 59 | Copyright (c) 2013 Shigeya Suzuki 60 | 61 | Permission is hereby granted, free of charge, to any person obtaining a copy 62 | of this software and associated documentation files (the "Software"), to deal 63 | in the Software without restriction, including without limitation the rights 64 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 65 | copies of the Software, and to permit persons to whom the Software is 66 | furnished to do so, subject to the following conditions: 67 | 68 | The above copyright notice and this permission notice shall be included in all 69 | copies or substantial portions of the Software. 70 | 71 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 72 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 73 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 74 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 75 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 76 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 77 | SOFTWARE. 78 | -------------------------------------------------------------------------------- /_plugins/category_archive_plugin.rb: -------------------------------------------------------------------------------- 1 | # Jekyll Module to create category archive pages 2 | # 3 | # Shigeya Suzuki, November 2013 4 | # Copyright notice (MIT License) attached at the end of this file 5 | # 6 | 7 | # 8 | # This code is based on the following works: 9 | # https://gist.github.com/ilkka/707909 10 | # https://gist.github.com/ilkka/707020 11 | # https://gist.github.com/nlindley/6409459 12 | # 13 | 14 | # 15 | # Archive will be written as #{archive_path}/#{category_name}/index.html 16 | # archive_path can be configured in 'path' key in 'category_archive' of 17 | # site configuration file. 'path' is default null. 18 | # 19 | 20 | module Jekyll 21 | 22 | module CategoryArchiveUtil 23 | def self.archive_base(site) 24 | site.config['category_archive'] && site.config['category_archive']['path'] || '' 25 | end 26 | end 27 | 28 | # Generator class invoked from Jekyll 29 | class CategoryArchiveGenerator < Generator 30 | def generate(site) 31 | posts_group_by_category(site).each do |category, list| 32 | site.pages << CategoryArchivePage.new(site, CategoryArchiveUtil.archive_base(site), category, list) 33 | end 34 | end 35 | 36 | def posts_group_by_category(site) 37 | category_map = {} 38 | site.posts.each {|p| p.categories.each {|c| (category_map[c] ||= []) << p } } 39 | category_map 40 | end 41 | end 42 | 43 | # Tag for generating a link to a category archive page 44 | class CategoryArchiveLinkTag < Liquid::Block 45 | 46 | def initialize(tag_name, category, tokens) 47 | super 48 | @category = category.split(' ').first || category 49 | end 50 | 51 | def render(context) 52 | # If the category is a variable in the current context, expand it 53 | if context.has_key?(@category) 54 | category = context[@category] 55 | else 56 | category = @category 57 | end 58 | 59 | 60 | if context.registers[:site].config['category_archive'] && context.registers[:site].config['category_archive']['slugify'] 61 | category = Utils.slugify(category) 62 | end 63 | 64 | href = File.join('/', context.registers[:site].baseurl, context.environments.first['site']['category_archive']['path'], 65 | category, 'index.html') 66 | "#{super}" 67 | end 68 | end 69 | 70 | # Actual page instances 71 | class CategoryArchivePage < Page 72 | ATTRIBUTES_FOR_LIQUID = %w[ 73 | category, 74 | content 75 | ] 76 | 77 | def initialize(site, dir, category, posts) 78 | @site = site 79 | @dir = dir 80 | @category = category 81 | 82 | if site.config['category_archive'] && site.config['category_archive']['slugify'] 83 | @category_dir_name = Utils.slugify(@category) # require sanitize here 84 | else 85 | @category_dir_name = @category 86 | end 87 | 88 | @layout = site.config['category_archive'] && site.config['category_archive']['layout'] || 'category_archive' 89 | self.ext = '.html' 90 | self.basename = 'index' 91 | self.content = <<-EOS 92 | {% for post in page.posts %}
  • {{ post.title }}
  • 93 | {% endfor %} 94 | EOS 95 | self.data = { 96 | 'layout' => @layout, 97 | 'type' => 'archive', 98 | 'title' => "Category archive for #{@category}", 99 | 'posts' => posts, 100 | 'url' => File.join('/', 101 | CategoryArchiveUtil.archive_base(site), 102 | @category_dir_name, 'index.html') 103 | } 104 | end 105 | 106 | def render(layouts, site_payload) 107 | payload = { 108 | 'page' => self.to_liquid, 109 | 'paginator' => pager.to_liquid 110 | }.merge(site_payload) 111 | do_layout(payload, layouts) 112 | end 113 | 114 | def to_liquid(attr = nil) 115 | self.data.merge({ 116 | 'content' => self.content, 117 | 'category' => @category 118 | }) 119 | end 120 | 121 | def destination(dest) 122 | File.join('/', dest, @dir, @category_dir_name, 'index.html') 123 | end 124 | 125 | end 126 | end 127 | 128 | Liquid::Template.register_tag('categorylink', Jekyll::CategoryArchiveLinkTag) 129 | 130 | # The MIT License (MIT) 131 | # 132 | # Copyright (c) 2013 Shigeya Suzuki 133 | # 134 | # Permission is hereby granted, free of charge, to any person obtaining a copy 135 | # of this software and associated documentation files (the "Software"), to deal 136 | # in the Software without restriction, including without limitation the rights 137 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 138 | # copies of the Software, and to permit persons to whom the Software is 139 | # furnished to do so, subject to the following conditions: 140 | # 141 | # The above copyright notice and this permission notice shall be included in all 142 | # copies or substantial portions of the Software. 143 | # 144 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 145 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 146 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 147 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 148 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 149 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 150 | # SOFTWARE. 151 | --------------------------------------------------------------------------------