diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 00000000000..d9f5d35ee4f --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,53 @@ +version: "2" +checks: + argument-count: + enabled: true + config: + threshold: 5 + file-lines: + enabled: true + config: + threshold: 300 + method-complexity: + enabled: true + config: + threshold: 15 + method-count: + enabled: true + config: + threshold: 50 + method-lines: + enabled: true + config: + threshold: 30 +plugins: + fixme: + enabled: false + rubocop: + enabled: true + channel: rubocop-0-60 + +exclude_patterns: + - "*.*" + - ".*" + + - Gemfile + - LICENSE + - Rakefile + + - benchmark/ + - docs/ + - exe/ + - features/ + - rake/ + - rubocop/ + - script/ + - spec/ + - test/ + - vendor/ + + - lib/blank_template/ + - lib/site_template/ + - lib/theme_template/ + - lib/jekyll/mime.types + - lib/jekyll/commands/serve/livereload_assets/livereload.js diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000000..93249a80ef7 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +FROM ruby:3.0 + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive + +# This Dockerfile adds a non-root user with sudo access. Use the "remoteUser" +# property in devcontainer.json to use it. On Linux, the container user's GID/UIDs +# will be updated to match your local UID/GID (when using the dockerFile property). +# See https://aka.ms/vscode-remote/containers/non-root-user for details. +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Configure apt and install packages +RUN apt-get update \ + && apt-get -y install --no-install-recommends apt-utils dialog locales 2>&1 \ + # Verify git, process tools installed + && apt-get -y install git openssh-client iproute2 procps lsb-release \ + # + # Install ruby-debug-ide and debase + && gem install ruby-debug-ide \ + && gem install debase \ + # + # Install node.js + && apt-get -y install curl software-properties-common \ + && curl -sL https://deb.nodesource.com/setup_18.x | bash - \ + && apt-get -y install nodejs \ + # + # Create a non-root user to use if preferred - see https://aka.ms/vscode-remote/containers/non-root-user. + && groupadd --gid $USER_GID $USERNAME \ + && useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \ + # [Optional] Add sudo support for the non-root user + && apt-get install -y sudo \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME\ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +# Set the locale +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \ + dpkg-reconfigure --frontend=noninteractive locales && \ + update-locale LANG=en_US.UTF-8 + +ENV LANG en_US.UTF-8 + +# Switch back to dialog for any ad-hoc use of apt-get +ENV DEBIAN_FRONTEND=dialog diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..e5a1a0aa582 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.101.1/containers/ruby-2 +{ + "name": "Ruby 3", + "dockerFile": "Dockerfile", + + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "rebornix.Ruby" + ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "bundle install" + + // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode" + +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000000..9d5248e86f3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..176a458f94e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000000..3077f286f1c --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,84 @@ +# The Jekyll project has 6 affinity teams, shown here: https://teams.jekyllrb.com/ +# They are as follows: +# +# 1. @jekyll/build +# 2. @jekyll/documentation +# 3. @jekyll/ecosystem +# 4. @jekyll/performance +# 5. @jekyll/stability +# 6. @jekyll/windows +# +# Each of these teams has a mission. Wherever possible, GitHub should +# automatically require review from these teams on the pieces of the +# repository they maintain. + +# @jekyll/documentation +/docs/ @jekyll/documentation + +# @jekyll/build +/exe/ @jekyll/build +/lib/jekyll.rb @jekyll/build +/lib/jekyll/cleaner.rb @jekyll/build +/lib/jekyll/collection.rb @jekyll/build +/lib/jekyll/command.rb @jekyll/build +/lib/jekyll/commands/ @jekyll/build +/lib/jekyll/converter.rb @jekyll/build +/lib/jekyll/converters/ @jekyll/build +/lib/jekyll/convertible.rb @jekyll/build +/lib/jekyll/document.rb @jekyll/build +/lib/jekyll/drops/ @jekyll/build +/lib/jekyll/entry_filter.rb @jekyll/build +/lib/jekyll/errors.rb @jekyll/build +/lib/jekyll/excerpt.rb @jekyll/build +/lib/jekyll/filters/ @jekyll/build +/lib/jekyll/filters.rb @jekyll/build +/lib/jekyll/layout.rb @jekyll/build +/lib/jekyll/liquid_extensions.rb @jekyll/build +/lib/jekyll/liquid_renderer/ @jekyll/build +/lib/jekyll/liquid_renderer.rb @jekyll/build +/lib/jekyll/log_adapter.rb @jekyll/build +/lib/jekyll/mime.types @jekyll/build +/lib/jekyll/page.rb @jekyll/build +/lib/jekyll/publisher.rb @jekyll/build +/lib/jekyll/reader.rb @jekyll/build +/lib/jekyll/readers/ @jekyll/build +/lib/jekyll/regenerator.rb @jekyll/build +/lib/jekyll/related_posts.rb @jekyll/build +/lib/jekyll/renderer.rb @jekyll/build +/lib/jekyll/site.rb @jekyll/build +/lib/jekyll/static_file.rb @jekyll/build +/lib/jekyll/stevenson.rb @jekyll/build +/lib/jekyll/tags/ @jekyll/build +/lib/jekyll/url.rb @jekyll/build +/lib/jekyll/utils/ @jekyll/build +/lib/jekyll/utils.rb @jekyll/build + +# @jekyll/ecosystem +/lib/jekyll/external.rb @jekyll/ecosystem +/lib/jekyll/generator.rb @jekyll/ecosystem +/lib/jekyll/hooks.rb @jekyll/ecosystem +/lib/jekyll/plugin.rb @jekyll/ecosystem +/lib/jekyll/plugin_manager.rb @jekyll/ecosystem +/lib/jekyll/theme.rb @jekyll/ecosystem +/lib/jekyll/theme_builder.rb @jekyll/ecosystem + +# @jekyll/stability +Gemfile @jekyll/stability +*.gemspec @jekyll/stability +/lib/jekyll/configuration.rb @jekyll/stability +/lib/jekyll/deprecator.rb @jekyll/stability +/lib/jekyll/frontmatter_defaults.rb @jekyll/stability +/lib/site_template @jekyll/stability +/lib/theme_template @jekyll/stability +/features/ @jekyll/stability +/test/ @jekyll/stability + +# Special cases +.github/ @jekyll/affinity-team-captains +CODE_OF_CONDUCT.markdown @jekyll/affinity-team-captains +History.markdown @jekyll/affinity-team-captains +LICENSE @jekyll/affinity-team-captains # This file should never change. +README.markdown @jekyll/affinity-team-captains +/lib/jekyll/version.rb @jekyll/affinity-team-captains +/rake/ @jekyll/affinity-team-captains +/script/ @jekyll/affinity-team-captains diff --git a/.github/CODE_OF_CONDUCT.markdown b/.github/CODE_OF_CONDUCT.markdown new file mode 100644 index 00000000000..0ab543e46ec --- /dev/null +++ b/.github/CODE_OF_CONDUCT.markdown @@ -0,0 +1,76 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [olivia@jekyllrb.com](mailto:olivia@jekyllrb.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/.github/CONTRIBUTING.markdown b/.github/CONTRIBUTING.markdown new file mode 100644 index 00000000000..68a41c87338 --- /dev/null +++ b/.github/CONTRIBUTING.markdown @@ -0,0 +1,158 @@ +# Contributing to Jekyll + +Hi there! Interested in contributing to Jekyll? We'd love your help. Jekyll is an open source project, built one contribution at a time by users like you. + +## Where to get help or report a problem + +See the [support guidelines](https://jekyllrb.com/docs/support/) + +## Ways to contribute + +Whether you're a developer, a designer, or just a Jekyll devotee, there are lots of ways to contribute. Here's a few ideas: + +- [Install Jekyll on your computer](https://jekyllrb.com/docs/installation/) and kick the tires. Does it work? Does it do what you'd expect? If not, [open an issue](https://github.com/jekyll/jekyll/issues/new) and let us know. +- Comment on some of the project's [open issues](https://github.com/jekyll/jekyll/issues). Have you experienced the same problem? Know a workaround? Do you have a suggestion for how the feature could be better? +- Read through the [documentation](https://jekyllrb.com/docs/home/), and click the "improve this page" button, any time you see something confusing, or have a suggestion for something that could be improved. +- Browse through the [Jekyll discussion forum](https://talk.jekyllrb.com/), and lend a hand answering questions. There's a good chance you've already experienced what another user is experiencing. +- Find an [open issue](https://github.com/jekyll/jekyll/issues) (especially [those labeled `help-wanted`](https://github.com/jekyll/jekyll/issues?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted)), and submit a proposed fix. If it's your first pull request, we promise we won't bite, and are glad to answer any questions. +- Help evaluate [open pull requests](https://github.com/jekyll/jekyll/pulls), by testing the changes locally and reviewing what's proposed. + +## Submitting a pull request + +### Pull requests generally + +- The smaller the proposed change, the better. If you'd like to propose two unrelated changes, submit two pull requests. + +- The more information, the better. Make judicious use of the pull request body. Describe what changes were made, why you made them, and what impact they will have for users. + +- If this is your first pull request, it may help to [understand GitHub Flow](https://guides.github.com/introduction/flow/). + +- If you're submitting a code contribution, be sure to read the [code contributions](#code-contributions) section below. + +### Submitting a pull request via github.com + +Many small changes can be made entirely through the github.com web interface. + +1. Navigate to the file within [`jekyll/jekyll`](https://github.com/jekyll/jekyll) that you'd like to edit. +2. Click the pencil icon in the top right corner to edit the file +3. Make your proposed changes +4. Click "Propose file change" +5. Click "Create pull request" +6. Add a descriptive title and detailed description for your proposed change. The more information the better. +7. Click "Create pull request" + +That's it! You'll be automatically subscribed to receive updates as others review your proposed change and provide feedback. + +### Submitting a pull request via Git command line + +1. Fork the project by clicking "Fork" in the top right corner of [`jekyll/jekyll`](https://github.com/jekyll/jekyll). +2. Clone the repository locally `git clone https://github.com//jekyll`. +3. Create a new, descriptively named branch to contain your change ( `git checkout -b my-awesome-feature` ). +4. Hack away, add tests. Not necessarily in that order. +5. Make sure everything still passes by running `script/cibuild` (see the [tests section](#running-tests-locally) below) +6. Push the branch up ( `git push origin my-awesome-feature` ). +7. Create a pull request by visiting `https://github.com//jekyll` and following the instructions at the top of the screen. + +## Proposing updates to the documentation + +We want the Jekyll documentation to be the best it can be. We've open-sourced our docs and we welcome any pull requests if you find it lacking. + +### How to submit changes + +You can find the documentation for jekyllrb.com in the [docs](https://github.com/jekyll/jekyll/tree/master/docs) directory. See the section above, [submitting a pull request](#submitting-a-pull-request) for information on how to propose a change. + +One gotcha, all pull requests should be directed at the `master` branch (the default branch). + +### Updating FontAwesome iconset for jekyllrb.com + +We use a custom version of FontAwesome which contains just the icons we use. + +If you ever need to update our documentation with an icon that is not already available in our custom iconset, you'll have to regenerate the iconset using Icomoon's Generator: + +1. Go to . +2. Click `Import Icons` on the top-horizontal-bar and upload the existing `/docs/icomoon-selection.json`. +3. Click `Add Icons from Library..` further down on the page, and add 'Font Awesome'. +4. Select the required icon(s) from the Library (make sure its the 'FontAwesome' library instead of 'IcoMoon-Free' library). +5. Click `Generate Font` on the bottom-horizontal-bar. +6. Inspect the included icons and proceed by clicking `Download`. +7. Extract the font files and adapt the CSS to the paths we use in Jekyll: + +- Copy the entire `fonts` directory over and overwrite existing ones at `/docs/`. +- Copy the contents of `selection.json` and overwrite existing content inside `/docs/icomoon-selection.json`. +- Copy the entire `@font-face {}` declaration and only the **new-icon(s)' css declarations** further below, to update the + `/docs/_sass/_font-awesome.scss` sass partial. +- Fix paths in the `@font-face {}` declaration by adding `../` before `fonts/FontAwesome.*` like so: + `('../fonts/Fontawesome.woff?9h6hxj')`. + +### Adding plugins + +If you want to add your plugin to the [list of plugins](https://jekyllrb.com/docs/plugins/#available-plugins), please submit a pull request modifying the [plugins page source file](https://github.com/jekyll/jekyll/blob/master/docs/_docs/plugins.md) by adding a link to your plugin under the proper subheading depending upon its type. + +## Code Contributions + +Interested in submitting a pull request? Awesome. Read on. There's a few common gotchas that we'd love to help you avoid. + +### Tests and documentation + +Any time you propose a code change, you should also include updates to the documentation and tests within the same pull request. + +#### Documentation + +If your contribution changes any Jekyll behavior, make sure to update the documentation. Documentation lives in the `docs/_docs` folder (spoiler alert: it's a Jekyll site!). If the docs are missing information, please feel free to add it in. Great docs make a great project. Include changes to the documentation within your pull request, and once merged, `jekyllrb.com` will be updated. + +#### Tests + +- If you're creating a small fix or patch to an existing feature, a simple test is more than enough. You can usually copy/paste from an existing example in the `tests` folder, but if you need you can find out about our tests suites [Shoulda](https://github.com/thoughtbot/shoulda/tree/master) and [RSpec-Mocks](https://github.com/rspec/rspec-mocks). + +- If it's a brand new feature, create a new [Cucumber](https://github.com/cucumber/cucumber/) feature, reusing existing steps where appropriate. + +### Code contributions generally + +- Jekyll uses the [Rubocop](https://github.com/bbatsov/rubocop) static analyzer to ensure that contributions follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby). Please check your code using `script/fmt` and resolve any errors before pushing your branch. + +- Don't bump the Gem version in your pull request (if you don't know what that means, you probably didn't). + +- You can use the command `script/console` to start a REPL to explore the result of + Jekyll's methods. It also provides you with helpful methods to quickly create a + site or configuration. [Feel free to check it out!](https://github.com/jekyll/jekyll/blob/master/script/console) + +- Previously, we've used the WIP Probot app to help contributors determine whether their pull request is ready for review. Please use a [draft pull request](https://help.github.com/en/articles/about-pull-requests#draft-pull-requests) instead. When you're ready, [mark the pull request as ready for review](https://help.github.com/en/articles/changing-the-stage-of-a-pull-request) + +## Running tests locally + +### Test Dependencies + +To run the test suite and build the gem you'll need to install Jekyll's dependencies by running the following command: + +```sh +script/bootstrap +``` + +Before you make any changes, run the tests and make sure that they pass (to confirm your environment is configured properly): + +```sh +script/cibuild +``` + +If you are only updating a file in `test/`, you can use the command: + +```sh +script/test test/blah_test.rb +``` + +If you are only updating a `.feature` file, you can use the command: + +```sh +script/cucumber features/blah.feature +``` + +Both `script/test` and `script/cucumber` can be run without arguments to +run its entire respective suite. + +## Visual Studio Code Development Container + +If you've got [Visual Studio Code](https://code.visualstudio.com/) with the [Remote Development Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) installed then simply opening this repository in Visual Studio Code and following the prompts to "Re-open In A Development Container" will get you setup and ready to go with a fresh environment with all the requirements installed. + +## A thank you + +Thanks! Hacking on Jekyll should be fun. If you find any of this hard to figure out, let us know so we can improve our process or documentation! diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..d72014bcc6c --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +# github: jekyll +open_collective: jekyll +tidelift: rubygems/jekyll diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000000..766e2b725a5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,104 @@ +name: Bug Report +description: "Is something not working as expected?" +title: "[Bug]: " +body: + - type: markdown + attributes: + value: | + Hi! Thank you for taking the time to report a bug with Jekyll. + + Please consider asking your question at https://talk.jekyllrb.com if one or more of the following is applicable to your situation: + + - You are not sure if the issue is a bug in Jekyll. + - The issue is caused by a third-party plugin. + - This is just a generic usage question. + + Additionally, please note that this platform is meant for bugs in Jekyll core only. + Issues regarding dependencies and plugins should be reported in their respective repositories. + - type: input + id: os + attributes: + label: Operating System + description: The operating system of your computer. + placeholder: "Ubuntu 21.10" + validations: + required: true + - type: input + id: ruby-version + attributes: + label: Ruby Version + description: | + The Ruby version you were using at the time. + Run `ruby -v` in your terminal and paste the output in the input field. + placeholder: "ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [x64-mingw32]" + validations: + required: true + - type: input + id: jekyll-version + attributes: + label: Jekyll Version + description: | + The version of Jekyll used in your project. + Run `bundle exec jekyll -v` and paste the output in the input field. + *If you are not using a Gemfile, run `jekyll -v` instead.* + placeholder: "jekyll 4.2.1" + validations: + required: true + - type: input + id: ghp-version + attributes: + label: GitHub Pages Version + description: | + Are you deploying your site using GitHub Pages? + If yes, then we need to know the `github-pages` version used by your project. Proceed ahead otherwise. + If you're using the `github-pages` gem in your Gemfile, paste the output from running the following: + ``` + bundle exec github-pages -v + ``` + Otherwise, enter `Latest` in the input field and proceed ahead. + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: Briefly describe what you expected to see or get with a certain functionality. + placeholder: | + I expected my site to be built successfully when I run the following: + ``` + bundle exec jekyll build + ``` + validations: + required: true + - type: textarea + id: actual + attributes: + label: Current Behavior + description: > + Describe the details of the bug. + Be sure to include any steps you took for the problem to exist, such as the directories + you created and the full command you ran. + Include any plugins you have configured for use in the site. + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant log output + description: | + Please copy and paste any relevant log output from your terminal. + *Note: This will be automatically formatted into code, so no need for backticks.* + render: shell + - type: textarea + id: sample + attributes: + label: Code Sample + description: > + The easiest way for someone to understand an issue is if they could reproduce your issue + in their environment. Therefore, please provide a link to your project repository alongwith + instructions to reproduce your issue. If your project is not publicly accessible, please + consider setting up a minimal test repository complete with necessary instructions. + placeholder: | + ### Steps to reproduce issue + + - Clone [my repo](https://github.com/owner/repo) + - Install site dependencies + - Run `bundle exec jekyll build -s src -d src/dist` diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..037c1df61fe --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Jekyll Community Forum + url: https://talk.jekyllrb.com/ + about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 00000000000..a8e11cf202f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,24 @@ +--- +name: Documentation +about: Found a typo or something that isn't crystal clear in our docs? +title: '[Docs]: ' +labels: documentation +assignees: '' + +--- + + + +## Motivation + + + + + +## Suggestion + + + + + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..fd2c5b4d29e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,73 @@ +--- +name: Feature Request +about: Want us to add any features to Jekyll? +title: 'feat: ' +labels: feature +assignees: '' + +--- + + + +## Summary + + + +## Motivation + + + +## Guide-level explanation + + + +## Reference-level explanation + + + +## Drawbacks + + + +## Unresolved Questions + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..19ce7c64602 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,46 @@ + + + + + + + + + + + +## Summary + + + +## Context + + diff --git a/.github/SECURITY.markdown b/.github/SECURITY.markdown new file mode 100644 index 00000000000..e130514c388 --- /dev/null +++ b/.github/SECURITY.markdown @@ -0,0 +1,32 @@ +# Security Policy + +## Supported Versions + +Security updates are applied to the latest MINOR version of Jekyll, and the version used by GitHub Pages, v3.10.x. + +| Version | Supported | +| ------- | ------------------ | +| 4.4.x | :white_check_mark: | +| 3.10.x | :white_check_mark: | +| < 3.10.x | :x: | + +## Reporting a Vulnerability + +Please report vulnerabilities by sending an email to security@jekyllrb.com with the following information: + +1. A description of the vulnerability +2. Reproduction steps and/or a sample site (share a private repo to the [Jekyll Security Team](docs/pages/team.md)) +3. Your contact information + +The Jekyll security team will respond to your submission and notify you whether it has been confirmed by the team. +Your confidentiality is kindly requested as we work on a fix. We will provide our patch to you to test and verify that the vulnerability has +been closed. + +If you have created a patch and would like to submit that to us as well, we will happily consider it though we cannot guarantee that we will +use it. If we use your patch, we will attribute authorship to you either as the commit author, or as a co-author. + +Once a fix is verified, we will release PATCH versions of the supported MINOR versions and assign a CVE to the vulnerability. You will receive +credit in our release post. + +Once the patched version has been released, we will no longer request you to maintain confidentiality and you may choose to share details on +how you found the vulnerability with the community. diff --git a/.github/SUPPORT.markdown b/.github/SUPPORT.markdown new file mode 100644 index 00000000000..0939723dff8 --- /dev/null +++ b/.github/SUPPORT.markdown @@ -0,0 +1,20 @@ +# Jekyll Support + +## Getting Help + +**Jekyll's issue tracker is not a support forum.** + +If you're looking for support for Jekyll, there are a lot of options: + +* Read [Jekyll Documentation](https://jekyllrb.com/docs/home/) +* If you have a question about using Jekyll, start a discussion on [Jekyll Forum](https://talk.jekyllrb.com/) or [StackOverflow](https://stackoverflow.com/questions/tagged/jekyll) +* Chat with Jekyllers — Join [our Gitter channel](https://gitter.im/jekyll/jekyll) or [our IRC channel on Freenode](irc:irc.freenode.net/jekyll) + +There are a bunch of helpful community members on these services that should be willing to point you in the right direction. + +## Report a bug + +* If you think you've found a bug within a Jekyll plugin, open an issue in that plugin's repository — First [look for the plugin on rubygems](https://rubygems.org/) then click on the `Homepage` link to access the plugin repository. +* If you think you've found a bug within Jekyll itself, [open an issue](https://github.com/jekyll/jekyll/issues/new). + +Happy Jekyllin'! diff --git a/.github/actions/spelling/README.md b/.github/actions/spelling/README.md new file mode 100644 index 00000000000..1f699f3de3d --- /dev/null +++ b/.github/actions/spelling/README.md @@ -0,0 +1,17 @@ +# check-spelling/check-spelling configuration + +File | Purpose | Format | Info +-|-|-|- +[dictionary.txt](dictionary.txt) | Replacement dictionary (creating this file will override the default dictionary) | one word per line | [dictionary](https://github.com/check-spelling/check-spelling/wiki/Configuration#dictionary) +[allow.txt](allow.txt) | Add words to the dictionary | one word per line (only letters and `'`s allowed) | [allow](https://github.com/check-spelling/check-spelling/wiki/Configuration#allow) +[reject.txt](reject.txt) | Remove words from the dictionary (after allow) | grep pattern matching whole dictionary words | [reject](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-reject) +[excludes.txt](excludes.txt) | Files to ignore entirely | perl regular expression | [excludes](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-excludes) +[only.txt](only.txt) | Only check matching files (applied after excludes) | perl regular expression | [only](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-only) +[patterns.txt](patterns.txt) | Patterns to ignore from checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns) +[candidate.patterns](candidate.patterns) | Patterns that might be worth adding to [patterns.txt](patterns.txt) | perl regular expression with optional comment block introductions (all matches will be suggested) | [candidates](https://github.com/check-spelling/check-spelling/wiki/Feature:-Suggest-patterns) +[line_forbidden.patterns](line_forbidden.patterns) | Patterns to flag in checked lines | perl regular expression (order matters, first match wins) | [patterns](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-patterns) +[expect.txt](expect.txt) | Expected words that aren't in the dictionary | one word per line (sorted, alphabetically) | [expect](https://github.com/check-spelling/check-spelling/wiki/Configuration#expect) +[advice.md](advice.md) | Supplement for GitHub comment when unrecognized words are found | GitHub Markdown | [advice](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples%3A-advice) + +Note: you can replace any of these files with a directory by the same name (minus the suffix) +and then include multiple files inside that directory (with that suffix) to merge multiple files together. diff --git a/.github/actions/spelling/advice.md b/.github/actions/spelling/advice.md new file mode 100644 index 00000000000..1004eeaa604 --- /dev/null +++ b/.github/actions/spelling/advice.md @@ -0,0 +1,25 @@ + +
If the flagged items are :exploding_head: false positives + +If items relate to a ... +* binary file (or some other file you wouldn't want to check at all). + + Please add a file path to the `excludes.txt` file matching the containing file. + + File paths are Perl 5 Regular Expressions - you can [test]( +https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your files. + + `^` refers to the file's path from the root of the repository, so `^README\.md$` would exclude [README.md]( +../tree/HEAD/README.md) (on whichever branch you're using). + +* well-formed pattern. + + If you can write a [pattern](https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns) that would match it, + try adding it to the `patterns.txt` file. + + Patterns are Perl 5 Regular Expressions - you can [test]( +https://www.regexplanet.com/advanced/perl/) yours before committing to verify it will match your lines. + + Note that patterns can't match multiline strings. + +
diff --git a/.github/actions/spelling/allow.txt b/.github/actions/spelling/allow.txt new file mode 100644 index 00000000000..2ed6a28c8a7 --- /dev/null +++ b/.github/actions/spelling/allow.txt @@ -0,0 +1,19 @@ +azion +builtins +github +hakiri +https +Linting +Microsoft +ssh +Statictastic +statictastic +supranode +ubuntu +Wikipedia +workaround +workaround +workarounds +WSL +decapcms +tina diff --git a/.github/actions/spelling/candidate.patterns b/.github/actions/spelling/candidate.patterns new file mode 100644 index 00000000000..dc17f842fa8 --- /dev/null +++ b/.github/actions/spelling/candidate.patterns @@ -0,0 +1,520 @@ +# marker to ignore all code on line +^.*/\* #no-spell-check-line \*/.*$ +# marker for ignoring a comment to the end of the line +// #no-spell-check.*$ + +# patch hunk comments +^\@\@ -\d+(?:,\d+|) \+\d+(?:,\d+|) \@\@ .* +# git index header +index [0-9a-z]{7,40}\.\.[0-9a-z]{7,40} + +# cid urls +(['"])cid:.*?\g{-1} + +# data url in parens +\(data:[^)]*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})[^)]*\) +# data url in quotes +([`'"])data:.*?(?:[A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,}).*\g{-1} +# data url +data:[-a-zA-Z=;:/0-9+]*,\S* + +# mailto urls +mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,} + +# magnet urls +magnet:[?=:\w]+ + +# magnet urls +"magnet:[^"]+" + +# obs: +"obs:[^"]*" + +# The `\b` here means a break, it's the fancy way to handle urls, but it makes things harder to read +# In this examples content, I'm using a number of different ways to match things to show various approaches +# asciinema +\basciinema\.org/a/[0-9a-zA-Z]+ + +# apple +\bdeveloper\.apple\.com/[-\w?=/]+ +# Apple music +\bembed\.music\.apple\.com/fr/playlist/usr-share/[-\w.]+ + +# appveyor api +\bci\.appveyor\.com/api/projects/status/[0-9a-z]+ +# appveyor project +\bci\.appveyor\.com/project/(?:[^/\s"]*/){2}builds?/\d+/job/[0-9a-z]+ + +# Amazon + +# Amazon +\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|) +# AWS S3 +\b\w*\.s3[^.]*\.amazonaws\.com/[-\w/&#%_?:=]* +# AWS execute-api +\b[0-9a-z]{10}\.execute-api\.[-0-9a-z]+\.amazonaws\.com\b +# AWS ELB +\b\w+\.[-0-9a-z]+\.elb\.amazonaws\.com\b +# AWS SNS +\bsns\.[-0-9a-z]+.amazonaws\.com/[-\w/&#%_?:=]* +# AWS VPC +vpc-\w+ + +# While you could try to match `http://` and `https://` by using `s?` in `https?://`, sometimes there +# YouTube url +\b(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|user/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_%]* +# YouTube music +\bmusic\.youtube\.com/youtubei/v1/browse(?:[?&]\w+=[-a-zA-Z0-9?&=_]*) +# YouTube tag +<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"] +# YouTube image +\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]* +# Google Accounts +\baccounts.google.com/[-_/?=.:;+%&0-9a-zA-Z]* +# Google Analytics +\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]* +# Google APIs +\bgoogleapis\.(?:com|dev)/[a-z]+/(?:v\d+/|)[a-z]+/[-@:./?=\w+|&]+ +# Google Storage +\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|) +# Google Calendar +\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+ +\w+\@group\.calendar\.google\.com\b +# Google DataStudio +\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|) +# The leading `/` here is as opposed to the `\b` above +# ... a short way to match `https://` or `http://` since most urls have one of those prefixes +# Google Docs +/docs\.google\.com/[a-z]+/(?:ccc\?key=\w+|(?:u/\d+|d/(?:e/|)[0-9a-zA-Z_-]+/)?(?:edit\?[-\w=#.]*|/\?[\w=&]*|)) +# Google Drive +\bdrive\.google\.com/(?:file/d/|open)[-0-9a-zA-Z_?=]* +# Google Groups +\bgroups\.google\.com/(?:(?:forum/#!|d/)(?:msg|topics?|searchin)|a)/[^/\s"]+/[-a-zA-Z0-9$]+(?:/[-a-zA-Z0-9]+)* +# Google Maps +\bmaps\.google\.com/maps\?[\w&;=]* +# Google themes +themes\.googleusercontent\.com/static/fonts/[^/\s"]+/v\d+/[^.]+. +# Google CDN +\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]* +# Goo.gl +/goo\.gl/[a-zA-Z0-9]+ +# Google Chrome Store +\bchrome\.google\.com/webstore/detail/[-\w]*(?:/\w*|) +# Google Books +\bgoogle\.(?:\w{2,4})/books(?:/\w+)*\?[-\w\d=&#.]* +# Google Fonts +\bfonts\.(?:googleapis|gstatic)\.com/[-/?=:;+&0-9a-zA-Z]* +# Google Forms +\bforms\.gle/\w+ +# Google Scholar +\bscholar\.google\.com/citations\?user=[A-Za-z0-9_]+ +# Google Colab Research Drive +\bcolab\.research\.google\.com/drive/[-0-9a-zA-Z_?=]* + +# GitHub SHAs (api) +\bapi.github\.com/repos(?:/[^/\s"]+){3}/[0-9a-f]+\b +# GitHub SHAs (markdown) +(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|) +# GitHub SHAs +\bgithub\.com(?:/[^/\s"]+){2}[@#][0-9a-f]+\b +# GitHub wiki +\bgithub\.com/(?:[^/]+/){2}wiki/(?:(?:[^/]+/|)_history|[^/]+(?:/_compare|)/[0-9a-f.]{40,})\b +# githubusercontent +/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]* +# githubassets +\bgithubassets.com/[0-9a-f]+(?:[-/\w.]+) +# gist github +\bgist\.github\.com/[^/\s"]+/[0-9a-f]+ +# git.io +\bgit\.io/[0-9a-zA-Z]+ +# GitHub JSON +"node_id": "[-a-zA-Z=;:/0-9+]*" +# Contributor +\[[^\]]+\]\(https://github\.com/[^/\s"]+\) +# GHSA +GHSA(?:-[0-9a-z]{4}){3} + +# GitLab commit +\bgitlab\.[^/\s"]*/\S+/\S+/commit/[0-9a-f]{7,16}#[0-9a-f]{40}\b +# GitLab merge requests +\bgitlab\.[^/\s"]*/\S+/\S+/-/merge_requests/\d+/diffs#[0-9a-f]{40}\b +# GitLab uploads +\bgitlab\.[^/\s"]*/uploads/[-a-zA-Z=;:/0-9+]* +# GitLab commits +\bgitlab\.[^/\s"]*/(?:[^/\s"]+/){2}commits?/[0-9a-f]+\b + +# binanace +accounts.binance.com/[a-z/]*oauth/authorize\?[-0-9a-zA-Z&%]* + +# bitbucket diff +\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}diff(?:stat|)(?:/[^/\s"]+){2}:[0-9a-f]+ +# bitbucket repositories commits +\bapi\.bitbucket\.org/\d+\.\d+/repositories/(?:[^/\s"]+/){2}commits?/[0-9a-f]+ +# bitbucket commits +\bbitbucket\.org/(?:[^/\s"]+/){2}commits?/[0-9a-f]+ + +# bit.ly +\bbit\.ly/\w+ + +# bitrise +\bapp\.bitrise\.io/app/[0-9a-f]*/[\w.?=&]* + +# bootstrapcdn.com +\bbootstrapcdn\.com/[-./\w]+ + +# cdn.cloudflare.com +\bcdnjs\.cloudflare\.com/[./\w]+ + +# circleci +\bcircleci\.com/gh(?:/[^/\s"]+){1,5}.[a-z]+\?[-0-9a-zA-Z=&]+ + +# gitter +\bgitter\.im(?:/[^/\s"]+){2}\?at=[0-9a-f]+ + +# gravatar +\bgravatar\.com/avatar/[0-9a-f]+ + +# ibm +[a-z.]*ibm\.com/[-_#=:%!?~.\\/\d\w]* + +# imgur +\bimgur\.com/[^.]+ + +# Internet Archive +\barchive\.org/web/\d+/(?:[-\w.?,'/\\+&%$#_:]*) + +# discord +/discord(?:app\.com|\.gg)/(?:invite/)?[a-zA-Z0-9]{7,} + +# Disqus +\bdisqus\.com/[-\w/%.()!?&=_]* + +# medium link +\blink\.medium\.com/[a-zA-Z0-9]+ +# medium +\bmedium\.com/\@?[^/\s"]+/[-\w]+ + +# microsoft +\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]* +# powerbi +\bapp\.powerbi\.com/reportEmbed/[^"' ]* +# vs devops +\bvisualstudio.com(?::443|)/[-\w/?=%&.]* +# microsoft store +\bmicrosoft\.com/store/apps/\w+ + +# mvnrepository.com +\bmvnrepository\.com/[-0-9a-z./]+ + +# now.sh +/[0-9a-z-.]+\.now\.sh\b + +# oracle +\bdocs\.oracle\.com/[-0-9a-zA-Z./_?#&=]* + +# chromatic.com +/\S+.chromatic.com\S*[")] + +# codacy +\bapi\.codacy\.com/project/badge/Grade/[0-9a-f]+ + +# compai +\bcompai\.pub/v1/png/[0-9a-f]+ + +# mailgun api +\.api\.mailgun\.net/v3/domains/[0-9a-z]+\.mailgun.org/messages/[0-9a-zA-Z=@]* +# mailgun +\b[0-9a-z]+.mailgun.org + +# /message-id/ +/message-id/[-\w@./%]+ + +# Reddit +\breddit\.com/r/[/\w_]* + +# requestb.in +\brequestb\.in/[0-9a-z]+ + +# sched +\b[a-z0-9]+\.sched\.com\b + +# Slack url +slack://[a-zA-Z0-9?&=]+ +# Slack +\bslack\.com/[-0-9a-zA-Z/_~?&=.]* +# Slack edge +\bslack-edge\.com/[-a-zA-Z0-9?&=%./]+ +# Slack images +\bslack-imgs\.com/[-a-zA-Z0-9?&=%.]+ + +# shields.io +\bshields\.io/[-\w/%?=&.:+;,]* + +# stackexchange -- https://stackexchange.com/feeds/sites +\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/) + +# Sentry +[0-9a-f]{32}\@o\d+\.ingest\.sentry\.io\b + +# Twitter markdown +\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\) +# Twitter hashtag +\btwitter\.com/hashtag/[\w?_=&]* +# Twitter status +\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|) +# Twitter profile images +\btwimg\.com/profile_images/[_\w./]* +# Twitter media +\btwimg\.com/media/[-_\w./?=]* +# Twitter link shortened +\bt\.co/\w+ + +# facebook +\bfburl\.com/[0-9a-z_]+ +# facebook CDN +\bfbcdn\.net/[\w/.,]* +# facebook watch +\bfb\.watch/[0-9A-Za-z]+ + +# dropbox +\bdropbox\.com/sh?/[^/\s"]+/[-0-9A-Za-z_.%?=&;]+ + +# ipfs protocol +ipfs://[0-9a-z]* +# ipfs url +/ipfs/[0-9a-z]* + +# w3 +\bw3\.org/[-0-9a-zA-Z/#.]+ + +# loom +\bloom\.com/embed/[0-9a-f]+ + +# regex101 +\bregex101\.com/r/[^/\s"]+/\d+ + +# figma +\bfigma\.com/file(?:/[0-9a-zA-Z]+/)+ + +# freecodecamp.org +\bfreecodecamp\.org/[-\w/.]+ + +# image.tmdb.org +\bimage\.tmdb\.org/[/\w.]+ + +# mermaid +\bmermaid\.ink/img/[-\w]+|\bmermaid-js\.github\.io/mermaid-live-editor/#/edit/[-\w]+ + +# Wikipedia +\ben\.wikipedia\.org/wiki/[-\w%.#]+ + +# gitweb +[^"\s]+/gitweb/\S+;h=[0-9a-f]+ + +# HyperKitty lists +/archives/list/[^@/]+\@[^/\s"]*/message/[^/\s"]*/ + +# lists +/thread\.html/[^"\s]+ + +# list-management +\blist-manage\.com/subscribe(?:[?&](?:u|id)=[0-9a-f]+)+ + +# kubectl.kubernetes.io/last-applied-configuration +"kubectl.kubernetes.io/last-applied-configuration": ".*" + +# pgp +\bgnupg\.net/pks/lookup[?&=0-9a-zA-Z]* + +# Spotify +\bopen\.spotify\.com/embed/playlist/\w+ + +# Mastodon +\bmastodon\.[-a-z.]*/(?:media/|\@)[?&=0-9a-zA-Z_]* + +# scastie +\bscastie\.scala-lang\.org/[^/]+/\w+ + +# images.unsplash.com +\bimages\.unsplash\.com/(?:(?:flagged|reserve)/|)[-\w./%?=%&.;]+ + +# pastebin +\bpastebin\.com/[\w/]+ + +# heroku +\b\w+\.heroku\.com/source/archive/\w+ + +# quip +\b\w+\.quip\.com/\w+(?:(?:#|/issues/)\w+)? + +# badgen.net +\bbadgen\.net/badge/[^")\]'\s]+ + +# statuspage.io +\w+\.statuspage\.io\b + +# media.giphy.com +\bmedia\.giphy\.com/media/[^/]+/[\w.?&=]+ + +# tinyurl +\btinyurl\.com/\w+ + +# getopts +\bgetopts\s+(?:"[^"]+"|'[^']+') + +# ANSI color codes +(?:\\(?:u00|x)1b|\x1b)\[\d+(?:;\d+|)m + +# URL escaped characters +\%[0-9A-F][A-F] +# IPv6 +\b(?:[0-9a-fA-F]{0,4}:){3,7}[0-9a-fA-F]{0,4}\b +# c99 hex digits (not the full format, just one I've seen) +0x[0-9a-fA-F](?:\.[0-9a-fA-F]*|)[pP] +# Punycode +\bxn--[-0-9a-z]+ +# sha +sha\d+:[0-9]*[a-f]{3,}[0-9a-f]* +# sha-... -- uses a fancy capture +(['"]|")[0-9a-f]{40,}\g{-1} +# hex runs +\b[0-9a-fA-F]{16,}\b +# hex in url queries +=[0-9a-fA-F]*?(?:[A-F]{3,}|[a-f]{3,})[0-9a-fA-F]*?& +# ssh +(?:ssh-\S+|-nistp256) [-a-zA-Z=;:/0-9+]{12,} + +# PGP +\b(?:[0-9A-F]{4} ){9}[0-9A-F]{4}\b +# GPG keys +\b(?:[0-9A-F]{4} ){5}(?: [0-9A-F]{4}){5}\b +# Well known gpg keys +.well-known/openpgpkey/[\w./]+ + +# uuid: +\b[0-9a-fA-F]{8}-(?:[0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}\b +# hex digits including css/html color classes: +(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9_a-fA-FgGrR]*?[a-fA-FgGrR]{2,}[0-9_a-fA-FgGrR]*(?:[uUlL]{0,3}|u\d+)\b +# integrity +integrity="sha\d+-[-a-zA-Z=;:/0-9+]{40,}" + +# https://www.gnu.org/software/groff/manual/groff.html +# man troff content +\\f[BCIPR] +# ' +\\\(aq + +# .desktop mime types +^MimeTypes?=.*$ +# .desktop localized entries +^[A-Z][a-z]+\[[a-z]+\]=.*$ +# Localized .desktop content +Name\[[^\]]+\]=.* + +# IServiceProvider +\bI(?=(?:[A-Z][a-z]{2,})+\b) + +# crypt +"\$2[ayb]\$.{56}" + +# scrypt / argon +\$(?:scrypt|argon\d+[di]*)\$\S+ + +# Input to GitHub JSON +content: "[-a-zA-Z=;:/0-9+]*=" + +# Python stringprefix / binaryprefix +# Note that there's a high false positive rate, remove the `?=` and search for the regex to see if the matches seem like reasonable strings +(?v# +(?:(?<=[A-Z]{2})V|(?<=[a-z]{2}|[A-Z]{2})v)\d+(?:\b|(?=[a-zA-Z_])) +# Compiler flags (Scala) +(?:^|[\t ,>"'`=(])-J-[DPWXY](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}) +# Compiler flags +(?:^|[\t ,"'`=(])-[DPWXYLlf](?=[A-Z]{2,}|[A-Z][a-z]|[a-z]{2,}) +# Compiler flags (linker) +,-B +# curl arguments +\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)* +# set arguments +\bset(?:\s+-[abefimouxE]{1,2})*\s+-[abefimouxE]{3,}(?:\s+-[abefimouxE]+)* +# tar arguments +\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+ +# tput arguments -- https://man7.org/linux/man-pages/man5/terminfo.5.html -- technically they can be more than 5 chars long... +\btput\s+(?:(?:-[SV]|-T\s*\w+)\s+)*\w{3,5}\b +# macOS temp folders +/var/folders/\w\w/[+\w]+/(?:T|-Caches-)/ diff --git a/.github/actions/spelling/excludes.txt b/.github/actions/spelling/excludes.txt new file mode 100644 index 00000000000..a340a91c70c --- /dev/null +++ b/.github/actions/spelling/excludes.txt @@ -0,0 +1,70 @@ +# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-excludes + +(?:^|/)(?i)COPYRIGHT +(?:^|/)(?i)LICEN[CS]E +(?:^|/)3rdparty/ +(?:^|/)go\.sum$ +(?:^|/)package(?:-lock|)\.json$ +(?:^|/)vendor/ + +/fonts/ +ignore$ + +\.avi$ +\.bmp$ +\.bz2$ +\.class$ +\.crt$ +\.dll$ +\.docx?$ +\.drawio$ +\.DS_Store$ +\.eot$ +\.exe$ +\.gif$ +\.gitattributes$ +\.graffle$ +\.gz$ +\.icns$ +\.ico$ +\.jar$ +\.jks$ +\.jpe?g$ +\.key$ +\.lib$ +\.lock$ +\.map$ +\.min\.. +\.mod$ +\.mp[34]$ +\.o$ +\.ocf$ +\.otf$ +\.pdf$ +\.pem$ +\.png$ +\.psd$ +\.pyc$ +\.s$ +\.svgz?$ +\.tar$ +\.tiff?$ +\.ttf$ +\.wav$ +\.webm$ +\.webp$ +\.woff$ +\.woff2$ +\.xlsx?$ +\.zip$ + +^docs/pages/redirects/github\.html$ +^lib/jekyll/mime\.types$ +^lib/theme_template/example/index\.html$ +^lib/theme_template/example/_post\.md$ +^test/fixtures/empty_permalink\.erb$ +^test/fixtures/webrick/bar/baz\.html$ +^test/fixtures/webrick/bar/foo\.xhtml$ +^test/source/_posts/2009-06-22-no-yaml\.markdown$ +^\.github/ +^\Q.github/workflows/spelling.yml\E$ diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt new file mode 100644 index 00000000000..bf9b463a9b3 --- /dev/null +++ b/.github/actions/spelling/expect.txt @@ -0,0 +1,479 @@ +adaoraul +AFile +afterall +Alexey +alfredxing +Anatoliy +andreyvit +Ankit +Anning +appveyor +arengu +ariejan +asciinema +asdf +ashmaroli +Autobuild +autoreconf +awood +awscli +backticks +barcamp +bbatsov +bdimcheff +bellvat +benbalter +Beney +binstubs +bitbucket +Blogger +blogging +blogs +bonafide +Bou +breadcrumbs +briandoll +bridgetown +bridgetownrb +brightbox +brighterplanet +buddyworks +builtatlightspeed +Burela +byparker +cachegrind +calavera +callgraphs +cartera +cavalle +CDNs +cgi +chango +Chayoung +Cheatsheet +Checkoway +Chrononaut +cibuild +cimg +circleci +CJK +classname +cloudcannon +Cloudinary +cloudsh +CLT +codeclimate +CODEOWNERS +coderay +codeslinger +colorator +commonmark +compatibilize +configyml +contentblocks +Cov +CRLFs +cruft +Currin +cygwin +daringfireball +Dassonville +datafiles +DCEU +Debian +defunkt +delegators +devcontainer +digitalocean +disqus +ditaa +dnf +doclist +doeorg +dommmel +dotfile +Dousse +duckduckgo +duritong +Dusseau +dysinger +ecf +eduardoboucas +Emacs +emojis +endcapture +endraw +endrender +endtablerow +Enumerables +erb +errordocument +Espinaco +eugenebolshakov +evaled +extnames +exts +Fengyun +ffi +Finazzo +firstimage +flakey +flickr +fontello +forloop +formcake +formcarry +formester +formingo +formkeep +formspark +formspree +formx +freenode +fsnotify +fullstory +Gaudino +gcc +gcnovus +gemfile +getform +getset +getsimpleform +gettalong +ghp +ghpages +giraffeacademy +githubcom +gitlab +gjtorikian +globbed +gotcha +Goulven +gridism +GSo +gsubbing +hashbang +henrik +heroku +hilighting +Hoizey +hostman +htmlproofer +Iaa +ial +iconset +ified +invokables +ivey +ize +jalali +jamstackthemes +jan +Jax +jcon +jdoe +jeffreytse +jeffrydegrande +Jekpack +jekyllbot +jekyllconf +Jekyllers +Jekyllin +jekyllized +jekylllayoutconcept +jekyllrb +jekyllthemes +jekyllup +jemoji +jmcglone +johnreilly +jqr +jsonify +juretta +jwarby +Kacper +Kasberg +Kentico +Kewin +keycdn +kickster +Kinnula +kinsta +kiwifruit +Kolesky +konklone +kontent +Kotvinsky +kramdown +Kulig +Kwokfu +Lamprecht +launchctl +launchy +laurilehmijoki +learnxinyminutes +lexers +linenos +linkify +liufengyun +localheinz +Locher +Losslessly +lovin +lsi +lstrip +lyche +macromates +mademistakes +Manmeet +markdownify +Maroli +Marsceill +maruku +mathjax +mathml +mattr +Maximiliano +mchung +memberspace +mentoring +mergable +Mertcan +mertkahyaoglu +metadatas +microdata +minibundle +Mittal +mkasberg +mkd +mkdn +mkdown +modernizr +mojombo +moncefbelyamani +moz +mreid +mswin +MSYS +Mvvm +myblog +mycontent +mydata +mydoc +myimage +mypage +myposts +myproject +myrepo +myvalue +myvar +Nadjib +nakanishi +navbars +nearlyfreespeech +nethack +netlify +Neue +nginx +ngx +nielsenramon +noifniof +notextile +onebox +oneclick +opensource +Optim +orderofinterpretation +OSVDB +osx +packagecontrol +pacman +pandoc +pantulis +parkr +parseable +paspagon +passthrough +pathawks +Pathutil +paywall +PDFs +Pelykh +pinboard +Piwigo +pjhyett +pkill +pkpass +planetjekyll +plantuml +podcasts +Porcel +Posterous +postfiles +postmodern +preinstalled +Prioritise +Probot +projectlist +pubstorm +pufuwozu +pygments +qrush +Quaid +rackup +razorops +rdiscount +realz +rebund +redcarpet +redcloth +redgreen +redhat +Refactors +Refheap +regen +remi +Responsify +revertable +rfelix +RHEL +ridk +rstrip +rtomayko +Rubo +rubychan +rubyinstaller +rubyprof +Ruparelia +Rusiczki +rvm +saas +samplelist +samrayner +Sassc +Schroers +Schwartzian +screenshot +scrollbars +SDKROOT +sectore +seo +shingo +shopify +shortlinks +shortlog +shoulda +sieversii +sigpipe +Singhaniya +siteleaf +SITENAME +Slicehost +slugified +smartforms +smartify +snipcart +socio +somedir +sonnym +Sonomy +sourced +spam +spotify +ssg +standalone +staticman +Stickyposts +styleguide +subdir +subdomain +subfolderitems +subpages +subpiece +subsubfolderitems +subthing +subvalues +subwidget +superdirectories +superdirs +SUSE +sverrirs +swfobject +swupd +tada +Taillandier +talkyard +technicalpickles +templating +Termux +textilize +textpattern +Theunissen +Thornquest +throughs +Tidelift +timeago +timezones +tmm +tomjoht +tomo +toshimaru +triaged +triaging +tsv +Tudou +Tumblr +Tweetsert +txtpen +Tyborska +tzinfo +ujh +ultron +undumpable +unencode +uppercasing +urlset +usernames +utm +vanpelt +Vasovi +vendored +versioned +versioning +vertycal +Veyor +vilcans +Vishesh +vnd +vohedge +vps +vwochnik +WAI +wdm +We'd +webfonts +webhosting +webmentions +website +wildcards +willcodeforfoo +wordpress +workflows +xcode +xdg +Xhmikos +Xiaoiver +XMinutes +xmlschema +Yarp +Yashu +Yastreb +Youku +youtube +yunbox +zeropadding +Zlatan +zoneinfo +zpinter +zypper +zzot diff --git a/.github/actions/spelling/line_forbidden.patterns b/.github/actions/spelling/line_forbidden.patterns new file mode 100644 index 00000000000..31ad2ddcd26 --- /dev/null +++ b/.github/actions/spelling/line_forbidden.patterns @@ -0,0 +1,62 @@ +# reject `m_data` as there's a certain OS which has evil defines that break things if it's used elsewhere +# \bm_data\b + +# If you have a framework that uses `it()` for testing and `fit()` for debugging a specific test, +# you might not want to check in code where you were debugging w/ `fit()`, in which case, you might want +# to use this: +#\bfit\( + +# s.b. GitHub +\bGithub\b + +# s.b. GitLab +\bGitlab\b + +# s.b. JavaScript +\bJavascript\b + +# s.b. Microsoft +\bMicroSoft\b + +# s.b. another +\ban[- ]other\b + +# s.b. greater than +\bgreater then\b + +# s.b. into +#\sin to\s + +# s.b. opt-in +\sopt in\s + +# s.b. less than +\bless then\b + +# s.b. otherwise +\bother[- ]wise\b + +# s.b. nonexistent +\bnon existing\b +\b[Nn]o[nt][- ]existent\b + +# s.b. preexisting +[Pp]re[- ]existing + +# s.b. preempt +[Pp]re[- ]empt\b + +# s.b. preemptively +[Pp]re[- ]emptively + +# s.b. reentrancy +[Rr]e[- ]entrancy + +# s.b. reentrant +[Rr]e[- ]entrant + +# s.b. workaround(s) +#\bwork[- ]arounds?\b + +# Reject duplicate words +\s([A-Z]{3,}|[A-Z][a-z]{2,}|[a-z]{3,})\s\g{-1}\s diff --git a/.github/actions/spelling/only.txt b/.github/actions/spelling/only.txt new file mode 100644 index 00000000000..af5f5b1cceb --- /dev/null +++ b/.github/actions/spelling/only.txt @@ -0,0 +1 @@ +^docs/.*\.md$ diff --git a/.github/actions/spelling/patterns.txt b/.github/actions/spelling/patterns.txt new file mode 100644 index 00000000000..53e41f97601 --- /dev/null +++ b/.github/actions/spelling/patterns.txt @@ -0,0 +1,164 @@ +# See https://github.com/check-spelling/check-spelling/wiki/Configuration-Examples:-patterns + +# data urls +(['"])data:.*?\g{-1} +data:[-a-zA-Z=;:/0-9+]*,\S* + +# YouTube +https?://(?:(?:www\.|)youtube\.com|youtu.be)/(?:channel/|embed/|playlist\?list=|watch\?v=|v/|)[-a-zA-Z0-9?&=_]* +<\s*youtube\s+id=['"][-a-zA-Z0-9?_]*['"] +\bimg\.youtube\.com/vi/[-a-zA-Z0-9?&=_]* +youtube_id:\s*[-a-zA-Z0-9?&=_]* + +# Google Analytics +\bgoogle-analytics\.com/collect.[-0-9a-zA-Z?%=&_.~]* + +# Google APIs +\bgoogleapis\.com/[a-z]+/v\d+/[a-z]+/[@./?=\w]+ +\b[-a-zA-Z0-9.]*\bstorage\d*\.googleapis\.com(?:/\S*|) + +# Google Calendar +\bcalendar\.google\.com/calendar(?:/u/\d+|)/embed\?src=[@./?=\w&%]+ +\w+\@group\.calendar\.google\.com\b + +# Google DataStudio +\bdatastudio\.google\.com/(?:(?:c/|)u/\d+/|)(?:embed/|)(?:open|reporting|datasources|s)/[-0-9a-zA-Z]+(?:/page/[-0-9a-zA-Z]+|) + +# The leading `/` here is as opposed to the `\b` above +# ... a short way to match `https://` or `http://` since most urls have one of those prefixes +# Google Docs +/docs\.google\.com/[a-z]+/d/(?:e/|)[0-9a-zA-Z_-]+/? + +# Google Groups +https://groups\.google\.com/d/topic/[^/]+/[a-zA-Z0-9]+/discussion +https://groups\.google\.com/d/msg/[^/]+/[a-zA-Z0-9]+/[a-zA-Z0-9]+ + +# Google themes +themes\.googleusercontent\.com/static/fonts/[^/]+/v\d+/[^.]+. + +# Google CDN +\bclients2\.google(?:usercontent|)\.com[-0-9a-zA-Z/.]* + +# Goo.gl +/goo\.gl/[a-zA-Z0-9]+ + +# Google Chrome Store +\bchrome\.google\.com/webstore/detail/\w*(?:/\w*|) + +# google_site_verification: +google_site_verification: [-a-zA-Z=;:/0-9+]* + +# Ruby-doc.org +https://ruby-doc\.org/.* + +# Contributors +alphabetical order.*:.* +twitter_handle: .* + +# apiKey +apiKey: '[a-f0-9]+' + +# FontAwesome +/(?:(?i)FontAwesome\.\w+\?\w+) + +# Lorem +(?:\w|\s|[,.])*\b(?i)(?:amet|consectetur|cursus|dolor|eros|ipsum|lacus|libero|ligula|lorem|magna|neque|nulla|suscipit|tempus|ultrices)\b(?:\w|\s|[,.])* + +# URL escaped characters +\%[0-9A-F]{2} +# c99 hex digits (not the full format, just one I've seen) + +# hex digits including css/html color classes: +(?:[\\0][xX]|\\u|[uU]\+|#x?|\%23)[0-9a-fA-FgGrR_]{2,}(?:[uU]?[lL]{0,2}|u\d+)\b + +# Automatically suggested patterns +# hit-count: 23 file-count: 15 +# GitHub SHAs (markdown) +(?:\[`?[0-9a-f]+`?\]\(https:/|)/(?:www\.|)github\.com(?:/[^/\s"]+){2,}(?:/[^/\s")]+)(?:[0-9a-f]+(?:[-0-9a-zA-Z/#.]*|)\b|) + +# hit-count: 7 file-count: 4 +# Wikipedia +\ben\.wikipedia\.org/wiki/[-\w%.#]+ + +# hit-count: 5 file-count: 3 +# Non-English +[a-zA-Z]*[ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź][a-zA-Z]{3}[a-zA-ZÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿĀāŁłŃńŅņŒœŚśŠšŜŝŸŽžź]* + +# hit-count: 4 file-count: 4 +# Twitter status +\btwitter\.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|) + +# hit-count: 3 file-count: 3 +# stackexchange -- https://stackexchange.com/feeds/sites +\b(?:askubuntu|serverfault|stack(?:exchange|overflow)|superuser).com/(?:questions/\w+/[-\w]+|a/) + +# hit-count: 3 file-count: 2 +# vs devops +\bvisualstudio.com(?::443|)/[-\w/?=%&.]* + +# hit-count: 2 file-count: 2 +# mailto urls +mailto:[-a-zA-Z=;:/?%&0-9+@.]{3,} + +# hit-count: 2 file-count: 2 +# githubusercontent +/[-a-z0-9]+\.githubusercontent\.com/[-a-zA-Z0-9?&=_\/.]* + +# hit-count: 2 file-count: 2 +# hex runs +\b[0-9a-fA-F]{16,}\b + +# hit-count: 2 file-count: 2 +# curl arguments +\b(?:\\n|)curl(?:\s+-[a-zA-Z]{1,2}\b)*(?:\s+-[a-zA-Z]{3,})(?:\s+-[a-zA-Z]+)* + +# hit-count: 2 file-count: 1 +# microsoft +\b(?:https?://|)(?:(?:download\.visualstudio|docs|msdn2?|research)\.microsoft|blogs\.msdn)\.com/[-_a-zA-Z0-9()=./%]* + +# hit-count: 1 file-count: 1 +# Amazon +\bamazon\.com/[-\w]+/(?:dp/[0-9A-Z]+|) + +# hit-count: 1 file-count: 1 +# gist github +\bgist\.github\.com/[^/\s"]+/[0-9a-f]+ + +# hit-count: 1 file-count: 1 +# Contributor +\[[^\]]+\]\(https://github\.com/[^/\s"]+\) + +# hit-count: 1 file-count: 1 +# medium +\bmedium\.com/\@?[^/\s"]+/[-\w]+ + +# hit-count: 1 file-count: 1 +# Twitter markdown +\[\@[^[/\]:]*?\]\(https://twitter.com/[^/\s"')]*(?:/status/\d+(?:\?[-_0-9a-zA-Z&=]*|)|)\) + +# Questionably acceptable forms of `in to` +# Personally, I prefer `log into`, but people object +# https://www.tprteaching.com/log-into-log-in-to-login/ +\b[Ll]og in to\b + +# acceptable duplicates +# ls directory listings +[-bcdlpsw](?:[-r][-w][-sx]){3}\s+\d+\s+(\S+)\s+\g{-1}\s+\d+\s+ +# C types and repeated CSS values +\s(center|div|inherit|long|LONG|none|normal|solid|thin|transparent|very)(?: \g{-1})+\s +# go templates +\s(\w+)\s+\g{-1}\s+\`(?:graphql|json|yaml): +# javadoc / .net +(?:[\\@](?:groupname|param)|(?:public|private)(?:\s+static|\s+readonly)*)\s+(\w+)\s+\g{-1}\s + +# Commit message -- Signed-off-by and friends +^\s*(?:(?:Based-on-patch|Co-authored|Helped|Mentored|Reported|Reviewed|Signed-off)-by|Thanks-to): (?:[^<]*<[^>]*>|[^<]*)\s*$ + +# Autogenerated revert commit message +^This reverts commit [0-9a-f]{40}\.$ + +# ignore long runs of a single character: +\b([A-Za-z])\g{-1}{3,}\b + +# ignore inline code +`\w+` diff --git a/.github/actions/spelling/reject.txt b/.github/actions/spelling/reject.txt new file mode 100644 index 00000000000..b5a6d36809f --- /dev/null +++ b/.github/actions/spelling/reject.txt @@ -0,0 +1,10 @@ +^attache$ +benefitting +occurences? +^dependan.* +^oer$ +Sorce +^[Ss]pae.* +^untill$ +^untilling$ +^wether.* diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 00000000000..3015da13f66 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,15 @@ +updateDocsComment: > + Thanks for opening this pull request! The maintainers of this repository would appreciate it if you would update some of our documentation based on your changes. + +updateDocsWhiteList: + - bug + - fix + - Backport + - dev + - Update + - WIP + - chore + +updateDocsTargetFiles: + - README + - docs/ diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..aaee7280c27 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: bundler + reviewers: + - "jekyll/core" + directory: / + schedule: + interval: weekly diff --git a/.github/first-timers-issue-template.md b/.github/first-timers-issue-template.md new file mode 100644 index 00000000000..c7787911a36 --- /dev/null +++ b/.github/first-timers-issue-template.md @@ -0,0 +1,44 @@ +### 🆕🐥☝ First Timers Only. + +This issue is reserved for people who never contributed to Open Source before. We know that the process of creating a pull request is the biggest barrier for new contributors. This issue is for you 💝 + +[About First Timers Only](https://www.firsttimersonly.com/). + +### 🤔 What you will need to know. + +Nothing. This issue is meant to welcome you to Open Source :) We are happy to walk you through the process. + +### 📋 Step by Step + +- [ ] 👌 **Join the team**: Add yourself to a Jekyll affinity team. + + Go to [teams.jekyllrb.com](https://teams.jekyllrb.com/) and join a team that best fits your interests. Once you click the link to join a team, you will soon receive an email inviting you to join the Jekyll organization. + +- [ ] 🙋 **Claim this issue**: Comment below. + + Leave a comment that you have claimed this issue. + +- [ ] 📝 **Update** the file [$FILENAME]($BRANCH_URL) in the `$REPO` repository (press the little pen Icon) and edit the line as shown below. + + +```diff +$DIFF +``` + + +- [ ] 💾 **Commit** your changes + +- [ ] 🔀 **Start a Pull Request**. There are two ways how you can start a pull request: + + 1. If you are familiar with the terminal or would like to learn it, [here is a great tutorial](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) on how to send a pull request using the terminal. + + 2. You can [edit files directly in your browser](https://help.github.com/articles/editing-files-in-your-repository/) + +- [ ] 🏁 **Done** Ask in comments for a review :) + +### 🤔❓ Questions + +Leave a comment below! + + +This issue was created by [First-Timers-Bot](https://github.com/hoodiehq/first-timers-bot). diff --git a/.github/first-timers.yml b/.github/first-timers.yml new file mode 100644 index 00000000000..9f866d72324 --- /dev/null +++ b/.github/first-timers.yml @@ -0,0 +1,6 @@ +repository: jekyll +labels: + - good first issue + - help-wanted + - first-time-only +template: .github/first-timers-issue-template.md diff --git a/.github/release-please-config.json b/.github/release-please-config.json new file mode 100644 index 00000000000..5f0f80976f9 --- /dev/null +++ b/.github/release-please-config.json @@ -0,0 +1,17 @@ +{ + "pull-request-title-pattern": "chore: release 💎 ${version}", + "packages": { + ".": { + "changelog-path": "History.markdown", + "release-type": "ruby", + "bump-minor-pre-major": false, + "bump-patch-for-minor-pre-major": false, + "draft": false, + "prerelease": false, + "include-component-in-tag": false, + "include-v-in-tag": true, + "version-file": "lib/jekyll/version.rb" + } + }, + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json" +} diff --git a/.github/release-please-manifest.json b/.github/release-please-manifest.json new file mode 100644 index 00000000000..f4b3cc51344 --- /dev/null +++ b/.github/release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "4.4.1" +} diff --git a/.github/workflows/actions/memprof.rb b/.github/workflows/actions/memprof.rb new file mode 100644 index 00000000000..f54186c1a47 --- /dev/null +++ b/.github/workflows/actions/memprof.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'jekyll' +require 'memory_profiler' + +MemoryProfiler.report(allow_files: ['lib/jekyll/', 'lib/jekyll.rb']) do + Jekyll::PluginManager.require_from_bundler + Jekyll::Commands::Build.process({ + "source" => File.expand_path(ARGV[0]), + "destination" => File.expand_path("#{ARGV[0]}/_site"), + "disable_disk_cache" => true, + }) + puts '' +end.pretty_print(scale_bytes: true, normalize_paths: true) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml new file mode 100644 index 00000000000..29052a248b4 --- /dev/null +++ b/.github/workflows/benchmark.yml @@ -0,0 +1,30 @@ +name: Micro Benchmark Runs + +on: + workflow_dispatch: + inputs: + path: + description: "Path to benchmark script relative to 'benchmark' directory." + required: true + default: "capture-assign.rb" + ruby_version: + description: "Ruby version to use (via `ruby/setup-ruby@v1`) action." + required: false + default: "2.7" + +jobs: + benchmark: + name: "Benchmark (${{ github.event.inputs.path }}) (Ruby ${{ github.event.inputs.ruby_version }})" + runs-on: "ubuntu-latest" + env: + BENCHMARK: true + steps: + - name: Checkout Jekyll + uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ github.event.inputs.ruby_version }} + bundler-cache: true + - name: Run Benchmark + run: "bundle exec ruby benchmark/${{ github.event.inputs.path }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..99c7389a855 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,87 @@ +name: Continuous Integration + +on: + push: + branches: + - master + - "*-stable" + paths-ignore: + - "docs/**" + pull_request: + branches: + - master + - "*-stable" + paths-ignore: + - "docs/**" + +jobs: + ci: + name: "Run Tests (${{ matrix.ruby.label }} on ${{ matrix.os.label }})" + runs-on: ${{ matrix.os.image }} + strategy: + fail-fast: false + matrix: + ruby: + - label: Ruby 2.7 + version: "2.7" + - label: Ruby 3.3 + version: "3.3" + - label: Ruby 3.4 + version: "3.4" + os: + - label: Linux + image: "ubuntu-latest" + - label: Windows + image: "windows-latest" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: "Set up ${{ matrix.ruby.label }}" + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby.version }} + bundler-cache: true + - name: Run Minitest based tests + run: bash script/test + - name: Run Cucumber based tests + run: bash script/cucumber --color + - name: Generate and Build a new site + run: bash script/default-site + + xtras: + name: "${{ matrix.job_name }} (${{ matrix.setup_label }})" + runs-on: "ubuntu-latest" + strategy: + fail-fast: false + matrix: + include: + - job_name: "Unit Test with JRuby" + setup_label: "JRuby 9.4.8.0" + step_name: "Run Minitest based tests" + script_file: "test" + ruby_version: "jruby-9.4.8.0" + - job_name: "Smoke Test with JRuby" + setup_label: "JRuby 9.4.8.0" + step_name: "Generate and Build a new site" + script_file: "default-site" + ruby_version: "jruby-9.4.8.0" + - job_name: "Profile Docs Site" + setup_label: "Ruby 2.7" + step_name: "Build and Profile docs site" + script_file: "profile-docs" + ruby_version: "2.7" + - job_name: "Style Check" + setup_label: "Ruby 2.7" + step_name: "Run RuboCop" + script_file: "fmt" + ruby_version: "2.7" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: "Set up ${{ matrix.setup_label }}" + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby_version }} + bundler-cache: true + - name: ${{ matrix.step_name }} + run: bash script/${{ matrix.script_file }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..8687ac80057 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,65 @@ +name: "CodeQL" + +on: +# push: +# branches: [ 'master' ] +# pull_request: +# # The branches below must be a subset of the branches above +# branches: [ 'master' ] + schedule: + - cron: '56 11 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'ruby', 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Use only 'java' to analyze code written in Java, Kotlin or both + # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml new file mode 100644 index 00000000000..3d8c47c6ee8 --- /dev/null +++ b/.github/workflows/conventional-commits.yml @@ -0,0 +1,50 @@ +# This workflow checks to ensure that all PR titles conform to the conventional +# commit spec and use the correct type and scopes. The spec for conventional +# commits can be found at https://www.conventionalcommits.org and there is a +# nice cheatsheet in a github gist at +# https://gist.github.com/qoomon/5dfcdf8eec66a051ecd85625518cfd13 +# +# The types in this workflow match the spec. The scopes are custom to +# Jekyll and can be changed if desired. +name: Conventional Commit Check + +permissions: + pull-requests: read + +on: + pull_request_target: + types: [opened, edited, synchronize, reopened, ready_for_review] + branches: + - master + +jobs: + commit_lint: + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5.5.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + perf + refactor + docs + style + test + chore + scopes: | + core + cli + commands + plugins + site + helpers + converters + filters + tags + drops + tests + docs + requireScope: false diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000000..a2c941976dd --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,54 @@ +name: Build and deploy Jekyll documentation site + +on: + push: + branches: + - master + paths: + - "docs/**" + +env: + RUBY_VERSION: 2.7 + +jobs: + deploy_docs: + if: "!contains(github.event.commits[0].message, '[ci skip]')" + runs-on: 'ubuntu-latest' + env: + BUNDLE_PATH: "vendor/bundle" + BUNDLE_JOBS: 4 + BUNDLE_RETRY: 3 + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ env.RUBY_VERSION }} + bundler-cache: true + - name: Clone target branch + run: | + REMOTE_BRANCH="${REMOTE_BRANCH:-gh-pages}" + REMOTE_REPO="https://${GITHUB_ACTOR}:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git" + + echo "Publishing to ${GITHUB_REPOSITORY} on branch ${REMOTE_BRANCH}" + rm -rf docs/_site/ + git clone --depth=1 --branch="${REMOTE_BRANCH}" --single-branch --no-checkout \ + "${REMOTE_REPO}" docs/_site/ + - name: Build site + run: bundle exec jekyll build --source docs --destination docs/_site --verbose --trace + env: + # For jekyll-github-metadata + JEKYLL_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Deploy to GitHub Pages + run: | + SOURCE_COMMIT="$(git log -1 --pretty="%an: %B" "$GITHUB_SHA")" + pushd docs/_site &>/dev/null + : > .nojekyll + + git add --all + git -c user.name="${GITHUB_ACTOR}" -c user.email="${GITHUB_ACTOR}@users.noreply.github.com" \ + commit --quiet \ + --message "Deploy docs from ${GITHUB_SHA}" \ + --message "$SOURCE_COMMIT" + git push + + popd &>/dev/null diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 00000000000..a869cd727f7 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,44 @@ +name: "Release, please!" + +on: + push: + branches: + - master + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + if: ${{ github.repository == 'jekyll/jekyll' }} + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - name: Run Release Please + id: release + uses: googleapis/release-please-action@v4 + with: + config-file: .github/release-please-config.json + manifest-file: .github/release-please-manifest.json + token: ${{ secrets.JEKYLLBOT_TOKEN }} + + publish-gem: + needs: release-please + if: ${{ needs.release-please.outputs.release_created == 'true' }} + runs-on: ubuntu-latest + permissions: + id-token: write + contents: write + steps: + - name: Checkout Repository + uses: actions/checkout@v6 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + - name: Build and Publish Gem + uses: rubygems/release-gem@v1 diff --git a/.github/workflows/spelling.yml b/.github/workflows/spelling.yml new file mode 100644 index 00000000000..a88313a4a7c --- /dev/null +++ b/.github/workflows/spelling.yml @@ -0,0 +1,95 @@ +name: Spell Check + +# Comment management is handled through a secondary job, for details see: +# https://github.com/check-spelling/check-spelling/wiki/Feature%3A-Restricted-Permissions +# +# `jobs.comment-push` runs when a push is made to a repository and the `jobs.spelling` job needs to make a comment +# (in odd cases, it might actually run just to collapse a comment, but that's fairly rare) +# it needs `contents: write` in order to add a comment. +# +# `jobs.comment-pr` runs when a pull_request is made to a repository and the `jobs.spelling` job needs to make a comment +# or collapse a comment (in the case where it had previously made a comment and now no longer needs to show a comment) +# it needs `pull-requests: write` in order to manipulate those comments. + +# Updating pull request branches is managed via comment handling. +# For details, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-expect-list +# +# These elements work together to make it happen: +# +# `on.issue_comment` +# This event listens to comments by users asking to update the metadata. +# +# `jobs.update` +# This job runs in response to an issue_comment and will push a new commit +# to update the spelling metadata. +# +# `with.experimental_apply_changes_via_bot` +# Tells the action to support and generate messages that enable it +# to make a commit to update the spelling metadata. +# +# `with.ssh_key` +# In order to trigger workflows when the commit is made, you can provide a +# secret (typically, a write-enabled github deploy key). +# +# For background, see: https://github.com/check-spelling/check-spelling/wiki/Feature:-Update-with-deploy-key + +on: + # Switch from `pull_request_target` event to reduce distraction from comments + # regarding errors reported in unmodified files. + pull_request: + branches: + - master + - "*-stable" + tags-ignore: + - "**" + types: + - 'opened' + - 'reopened' + - 'synchronize' + +jobs: + spelling: + name: Spell Check + permissions: + contents: read + pull-requests: read + actions: read + outputs: + followup: ${{ steps.spelling.outputs.followup }} + runs-on: ubuntu-latest + if: "contains(github.event_name, 'pull_request') || github.event_name == 'push'" + concurrency: + group: spelling-${{ github.event.pull_request.number || github.ref }} + # note: If you use only_check_changed_files, you do not want cancel-in-progress + cancel-in-progress: true + steps: + - name: check-spelling + id: spelling + uses: check-spelling/check-spelling@v0.0.26 + with: + # This workflow runs in response to both `push` and `pull_request`, if there's an open `pull_request` in the same repository + # for a given branch, there's no reason to spend resources checking both the `push` and the `pull_request`, so this flag tells + # the action while running for the `push` to find the `pull_request` and stop working early: + suppress_push_for_open_pull_request: 1 + # The action will manage checking out the repository itself instead of requiring the workflow to use `actions/checkout...`: + checkout: true + # If running without `: write`, posting a comment won't work, and for security `: write` permissions are left to a distinct + # (optional) job, here we skip trying to post a comment: + post_comment: 0 + use_magic_file: 1 + extra_dictionary_limit: 10 + extra_dictionaries: + cspell:software-terms/software-terms.txt + cspell:php/php.txt + cspell:node/node.txt + cspell:django/django.txt + cspell:html/html.txt + cspell:npm/npm.txt + cspell:ruby/ruby.txt + cspell:fullstack/fullstack.txt + cspell:filetypes/filetypes.txt + check_extra_dictionaries: '' + dictionary_source_prefixes: >- + {"cspell": "https://raw.githubusercontent.com/check-spelling/cspell-dicts/v20241114/dictionaries/"} + +# This workflow has opted not to use comments (users can view the report in GitHub Step Summary) diff --git a/.github/workflows/third-party.yml b/.github/workflows/third-party.yml new file mode 100644 index 00000000000..7e9498ca4b6 --- /dev/null +++ b/.github/workflows/third-party.yml @@ -0,0 +1,36 @@ +name: Third-Party Repository Profiling + +on: + workflow_dispatch: + +jobs: + build_n_profile: + runs-on: "ubuntu-latest" + env: + BUNDLE_GEMFILE: "sandbox/Gemfile" + BUNDLE_PATH: "vendor/bundle" + BUNDLE_JOBS: 4 + BUNDLE_RETRY: 3 + steps: + - name: Checkout Jekyll + uses: actions/checkout@v4 + with: + fetch-depth: 5 + path: jekyll + - name: Checkout Third-Party Repository + uses: actions/checkout@v4 + with: + repository: ashmaroli/tomjoht.github.io + path: sandbox + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.4 + bundler-cache: true + - name: Run Jekyll Build 3 times + run: | + bundle exec jekyll build -s sandbox -d sandbox/_site --trace + bundle exec jekyll build -s sandbox -d sandbox/_site --trace + bundle exec jekyll build -s sandbox -d sandbox/_site --trace + - name: Memory Analysis of Jekyll Build + run: bundle exec ruby jekyll/.github/workflows/actions/memprof.rb sandbox diff --git a/.gitignore b/.gitignore index d75a4982cd2..0ef83cf9722 100644 --- a/.gitignore +++ b/.gitignore @@ -1,20 +1,28 @@ -Gemfile.lock -test/dest -*.gem -pkg/ -*.swp -*~ +# Jekyll _site/ +*-cache/ +.jekyll-metadata + +# Ruby .bundle/ +.byebug_history +.ruby-gemset +.ruby-version +*.gem +Gemfile.lock + +# Files +.analysis .DS_Store +*.swp +*~ + +# Folders +/vendor bbin/ -gh-pages/ -site/_site/ +bin/ coverage -.ruby-version -.ruby-gemset -.sass-cache +gh-pages/ +pkg/ +test/dest tmp/* -.jekyll-metadata -/vendor -/test/source/file_name.txt diff --git a/.jrubyrc b/.jrubyrc index c4f93701522..39aa437d81f 100644 --- a/.jrubyrc +++ b/.jrubyrc @@ -1,6 +1,3 @@ backtrace.mask=true -compile.invokedynamic=true -objectspace.enabled=true backtrace.color=true -compat.version=2.2 backtrace.style=mri diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 00000000000..1ae42a4ac82 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,605 @@ +# ----------------------------------------------------------------------------- +# This file has been formatted via a Rake Task configuring cops from +# RuboCop v1.57.2. +# +# To add more cops, paste configurations at the end of the file and run +# the rake task via `bundle exec rake rubocop:format_config`. +# ----------------------------------------------------------------------------- + +inherit_from: ".rubocop_todo.yml" + +require: +- "./rubocop/jekyll" +- rubocop-minitest +- rubocop-performance +- rubocop-rake +- rubocop-rspec + +# Directive for all cops +AllCops: + TargetRubyVersion: 2.7 + Include: + - lib/**/*.rb + - test/**/*.rb + Exclude: + - benchmark/**/* + - bin/**/* + - exe/**/* + - script/**/* + - tmp/**/* + - vendor/**/* + +# Configure custom cop +Jekyll/NoPutsAllowed: + Exclude: + - rake/*.rake + +# Configure built-in cops +# ======================= + +# Gemspec cops +# ---------------------------------------- +Gemspec/DeprecatedAttributeAssignment: + Enabled: true +Gemspec/DevelopmentDependencies: + Enabled: false +Gemspec/RequireMFA: + Enabled: false + +# Layout cops +# ---------------------------------------- +Layout/BeginEndAlignment: + Enabled: true +Layout/EmptyComment: + Enabled: false +Layout/EmptyLinesAroundAttributeAccessor: + Enabled: true +Layout/EndAlignment: + Severity: error +Layout/EndOfLine: + Enabled: false +Layout/FirstArrayElementIndentation: + EnforcedStyle: consistent +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent +Layout/HashAlignment: + EnforcedHashRocketStyle: table +Layout/IndentationWidth: + Severity: error +Layout/LineContinuationLeadingSpace: + Enabled: true +Layout/LineContinuationSpacing: + Enabled: true +Layout/LineEndStringConcatenationIndentation: + Enabled: true +Layout/LineLength: + Exclude: + - Gemfile + - Rakefile + - features/**/*.rb + - rake/**/*.rake + Max: 100 + Severity: warning +Layout/MultilineMethodCallIndentation: + EnforcedStyle: indented +Layout/MultilineOperationIndentation: + EnforcedStyle: indented +Layout/SpaceAroundMethodCallOperator: + Enabled: true +Layout/SpaceBeforeBrackets: + Enabled: true +Layout/SpaceInsideHashLiteralBraces: + Enabled: true + Exclude: + - test/**/*.rb + +# Lint cops +# ---------------------------------------- +Lint/AmbiguousAssignment: + Enabled: true +Lint/AmbiguousOperatorPrecedence: + Enabled: true +Lint/AmbiguousRange: + Enabled: true +Lint/BinaryOperatorWithIdenticalOperands: + Enabled: true +Lint/ConstantDefinitionInBlock: + Enabled: true + Exclude: + - test/**/*.rb +Lint/ConstantOverwrittenInRescue: + Enabled: true +Lint/DeprecatedConstants: + Enabled: true +Lint/DeprecatedOpenSSLConstant: + Enabled: true +Lint/DuplicateBranch: + Enabled: true +Lint/DuplicateElsifCondition: + Enabled: true +Lint/DuplicateMagicComment: + Enabled: true +Lint/DuplicateMatchPattern: + Enabled: true +Lint/DuplicateRegexpCharacterClassElement: + Enabled: true +Lint/DuplicateRequire: + Enabled: true +Lint/DuplicateRescueException: + Enabled: true +Lint/EmptyBlock: + Enabled: true +Lint/EmptyClass: + Enabled: true +Lint/EmptyConditionalBody: + Enabled: true +Lint/EmptyFile: + Enabled: true +Lint/FloatComparison: + Enabled: true +Lint/HashCompareByIdentity: + Enabled: true +Lint/IdentityComparison: + Enabled: true +Lint/LambdaWithoutLiteralBlock: + Enabled: true +Lint/MissingSuper: + Enabled: false +Lint/MixedCaseRange: + Enabled: true +Lint/MixedRegexpCaptureTypes: + Enabled: false +Lint/NestedPercentLiteral: + Exclude: + - test/test_site.rb +Lint/NoReturnInBeginEndBlocks: + Enabled: true +Lint/NumberedParameterAssignment: + Enabled: true +Lint/OrAssignmentToConstant: + Enabled: true +Lint/OutOfRangeRegexpRef: + Enabled: true +Lint/RaiseException: + Enabled: true +Lint/RedundantDirGlobSort: + Enabled: true +Lint/RedundantRegexpQuantifiers: + Enabled: true +Lint/RedundantSafeNavigation: + Enabled: true +Lint/RefinementImportMethods: + Enabled: true +Lint/RequireRangeParentheses: + Enabled: true +Lint/RequireRelativeSelfPath: + Enabled: true +Lint/SelfAssignment: + Enabled: true +Lint/StructNewOverride: + Enabled: true +Lint/SymbolConversion: + Enabled: true +Lint/ToEnumArguments: + Enabled: false +Lint/TopLevelReturnWithArgument: + Enabled: true +Lint/TrailingCommaInAttributeDeclaration: + Enabled: true +Lint/TripleQuotes: + Enabled: true +Lint/UnexpectedBlockArity: + Enabled: true +Lint/UnmodifiedReduceAccumulator: + Enabled: true +Lint/UnreachableCode: + Severity: error +Lint/UnreachableLoop: + Enabled: true +Lint/UselessMethodDefinition: + Enabled: true +Lint/UselessRuby2Keywords: + Enabled: true +Lint/UselessTimes: + Enabled: true +Lint/Void: + Exclude: + - lib/jekyll/site.rb + +# Metrics cops +# ---------------------------------------- +Metrics/AbcSize: + Max: 23 +Metrics/BlockLength: + Exclude: + - lib/jekyll/configuration.rb + - rake/**/*.rake + - test/**/*.rb +Metrics/ClassLength: + Exclude: + - features/**/*.rb + - lib/jekyll/commands/serve.rb + - lib/jekyll/configuration.rb + - lib/jekyll/document.rb + - lib/jekyll/site.rb + - test/**/*.rb + Max: 240 +Metrics/CollectionLiteralLength: + Enabled: true +Metrics/CyclomaticComplexity: + Exclude: + - lib/jekyll/commands/serve.rb + - lib/jekyll/utils.rb + Max: 11 +Metrics/MethodLength: + CountComments: false + Max: 20 + Severity: error +Metrics/ModuleLength: + Exclude: + - lib/jekyll/filters.rb + Max: 240 +Metrics/ParameterLists: + Max: 4 +Metrics/PerceivedComplexity: + Max: 13 + +# Minitest cops +# ---------------------------------------- +Minitest/AssertEmptyLiteral: + Enabled: false +Minitest/AssertInDelta: + Enabled: true +Minitest/AssertKindOf: + Enabled: true +Minitest/AssertOperator: + Enabled: false +Minitest/AssertOutput: + Enabled: true +Minitest/AssertPathExists: + Enabled: true +Minitest/AssertPredicate: + Enabled: false +Minitest/AssertRaisesWithRegexpArgument: + Enabled: true +Minitest/AssertSame: + Enabled: true +Minitest/AssertSilent: + Enabled: true +Minitest/AssertWithExpectedArgument: + Enabled: true +Minitest/AssertionInLifecycleHook: + Enabled: true +Minitest/DuplicateTestRun: + Enabled: true +Minitest/EmptyLineBeforeAssertionMethods: + Enabled: false +Minitest/LifecycleHooksOrder: + Enabled: true +Minitest/LiteralAsActualArgument: + Enabled: true +Minitest/MultipleAssertions: + Enabled: true +Minitest/NonExecutableTestMethod: + Enabled: true +Minitest/NonPublicTestMethod: + Enabled: true +Minitest/RedundantMessageArgument: + Enabled: true +Minitest/RefuteInDelta: + Enabled: true +Minitest/RefuteKindOf: + Enabled: true +Minitest/RefuteOperator: + Enabled: false +Minitest/RefutePathExists: + Enabled: true +Minitest/RefutePredicate: + Enabled: false +Minitest/RefuteSame: + Enabled: true +Minitest/ReturnInTestMethod: + Enabled: true +Minitest/SkipEnsure: + Enabled: true +Minitest/SkipWithoutReason: + Enabled: true +Minitest/TestFileName: + Enabled: true + Exclude: + - test/helper.rb +Minitest/TestMethodName: + Enabled: false +Minitest/UnreachableAssertion: + Enabled: true +Minitest/UnspecifiedException: + Enabled: true +Minitest/UselessAssertion: + Enabled: true + +# Naming cops +# ---------------------------------------- +Naming/FileName: + Enabled: false +Naming/HeredocDelimiterNaming: + Exclude: + - test/**/*.rb +Naming/MemoizedInstanceVariableName: + Exclude: + - lib/jekyll/convertible.rb + - lib/jekyll/drops/site_drop.rb + - lib/jekyll/drops/unified_payload_drop.rb + - lib/jekyll/page_without_a_file.rb + +# Performance cops +# ---------------------------------------- +Performance/AncestorsInclude: + Enabled: false +Performance/ArraySemiInfiniteRangeSlice: + Enabled: true +Performance/BigDecimalWithNumericArgument: + Enabled: true +Performance/BlockGivenWithExplicitBlock: + Enabled: true +Performance/ChainArrayAllocation: + Enabled: true +Performance/CollectionLiteralInLoop: + Enabled: true +Performance/ConstantRegexp: + Enabled: true +Performance/MapCompact: + Enabled: true +Performance/MapMethodChain: + Enabled: true +Performance/MethodObjectAsBlock: + Enabled: true +Performance/RedundantEqualityComparisonBlock: + Enabled: false +Performance/RedundantSortBlock: + Enabled: true +Performance/RedundantSplitRegexpArgument: + Enabled: true +Performance/RedundantStringChars: + Enabled: true +Performance/ReverseFirst: + Enabled: true +Performance/SortReverse: + Enabled: false +Performance/Squeeze: + Enabled: true +Performance/StringIdentifierArgument: + Enabled: true +Performance/StringInclude: + Enabled: true + Exclude: + - lib/jekyll/utils/platforms.rb +Performance/Sum: + Enabled: true + +# Security cops +# ---------------------------------------- +Security/CompoundHash: + Enabled: true +Security/IoMethods: + Enabled: true +Security/MarshalLoad: + Exclude: + - lib/jekyll/regenerator.rb + - test/**/*.rb +Security/YAMLLoad: + Exclude: + - features/**/*.rb + - test/**/*.rb + +# Style cops +# ---------------------------------------- +Style/AccessModifierDeclarations: + Enabled: false +Style/AccessorGrouping: + Enabled: true +Style/Alias: + EnforcedStyle: prefer_alias_method +Style/AndOr: + Severity: error +Style/ArgumentsForwarding: + Enabled: false +Style/ArrayCoercion: + Enabled: true +Style/ArrayIntersect: + Enabled: true +Style/BisectedAttrAccessor: + Enabled: true +Style/CaseLikeIf: + Enabled: true +Style/ClassAndModuleChildren: + Exclude: + - test/**/*.rb +Style/ClassEqualityComparison: + Enabled: true +Style/CollectionCompact: + Enabled: true +Style/CombinableLoops: + Enabled: true +Style/ConcatArrayLiterals: + Enabled: true +Style/DirEmpty: + Enabled: true +Style/DocumentDynamicEvalDefinition: + Enabled: true +Style/Documentation: + Enabled: false +Style/DoubleNegation: + Enabled: false +Style/EmptyHeredoc: + Enabled: true +Style/EndlessMethod: + Enabled: true +Style/EnvHome: + Enabled: true +Style/ExactRegexpMatch: + Enabled: true +Style/ExplicitBlockArgument: + Enabled: false +Style/ExponentialNotation: + Enabled: true +Style/FetchEnvVar: + Enabled: false +Style/FileEmpty: + Enabled: true +Style/FileRead: + Enabled: false +Style/FileWrite: + Enabled: true +Style/FormatStringToken: + Exclude: + - lib/jekyll/liquid_renderer/table.rb + - lib/jekyll/profiler.rb + - lib/jekyll/utils/ansi.rb +Style/FrozenStringLiteralComment: + EnforcedStyle: always +Style/GlobalStdStream: + Enabled: true +Style/GuardClause: + Enabled: false +Style/HashAsLastArrayItem: + Enabled: true +Style/HashConversion: + Enabled: true +Style/HashEachMethods: + Enabled: true +Style/HashExcept: + Enabled: true +Style/HashLikeCase: + Enabled: true +Style/HashSyntax: + EnforcedStyle: hash_rockets + Severity: error +Style/HashTransformKeys: + Enabled: false +Style/HashTransformValues: + Enabled: true +Style/IfWithBooleanLiteralBranches: + Enabled: true +Style/KeywordParametersOrder: + Enabled: true +Style/MagicCommentFormat: + Enabled: true +Style/MapCompactWithConditionalBlock: + Enabled: true +Style/MapToHash: + Enabled: true +Style/MinMaxComparison: + Enabled: true +Style/MixinUsage: + Exclude: + - test/helper.rb +Style/ModuleFunction: + Enabled: false +Style/MultilineTernaryOperator: + Severity: error +Style/NegatedIfElseCondition: + Enabled: true +Style/NestedFileDirname: + Enabled: true +Style/NilLambda: + Enabled: true +Style/ObjectThen: + Enabled: true +Style/OperatorMethodCall: + Enabled: true +Style/OptionalBooleanParameter: + Enabled: true + Exclude: + - lib/jekyll/log_adapter.rb +Style/PercentLiteralDelimiters: + PreferredDelimiters: + "%Q": "{}" + "%W": "()" + "%q": "{}" + "%r": "!!" + "%s": "()" + "%w": "()" + "%x": "()" +Style/QuotedSymbols: + Enabled: true +Style/RedundantArgument: + Enabled: true +Style/RedundantArrayConstructor: + Enabled: true +Style/RedundantAssignment: + Enabled: true +Style/RedundantConstantBase: + Enabled: true +Style/RedundantCurrentDirectoryInPath: + Enabled: true +Style/RedundantDoubleSplatHashBraces: + Enabled: true +Style/RedundantEach: + Enabled: true +Style/RedundantFetchBlock: + Enabled: false +Style/RedundantFileExtensionInRequire: + Enabled: true +Style/RedundantFilterChain: + Enabled: true +Style/RedundantHeredocDelimiterQuotes: + Enabled: true +Style/RedundantInitialize: + Enabled: true + Exclude: + - lib/jekyll/plugin.rb +Style/RedundantLineContinuation: + Enabled: true +Style/RedundantRegexpArgument: + Enabled: true +Style/RedundantRegexpCharacterClass: + Enabled: true +Style/RedundantRegexpConstructor: + Enabled: true +Style/RedundantRegexpEscape: + Enabled: true +Style/RedundantSelfAssignment: + Enabled: true +Style/RedundantSelfAssignmentBranch: + Enabled: true +Style/RedundantStringEscape: + Enabled: true +Style/RegexpLiteral: + EnforcedStyle: percent_r +Style/RescueModifier: + Enabled: false +Style/ReturnNilInPredicateMethodDefinition: + Enabled: true +Style/SafeNavigation: + Exclude: + - lib/jekyll/document.rb + - lib/jekyll/page.rb +Style/SignalException: + EnforcedStyle: only_raise +Style/SingleArgumentDig: + Enabled: true +Style/SingleLineDoEndBlock: + Enabled: true +Style/SlicingWithRange: + Enabled: false +Style/SoleNestedConditional: + Enabled: true +Style/StringChars: + Enabled: true +Style/StringConcatenation: + Enabled: true + Exclude: + - lib/jekyll/commands/*.rb + - test/**/*.rb +Style/StringLiterals: + EnforcedStyle: double_quotes +Style/StringLiteralsInInterpolation: + EnforcedStyle: double_quotes +Style/SwapValues: + Enabled: true +Style/SymbolArray: + EnforcedStyle: brackets +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: consistent_comma +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: consistent_comma diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 00000000000..f7477b86681 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,25 @@ +# This configuration was generated by +# `rubocop --auto-gen-config --auto-gen-only-exclude` +# on 2022-04-06 10:48:47 UTC using RuboCop version 1.26.1. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 1 +# This cop supports safe auto-correction (--auto-correct). +Performance/BindCall: + Exclude: + - 'test/helper.rb' + +# Offense count: 1 +Style/CombinableLoops: + Exclude: + - 'lib/jekyll/tags/post_url.rb' + +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: respond_to_missing? +Style/OptionalBooleanParameter: + Exclude: + - 'lib/jekyll/log_adapter.rb' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8026187c503..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,35 +0,0 @@ -language: ruby -cache: bundler -sudo: false -rvm: -- 2.2 -- 2.1 -- 2.0 -- ruby-head -- jruby-9.0.3.0 -matrix: - allow_failures: - - rvm: ruby-head - - rvm: jruby-9.0.3.0 - exclude: - - rvm: jruby-9.0.3.0 - env: TEST_SUITE=cucumber -env: - matrix: - - TEST_SUITE=test - - TEST_SUITE=cucumber -before_script: bundle update -script: script/cibuild -notifications: - irc: - on_success: change - on_failure: change - channels: - - irc.freenode.org#jekyll - template: - - "%{repository}#%{build_number} (%{branch}) %{message} %{build_url}" - email: - on_success: never - on_failure: never - slack: - secure: dNdKk6nahNURIUbO3ULhA09/vTEQjK0fNbgjVjeYPEvROHgQBP1cIP3AJy8aWs8rl5Yyow4YGEilNRzKPz18AsFptVXofpwyqcBxaCfmHP809NX5PHBaadydveLm+TNVao2XeLXSWu+HUNAYO1AanCUbJSEyJTju347xCBGzESU= diff --git a/CONDUCT.md b/CONDUCT.md deleted file mode 100644 index 65c05c57488..00000000000 --- a/CONDUCT.md +++ /dev/null @@ -1,22 +0,0 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, such as physical or electronic addresses, without explicit permission -* Other unethical or unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. - -This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) \ No newline at end of file diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown deleted file mode 100644 index f83249c921e..00000000000 --- a/CONTRIBUTING.markdown +++ /dev/null @@ -1,106 +0,0 @@ -Contribute -========== - -So you've got an awesome idea to throw into Jekyll. Great! Please keep the -following in mind: - -* **Use https://talk.jekyllrb.com for non-technical or indirect Jekyll questions that are not bugs.** -* **Contributions will not be accepted without tests or necessary documentation updates.** -* If you're creating a small fix or patch to an existing feature, just a simple - test will do. Please stay in the confines of the current test suite and use - [Shoulda](https://github.com/thoughtbot/shoulda/tree/master) and - [RSpec-Mocks](https://github.com/rspec/rspec-mocks). -* If it's a brand new feature, make sure to create a new - [Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps - where appropriate. Also, whipping up some documentation in your fork's `site` - would be appreciated, and once merged it will be transferred over to the main - `site`, jekyllrb.com. -* If your contribution changes any Jekyll behavior, make sure to update the - documentation. It lives in `site/_docs`. If the docs are missing information, - please feel free to add it in. Great docs make a great project! -* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby) - when modifying Ruby code. -* Please do your best to submit **small pull requests**. The easier the proposed - change is to review, the more likely it will be merged. -* When submitting a pull request, please make judicious use of the pull request - body. A description of what changes were made, the motivations behind the - changes and [any tasks completed or left to complete](http://git.io/gfm-tasks) - will also speed up review time. - -Test Dependencies ------------------ - -To run the test suite and build the gem you'll need to install Jekyll's -dependencies. Simply run this command to get all setup: - - $ script/bootstrap - -Before you start, run the tests and make sure that they pass (to confirm your -environment is configured properly): - - $ script/cibuild - -If you are only updating a file in `test/`, you can use the command: - - $ script/test test/blah_test.rb - -If you are only updating a `.feature` file, you can use the command: - - $ script/cucumber features/blah.feature - -Both `script/test` and `script/cucumber` can be run without arguments to -run its entire respective suite. - -Workflow --------- - -Here's the most direct way to get your work merged into the project: - -* Fork the project. -* Clone down your fork ( `git clone git@github.com:[username]/jekyll.git` ). -* Create a topic branch to contain your change ( `git checkout -b my_awesome_feature` ). -* Hack away, add tests. Not necessarily in that order. -* Make sure everything still passes by running `script/cibuild`. -* If necessary, rebase your commits into logical chunks, without errors. -* Push the branch up ( `git push origin my_awesome_feature` ). -* Create a pull request against jekyll/jekyll and describe what your change - does and the why you think it should be merged. - -Updating Documentation ----------------------- - -We want the Jekyll documentation to be the best it can be. We've -open-sourced our docs and we welcome any pull requests if you find it -lacking. - -You can find the documentation for jekyllrb.com in the -[site](https://github.com/jekyll/jekyll/tree/master/site) directory of -Jekyll's repo on GitHub.com. - -All documentation pull requests should be directed at `master`. Pull -requests directed at another branch will not be accepted. - -The [Jekyll wiki](https://github.com/jekyll/jekyll/wiki) on GitHub -can be freely updated without a pull request as all GitHub users have access. - -If you want to add your plugin to the -[list of plugins](http://jekyllrb.com/docs/plugins/#available-plugins), -please submit a pull request modifying the -[plugins page source file](site/_docs/plugins.md) by adding a -link to your plugin under the proper subheading depending upon its type. - -Gotchas -------- - -* Please do not bump the gem version in your pull requests. -* Try to keep your patch(es) based from the latest commit on jekyll/jekyll. - The easier it is to apply your work, the less work the maintainers have to do, - which is always a good thing. -* Please don't tag your GitHub issue with [fix], [feature], etc. The maintainers - actively read the issues and will label it once they come across it. - -Finally... ----------- - -Thanks! Hacking on Jekyll should be fun. If you find any of this hard to figure -out, let us know so we can improve our process or documentation! diff --git a/Earthfile b/Earthfile new file mode 100644 index 00000000000..2abed46877f --- /dev/null +++ b/Earthfile @@ -0,0 +1,49 @@ +FROM alpine + +# Run locally: `earthly +all` to run full CI process +all: + BUILD --build-arg RUBY=3.0 +test + BUILD --build-arg RUBY=2.7 +test + BUILD --build-arg RUBY=2.5 +test + BUILD --build-arg RUBY=jruby:9.2.14.0 +test + BUILD style-check + BUILD profile-docs + +# Run locally: `earthly +test` +# Run with specific version: `earthly --build-arg RUBY=2.5 +test` +test: + FROM +deps + RUN script/test + RUN script/cucumber + RUN script/default-site + +style-check: + FROM +deps + RUN script/fmt + +profile-docs: + FROM +deps + RUN bundle install --jobs 4 + RUN script/profile-docs + RUN script/memprof + +# Install dependencies and copy in source +# used in above steps +deps: + ARG RUBY=3.0 + IF case $RUBY in jruby*) ;; *) false; esac + FROM $RUBY + ENV JRUBY_OPTS="--dev -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -J-XX:CompileThreshold=10 -J-XX:ReservedCodeCacheSize=128M" + ELSE + FROM ruby:$RUBY + END + WORKDIR /src + RUN apt-get update && apt-get install nodejs dnsutils git make coreutils g++ build-essential -y + RUN gem install bundler + RUN gem install sassc -v '2.4.0' --source 'https://rubygems.org/' + COPY Gemfile . + COPY jekyll.gemspec . + COPY lib/jekyll/version.rb lib/jekyll/version.rb + COPY test test + RUN bundle install --jobs 4 + COPY . . \ No newline at end of file diff --git a/Gemfile b/Gemfile index 9b64809eca1..68220b0d773 100644 --- a/Gemfile +++ b/Gemfile @@ -1,55 +1,122 @@ -source 'https://rubygems.org' -gemspec name: 'jekyll' +# frozen_string_literal: true + +source "https://rubygems.org" +gemspec :name => "jekyll" + +gem "rake", "~> 13.0" -gem 'rake', '~> 10.1' group :development do - gem 'rdoc', '~> 4.2' - gem 'launchy', '~> 2.3' - gem 'toml', '~> 0.1.0' - gem 'pry' + gem "launchy", "~> 2.3" + gem "pry" + + gem "pry-byebug" unless RUBY_ENGINE == "jruby" end +# + group :test do - gem 'redgreen', '~> 1.2' - gem 'shoulda', '~> 3.5' - gem 'cucumber', '~> 2.0', '< 2.1' - gem 'simplecov', '~> 0.9' - gem 'jekyll_test_plugin' - gem 'jekyll_test_plugin_malicious' - gem 'minitest-reporters' - gem 'minitest-profile' - gem 'minitest' - gem 'rspec-mocks' - - if RUBY_PLATFORM =~ /cygwin/ || RUBY_VERSION.start_with?("2.2") - gem 'test-unit' - end + gem "activesupport", "< 7.1.0" + gem "cucumber", "~> 9.0" + gem "httpclient" + gem "jekyll_test_plugin" + gem "jekyll_test_plugin_malicious" + gem "memory_profiler" + + # Runtime dependency of gem `httpclient`. _Needed only in Ruby 3.4+_. + # Remove once gem `httpclient` ships with `mutex_m` listed as a dependency in its gemspec. + gem "mutex_m", "~> 0.3" if RUBY_VERSION >= "3.4" - if ENV['PROOF'] - gem 'html-proofer', '~> 2.0' + gem "nokogiri", "~> 1.7" + gem "rspec" + gem "rspec-mocks" + gem "rubocop", "~> 1.57.2" + gem "rubocop-minitest" + gem "rubocop-performance" + gem "rubocop-rake" + gem "rubocop-rspec" + gem "test-dependency-theme", :path => File.expand_path("test/fixtures/test-dependency-theme", __dir__) + gem "test-theme", :path => File.expand_path("test/fixtures/test-theme", __dir__) + gem "test-theme-skinny", :path => File.expand_path("test/fixtures/test-theme-skinny", __dir__) + gem "test-theme-symlink", :path => File.expand_path("test/fixtures/test-theme-symlink", __dir__) + gem "test-theme-w-empty-data", :path => File.expand_path("test/fixtures/test-theme-w-empty-data", __dir__) + + if RUBY_ENGINE == "jruby" + gem "http_parser.rb", "~> 0.6.0" + gem "jruby-openssl" end end +# + +group :test_legacy do + gem "test-unit" if RUBY_PLATFORM =~ %r!cygwin! + + gem "minitest" + gem "minitest-profile" + gem "minitest-reporters" + gem "shoulda-context" + gem "simplecov" +end + +# + group :benchmark do - if ENV['BENCHMARK'] - gem 'ruby-prof' - gem 'rbtrace' - gem 'stackprof' - gem 'benchmark-ips' + if ENV["BENCHMARK"] + gem "benchmark-ips" + gem "rbtrace" + gem "ruby-prof" + gem "stackprof" end end -gem 'jekyll-paginate', '~> 1.0' -gem 'jekyll-coffeescript', '~> 1.0' -gem 'jekyll-feed' -gem 'jekyll-gist', '~> 1.0' -gem 'mime-types', '~> 2.6' -gem 'kramdown', '~> 1.9' - -platform :ruby, :mswin, :mingw do - gem 'rdiscount', '~> 2.0' - gem 'pygments.rb', '~> 0.6.0' - gem 'redcarpet', '~> 3.2', '>= 3.2.3' - gem 'classifier-reborn', '~> 2.0' - gem 'liquid-c', '~> 3.0' +# + +group :jekyll_optional_dependencies do + gem "jekyll-coffeescript" + gem "jekyll-docs", :path => "../docs" if Dir.exist?("../docs") && ENV["JEKYLL_VERSION"] + gem "jekyll-feed", "~> 0.9" + gem "jekyll-gist" + gem "jekyll-paginate" + gem "jekyll-redirect-from" + gem "kramdown-syntax-coderay" + gem "matrix" + gem "mime-types", "~> 3.0" + gem "tomlrb" + + platforms :ruby, :mswin, :mingw, :x64_mingw do + gem "classifier-reborn", "~> 2.2" + gem "liquid-c", "~> 4.0" + gem "yajl-ruby", "~> 1.4" + end + + # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem + # and associated library + platforms :jruby, :mswin, :mingw, :x64_mingw do + gem "tzinfo", ENV["TZINFO_VERSION"] if ENV["TZINFO_VERSION"] + gem "tzinfo-data" + end +end + +# + +group :rdoc, :optional => true do + # Psych 5 has stopped bundling `libyaml` and expects it to be installed on the host system prior + # to being invoked. + # Since we don't have a direct dependency on the Psych gem (it gets included in the gem bundle as + # a dependency of the `rdoc` gem), lock psych gem to v4.x instead of installing `libyaml` in our + # development / CI environment. + gem "psych", "~> 4.0" + gem "rdoc", "~> 6.0" +end + +# + +group :site do + gem "html-proofer", "~> 3.4" if ENV["PROOF"] + + gem "jekyll-avatar" + gem "jekyll-mentions" + gem "jekyll-seo-tag" + gem "jekyll-sitemap" + gem "jemoji" end diff --git a/History.markdown b/History.markdown index cbc710e6a02..eaa52ff5c1d 100644 --- a/History.markdown +++ b/History.markdown @@ -1,19 +1,2348 @@ ## HEAD +### Bug Fixes + + * Avoid caching resource when called via `include_relative` tag (#9784) + * Fix logs containing IPv6 URLs (#9813) + * Do not treat colons in `url_placeholders` as URI delimiters (#9850) + * Fix servlet do_GET header logic (#9867) + * Add logger to Gemfile for Ruby 4.0 (#9920) + +### Documentation + + * Improve documentation on collections in step-by-step walkthrough (#9803) + * Add `https://form.taxi` as a third-party resource for forms (#9802) + * Add Supranode to third-party deployment guide (#9786) + * Document the need for a `Gemfile` in deployment step of step-by-step walkthrough (#9805) + * Add Azion to the 3rd party deployment docs (#9811) + * Add ruby-erb prerequisite for Arch Linux installations (#9832) + * Add jekyllup.com to themes documentation (#9882) + * docs: Update contributor badge in README to include avatar height and limit parameters (#9912) + * Update WDM (0.1.1 → 0.2.0) in the Windows docs (#9897) + * Bump supported versions (#9923) + * Add GitCMS to resources docs (#9960) + +### Development Fixes + + * Improve readability of `post_url` tag (#9829) + * Fix flaky test that depends on current minute (#9889) + * build: fix broken CI on newer rubies (#9954) + +### Minor Enhancements + + * feat: Allowing post_url tag to receive liquid variables (#9776) + * Add .ruby-lsp to default excludes (#9914) + * Allow configuring future metadata for individual collections (#9925) + +## 4.4.1 / 2025-01-29 + +### Bug Fixes + + * Restore globbed path behavior in front matter defaults (#9762) + +## 4.4.0 / 2025-01-27 + +### Minor Enhancements + + * Allow marking specific highlighted lines via Liquid (#9138) + * Add gem `csv` to runtime dependency list (#9522) + * Bump the minimum ruby version to 2.7 (#9525) + * Acknowledge `livereload_port` from site config too (#9606) + * Add gem `base64` as runtime dependency (#9740) + * Add gem `json` as runtime_dependency (#9671) + * Remove unnecessary constraint on gem `mercenary` (#9758) + +### Bug Fixes + + * Optimize default front matter using `File.fnmatch?` (#9185) + * Remove totals in profile table properly (#9186) + * Optimize `Site#each_site_file` (#9187) + * Rename sass partial created for new blank site (#9257) + * Fix `jekyll serve --detach` with jekyll-sass-converter 3.x (#9304) + * Handle TypeError from `where` filter gracefully (#9292) + * Add support for upcoming logger 1.4.3 (#9392) + * Fix typo in devcontainer.json (#9364) + * Correct rubocop lint errors (#9600) + * Fix inexistent layout warning for the default 404 page (#9589) + * Relax version constraint on `wdm` in new Gemfile (#9662) + * Fix `--livereload-ignore` option (#9570) + * Render theme-gem root only in development (#9680) + +### Development Fixes + + * Cleanup highlight tag (#9177) + * Run tests in utc (#9168) + * Lock Ruby in CI to v3.1.2 and bump JRuby to v9.4.0.0 (#9196) + * Update sass related tests for jekyll-sass-converter 3.x (#9223) + * Split `test/test_tags.rb` into multiple files (#9230) + * test: use hash explicitly for Struct initializer for ruby 3.2 (#9237) + * script/default-site: accept flags for `jekyll new` (#9259) + * Bump check-spelling/check-spelling from 0.0.20 to 0.0.21 (#9205) + * Use check-spelling/check-spelling@v0.0.21 (#9199) + * Bump RuboCop to v1.45.x (#9305) + * Bump Rubocop to version 1.48.x (#9326) + * Bump versions of ruby & nodejs in devcontainer (#9360) + * Bump rubocop version to 1.52.x (#9361) + * Upgrade RuboCop to 1.54 (#9401) + * Add CodeQL workflow (#9397) + * Bump actions/checkout from 3 to 4 (#9442) + * Test suite uses shoulda-context only. (#9441) + * Keep activesupport at version 7.0.x (#9469) + * Bump Rubocop to 1.56.4 (#9459) + * Configure dependabot to handle rubygems dependencies (#9445) + * Update rubocop gem (#9476) + * Fix Performance/StringIdentifierArgument violation in site.rb and allow activesupport 6 for windows tests (#9512) + * Add a few more emeritus team members (#9535) + * Make custom cop inherit `RuboCop::Cop::Base` (#9597) + * CI: Use JRuby 9.4.8.0 (#9654) + * Stop testing with Cucumber on JRuby (#9661) + * Windows CI on GitHub Actions (#9659) + * Run GitHub Actions only if needed (#9664) + * Format `.rubocop.yml` via a rake task (#9687) + * Configure some new cops (#9688) + * Fix expected markup per WAI-ARIA requirements (#9737) + * Add an optional `:rdoc` group of gems (#9742) + * Test `inspect` filter with custom object (#9743) + * Bump cucumber to v9 (#9747) + * Add Ruby 3.4 to CI matrix (#9740) + * Remove unnecessary runtime dependency (#9753) + * Bump `check-spelling/check-spelling` action (#9756) + +### Documentation + + * Fix Nested tree navigation with recursion example (#9174) + * Fix typo on website (#9203) + * Publish post on major release of sass-converter (#9225) + * Update Jekyll on macOS (macos.md) and current ruby version to 3.1.3 in ruby.yml (#9195) + * Add release post for v4.3.2 (#9263) + * Grammatical reordering in 3-to-4 upgrading docs (#9245) + * fixed grammatical mistake on "showcase" page (#9264) + * Mark `highlight` `mark_lines` feature as 4.4 in docs (#9184) + * Add v3.9.3 release history & post to `master` branch (#9284) + * Update S3 deployment to remove s3_website (#9221) + * Document Exclude behavior, Include overrides and the default exclusion list (#9376) + * Update macos.md, remove Catalina (macOS 10.15) (#9405) + * Update macos.md, add support for Ventura (#9406) + * Typo fix - update to hooks and 3rd party deployment and one other article (#9411) + * Update 07-assets.md (#9393) + * Mention the front matter requirement in pages.md (#9423) + * Point to the Rouge GitHub repo rather than broken website (#9362) + * Add new theme directory to themes resources (#9356) + * Adds Kinsta to 3rd party deployments (#9331) + * Update Fedora prerequisites to include g++ (#9290) + * Update convert-site-to-jekyll.md (#9348) + * Update github-actions documentation (#9426) + * Update resources.md (#9449) + * Add GitHub Pages helpful notes (#9235) + * Clarify which version of Jekyll needs 'jekyll-paginate' (#9477) + * chore: update showcases (#9473) + * Add FreeBSD installation instructions (#9481) + * Fix broken link for the security team page (#9497) + * Fix broken links for several Jekyll integrations (#9496) + * Add release post for v4.3.3 (#9511) + * Add docs version badge to page_excerpts feature (#9520) + * Improve accessibility of the docs (#9338) + * Fix gem quote consistency on docs (#9517) + * Make site search work again (#9530) + * Jekyll docs template typo - All pages show "Deployment" (#9548) + * Fixed: Wrong navigation style on the right side of news and docs pages (#9586) + * Add redirect for step-by-step tutorial (#9593) + * Add Jekyll 3.10.0 release post & history (#9625) + * Fix minor docs error (#9641) + * Update windows.md (#9644) + * Document keys of global variable `{{ jekyll }}` (#9653) + * Fix incorrect and inconsistent variables in the permalinks page (#9591) + * Fix lapses in documentation of page variables (#9667) + * Add note about VSCode warning for SCSS files (#9609) + * docs: Fix incorrect parentheses (#9629) + * docs: Fix of a bug in the pagination section (#8890) + * Update current Ruby version renders and macOS docs (#9614) + * Improve docs around using GitHub Actions to build and deploy Jekyll sites (#9682) + * Fix grammar in the description of `page.excerpt` variable (#9689) + * Render HTML tables at `/docs/permalinks/` using a data file (#9666) + * Fix HTML attribute separation whitespace placement in the Navigation include code of Assets step of the Step by Step Tutorial (#9695) + * Fix missing glob matching pattern support description in the documentation of the `include` and `exclude` configuration options (#9697) + * Fix missing `url` configuration option documentation (#9699) + * Link to GitHub Pages Dependency versions page instead of explicitly specifying Jekyll version (#9715) + * Fix broken link on third-party.md (#9704) + * Fix: remove inaccessible links and their descriptions (#9745) + * Add release post for v4.4.0 (#9759) + +### Site Enhancements + + * Extract markup for `Improve this page` into an inclusion (#9675) + +## 4.3.4 / 2024-09-16 + +### Bug Fixes + + * Backport #9662 for v4.3.x: Relax version constraint on wdm in new Gemfile (#9683) + * Backport #9680 for v4.3.x: Render theme-gem root only in development (#9684) + +### Development Fixes + + * Sync workflows with counterparts on `master` (#9681) + +## 4.3.3 / 2023-12-27 + +### Bug Fixes + + * Backport #9392 for v4.3.x: Fix backward compatibility issues in the Logger (#9510) + +### Development Fixes + + * Backport #9237 for v4.3.x: Use Hash explicitly for Struct initializer (#9285) + +## 3.10.0 / 2024-06-23 + +### Minor Enhancements + + * Backport add-csv-dependency from #9522 to Jekyll 3 (#9616) + * 3.10-stable: Add webrick as a dependency (#9620) + +## 3.9.5 / 2024-02-12 + +### Minor Enhancements + + * 3.9-stable: allow Pages to be Excerpted (#9550) + +## 3.9.4 / 2023-12-28 + +### Bug Fixes + + * Backport #9392 for v3.9.x: Add support for Ruby 3.3 Logger (#9513) + +## 3.9.3 / 2023-01-29 + +### Bug Fixes + + * 3.9.x: Support i18n 1.x (#9269) + * Backport #8880 for v3.9.x: Support both tzinfo v1 and v2 along with non-half hour offsets (#9280) + +### Development Fixes + + * v3.9.x: test under Ruby 3.2 #9272) + * v3.9.x: fix rdiscount test (#9277) + +## 4.3.2 / 2023-01-20 + +### Bug Fixes + + * Backport #9257 for v4.3.x: Rename sass partial created for new blank site (#9262) + * Backport #9187 for v4.3.x: Optimize `Site#each_site_file` (#9256) + * Backport #9186 for v4.3.x: Remove totals in profile table properly (#9255) + +### Development Fixes + + * Backport #9223 for 4.3.x: Update sass related tests for jekyll-sass-converter 3.x (#9254) + +## 4.3.1 / 2022-10-26 + +### Bug Fixes + + * Respect user-defined name attribute in documents (#9167) + * Revert "Incrementally rebuild when a data file is changed" (#9170) + +### Documentation + + * Release post for v4.3.1 (#9171) + +## 4.3.0 / 2022-10-20 + +### Minor Enhancements + + * Add webrick as a dependency (#8524) + * Regenerate supported mime types (#8542) + * Update include tag to be more permissive (#8618) + * Optimize `Jekyll::Utils.parse_date` (#8425) + * Update rubocop from 1.12 to 1.18 and min ruby from 2.4 to 2.5 (#8741) + * Always hide cache-dir contents from Git (#8798) + * Remove the warning about auto-regeneration on Windows (#8821) + * Propagate _data folder from theme (#8815) + * Support both tzinfo v1 and v2 along with non-half hour offsets. (#8880) + * Run vendor-mimes to update mime.types (#8940) + * Expose collection static files via `site.static_files` (#8961) + * Expose `basename` from `document.rb` as `name` to Liquid templates (#8761) + * Allow Configurable Converters on CSV (#8858) + * Introduce `theme` drop to expose theme-gem details (#9129) + * Relax version constraint to allow Rouge 4.x (#9134) + * Incrementally rebuild when a data file is changed (#8771) + * Support jekyll-sass-converter 3.x (#9132) + +### Bug Fixes + + * fix: pin rubocop to 1.12 due to error with ruby 2.4 (#8651) + * Load Jekyll plugins from BUNDLE_GEMFILE location (#8585) + * fix(security): CVE-2021-28834 (#8680) + * Inject livereload script using `location.protocol` instead of `http:` (#8718) + * Respect collections_dir config within include tag (#8756) + * Fix regression in Convertible module from v4.2.0 (#8786) + * Revert #7253: "Don't reset site.url to localhost:4000 by default" (#8620) + * Improve readability of CI logs (#8877) + * Fix deprecation message for missing doc method (#8960) + * Fix response header for content served via `jekyll serve` (#8965) + * Trigger livereload in sites without pages (#8337) + * Only enable BOM encoding option on UTF encodings (#8363) + * Ensure theme config is a `Jekyll::Configuration` object (#8988) + * Remove misleading totals row from `--profile` table (#9039) + * Unlock Psych dependency (#9135) + * Fix false positive conflicts for static files in a collection (#9141) + +### Development Fixes + + * style: enable new cops (#8538) + * Allow dependabot to keep github actions up-to-date (#8540) + * Update actions/cache requirement to v2.1.3 (#8543) + * Pin rubocop version (#8564) + * style: add rubocop 1.9 cops (#8567) + * Cross Version Testing Locally and Faster CI (#8610) + * Use official Ruby setup GH action (#8614) + * Spell check action for markdown documentation (#8675) + * Update expect to cover docs/_posts (#8677) + * Bump check-spelling/check-spelling from 0.0.18 to 0.0.19 (#8740) + * Enable Rubocop accessor grouping, fix existing offenses (#8293) + * Tags:Highlight: Decomposed HTMLLegacy formatter (#8623) + * Relax Rubocop Dependency (#8831) + * Add a workflow to build gems consistently (#8830) + * Fix random test failures in TestExcerpt #to_liquid (#8884) + * Lock gem `psych` to `v3.x` (#8918) + * Fix typo in Bug Report template (#8951) + * Check symlink outside site_source without Pathutil (#9015) + * Stop testing with Rubies older than 2.7 on non-Windows (#8955) + * Bump actions/checkout from 2 to 3 (#8986) + * Remove git.io shortlinks from repo (#9045) + * Bump rubocop to 1.32 (#9093) + * Bump RuboCop to `1.36.x` (#9125) + * Use check-spelling/check-spelling@v0.0.20 (#9111) + * Disable pending cops when running rubocop (#9136) + * Relax RDoc version dependency (#9142) + +### Documentation + + * typo - do instead of don't (#8518) + * Document support for TSV files consistently (#8488) + * Add a disclaimer to tutorials involving Ruby code (#8525) + * Improve documentation on developing generators (#8527) + * Fixes typo in layouts_dir documentation (#8532) + * Fix i.e. typos in collections.md (#8529) + * Remove GitHub Pages content which is in GitHub docs (#8533) + * Step By Step Instructions Review (#8399) + * Fix typo in migrating from 3.0 to 4.0 page (#8572) + * Fix for important missing step in macOS Installation Docs: Add the Homebrew gems directory to the PATH (#8496) + * Use latest Jekyll-action configuration (#8579) + * docs: troubleshoot macOS with ARM64 architecture (#8560) + * docs: add overview of .jekyll-cache dir (#8648) + * docs: clarify where .jekyll-metadata comes from (#8646) + * Razorops CI/CD added (#8656) + * Specify default port and host for serve commands in docs (#8624) + * Update third-party.md (#8652) + * Add documentation for Sass configuration options (#8587) + * Add formcarry to forms section (#8471) + * Add step to set SDKROOT (#8478) + * Improve the "Markdown Options" Docs (#8681) + * Add 'webrick' warning note to "Quickstart" Docs (#8727) + * Update windows.md (#8701) + * IRC networks - Libera, Freenode (#8706) + * Improve GitHub Flavored Markdown Docs (#8684) + * Fixing URL in MacOS install for rbenv-doctor (#8693) + * Fix adjective in `troubleshooting.md` document (#8777) + * Goodbye Frank. We'll miss you. 💔 (#8807) + * Update index.html: Grammar fix. (#8803) + * Prefer Libera. Remove Freenode. (#8811) + * Update feature_request.md (#8797) + * Remove AWS Amplify from the showcase (#8812) + * Move Frank to Emeritus Core Team Members (#8813) + * Release post for v4.2.1 (#8818) + * Update CircleCI example (#8829) + * Fix typo (#8835) + * Added docs for running locally (#8852) + * Linting README.markdown (#8900) + * Remove text on GITHUB_TOKEN which is now built-in (#8907) + * Add Security Policy document (#8823) + * Manage repository meta documents consistently (#8908) + * docs: add Layer0 deployment guide (#8915) + * docs: Update README generated by `jekyll new-theme` (#8919) + * Update resources.md (#8925) + * Rewrite documentation on installing plugins (#8921) + * Improve maintainers guide on releasing a new version (#8928) + * Fix link for "CloudSh" (#8934) + * Recommend using `actions/cache` in GitHub Actions documentation (#8948) + * Remove references to EOL hakiri.io service (#8946) + * Release post for v4.2.2 (#8982) + * Document releasing off `*-stable` branches (#8984) + * Update document by fix yaml syntax error (#8991) + * Enhance option's case for Jekyll configuration (#8992) + * Fix typo in `_docs/deployment/manual.md` (#8997) + * Add quiet/verbose options (#8996) + * Update README.markdown re IRC Pointer (#9005) + * Remove Aerobatic (#9007) + * Add Jekyll 3.9.2 release post to 'master' branch (#9013) + * Simplify macOS installation docs (#8993) + * Improve document about GitHub Actions section (#8853) + * Update permalinks.md (#9017) + * Add clarity to docs on permalinks placeholders and built-ins (#8995) + * Remove Ionic Framework site from showcase (#9057) + * Windows: describe which option to choose (#9049) + * Improve links (http -> https) (#9064) + * Update ruby version for macos guide (#9086) + * Update posts.md (#9151) + * Release post for v4.3.0 (#9157) + +### Site Enhancements + + * Improvements to CSS (#7834) + * Slightly update lang `sh` code-block styling (#8857) + +## 4.2.2 / 2022-03-03 + +### Bug Fixes + + * Lock `http_parser.rb` gem to `v0.6.x` on JRuby. + +### Development Fixes + + * Backport #8830 for v4.2.x: Add a workflow to build gems consistently (#8869) + * Lock `rubocop-performance` to `v1.11.x`. + +## 4.2.1 / 2021-09-27 + +### Bug Fixes + + * Backport #8620 for v4.2.x: Revert #7253: "Don't reset site.url to localhost:4000 by default" (#8808) + * Backport #8756 for v4.2.x: Respect collections_dir config within include tag (#8794) + * Backport #8786 for v4.2.x: Fix regression in Convertible module from v4.2.0 (#8793) + +## 4.2.0 / 2020-12-14 + +### Minor Enhancements + + * Warn on command-line with permalink conflict (#8342) + * Suppress warning issued for redirect pages (#8347) + * Enhance detection of conflicting destination URLs (#8459) + * Add `:post_convert` hook to modify HTML content before layout (#8368) + * Allow triggering `:post_convert` events atomically (#8465) + * Debug reading Page and Layout objects (#8100) + * Do not reset `site.url` to `http://localhost:4000` by default (#7253) + * Add custom debug strings for Jekyll objects (#8473) + * Debug reading data files in a site (#8481) + +### Bug Fixes + + * Replace nested conditional with guard clauses (#8294) + * Fix: security bump (#8349) + * Fix path matching regex in post_url Liquid tag (#8375) + * Enable `Performance/ChainArrayAllocation` cop (#8404) + * Enable Lint/NoReturnInBeginEndBlocks Cop (#8457) + * Generate items from `site.include` list only once (#8463) + * Explicitly return nil after site process phase (#8472) + +### Optimization Fixes + + * Implement custom delegators for drop methods (#8183) + * Handle `nil` argument to `Jekyll.sanitized_path` (#8415) + * Cache `Jekyll.sanitized_path` (#8424) + * Memoize array of drop getter method names (#8421) + * Reduce string allocations from the `link` tag (#8387) + * Optimize parsing of parameters in `include` tag (#8192) + * Stash documents `write?` attribute in a variable (#8389) + * Reduce string allocations from generating doc URLs (#8392) + * Check if site is in incremental mode optimally (#8401) + * Utilize flexibility of `Site#in_dest_dir` (#8403) + * Reduce allocations from rendering item as liquid (#8406) + * Compute relative_path of pages using PathManager (#8408) + * Reduce allocation from `normalize_whitespace` filter (#8400) + * Use `Regexp#match?` when `MatchData` is not required (#8427) + * Check default front matter scope against symbols (#8393) + * Stash frequently used `Drop` setter keys for reuse (#8394) + * Memoize defaults computed for Convertibles (#8451) + * Reduce array allocations from merging categories (#8453) + * Memoize destination of pages, documents and staticfiles (#8458) + * Reduce allocations from computing item property (#8485) + * Optimize `Page#dir` with a private method (#8489) + * Stash attribute hash for Liquid computed for pages (#8497) + +### Development Fixes + + * Update cucumber gem to version 4.1 (#8278) + * Move permalink styles data to constant (#8282) + * Update rubocop gem to 0.87.1 (#8287) + * Update RuboCop to-do file (#8296) + * Fix `rake console` generating LoadError (#8312) + * Configure Performance cops (#8369) + * Update rubocop gem to 0.90.0 (#8313) + * Refactor `Jekyll::Utils::Platforms` (#7236) + * Bump RuboCop to v0.91.x (#8391) + * Add workflow to build and profile third-party repo (#8398) + * Bump RuboCop to v0.92.x + * Update cucumber gem version to 5.1.2 (#8413) + * Fix test suite compatibility with JRuby (#8418) + * chore(deps): bump Rubocop to 0.93.0 (#8430) + * Use Ruby 2.7.1 in GitHub Actions (#8444) + * Test that Liquid expressions are not deeply evaled (#8292) + * Test rendering arbitrary Liquid variables by default (#7414) + * Migrate TravisCI jobs to GitHub Actions (#8492) + +### Documentation + + * Update pointer to special permalink variables for collections (#8274) + * Fix special treatment for 'page 1' in docs of pagination (#8230) + * Add Formcake to forms section (#8283) + * Add a note on the rendering process in the docs (#8291) + * Add refactoring type to PULL_REQUEST_TEMPLATE (#8297) + * Update resources.md (#7864) + * Extra apostrophes in an URL (#8319) + * Clarify target of subordinate clause (#8320) + * Cherry-pick commits from conflicting branch `docs-40` + * Update documentation on third party site (#8352) + * Update default.md with info requested in #8314 (#8353) + * Clarify description of `safe` option (#8354) + * Simplifying the Git post-receive hook-example (#8358) + * Add missing doc for build and serve commands (#8365) + * Docs Review: Getting Started (#8372) + * Add note about rebooting system after installation (#8359) + * Use data file to render table at `/docs/configuration/options/#global-configuration` (#8377) + * Use data file(s) to render table(s) at `/docs/configuration/options/` (#8380) + * Improve maintainability of config option data (#8383) + * Remove CircleCI v1 docs (#8410) + * Remove `NOKOGIRI_USE_SYSTEM_LIBRARIES` from Travis CI docs (#8409) + * Add links to all Jekyll themes on GitHub tagged with #jekyll-theme (#8447) + * Document initializing project Gemfile from scratch (#8450) + * Document installation of additional dependencies for installing Jekyll on Fedora (#8456) + * Improve documentation on Hooks in Jekyll (#8467) + * Build docs site with GitHub Actions (#8201) + * Add link to Assets page from `_sass` section in `_docs/structure.md` (#8486) + +### Site Enhancements + + * Fix rendering of *showcase* images (#8504) + +## 4.1.1 / 2020-06-24 + +### Bug Fixes + + * Disable page excerpts by default (#8222) + * Revert introduction of PageDrop (#8221) + * Don't generate excerpts for non-html pages (#8234) + * Make page excerpts consistent with doc excerpts (#8236) + +### Documentation + + * Replace deprecated 'show' command with 'info' (#8235) + * Change name to ▲Vercel (#8247) + * Add language and examples to describe how to use the configuration op… (#8249) + * Fix missing yaml front matter colon and adjust/add clarifying language. (#8250) + * correct typo (#8261) + * Allow hyperlinks to specific filter documentation (#8231) + * Update link to Netlify step-by-step guide (#8264) + * Fix grammar in documentation section (#8265) + +### Site Enhancements + + * Including correct Sketch website (#8241) + * Release post for v4.1.1 (#8243) + +### Development Fixes + + * Bump RuboCop to v0.85.x (#8223) + * Expect drive letter only on vanilla windows (#8227) + +## 4.1.0 / 2020-05-27 + +### Bug Fixes + + * Memoize `absolute_url` and `relative_url` filters (#7793) + * Fix documentation comment for `Jekyll::Converters::Identity` (#7883) + * Optimize `Jekyll::Filters#item_property` (#7696) + * Allow multiple binary operators in `where_exp` filter (#8047) + * Fix documents custom-ordering logic (#8028) + * Use `layout.path` when rendering the Liquid layout (#8069) + * Reduce array allocations from `StaticFile#path` (#8083) + * Simplify `Jekyll::Renderer#validate_layout` (#8064) + * Add static file's basename to its `url_placeholder` (#7908) + * Clear cached Liquid template scope before render (#7967) + * Cache `URLFilter` results of string inputs per site (#7990) + * Use `platforms` instead of `install_if` in Gemfile (#8140) + * Config include trailing slash (#8113) + * Improve path normalization in liquid_renderer (#8075) + * Switch slugify regex to support more Unicode character groups (#8167) + * Check if entry is a directory once per enumerator (#8177) + * Filter out exclusively excluded entries sooner (#7482) + * Return `relative_url` if site.url is an empty string (#7988) + * Configure kramdown toc_levels as array by default (#8015) + * Reduce `Pathname` objects from front matter defaults (#8067) + * Simplify `Jekyll::Hooks.trigger` logic (#8044) + * Quicker categories for documents without superdirs (#7987) + * Reduce `Jekyll::Renderer` instances during a build (#7570) + * Escape regex characters in paths to match (#8138) + * Provide invokables for common drop query keys (#8165) + * Optimize path sanitization of default front matter (#8154) + * Initialize static files' data hash only if needed (#8188) + * Initialize include-files as Jekyll objects (#8158) + +### Minor Enhancements + + * serve: add support for ECC certificates (#7768) + * Update `item_property` to recognize integers (#7878) + * Include `_config.yml` in a new theme's gemspec (#7865) + * Add an option to easily disable disk-cache (#7928) + * Optimize markdown parsing with Kramdown by reusing the options and parser objects (#8013) + * Add `PageDrop` to provide Liquid templates with data (#7992) + * Optimize `Kramdown::JekyllDocument#to_html` calls (#8041) + * Configure default language for syntax-highlighting (#8035) + * Remove dev dependencies from new theme-gem gemspec (#8042) + * Allow disabling import of theme configuration (#8131) + * Allow excerpts to be generated for `Page` objects (#7642) + * Profile various stages of a site's build process (#6760) + * Add find filters to optimize where-first chains (#8171) + * Make `number_of_words` filter respect CJK characters (#7813) + * Allow extensionless document in a strict site (#7950) + * Add `:slugified_categories` URL placeholder (#8094) + +### Documentation + + * Add dropped 'title: Staff' to the code (#7805) + * Clarify docs for static files in collection (#7812) + * Rephrase the CircleCI v2 section (#7815) + * Update old GitHub wiki URL with new one (#7823) + * Update JekyllConf page with 2019 talks (#7826) + * link for memberships (#7825) + * Doc: minor fix, should be greater or equal to min version (#7856) + * Update third-party.md - Fix broken link (#7857) + * clarify _config.yml/collections type (#7873) + * Replace backticks with HTML tags in data file (#7879) + * add new theme source (#7875) + * fixed grammatical error (it's --> its) (#7887) + * Docs: Clarify organizing pages into subfolders (#7896) + * Disambiguate the placeholder of permalink (#7906) + * docs: add short serve command for livereload (#7919) + * docs: add options for watch and force polling (#7918) + * add install instructions for ArchLinux and openSUSE (#7920) + * Improve index page of Jekyll documentation (#7926) + * Include path in `jekyll new` commands (Usage docs) (#7931) + * Change `affect` to `effect` in the collections docs (#7937) + * Changed deprecated command in themes documentation (#7941) + * Adds some documentation for the `:clean`, `:on_obsolete` hook (#7954) + * docs: fix broken link (#7955) + * Corrected typo (#7975) + * docs: remove watch option in config (#7940) + * Correct a sentence in the documentation (#7978) + * Fix YAML representation of `group_by` result (#7979) + * Move `--baseurl` to build command options (#7985) + * Correct documentation of filters (#7989) + * Document sorting two documents by their `date` (#7870) + * Fix English grammar error (#7994) + * Update 03-front-matter.md (#7996) + * Add Kentico Kontent CMS integration to resources (#8000) + * Update 07-assets.md (#7413) + * Fix file references in Step by Step Tutorial's Assets step (#8007) + * docs: improve highlighting of code blocks (#8017) + * remove leading slash from Sass file location (#8021) + * [Docs] Fix asset link ref in step-by-step tutorial (#8026) + * Corrected command to modify PATH (#8029) + * Corrected command to modify PATH (#8030) + * Docs: Render full contents of just the latest post (#8032) + * docs: improvements for note boxes (#8037) + * Non-deprecated `vendor/bundle` path configuration (#8048) + * Update 09-collections.md (#8060) + * Remove extra paragraph tags (#8063) + * Add default front matter for tutorials collection (#8081) + * Create CSV to table tutorial (#8090) + * Add version badge for Custom Sorting of Documents (#8098) + * Docs: Fix grammar in `_docs/front-matter.md` (#8097) + * Update variables.md (#8106) + * Add help about Gentoo/Linux (#8002) + * Update documentation on third party site (#8122) + * Added Clear Linux (#8132) + * Added note about OS specific installation instructions. (#8135) + * Fix broken URL in the Resources Page on the Documentation Site (#8136) + * Docs: Deploy Jekyll site with GitHub Actions (#8119) + * Clarify `bundle config` in Bundler tutorial (#8150) + * docs: update your-first-plugin.md (#8147) + * Fix typo in documentation on GitHub Actions (#8162) + * Ease discovery of CLI commands (in their entirety) (#8178) + * Remove `sudo` from Travis CI tutorial (#8187) + * Add GitLab Pages to 3rd party list (#8191) + * docs: add 21yunbox for deployment (#8193) + * Improve documentation on tags and categories (#8196) + +### Development Fixes + + * Ci/GitHub actions (#7822) + * Rubocop version upgrade (#7846) + * Split action steps to avoid using `&&` on Windows (#7885) + * Upgrade rake to use version 13 (#7910) + * Update dependency constraint to allow RuboCop v0.76 (#7893) + * Use bash executable consistently (#7909) + * Test with JRuby 9.2.9.0 (#7779) + * Bump RuboCop to v0.79.x (#7970) + * Remove post-install message from gemspec (#7974) + * Attain Ruby 3.0 compatibility (#7948) + * Test `where` filter handling numeric property values (#7821) + * chore(deps): rubocop 0.80.0 (#8012) + * Update unit tests for Kramdown-based converter (#8014) + * Add Visual Studio Code Development Container (#8016) + * chore: simplify require for `Jekyll::VERSION` (#8057) + * Remove version-constraint relaxation for i18n gem (#8055) + * Mirror `spec.homepage` as `metadata["homepage_uri"]` (#8056) + * Bump Ruby versions on Travis builds (#8088) + * chore(ci): cache dependencies (#8168) + +### Site Enhancements + + * Optimize rendering of the documentation site (#8020) + * Utilize `relative_url` filter in documentation site (#8089) + * Render tutorial metadata in documentation site (#8092) + * Improve syntax-highlighting in documentation site (#8079) + * Site: Filter through just the *docs* collection (#8170) + +## 4.0.1 / 2020-05-08 + +### Bug Fixes + + * Prevent console warning with Ruby 2.7 (#8124) + * Clear cached Liquid template scope before render (#8141) + * Add static file's basename to its url_placeholder (#8142) + * Update item_property to recognize integers (#8160) + +### Development Fixes + + * Fix Kramdown converter based tests for v4.0.x (#8143) + +## 3.9.2 / 2022-03-27 + +### Bug Fixes + + * Lock `http_parser.rb` gem to `v0.6.x` on JRuby (#8943) + * Backport #8756 for v3.9.x: Respect collections_dir config within include tag (#8795) + * Backport #8965 for v3.9.x: Fix response header for content served via `jekyll serve` (#8976) + +### Development Fixes + + * Update and fix CI for `3.9-stable` on Ruby 3.x (#8942) + * Fix CI for commits to `3.9-stable` branch (#8788) + +## 3.9.1 / 2021-04-08 + +### Bug Fixes + + * Backport #8618 for v3.9.x: Update include tag to be more permissive (#8629) + +## 3.9.0 / 2020-08-05 + +### Minor Enhancements + + * Allow use of kramdown v2 (#8322) + * Add default language for kramdown syntax highlighting (#8325) + +## 3.8.7 / 2020-05-08 + +### Bug Fixes + + * Prevent console warnings with Ruby 2.7 (#8125) + +## 4.0.0 / 2019-08-19 + +### Major Enhancements + + * Drop ruby 2.3 (#7454) + * Drop support for Ruby 2.1 and 2.2 (#6560) + * Drop support for older versions of Rouge (#6978) + * Drop support for pygments as syntax-highlighter (#7118) + * Drop support for Redcarpet (#6987) + * Drop support for rdiscount (#6988) + * Drop support for `jekyll-watch-1.4.0` and older (#7287) + * Incorporate `relative_url` filter in `link` tag (#6727) + * Upgrade kramdown dependency to v2.x (#7492) + * Upgrade jekyll-sass-converter to v2.x - Sassc + sourcemaps (#7778) + * Upgrade i18n to v1.x (#6931) + * Add `Jekyll::Cache` class to handle caching on disk (#7169) + * Cache converted markdown (#7159) + * Cache: Do not dump undumpable objects (#7190) + * Cache matched defaults sets for given parameters (#6888) + * Ignore cache directory (#7184) + * Add `Site#in_cache_dir` helper method (#7160) + * Remove 'cache_dir' during `jekyll clean` (#7158) + * Cache parsed Liquid templates in memory (#7136) + * Only read layouts from source_dir or theme_dir (#6788) + * Allow custom sorting of collection documents (#7427) + * Always exclude certain paths from being processed (#7188) + * Remove Jekyll::Utils#strip_heredoc in favor of a Ruby > 2.3 built in (#7584) + * Incorporate `relative_url` within `post_url` tag (#7589) + * Remove patch to modify config for kramdown (#7699) + +### Minor Enhancements + + * Enhance `--blank` scaffolding (#7310) + * Use `jekyll-compose` if installed (#6932) + * Disable Liquid via front matter (#6824) + * Configure cache_dir (#7232) + * ISO week date drops (#5981) + * Fix custom 404 page for GitHub pages (#7132) + * Load config file from within current theme-gem (#7304) + * Suggest re-running command with `--trace` on fail (#6551) + * Support for binary operators in where_exp filter (#6998) + * Automatically load `_config.toml` (#7299) + * Add vendor folder to a newly installed site's .gitignore (#6968) + * Output Jekyll Version while debugging (#7173) + * Memoize computing excerpt's relative_path (#6951) + * Skip processing posts that can not be read (#7302) + * Memoize the return value of Site#documents (#7273) + * Cache globbed paths in front matter defaults (#7345) + * Cache computed item property (#7301) + * Cleanup Markdown converter (#7519) + * Do not process Liquid in post excerpt when disabled in front matter (#7146) + * Liquefied link tag (#6269) + * Update item_property to return numbers as numbers instead of strings (#6608) + * Use `.markdown` extension for page templates (#7126) + * Add support for `*.xhtml` files (#6854) + * Allow i18n v0.9.5 and higher (#7044) + * Ignore permission error of /proc/version (#7267) + * Strip extra slashes via `Jekyll.sanitized_path` (#7182) + * Site template: remove default config for markdown (#7285) + * Add a custom inspect string for StaticFile objects (#7422) + * Remind user to include gem in the Gemfile on error (#7476) + * Search Front matter defaults for Page objects with relative_path (#7261) + * Lock use of `tzinfo` gem to v1.x (#7521, #7562) + * Utilize absolute paths of user-provided file paths (#7450) + * Detect `nil` and empty values in objects with `where` filter (#7580) + * Initialize mutations for Drops only if necessary (#7657) + * Reduce Array allocations via Jekyll::Cleaner (#7659) + * Encode and unencode urls only as required (#7654) + * Reduce string allocations with better alternatives (#7643) + * Reduce allocations from Jekyll::Document instances (#7625) + * Add `type` attribute to Document instances (#7406) + * Reduce allocations from where-filter (#7653) + * Memoize SiteDrop#documents to reduce allocations (#7697) + * Add PathManager class to cache interim paths (#7732) + * Remove warnings and fixes for deprecated config (#7440) + * Delegate --profile tabulation to `terminal-table` (#7627) + +### Bug Fixes + + * Security: fix `include` bypass of `EntryFilter#filter` symlink check (#7226) + * Theme gems: ensure directories aren't symlinks (#7419) + * Add call to unused method `validate_options` in `commands/serve.rb` (#7122) + * Check if scope applies to type before given path (#7263) + * Document two methods, simplify one of the methods (#7270) + * Check key in collections only if it isn't "posts" (#7277) + * Interpolate Jekyll::Page subclass on inspection (#7203) + * Measure the no. of times a template gets rendered (#7316) + * Reduce array traversal in Jekyll::Reader (#7157) + * Re-implement handling Liquid blocks in excerpts (#7250) + * Documents should be able to render their date (#7404) + * Fix Interpreter warning from Jekyll::Renderer (#7448) + * Loggers should accept both numbers and symbols (#6967) + * Replace regex arg to :gsub with a string arg (#7189) + * Dont write static files from unrendered collection (#7410) + * Excerpt handling of custom and intermediate tags (#7382) + * Change future post loglevel to warn to help user narrow down issues (#7527) + * Handle files with trailing dots in their basename (#7315) + * Fix unnecessary allocations via StaticFileReader (#7572) + * Don't check if site URL is absolute if it is nil (#7498) + * Avoid unnecessary duplication of pages array (#7272) + * Memoize Site#post_attr_hash (#7276) + * Memoize Document#excerpt_separator (#7569) + * Optimize Document::DATE_FILENAME_MATCHER to match valid filenames (#7292) + * Escape valid special chars in a site's path name (#7568) + * Replace `name` in Page#inspect with relative_path (#7434) + * Log a warning when the slug is empty (#7357) + * Push Markdown link refs to excerpt only as required (#7577) + * Fix broken include_relative usage in excerpt (#7633) + * Initialize and reset glob_cache only as necessary (#7658) + * Revert memoizing Site#docs_to_write and #documents (#7684) + * Backport #7684 for v3.8.x: Revert memoizing Site#docs_to_write and refactor #documents (#7689) + * Backport #7213 and #7633 for v3.8.x: Fix broken include_relative usage in excerpt (#7690) + * Don't read symlinks in site.include in safe mode (#7711) + * Replace `String#=~` with `String#match?` (#7723) + * Update log output for an invalid theme directory (#7679) + * Remove configuration of theme sass files from Core (#7290) + * Actually conditionally include liquid-c (#7792) + * Test number_like regex on stringified property (#7788) + +### Development Fixes + + * Upgrade liquid-c to v4.0 (#7375) + * Bump RuboCop to v0.71.0 (#7687) + * Target Ruby 2.4 syntax (#7583) + * Fix: RuboCop offenses (#7769) + * Use communicative method parameters (#7566) + * Scan `assert_equal` methods and rectify any offenses with a custom RuboCop cop (#7130) + * CI: Test with Ruby 2.6 (#7438) + * CI: Test with Ruby 2.6 on AppVeyor (#7518) + * CI: Update RuboCop config (#7050) + * CI: Add a script to profile docs (#7540) + * CI(Appveyor): shallow clone with 5 last commits (#7312) + * CI: Test with oldest and latest Ruby only (#7412) + * CI: Update excludes for CodeClimate Analyses (#7365) + * CI: Lock Travis to Bundler-1.16.2 (#7144) + * CI: Bump tested version of JRuby to 9.2.7.0 (#7612) + * CI: Do not install docs on updating gems on Travis (#7706) + * Update gemspec (#7425) + * deps: relax version constraint on classifier-reborn gem (#7471) + * deps: update yajl-ruby (#7278) + * deps: bump yajl-ruby to v1.4.0 (#6976) + * Create symlink only if target is accessible (#7429) + * Switch to `:install_if` for wdm gem (#7372) + * Add cucumber feature to test include_relative tag (#7213) + * Small benchmark refactoring (#7211) + * Fix incorrectly passed arguments to assert_equal (#7134) + * fix up refute_equal call (#7133) + * Fix RuboCop offences in test files (#7128) + * Use assert_include (#7093) + * Remember to release docs gem (#7066) + * Useless privates removed (#6768) + * Load Rouge for TestKramdown (#7007) + * Update instructions for releasing docs Gem (#6975) + * We are not using Ruby 2.2 anymore (#6977) + * Remove unnecessary Jekyll::Page constant (#6770) + * Remove unused error class (#6511) + * Add a Cucumber feature for post_url tag (#7586) + * Generate a "TOTAL" row for build-profile table (#7614) + * Refactor Jekyll::Cache (#7532) + * Store list of expected extnames in a constant (#7638) + * Profile allocations from a build session (#7646) + * Update small typo in contributing.md (#7671) + * Remove override to Jekyll::Document#respond_to? (#7695) + * Update TestTags in sync with Rouge v3.4 (#7709) + * Use regexp to filter special entries (#7702) + * Reduce Array objects generated from utility method (#7749) + * Update mime.types (#7756) + * Replace redundant Array#map with Array#each (#7761) + * Reduce allocations by using #each_with_object (#7758) + * Memoize fallback_data for Drop (#7728) + * Use String#end_with? to check if entry is a backup (#7701) + +### Documentation + + * Refactor docs (#7205) + * Add a link to Giraffe Academy's tutorial (#7325) + * Do not advise users to install Jekyll outside of Bundler (#6927) + * Remove documentation for using Redcarpet (#6990) + * Install Docs that Work on MacOS 10.14 (#7561) + * Add Installation Instructions for Ubuntu (#6925) + * Don't prompt for sudo when installing with Ubuntu WSL (#6781) + * Installation instructions for Fedora (#7198) + * Update Windows install docs (#6926) + * List all standard liquid filters (#7333) + * List all static files variables (#7002) + * Improve how to include Rouge stylesheets (#7752) + * Mention CommonMark plugins (#7418) + * Add TSV to list of supported _data files. (#7168) + * How to deploy using pre-push git hook (#7179) + * Hosting with AWS Amplify (#7510) + * CircleCI deployment through CircleCI v2 (#7024) + * GitHub Pages: use themes from other repos (#7112) + * Document page.dir and page.name (#7373) + * Document custom tag blocks (#7359) + * Document converter methods (#7289) + * Document `{{ page.collection }}` (#7430) + * Document Jekyll Filters with YAML data (#7335) + * Document where Jekyll looks for layouts in a site (#7564) + * plugin: liquid tag jekyll-flickr (#6946) + * plugin: jekyll-target-blank (#7046) + * plugin: json-get. (#7086) + * plugin: `jekyll-info` (#7091) + * plugin: jekyll-xml-source (#7114) + * plugin: jekyll-firstimage filter (#7127) + * plugin: CAT (#7011) + * Resources: Statictastic (#7593) + * Resources: Bonsai Search (#7543) + * Resources: Formspark (#7601) + * Resources: Jekpack(#7598) + * Resources: formX (#7536) + * Resources: 99inbound's Jekyll post (#7348) + * Resources: CloudSh (#7497) + * Community: DEV Community's Jekyll tag (#7139) + * Showcase: developer.spotify.com (#7217) + * Showcase: Isomer (#7300) + * Add version number for group_by_exp doc (#6956) + * Updated nginx configuration for custom-404-page documentation (#6994) + * Clarify definition of 'draft' (#7037) + * _drafts need to be contained within the custom collection directory (#6985) + * Updated to supported version (#7031) + * Add Hints for some Improved Travis Config in Doc (#7049) + * Update travis-ci.md to point out "this is an example Gemfile" (#7089) + * Instructions to view theme’s files under Linux (#7095) + * Use a real theme in the example (#7125) + * Update docs about post creation (#7138) + * Initialize upgrading doc for v4.0 (#7140) + * Add version badge for date filters with ordinal (#7162) + * Corrected sample usage of postfiles (#7181) + * Resolve "Unable to locate package ruby2.4" error (#7196) + * Correct stylesheet url in tutorial step 7 (#7210) + * Removes quotes from markdown for assets (#7223) + * Clarified front matter requirement (#7234) + * Explicit location of where to create blog.html (#7241) + * Reference the build command options that allows multiple config files (#7266) + * Add more issue template(s) and pull request template (#7269) + * Suggest sites use OpenSSL instead of GnuTLS for their site's CI (#7010) + * Fix broken Contributors link in README.markdown (#7200) + * Add title tag to item in RSS template (#7282) + * Add link tag to item in RSS template (#7291) + * Remove redundant instruction comment (#7342) + * Textile is only supported through a converter plugin (#7003) + * Add recursive navigation tutorial (#7720) + * Remove installation instructions with Homebrew (#7381) + * Fix dead link and misleading prose (#7383) + * Fix content management section (#7385) + * Apply ruby official guide documents (#7393) + * Fix group_by_exp filter example (#7394) + * Remove alt attribute from a tags (#7407) + * Fix BASH code-block in ubuntu.md (#7420) + * zlib is missing (#7428) + * Fixed unnecessary articles and pronouns (#7466) + * Store SSL key and cert in site source (#7473) + * Fix typo in tutorial for converting existing site (#7524) + * Check if var exists before include tag (#7530) + * Clarify docs on collections regarding the need for front matter (#7538) + * Fix incorrect Windows path in themes.md (#7525) + * Addresses bundle not found. (#7351) + * Update the contribution docs for draft pull requests (#7619) + * Data file section adds TSV (#7640) + * Indicate where the _sass folder is by default (#7644) + * Docs: add version tags to new placeholders (#5981) for permalinks (#7647) + * Solve "GitHub Page build failure" in 10-deployment.md (#7648) + * fix link to Site Source config (#7708) + * Introduce frontmatter in step 2 (#7704) + * Add @ashmaroli to Core Team listing (#7398) + * Link to Tidelift in site's footer (#7377) + * Link to OpenCollective backing (#7378 + * Link to sponsor listing in README (#7405) + * Adjust team page listings (#7395) + * Updates to CODE OF CONDUCT (v1.4.0) (#7105) + * More inclusive writing (#7283) + * Update Ruby version used in Travis-CI example (#7783) + * Documentation for binary operators in where_exp (#7786) + * Adding SmartForms as Forms service (#7794) + +### Site Enhancements + + * Better Performance (#7388) + * Add some minor improvements to image loading in Showcase page (#7214) + * Simplify assigning classname to docs' aside-links (#7609) + * Simplify couple of includes in the docs site (#7607) + * Avoid generating empty classnames (#7610) + * Minimize rendering count (#7343) + +### Release + + * Jekyll v4.0 release (#7782) + * Release post for v4.0.0 beta1 (#7716) + * Release post for v4.0.0.pre.alpha1 (#7574) + * Release post for v3.8.0 (#6849) + * Release post for v3.6.3, v3.7.4 and v3.8.4 (#7259) + * Post: v4.0 development (#6934) + +## 3.8.6 / 2019-07-02 + +### Bug Fixes + + * Update log output for an invalid theme directory (#7734) + * Memoize `SiteDrop#documents` to reduce allocations (#7722) + * Excerpt handling of custom and intermediate tags (#7467) + * Escape valid special chars in a site's path name (#7573) + * Revert memoizing `Site#docs_to_write` and refactor `#documents` (#7689) + * Fix broken `include_relative` usage in excerpt (#7690) + * Install platform-specific gems as required (3c06609406) + +### Security Fixes + + * Theme gems: ensure directories aren't symlinks (#7424) + +## 3.8.5 / 2018-11-04 + +### Bug Fixes + + * Re-implement handling Liquid blocks in excerpts (#7250) + +## 3.8.4 / 2018-09-18 + +### Bug Fixes + + * 3.8.x: security: fix `include` bypass of `EntryFilter#filter` symlink check (#7228) + +## 3.8.3 / 2018-06-05 + +### Bug Fixes + + * Fix --unpublished not affecting collection documents (#7027) + +## 3.8.2 / 2018-05-18 + +### Development Fixes + + * Update rubocop version (#7016) + +### Bug Fixes + + * Add whitespace control to LIQUID_TAG_REGEX (#7015) + +## 3.8.1 / 2018-05-01 + +### Bug Fixes + + * Fix rendering Liquid constructs in excerpts (#6945) + * Liquify documents unless published == false (#6959) + +## 3.8.0 / 2018-04-19 + +### Development Fixes + + * move duplicate code to a single private method (#6593) + * Test against Ruby 2.5 on AppVeyor (#6668) + * Replace simple regex with a native Ruby method (#6732) + * Codeclimate: exclude livereload.js (#6776) + * Add a cucumber feature to test link tag (#6777) + * Fix theme gem feature (#6784) + * Replace simple regex with equivalent Ruby methods (#6736) + * Rewrite `script/rubyprof` as a Ruby script (#6813) + * Add debug output to theme rendering (#5195) + * fix minitest deprecation warning in test (#6839) + * Memoize `Site#site_data` (#6809) + * Memoize document output extension (#6814) + * Access document permalink attribute efficiently (#6740) + * Minimize array allocations in the `where` filter (#6860) + * Bump JRuby (#6878) + * Assert existence of <collection>.files (#6907) + * Bump RuboCop to 0.54.x (#6915) + * Regenerate unconditionally unless its an incremental build (#6917) + * Centralize require statements (#6910) + * Bump to RuboCop 0.55 (#6929) + * Refactor private method `HighlightBlock#parse_options` (#6822) + +### Minor Enhancements + + * Two massive performance improvements for large sites (#6730) + * Cache the list of documents to be written (#6741) + * Allow Jekyll Doctor to detect stray posts dir (#6681) + * Excerpt relative-path should match its path (#6597) + * Remind user to resolve conflict in `jekyll new` with `--force` (#6801) + * Memoize helper methods in site-cleaner (#6808) + * Compute document's relative_path faster (#6767) + * Create a single instance of PostReader per site (#6759) + * Allow date filters to output ordinal days (#6773) + * Change regex to sanitize and normalize filenames passed to LiquidRenderer (#6610) + * Allow passing :strict_variables and :strict_filters options to Liquid's renderer (#6726) + * Debug writing files during the build process (#6696) + * Improve regex usage in `Tags::IncludeTag` (#6848) + * Improve comment included in the starter index.md (#6916) + * Store and retrieve converter instances for Jekyll::Filters via a hash (#6856) + * Implement a cache within the `where` filter (#6868) + * Store regexp in a constant (#6887) + * Optimize computing filename in LiquidRenderer (#6841) + +### Documentation + + * Adding the jekyll-algolia plugin to the list of plugins (#6737) + * Added Premonition plugin to list of plugins (#6750) + * Add document on releasing a new version (#6745) + * Mention Talkyard, a new commenting system for Jekyll and others. (#6752) + * Add 'jekyll-fontello' to plugins (#6757) + * Install dh-autoreconf on Windows (#6765) + * Fix common typos (#6764) + * Fix documentation for `{{ page.excerpt }}` (#6779) + * Update docs on permalink configuration (#6775) + * Propose fix some typos (#6785) + * Say hello to Jekyll's New Lead Developer (#6790) + * Add reference to Liquid to plugin docs (#6794) + * Draft a release post for v3.7.3 (#6803) + * add missing step for gem-based theme conversion (#6802) + * Update windows.md to explain an issue with jekyll new. (#6838) + * Add Bundler Installation Instructions (#6828) + * Docs: describe difference between tags and categories (#6882) + * Add `jekyll-random` plugin to docs (#6833) + * Fixed typo in description of categories and tags (#6896) + * Add missing ul-tag (#6897) + * doc: add liquid tag plugin jekyll-onebox for html previews (#6898) + * Add `jekyll-w2m` to plugins (#6855) + * Fix tutorials navigation HTML (#6919) + * add Arch Linux installation troubleshoot (#6782) + * Docs: Install Jekyll on macOS (#6881) + * Fix CodeClimate badges [ci skip] (#6930) + * Update index.md (#6933) + +### Site Enhancements + + * Remove links to Gists (#6751) + * Always load Google Fonts over HTTPS (#6792) + * always load analytics.js over HTTPS (#6807) + +### Bug Fixes + + * Append appropriate closing tag to Liquid block in an excerpt ### -minor (#6724) + * Bypass rendering via Liquid unless required (#6735) + * Delegated methods after `private` keyword are meant to be private (#6819) + * Improve handling non-default collection documents rendering and writing (#6795) + * Fix passing multiline params to include tag when using the variable syntax (#6858) + * `include_relative` tag should find related documents in collections gathered within custom `collections_dir` (#6818) + * Handle liquid tags in excerpts robustly (#6891) + * Allow front matter defaults to be applied properly to documents gathered under custom `collections_dir` (#6885) + +## 3.7.4 / 2018-09-07 + +### Bug Fixes + + * Security: fix `include` bypass of EntryFilter#filter symlink check (#7224) + +## 3.7.3 / 2018-02-25 + +### Bug Fixes + + * Do not hardcode locale unless certainly necessary (#6791) + +## 3.7.2 / 2018-01-25 + +### Development Fixes + + * CI: Test against Ruby 2.5.0 (#6664) + * Bump rdoc to 6.0 (#6600) + * Lint file and bump theme dependencies (#6698) + * Write a Rubocop Cop to ensure no `#p` or `#puts` calls get committed to master. (#6615) + * Remove redgreen gem (#6720) + +### Site Enhancements + + * Display latest version in header (#6676) + * Update version in `config.yml` via YAML load / dump (#6677) + +### Documentation + + * Fix: Add note about posts in context of collections_dir (#6680) + * Update deploy-script in documentation (#6666) + * Add note about naming of collections_dir (#6703) + * Update installation.md (#6694) + * Add `jekyll-html` to plugins. (#6654) + * Update plugins.md (#6716) + * Release v3.7.1 (#6695) + +### Bug Fixes + + * inform that symlinks are not allowed in safe mode (#6670) + * Glob scope path only if configured with a pattern (#6692) + * Add gem "wdm" to all newly generated Gemfiles (#6711) + * Fix timezone inconsistencies between different ruby version (#6697) + * Refactor collections_dir feature for consistency (#6685) + +### Minor Enhancements + + * Require external library only if necessary (#6596) + +## 3.7.0 / 2018-01-02 + +### Minor Enhancements + + * Add LiveReload functionality to Jekyll. (#5142) + * Add Utils::Internet.connected? to determine whether host machine has internet connection. (#5870) + * Disable default layouts for Pages with a `layout: none` declaration (#6182) + * Scope path glob (#6268) + * Allow the user to set collections_dir to put all collections under one subdirectory (#6331) + * Upgrade to Rouge 3 (#6381) + * Allow URL filters to work directly with documents (#6478) + * filter relative_url should keep absolute urls with scheme/authority (#6490) + * `.sass-cache` doesn't *always* land in `options['source']` (#6500) + * Allow plugins to modify the obsolete files. (#6502) + * Add latin mode to `slugify` (#6509) + * Log Kramdown warnings if log level is WARN (#6522) + * Add an option to configure kramdown warning output (#6554) + * Add `json` extension to list of directory indices (#6550) + * Dependency: Bump jekyll-watch to 2.0 (#6589) + * Remove paginate check (#6606) + * update classifier-reborn to 2.2.0 (#6631) + * Switch to an actively-maintained TOML parser. (#6652) + * Do not coerce layout paths in theme-gem to the source directory (#6603) + +### Bug Fixes + + * Raise when theme root directory is not available (#6455) + * Avoid block parser warning in SmartyPants (#6565) + * Fail gracefully if "sass" gem cannot be loaded (#6573) + * return correct file in dir if dir has same name as file (#6569) + * Register reload hooks in Server#process (#6605) + * Memoize path to metadata file (#6602) + * Use `require_relative` to load Jekyll classes (#6609) + +### Development Fixes + + * Added direct collection access to future collection item feature test(#6151) + * add failing test for non-utf8 encoding (#6339) + * Upgrade to Cucumber 3.0 (#6395) + * Provide a better default hash for tracking liquid stats (#6417) + * Add configuration for first-timers bot (#6431) + * Do not linkify escaped characters as PRs in History (#6468) + * Rely on jekyll-mentions for linking usernames (#6469) + * Update first-timers-issue-template.md (#6472) + * Enable `Lint/RescueWithoutErrorClass` Cop (#6482) + * Clean up Rubocop config (#6495) + * Use Gem to discover the location of bundler (#6499) + * Remove unnecessary encoding comment (#6513) + * Suggest using Rubocop to automatically fix errors (#6514) + * Assert raising Psych::SyntaxError when`"strict_front_matter"=>true` (#6520) + * Use Kernel#Array instead of explicit Array check (#6525) + * RuboCop: Enable `Style/UnneededCapitalW` cop (#6526) + * Refactor method to reduce ABC Metric size (#6529) + * Remove parentheses around arguments to raise (#6532) + * Use double-quotes around gem name (#6535) + * Dependencies: upgrade to toml 0.2.0 (#6541) + * Lock to cucumber 3.0.1 on Ruby 2.1 (#6546) + * Bump JRuby version in Travis config (#6561) + * Rescue from Psych::SyntaxError instead of SyntaxError after parsing YAML(#5828) + * Drop forwarding to private methods by exposing those methods as public(#6577) + * Upgrade pygments to v1.x (#5937) + * Bump yajl-ruby (#6582) + * Cleanup test_redcarpet.rb (#6584) + * Add PageWithoutAFile class from jekyll plugins (#6556) + * Cleanup LiveReloadReactor (#6607) + +### Documentation + + * Add formester to the list of saas form backend (#6059) + * GitHub Pages instructions (#6384) + * Improve documentation for theme-gem installation (#6387) + * Fix diff syntax-highlighting (#6388) + * Update instructions (#6396) + * Fix code-block highlighting in docs (#6398) + * Filtering Posts with categories, tags, or other variables (#6399) + * Fixes formatting on pre-formatted text. (#6405) + * Added new tutorial to tutorials section on docs (#6406) + * Updates (#6407) + * Fix `collections_dir` example (#6408) + * Renaming duplicate of "Scenario 6" to "Scenario 7" (#6411) + * Mark `collection_dir` as unreleased (#6412) + * Fix link to SUPPORT (#6415) + * Fix list appearance by adding missing `ol` tag (#6421) + * Explain how to override output collection index page (#6424) + * Added github-cards to the list of plugins (#6425) + * CoC violation correspondents (#6429) + * Add a note about Liquid and syntax highlighting (#6466) + * Remove `sudo` from macOS troubleshooting instructions (#6486) + * Add a note on `:jekyll_plugins` group in the docs (#6488) + * Updated custom-404-page.md (#6489) + * Fix a few minor issues in the docs (#6494) + * Add jekyll-pwa-plugin (#6533) + * Remove Jekyll-Smartify from plugins directory (#6548) + * Updated Jekyll-Pug listing to include official website (#6555) + * Remove link to severely outdated asset plugin (#6613) + * Default time zone depends upon server (#6617) + * Add `disqus-for-jekyll` to plugins. (#6618) + * Update "Requirements" for Ruby version (#6623) + * Fix: Update link to i18n_filter plugin (#6638) + * Correct WordPress capitalization (#6645) + * Add Tweetsert, Stickyposts, Paginate::Content (#6651) + * Post: Jekyll 3.7.0 released (#6634) + +### Site Enhancements + + * Add special styling for code-blocks run in shell (#6389) + * Add post about diversity (#6447) + * Update list of files excluded from Docs site (#6457) + * Update site History (#6460) + * Add default twitter card image (#6476) + * Update normalize.css to v7.0.0 (#6491) + * Optimize images (#6519) + * Back to original main navigation (#6544) + * Styles: mobile-docs select element (#6545) + * Search with DocSearch by @Algolia (#6557) + * Site header redesign (#6567) + * Move logo above site navigation on small screens (#6570) + * Docs: Include version badge for latest features (#6574) + * Use version-badge on an existing feature intro (#6575) + * Add jekyll-category-pages plugin (#6632) + * Improve docs styling for code to be run in shell (#6641) + * Fix permalink icon markup in news-item layout (#6639) + +## 3.6.3 / 2018-09-18 + +### Bug Fixes + + * 3.6.x: security: fix `include` bypass of `EntryFilter#filter` symlink check (#7229) + +## 3.6.2 / 2017-10-21 + +### Development Fixes + + * Update Rubocop to 0.51.0 (#6444) + * Add test for layout as string (#6445) + +### Bug Fixes + + * Problematic UTF+bom files (#6322) + * Always treat `data.layout` as a string (#6442) + +## 3.6.1 / 2017-10-20 + +### Documentation + + * Doc y_day in docs/permalinks (#6244) + * Update frontmatter.md (#6371) + * Elaborate on excluding items from processing (#6136) + * Style lists in tables (#6379) + * Remove duplicate "available" (#6380) + +### Development Fixes + + * Bump rubocop to use `v0.50.x` (#6368) + +## 3.6.0 / 2017-09-21 + +### Minor Enhancements + + * Ignore final newline in folded YAML string (#6054) + * Add URL checks to Doctor (#5760) + * Fix serving files that clash with directories (#6222) (#6231) + * Bump supported Ruby version to `>= 2.1.0` (#6220) + * set `LiquidError#template_name` for errors in included file (#6206) + * Access custom config array throughout session (#6200) + * Add support for Rouge 2, in addition to Rouge 1 (#5919) + * Allow `yield` to logger methods & bail early on no-op messages (#6315) + * Update mime-types. (#6336) + * Use a Schwartzian transform with custom sorting (#6342) + * Alias `Drop#invoke_drop` to `Drop#[]` (#6338) + +### Bug Fixes + + * `Deprecator`: fix typo for `--serve` command (#6229) + * `Reader#read_directories`: guard against an entry not being a directory (#6226) + * kramdown: symbolize keys in-place (#6247) + * Call `to_s` on site.url before attempting to concatenate strings (#6253) + * Enforce Style/FrozenStringLiteralComment (#6265) + * Update theme-template README to note 'assets' directory (#6257) + * Memoize the return value of `Document#url` (#6266) + * delegate `StaticFile#to_json` to `StaticFile#to_liquid` (#6273) + * Fix `Drop#key?` so it can handle a nil argument (#6281) + * Guard against type error in absolute url (#6280) + * Mutable drops should fallback to their own methods when a mutation isn't present (#6350) + * Skip adding binary files as posts (#6344) + * Don't break if bundler is not installed (#6377) + +### Documentation + + * Fix a typo in `custom-404-page.md` (#6218) + * Docs: fix links to issues in History.markdown (#6255) + * Update deprecated gems key to plugins. (#6262) + * Fixes minor typo in post text (#6283) + * Execute build command using bundle. (#6274) + * name unification - buddy details (#6317) + * name unification - application index (#6318) + * trim and relocate plugin info across docs (#6311) + * update Jekyll's README (#6321) + * add SUPPORT file for GitHub (#6324) + * Rename CODE_OF_CONDUCT to show in banner (#6325) + * Docs : illustrate page.id for a collection's document (#6329) + * Docs: post's date can be overridden in front matter (#6334) + * Docs: `site.url` behavior on development and production environments (#6270) + * Fix typo in site.url section of variables.md :-[ (#6337) + * Docs: updates (#6343) + * Fix precedence docs (#6346) + * add note to contributing docs about `script/console` (#6349) + * Docs: Fix permalink example (#6375) + +### Site Enhancements + + * Adding DevKit helpers (#6225) + * Customizing url in collection elements clarified (#6264) + * Plugins is the new gems (#6326) + +### Development Fixes + + * Strip unnecessary leading whitespace in template (#6228) + * Users should be installing patch versions. (#6198) + * Fix tests (#6240) + * Define path with `__dir__` (#6087) + * exit site.process sooner (#6239) + * make flakey test more robust (#6277) + * Add a quick test for DataReader (#6284) + * script/backport-pr: commit message no longer includes the `#` (#6289) + * Add CODEOWNERS file to help automate reviews. (#6320) + * Fix builds on codeclimate (#6333) + * Bump rubies on Travis (#6366) + +## 3.5.2 / 2017-08-12 + +### Bug Fixes + + * Backport #6281 for v3.5.x: Fix `Drop#key?` so it can handle a nil argument (#6288) + * Backport #6280 for v3.5.x: Guard against type error in `absolute_url` (#6287) + * Backport #6266 for v3.5.x: Memoize the return value of `Document#url` (#6301) + * Backport #6273 for v3.5.x: delegate `StaticFile#to_json` to `StaticFile#to_liquid` (#6302) + * Backport #6226 for v3.5.x: `Reader#read_directories`: guard against an entry not being a directory (#6304) + * Backport #6247 for v3.5.x: kramdown: symbolize keys in-place (#6303) + +## 3.5.1 / 2017-07-17 + +### Minor Enhancements + + * Use Warn for deprecation messages (#6192) + * site template: Use plugins key instead of gems (#6045) + +### Bug Fixes + + * Backward compatibilize URLFilters module (#6163) + * Static files contain front matter default keys when `to_liquid`'d (#6162) + * Always normalize the result of the `relative_url` filter (#6185) + +### Documentation + + * Update reference to trouble with OS X/macOS (#6139) + * added BibSonomy plugin (#6143) + * add plugins for multiple page pagination (#6055) + * Update minimum Ruby version in installation.md (#6164) + * Add information about finding a collection in `site.collections` (#6165) + * Add `{% raw %}` to Liquid example on site (#6179) + * Added improved Pug plugin - removed 404 Jade plugin (#6174) + * Linking the link (#6210) + * Small correction in documentation for includes (#6193) + * Fix docs site page margin (#6214) + +### Development Fixes + + * Add jekyll doctor to GitHub Issue Template (#6169) + * Test with Ruby 2.4.1-1 on AppVeyor (#6176) + * set minimum requirement for jekyll-feed (#6184) + +## 3.5.0 / 2017-06-18 + +### Minor Enhancements + + * Upgrade to Liquid v4 (#4362) + * Convert StaticFile liquid representation to a Drop & add front matter defaults support to StaticFiles (#5871) + * Add support for Tab-Separated Values data files (`*.tsv`) (#5985) + * Specify version constraint in subcommand error message. (#5974) + * Add a template for custom 404 page (#5945) + * Require `runtime_dependencies` of a Gem-based theme from its `.gemspec` file (#5914) + * Don't raise an error if URL contains a colon (#5889) + * Date filters should never raise an exception (#5722) + * add `plugins` config key as replacement for `gems` (#5130) + * create configuration from options only once in the boot process (#5487) + * Add option to fail a build with front matter syntax errors (#5832) + * Disable default layouts for documents with a `layout: none` declaration (#5933) + * In `jekyll new`, make copied site template user-writable (#6072) + * Add top-level `layout` liquid variable to Documents (#6073) + * Address reading non-binary static files in themes (#5918) + * Allow filters to sort & select based on subvalues (#5622) + * Add strip_index filter (#6075) + +### Documentation + + * Install troubleshooting on Ubuntu (#5817) + * Add Termux section on troubleshooting (#5837) + * fix ial css classes in theme doc (#5876) + * Update installation.md (#5880) + * Update Aerobatic docs (#5883) + * Add note to collections doc on hard-coded collections. (#5882) + * Makes uri_escape template docs more specific. (#5887) + * Remove duplicate footnote_nr from default config (#5891) + * Fixed tutorial for publishing gem to include repo. (#5900) + * update broken links (#5905) + * Fix typo in contribution information (#5910) + * update plugin repo URL to reflect repo move (#5916) + * Update exclude array in configuration.md (#5947) + * Fixed path in "Improve this page" link in Tutorials section (#5951) + * Corrected permalink (#5949) + * Included more details about adding defaults to static files (#5971) + * Create buddyworks (#5962) + * added (buddyworks) to ci list (#5965) + * Add a tutorial on serving custom Error 404 page (#5946) + * add custom 404 to tutorial navigation (#5978) + * Add link to order of interpretation tutorial in Tutorials nav (#5952) + * Document Jekyll's Philosophy (#5792) + * Require Ruby > 2.1.0 (#5983) + * Fix broken link (#5994) + * Default options for script/proof (#5995) + * Mention Bash on Ubuntu on Windows (#5960) + * Document `--unpublished` flag introduced in 91e9ecf (#5959) + * Update upgrading.md to mention usage of `bundle update` (#5604) + * Fix missing quotation mark (#6002) + * New tutorial: Convert an HTML site to Jekyll (#5881) + * Revamp Permalink section (#5912) + * Fixup tutorial on creating theme from existing HTML templates (#6006) + * Standardise on "URLs" without apostrophe in docs (#6018) + * Added txtpen in tutorial (#6021) + * fix typo using past participle (#6026) + * changed formatting to fit the style of the documentation (#6027) + * doc fix typo word usage (#6028) + * corrected reference to layout in index.md (#6032) + * (Minor) Update MathJax CDN (#6013) + * Add MvvmCross to samples (#6035) + * Update travis-ci.md to correct procedure (#6043) + * fix sentence in documentation (#6048) + * rephrase a sentence in posts.md to be more direct (#6049) + * Compress Website Sass output (#6009) + * doc correct spelling error (#6050) + * adjusted date-format in sitemap (#6053) + * Typo fix (welcomed change -> welcome change). (#6070) + * Fixed documentation inconsistency (#6068) + * Add own plugin -> Jekyll Brand Social Wall (#6064) + * Added plugin jekyll-analytics (#6042) + * Use more precise language when explaining links (#6078) + * Update plugins.md (#6088) + * windows 10 tutorial (#6100) + * Explain how to override theme styles (#6107) + * updated Bash on Ubuntu on Windows link in tutorial (#6111) + * Fix wording in `_docs/templates.md` links section (#6114) + * Update windows.md (#6115) + * Added windows to docs.yml (#6109) + * Be more specific on what to upload (#6119) + * Remove Blank Newlines from "Jekyll on Windows" Page (#6126) + * Link the troubleshooting page in the quickstart page (#6134) + * add documentation about the "pinned" label (#6147) + * docs(JekyllOnWindows): Add a new Installation way (#6141) + * corrected windows.md (#6149) + * Refine documentation for Windows (#6153) + +### Development Fixes + + * Rubocop: add missing comma (#5835) + * Appease classifier-reborn (#5934) + * Allow releases & development on `*-stable` branches (#5926) + * Add script/backport-pr (#5925) + * Prefer .yaml over .toml (#5966) + * Fix Appveyor with DST-aware cucumber steps (#5961) + * Use Rubocop v0.47.1 till we're ready for v0.48 (#5989) + * Test against Ruby 2.4.0 (#5687) + * rubocop: lib/jekyll/renderer.rb complexity fixes (#5052) + * Use yajl-ruby 1.2.2 (now with 2.4 support) (#6007) + * Bump Rubocop to v0.48 (#5997) + * doc use example.com (#6031) + * fix typo (#6040) + * Fix CI (#6044) + * Remove `ruby RUBY_VERSION` from generated Gemfile (#5803) + * Test if hidden collections output a document with a future date (#6103) + * Add test for uri_escape on reserved characters (#6086) + * Allow you to specify the rouge version via an environment variable for testing (#6138) + * Bump Rubocop to 0.49.1 (#6093) + * Lock nokogiri to 1.7.x for Ruby 2.1 (#6140) + +### Site Enhancements + + * Corrected date for version 3.4.0 (#5842) + * Add the correct year to the 3.4.0 release date (#5858) + * Add documentation about order of interpretation (#5834) + * Documentation on how to build navigation (#5698) + * Navigation has been moved out from docs (#5927) + * Make links in sidebar for current page more prominent (#5820) + * Update normalize.css to v6.0.0 (#6008) + * Docs: rename `gems` to `plugins` (#6082) + * plugins -> gems (#6110) + * Document difference between cgi_escape and uri_escape #5970 (#6081) + +### Bug Fixes + + * Exclude Gemfile by default (#5860) + * Convertible#validate_permalink!: ensure the return value of `data["permalink"]` is a string before asking if it is empty (#5878) + * Allow abbreviated post dates (#5920) + * Remove dependency on include from default about.md (#5903) + * Allow colons in `uri_escape` filter (#5957) + * Re-surface missing public methods in `Jekyll::Document` (#5975) + * absolute_url should not mangle URL if called more than once (#5789) + * patch URLFilters to prevent `//` (#6058) + * add test to ensure variables work in `where_exp` condition (#5315) + * Read explicitly included dot-files in collections. (#6092) + * Default `baseurl` to `nil` instead of empty string (#6137) + * Filters#time helper: Duplicate time before calling #localtime. (#5996) + +## 3.4.5 / 2017-06-30 + + * Backport #6185 for v3.4.x: Always normalize the result of the `relative_url` filter (#6186) + +## 3.4.4 / 2017-06-17 + + * Backport #6137 for v3.4.x: Default `baseurl` to `nil` instead of empty string (#6146) + +## 3.4.3 / 2017-03-21 + + * Backport #5957 for v3.4.x: Allow colons in `uri_escape` filter (#5968) + +## 3.4.2 / 2017-03-09 + + * Backport #5871 for v3.4.x: Convert StaticFile liquid representation to a Drop & add front matter defaults support to StaticFiles (#5940) + +## 3.4.1 / 2017-03-02 + + * Backport #5920 for v3.4.x: Allow abbreviated post dates (#5924) + +## 3.4.0 / 2017-01-27 + +### Minor Enhancements + + * Add connector param to `array_to_sentence_string` filter (#5597) + * Adds `group_by_exp` filter (#5513) + * Use Addressable instead of URI to decode (#5726) + * throw IncludeTagError if error occurs in included file (#5767) + * Write Jekyll::Utils::Exec.run for running shell commands. (#5640) + * Use the current year for the LICENSE of theme (#5712) + * Update License (#5713) + +### Bug Fixes + + * Escaped regular expressions when using `post_url`. (#5605) + * fix date parsing in file names to be stricter (#5609) + * Add a module to re-define `ENV["TZ"]` in Windows (#5612) + * Use each instead of map to actually return nothing (#5668) + * include: fix 'no implicit conversion of nil to String' (#5750) + * Don't include the theme's includes_path if it is nil. (#5780) + * test double slash when input = '/' (#5542) + * use logger.info for related posts (#5822) + +### Site Enhancements + + * Use only the used Font Awesome icons. (#5530) + * Switch to `https` when possible. (#5611) + * Update `_font-awesome.scss` to move .woff file before .ttf (#5614) + * Update documentation on updating FontAwesome Iconset (#5655) + * Use defaults for docs and news-items (#5744) + * Sort gems in `docs/_config.yml` (#5746) + * Add missing class (#5791) + * Improve template docs (#5694) + +### Development Fixes + + * clean unit-test names in `test/test_tags.rb` (#5608) + * Add cucumber feature to test for bonafide theme gems (#5384) + * Use `assert_nil` instead of `assert_equal nil` (#5652) + * Rubocop -a on lib/jekyll (#5666) + * Bump to rake 12.0 (#5670) + * Rubocop Gemfile (#5671) + * update Classifier-Reborn to 2.1.0 (#5711) + * Rubocop: fix Rakefile and gemspec (#5745) + * Use `assert_nil` (#5725) + * Sort gems in `jekyll.gemspec` (#5746) + * Rubocop: Require consistent comma in multiline literals (#5761) + * Bump rubocop (#5765) + * New rubocop security checks (#5768) + * test/helper: fix flaky plugin path test by removing calls to Dir.chdir without a block (#5779) + * Use latest jemoji gem (#5782) + * Bump htmlproofer (#5781) + * Bump rubies we test against (#5784) + * Bump rdoc to v5.0 (#5797) + * Bump codeclimate-test-reporter to v1.0.5 (#5798) + +### Documentation + + * Improve quickstart docs (#5689) + * Add Jekyll-Post to list of plugins (#5705) + * Add jekyll-numbered-headings (#5688) + * Docs: move permalinks from documents into config (#5544) + * Improve collections docs (#5691) + * Fix #5730: add gcc and make to the list of requirements (#5731) + * Remove instructions to install Jekyll 2 on Windows (#5582) + * Fix example URL inconsistency (#5592) + * Replace backticks within HTML blocks with HTML tags (#5435) + * Add jekyll-migrate-permalink (#5600) + * Fix bad config YAML in collections example (#5587) + * Bring documentation on 'Directory Structure' up-to-date (#5573) + * Fixed typo (#5632) + * use backticks for Gemfile for consistency since in the next sentence … (#5641) + * Update Core team list in the README file (#5643) + * Improve Permalinks documentation. (#5653) + * Fix typo in Variables doc page (#5657) + * Fix a couple of typos in the docs (#5658) + * Update windows.md (#5683) + * Improve permalinks docs (#5693) + * Document --unpublished build option (#5720) + * Improve pages docs (#5692) + * Added new includes.md topic to docs (#5696) + * Replace a dead link with a web-archived one (#5738) + * Remove duplicate paragraph. (#5740) + * Addition of a sample "typical post" (#5473) + * Fix a minor grammatical mistake on themes' document ### -dev (#5748) + * Correct comments in data_reader.rb (#5621) + * Add jekyll-pre-commit to plugins list (#5752) + * Update quickstart.md (#5758) + * Correct minor typo (#5764) + * Fix a markdown link to look properly on the web (#5769) + * Info about the help command usage (#5312) + * Add missing merge labels for jekyllbot (#5753) + * Fix broken links in documentation (#5736) + * Docs: add `match_regex` and `replace_regex` filters (#5799) + * Got that diaper money? (#5810) + * Sort content by popularity using Google Analytics (#5812) + * Rework CI doc to include multiple providers. (#5815) + * Improve theme docs (#5690) + * Add mention of classifier-reborn for LSI (#5811) + * Added note about --blank flag (#5802) + * Fixed inaccuracy in "Built-in permalink styles" docs (#5819) + +## 3.3.1 / 2016-11-14 + +### Minor Enhancements + + * Collapse `gsub` for performance (#5494) + * URL: warn if key doesn't exist in url drop (#5524) + +### Bug Fixes + + * Fix typo in `theme_template` README (#5472) + * Do not swallow all exceptions on render (#5495) + * Site template: fixed `_config.yml` comment typo (#5511) + * `jekyll new-theme` should specify Jekyll as a runtime dependency for the theme (#5457) + * Be much more specific about ignoring specific vendored directories. (#5564) + * Only warn about auto-regeneration bug on Bash On Windows. (#5464) + * Allow permalink template to have underscores (#5572) + +### Site Enhancements + + * Documentation: `link` Liquid tag (#5449) + * Updating install instruction link for Jekyll 3 on Windows (#5475) + * Update normalize.css to v5.0.0 (#5471) + * Add jekyll-data to the list of plugins (#5491) + * Add info about checking version + updating (#5497) + * Add jekyll-include-absolute-plugin to list of third-party plugins (#5492) + * Remove jekyll-hook from deployment methods (#5502) + * Update deployment-methods.md (#5504) + * Ubuntu users should install ruby2.3-dev (#5512) + * Remove Glynn as deployment option (#5519) + * Fix broken forum link (#5466) + * Move documentation to docs folder (#5459) + * Fix broken links in CONTRIBUTING (#5533) + * Update documentation on jekyllrb.com (#5540) + * Fix HTML rendering (#5536) + * Remove outdated deployment information (#5557) + * no more invalid US-ASCII on lines 30 and 97 (#5520) + * Add permalinks to docs in '/maintaining/' (#5532) + * Add jekyll-pinboard to list of third-party plugins (#5514) + * Fix formatting in 2-to-3.md (#5507) + * Add two plugins to the plugins page (#5493) + * Use site.baseurl before link and post_url tags (#5559) + * Fix link to jekyll-pinboard plugin (#5570) + * mention `docs` folder as a way to deploy on GitHub Pages (#5571) + +### Development Fixes + + * fix rubocop errors on testing with Rubocop 0.44 (#5489) + * script/test: add missing whitespace (#5479) + * Restrict Rubocop version (#5496) + * include a hashbang for all benchmark scripts & make them executable (#5505) + * Update source in script/proof (#5538) + * Collections.feature: conditional steps to have it pass on Windows (#5546) + * Fix tests to get script/test to pass on Windows (#5526) + +## 3.3.0 / 2016-10-06 + +### Minor Enhancements + + * Colorize interpolated output in logger.info (#5239) + * Site template: exclude Gemfile and Gemfile.lock in site config (#5293) + * Fix #5233: Increase our ability to detect Windows. (#5235) + * update gitignore template to ignore theme gems built by user (#5326) + * Adds ability to link to all files (#5199) + * Exclude vendor by default (#5361) + * Add ThemeAssetsReader which reads assets from a theme (#5364) + * Add bundle install to jekyll new command (#5237) + * Add absolute_url and relative_url filters. (#5399) + * Site template: remove `css/` from new site scaffolding (#5402) + * Site template: Move contents of the index.html page to the 'home' layout (#5420) + * Exclude node_modules by default (#5210) + * Run hooks in priority order. (#5157) + * Add `static_file.name` and `.basename` Liquid attributes (#5264) + * set site.url in dev environment to `http://localhost:4000` (#5431) + * Add support for indented link references on excerpt (#5212) + +### Bug Fixes + + * Use jekyll-feed to generate the default site's RSS feed (#5196) + * Site#configure_theme: do not set theme unless it's a string (#5189) + * Convertible: set self.output in #render_all_layouts and #do_layout (#5337) + * Only complain about `kramdown.coderay` if it is actually in the config (#5380) + * Clarify documentation in theme gem's README template (#5376) + * Allow underscore in highlighter language (#5375) + * Site template: set empty url in config file by default (#5338) + * Site template config: prepend 'jekyll serve' with 'bundle exec' (#5430) + * Don't call `File.utime` for StaticFiles if it's a symlink (#5427) + * Fix handling of non-ASCII characters in new `*_url` filters (#5410) + * Remove autoload of Draft which no longer exists. (#5441) + * Fix issue where Windows drive name is stripped from Jekyll.sanitized_path incorrectly (#5256) + * Fix bug where `post_url` tag matched incorrect post with subdirectory (#4873) + * Fix loading data from subdir with a period in name (#5433) + * Revert Commands::Serve#server_address signature change. (#5456) + +### Site Enhancements + + * Document `to_integer` and `inspect` filters (#5185) + * Fix path in the prompt (#5194) + * need subcommand build (#5190) + * Add the Jekyll Cloudinary plugin (#5183) + * Documentation : `new-theme` command (#5205) + * Document `link` Liquid tag (#5182) + * Remove mention of page for link tag in release post (#5214) + * fixed typo (#5226) + * Add missing comma (#5222) + * Maintain aspect ratio with `height: auto;` (#5254) + * Fix a link in deployment-methods.md (#5244) + * Documentation: improve highlight in `Creating a theme` (#5249) + * Bundler isn't installed by default (#5258) + * Update troubleshooting documentation to include fix for issue with vendored gems (#5271) + * Link `--lsi` option's description to Wikipedia docs on LSI (#5274) + * Document `--profile` option on the configuration page (#5279) + * Update homepage to sync with merge of #5258 (#5287) + * Add post about Jekyll Admin initial release (#5291) + * Replace liquid highlight tag with backticks (#5262) + * Word update (#5294) + * Site documentation section links always point to https://jekyllrb.com (#5281) + * Missing `:site, :post_render` payload documentation on site (#5280) + * Site: exclude README.md and .gitignore (#5304) + * Add link to Staticman (#5224) + * Update url for OpenShift (#5320) + * Add help for missing static_file e.g. on heroku (#5334) + * Add a line about updating theme-gems in the docs (#5318) + * Explain how to copy a theme's files (#5335) + * .md as default extension in examples (#5316) + * Fix small typo in docs (#5347) + * Add missing period to sentence in first paragraph. (#5372) + * added jekyll-spotify plugin (#5369) + * Add jekyll-menus to the list of plugins. (#5397) + * macOS and one grammar fix (#5403) + * Add documentation for `relative_url` and `absolute_url` (#5405) + * Bugfix on logo in JSON-LD (#5421) + * Fix Travis.ci documentation (#5413) + * Update documentation regarding `bundle install` after `jekyll new` (#5428) + * Replace classic box-sizing reset with inheritance reset (#5411) + * Update Wikipedia YAML list link (#5452) + * Add Jekyll 3.3 release post (#5442) + +### Development Fixes + + * Update appveyor.yml and fix optional deps for Ruby x64 (#5180) + * Improve tests for Jekyll::PluginManager (#5167) + * Update Ruby versions in travis.yml (#5221) + * Avoid installing unnecessary gems for site testing (#5272) + * Proposal: Affinity teams and their captains (#5273) + * Replace duplicate with positive local test in issue template (#5286) + * Update AppVeyor config. (#5240) + * Execute jekyll from clone instead of defined binary when running 'script/default-site' (#5295) + * rubocop: lib/jekyll/document.rb complexity fixes (#5045) + * Proxy a number of Convertible methods to Renderer (#5308) + * Run executable for Cucumber via Ruby instead of Shell (#5383) + * Appease Rubocop (#5381) + * remove features' directories on windows with proper access (#5389) + * `site_configuration.feature`: use UTC format in timezone (#5416) + * swallow bundle output from `jekyll new` while in CI (#5408) + * Add .editorconfig (#5412) + +## 3.2.1 / 2016-08-02 + +### Bug Fixes + + * Include theme directories in default gemspec (#5152) + * Fix for symlinked themes (#5156) + * Layout: set `relative_path` without using Pathname (#5164) + +### Development Fixes + + * Add test to build the default site (#5154) + * script/default-site: specify `BUNDLE_GEMFILE` for new site (#5178) + * script/default-site: read Jekyll source from local clone (#5188) + +### Site Enhancements + + * Enable site excerpts (#5150) + * Initial 404 page (#5143) + * Remove the "this feature is unreleased" warning from the theme docs (#5158) + * Future True on GitHub Pages note (#5173) + * Minor updates and corrections (#5177) + * index.html: update instructions to require bundler (#5169) + * docs/quickstart: update instructions to require bundler (#5168) + +## 3.2.0 / 2016-07-26 + +### Minor Enhancements + + * Stop testing with Ruby 2.0.x EOL (#4381) + * Allow collections to have documents that have no file extension (#4545) + * Add size property to `group_by` result (#4557) + * Site Template: Removed unnecessary nesting from `_base.scss` (#4637) + * Adding a debug log statement for skipped future documents. (#4558) + * Site Template: Changed main `
` to `
` and added accessibility info (#4636) + * Add array support to `where` filter (#4555) + * 'jekyll clean': also remove .sass-cache (#4652) + * Clean up `Tags::PostUrl` a bit, including better errors and date parsing (#4670) + * Use `String#encode` for `xml_escape` filter instead of `CGI.escapeHTML` (#4694) + * Add `show_dir_listing` option for serve command and fix index file names (#4533) + * Site Template: write a Gemfile which is educational to the new site (#4542) + * Site template: add explanation of site variables in the example `_config.yml` (#4704) + * Adds `link` Liquid tag to make generation of URLs easier (#4624) + * Allow static files to be symlinked in unsafe mode or non-prod environments (#4640) + * Add `:after_init` hook & add `Site#config=` to make resetting config easy (#4703) + * DocumentDrop: add `#<=>` which sorts by date (falling back to path) (#4741) + * Add a `where_exp` filter for filtering by expression (#4478) + * Globalize Jekyll's Filters. (#4792) + * Gem-based themes (#4595) + * Allow symlinks if they point to stuff inside `site.source` (#4710) + * Update colorator dependency to v1.x (#4855) + * Move EntryFilter to use Pathutil & fix `glob_include?` (#4859) + * Add 'jekyll new-theme' command to help users get up and running creating a theme (#4848) + * `markdownify` and `smartify` should convert input to string before conversion (#4958) + * Run `Site#generate` for 'jekyll doctor' to catch plugin issues (#5005) + * Add `normalize_whitespace` filter (#4917) + * Move bin/jekyll to exe/jekyll to prevent collision with binstubs (#5014) + * Cleaning up site template & theme updates. (#4922) + * Add fetch method to Drops (#5056) + * Extract tag name to class method (#5063) + * check if relative URL contains a colon (#5069) + * Enable strict (or lax) liquid parsing via a config variable. (#5053) + * Add filter: `to_integer` (#5101) + * watcher: pass site instance to watch plugin (#5109) + * Show liquid warnings. (#5129) + * Add `--baseurl` to `build` subcommand (#5135) + +### Bug Fixes + + * Site Template: Added a default lang attribute (#4633) + * Site template: Escape title and description where it is used in HTML (#4606) + * `Document#date`: drafts which have no date should use source file mtime (#4611) + * `Filters#time`: clone an input Time so as to be non-destructive (#4590) + * Doctor: fix issue where `--config` wasn't a recognized flag (#4598) + * Ensures `related_posts` are only set for a post (#4620) + * `EntryFilter#special?`: ignore filenames which begin with `~` (#4491) + * Cleaner: `keep_files` should only apply to the beginning of paths, not substrings with index > 0 (#3849) + * Use SSLEnable instead of EnableSSL and make URL HTTPS. (#4693) + * convertible: use `Document::YAML_FRONT_MATTER_REGEXP` to parse transformable files (#4786) + * Example in the site template should be IANA-approved example.com (#4793) + * 3.2.x/master: Fix defaults for Documents (posts/collection docs) (#4808) + * Don't rescue LoadError or bundler load errors for Bundler. (#4857) + * `Serve.process` should receive same config as `Build.process` (#4953) + * Prevent reset of page in Liquid payload right before rendering layouts (#5009) + * Add missing fields to ExcerptDrop (#5067) + * Stringify configuration overrides before first use (#5060) + * hooks: move `after_init` hook call at the end of `Site#initialize` (#5106) + * filters: raise error if no input given to date filters (#5127) + * `where_exp` filter should filter posts (#4860) + +### Forward Ports + + * From v3.1.4: Add ExcerptDrop and remove excerpt's ability to refer to itself in Liquid (#4941) + * From v3.1.4: Configuration permalink fix and addition of Configuration.from and sorting `site.collections` by label (#4942) + * From v3.1.4: Fix `{{ layout }}` oddities (proper inheritance & fixing overflow of old data) (#4943) + * From v3.1.5: Sort the results of the `require_all` glob (#4944) + * From v3.1.6: Add ability to render drops as JSON (#4945) + +### Development Fixes + + * Add project maintainer profile links (#4591) + * Fix state leakage in Kramdown test (#4618) + * Unify method for copying special files from repo to site (#4601) + * Refresh the contributing file (#4596) + * change smartify doc from copy/paste of markdownify doc (#4653) + * Update Rake & disable warnings when running tests (#4720) + * Fix many warnings (#4537) + * Don't blindly assume the last system when determining "open" cmd (#4717) + * Fix "locally" typo in contributing documentation (#4756) + * Update Rubocop rules (#4886) + * Flesh out the issue template to be much more detailed (#4849) + * Fixing rubocop offenses in lib/jekyll/cleaner.rb (#4892) + * Update `jekyll/commands*` to pass rubocop rules (#4888) + * Clean up many test files to pass Rubocop rules (#4902) + * Rubocop cleanup for some utils and further test files (#4916) + * Rubocop: Low hanging fruit (#4936) + * Rubocop: `Drop` changes from v3.1 forward-ports (#4949) + * Rubocop: cleanup for misc files (#4946) + * Rubocop: Stevenson (#4951) + * Rubocop: lib/jekyll/entry_filter.rb (#4950) + * Rubocop: `test/*` (#4947) + * Rubocop: features (#4934) + * Rubocop: Liquid renderer (#4933) + * Rubocop: converters (#4931) + * Rubocop: Site Drop (#4948) + * Rubocop: tags (#4938) + * Rubocop: Readers (#4932) + * rubocop: jekyll/lib/frontmatter_defaults.rb (#4974) + * rubocop: features/step_definitions.rb (#4956) + * Rubocop theme and url jekyll libs (#4959) + * Rubocop jekyll.rb (#4966) + * Rubocop: use %r for all regular expressions. (#4979) + * Cleanup and make misc files compliant with Rubocop. (#4940) + * Rubocop: jekyll/lib/site.rb (#4973) + * Add timings for each scenario in cucumber & print worst offenders (#4908) + * rubocop: jekyll/lib/filters.rb (#4993) + * Fix rubocop offenses in exe/jekyll (#5017) + * Rubocop: lib/jekyll/command.rb (#5018) + * rubocop: lib/jekyll/static_file.rb (#5019) + * rubocop: lib/jekyll/utils.rb (#5026) + * rubocop: lib/jekyll/regenerator.rb (#5025) + * rubocop: lib/jekyll/configuration.rb (#5024) + * rubocop: lib/jekyll/renderer.rb style fixes (#5032) + * rubocop: lib/jekyll/convertible.rb style fixes (#5031) + * rubocop: lib/jekyll/document.rb style fixes (#5030) + * Remove ruby-head from Travis matrix & fix jruby failures (#5015) + * Remove useless statement from Configuration test (#5065) + * Change baseurl to example.com for some test cases (#5068) + * use activesupport < 5 if we are on a Ruby < 2.2.2 (#5100) + * Internal documentation for working on Jekyll (#5011) + * rubocop: lib/jekyll/collection.rb (#5022) + * tests: Typo fixes. (#5114) + * Normalize yml files. (#5116) + * Whitespace cleanup. (#5113) + * Add AppVeyor support. (#5115) + * appveyor.yml: drop Ruby 2.0.0. (#5119) + * Fix indentation in benchmark (#5124) + * Style fixes for Rubocop 0.42.0 - var == 0 becomes var.zero? - when defining method_missing, also define respond_to_missing? (#5137) + +### Site Enhancements + + * Add jekyll-seo-tag, jekyll-avatar, and jekyll-sitemap to the site (#4553) + * Add Google search query to /docs/help/ (#4589) + * Upgrading, documentation (#4597) + * Add 'view source' entry (#4602) + * Add jekyll-video-embed to list of third-party plugins. (#4621) + * Adding Aerobatic to list of deployment options (#4630) + * Update documentation: HTMLProofer CLI command (#4641) + * Document that subdirectories of `_posts` are no longer categories (#4639) + * Update continuous-integration docs with sudo: false information (#4628) + * Blog post on refreshed contributing file and new affinity teams (#4645) + * Fixes typo on collections (#4647) + * Documentation: future option also works for collections (#4682) + * Additional package needed for Fedora 23 Workspace (#4685) + * Fix typo on Chocolatey name in Windows documentation (#4686) + * Use the correct URL, Fixes #4698 (#4699) + * Add jekyll-paspagon plugin (#4700) + * Bold-italicize note in assets documentation about needing front matter (#4706) + * Highlight the `script/` calls in the Contributing documentation (#4712) + * Add Hawkins to the list of third-party plugins (#4755) + * Fix a typo in pagination doc (#4763) + * Switch second GitHub Pages link to HTTPS (#4760) + * Explain data file format requirements more clearly in documentation (#4781) + * Add jekyll-i18n_tags to list of third-party plugins (#4775) + * Remove Leonard Lamprecht's website from Sites page (#4771) + * Updates documentation for collections to include `date` property (#4769) + * Added an explicit rerun note to configuration.md, defaults section (#4734) + * Update Rack-Jekyll Heroku deployment blog post url (#4789) + * Added missing single quote on rsync client side command (#4813) + * Organize Form Platforms-as-a-Service into unified list & add FormSpree.io (#4754) + * Fixed typo on Configuration page (#4804) + * Update FormKeep URL on the Resources doc (#4844) + * site: use liquid & reduce some whitespace noise (#4854) + * Add jekyll-breadcrumbs to list of third-party plugins (#4874) + * Added Pug converter to list of third-party plugins (#4872) + * Add jekyll-ideal-image-slider to list of third-party plugins (#4863) + * Add Jekyll Tips and the Cheatsheet to the list of resources (#4887) + * Removed extra `

` from `site/_docs/permalinks.md` (#4890) + * Add pubstorm deployment instructions to docs (#4881) + * Corrected pagination docs for hidden: true feature (#4903) + * Remove a Broken Link for Refheap Plugin (#4971) + * Instructions on how to install github-gem on Windows (#4975) + * Minor tweak to fix missing apostrophe (#4962) + * Instructions on how to install github-gem on Windows (v2) (#4977) + * Fix inaccurate HTTP response header field name (#4976) + * Add post about GSoC project (#4980) + * Link to the HTML page instead of Markdown (#4985) + * Update normalize.css to v4.0.0. (#4989) + * Add jekyll-tags-list-plugin to list of third-party plugins (#5000) + * Windows docs: Command needs to be called from blog path (#5006) + * Update text to be consistent with example (#5010) + * Update template links to point to core Liquid site (#5012) + * Add generator-jekyllized to third-party plugins (#5027) + * Add Jekyll Art Gallery generator plugin to list of third-party plugins (#5043) + * Add Formingo to the list of Jekyll form SaaS (#5054) + * Highlight help nav item when navigated to. (#5058) + * Update normalize.css to v4.2.0. (#5096) + * Updates html-proofer code (#5098) + * Jekyll Community (#5097) + * Typo in documentation file templates.md (#5117) + * Slightly, improve PNG compression. (#5112) + * docs: add jekyll-maps plugin reference (#5123) + * docs: fix link to plugins page source (#5122) + * Update the configuration docs to match the code (#5131) + * Removed confusing word repetition. (#5139) + * Add a note about script/fmt (#5138) + +## 3.1.6 / 2016-05-19 + +### Bug Fixes + + * Add ability to `jsonify` Drops such that, e.g. `site | jsonify`, works. (#4914) + +## 3.1.5 / 2016-05-18 + +### Bug Fixes + + * Sort the results of the `require_all` glob (affects Linux only). (#4912) + +## 3.1.4 / 2016-05-18 + +### Bug Fixes + + * Add `ExcerptDrop` and remove excerpt's ability to refer to itself in Liquid (#4907) + * Configuration permalink fix where `collections.posts.permalink` inherits properly from `permalink` only when it doesn't exist (#4910) + * Add `Configuration.from` to make it easier to build configs from just a hash + * Sorting `site.collections` in Liquid by label (#4910) + * Fix bug where `layout` in Liquid would inherit from previously-rendered layouts' metadatas (#4909) + * Fix bug where `layout` in Liquid would override in the wrong direction (more-specific layouts' data were overwritten by their parent layouts' data; this has now been reversed) (#4909) + +## 3.1.3 / 2016-04-18 + + * Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` (#4807) + * Use SSLEnable instead of EnableSSL and make URL HTTPS (WEBrick) (#4693) + +## 3.1.2 / 2016-02-19 + +### Minor Enhancements + + * Include `.rubocop.yml` in Gem (#4437) + * `LiquidRenderer#parse`: parse with line numbers. (#4452) + * Add consistency to the no-subcommand deprecation message (#4505) + +### Bug Fixes + + * Fix syntax highlighting in kramdown by making `@config` accessible in the Markdown converter. (#4428) + * `Jekyll.sanitized_path`: sanitizing a questionable path should handle tildes (#4492) + * Fix `titleize` so already capitalized words are not dropped (#4525) + * Permalinks which end in a slash should always output HTML (#4546) + +### Development Fixes + + * Require at least cucumber version 2.1.0 (#4514) + +### Site Enhancements + + * Add jekyll-toc plugin (#4429) + * Docs: Quickstart - added documentation about the `--force` option (#4410) + * Fix broken links to the Code of Conduct (#4436) + * Upgrade notes: mention trailing slash in permalink; fixes #4440 (#4455) + * Add hooks to the plugin categories toc (#4463) + * Jekyll 3 requires newer version of Ruby. (#4461) + * Fix typo in upgrading docs (#4473) + * Add note about upgrading documentation on jekyllrb.com/help/ (#4484) + * Update Rake link (#4496) + * Update & prune the short list of example sites (#4374) + * Added amp-jekyll plugin to plugins docs (#4517) + * A few grammar fixes (#4512) + * Correct a couple mistakes in structure.md (#4522) + +## 3.1.1 / 2016-01-29 + +### Meta + + * Update the Code of Conduct to the latest version (#4402) + +### Bug Fixes + + * `Page#dir`: ensure it ends in a slash (#4403) + * Add `Utils.merged_file_read_opts` to unify reading & strip the BOM (#4404) + * `Renderer#output_ext`: honor folders when looking for ext (#4401) + +### Development Fixes + + * Suppress stdout in liquid profiling test (#4409) + +## 3.1.0 / 2016-01-23 + ### Minor Enhancements + * Use `Liquid::Drop`s instead of `Hash`es in `#to_liquid` (#4277) + * Add 'sample' Liquid filter Equivalent to Array#sample functionality (#4223) * Cache parsed include file to save liquid parsing time. (#4120) * Slightly speed up url sanitization and handle multiples of ///. (#4168) + * Print debug message when a document is skipped from reading (#4180) + * Include tag should accept multiple variables in the include name (#4183) + * Add `-o` option to serve command which opens server URL (#4144) + * Add CodeClimate platform for better code quality. (#4220) + * General improvements for WEBrick via jekyll serve such as SSL & custom headers (#4224, #4228) + * Add a default charset to content-type on webrick. (#4231) + * Switch `PluginManager` to use `require_with_graceful_fail` for better UX (#4233) + * Allow quoted date in front matter defaults (#4184) + * Add a Jekyll doctor warning for URLs that only differ by case (#3171) + * drops: create one base Drop class which can be set as mutable or not (#4285) + * drops: provide `#to_h` to allow for hash introspection (#4281) + * Shim subcommands with indication of gem possibly required so users know how to use them (#4254) + * Add smartify Liquid filter for SmartyPants (#4323) + * Raise error on empty permalink (#4361) + * Refactor Page#permalink method (#4389) + +### Bug Fixes + + * Pass build options into `clean` command (#4177) + * Allow users to use .htm and .xhtml (XHTML5.) (#4160) + * Prevent Shell Injection. (#4200) + * Convertible should make layout data accessible via `layout` instead of `page` (#4205) + * Avoid using `Dir.glob` with absolute path to allow special characters in the path (#4150) + * Handle empty config files (#4052) + * Rename `@options` so that it does not impact Liquid. (#4173) + * utils/drops: update Drop to support `Utils.deep_merge_hashes` (#4289) + * Make sure jekyll/drops/drop is loaded first. (#4292) + * Convertible/Page/Renderer: use payload hash accessor & setter syntax for backwards-compatibility (#4311) + * Drop: fix hash setter precedence (#4312) + * utils: `has_yaml_header?` should accept files with extraneous spaces (#4290) + * Escape html from site.title and page.title in site template (#4307) + * Allow custom file extensions if defined in `permalink` front matter (#4314) + * Fix deep_merge_hashes! handling of drops and hashes (#4359) + * Page should respect output extension of its permalink (#4373) + * Disable auto-regeneration when running server detached (#4376) + * Drop#: only use public_send for keys in the content_methods array (#4388) + * Extract title from filename successfully when no date. (#4195) ### Development Fixes * `jekyll-docs` should be easily release-able (#4152) + * Allow use of Cucumber 2.1 or greater (#4181) + * Modernize Kramdown for Markdown converter. (#4109) + * Change TestDoctorCommand to JekyllUnitTest... (#4263) + * Create namespaced rake tasks in separate `.rake` files under `lib/tasks` (#4282) + * markdown: refactor for greater readability & efficiency (#3771) + * Fix many Rubocop style errors (#4301) + * Fix spelling of "GitHub" in docs and history (#4322) + * Reorganize and cleanup the Gemfile, shorten required depends. (#4318) + * Remove script/rebund. (#4341) + * Implement codeclimate platform (#4340) + * Remove ObjectSpace dumping and start using inherited, it's faster. (#4342) + * Add script/travis so all people can play with Travis-CI images. (#4338) + * Move Cucumber to using RSpec-Expectations and furthering JRuby support. (#4343) + * Rearrange Cucumber and add some flair. (#4347) + * Remove old FIXME (#4349) + * Clean up the Gemfile (and keep all the necessary dependencies) (#4350) ### Site Enhancements * Add three plugins to directory (#4163) * Add upgrading docs from 2.x to 3.x (#4157) - * Add protect_email to the plugins index. (#4169) + * Add `protect_email` to the plugins index. (#4169) + * Add `jekyll-deploy` to list of third-party plugins (#4179) + * Clarify plugin docs (#4154) + * Add Kickster to deployment methods in documentation (#4190) + * Add DavidBurela's tutorial for Windows to Windows docs page (#4210) + * Change GitHub code block to highlight tag to avoid it overlaps parent div (#4121) + * Update FormKeep link to be something more specific to Jekyll (#4243) + * Remove example Roger Chapman site, as the domain doesn't exist (#4249) + * Added configuration options for `draft_posts` to configuration docs (#4251) + * Fix checklist in `_assets.md` (#4259) + * Add Markdown examples to Pages docs (#4275) + * Add jekyll-paginate-category to list of third-party plugins (#4273) + * Add `jekyll-responsive_image` to list of third-party plugins (#4286) + * Add `jekyll-commonmark` to list of third-party plugins (#4299) + * Add documentation for incremental regeneration (#4293) + * Add note about removal of relative permalink support in upgrading docs (#4303) + * Add Pro Tip to use front matter variable to create clean URLs (#4296) + * Fix grammar in the documentation for posts. (#4330) + * Add documentation for smartify Liquid filter (#4333) + * Fixed broken link to blog on using mathjax with jekyll (#4344) + * Documentation: correct reference in Precedence section of Configuration docs (#4355) + * Add @jmcglone's guide to github-pages doc page (#4364) + * Added the Wordpress2Jekyll Wordpress plugin (#4377) + * Add Contentful Extension to list of third-party plugins (#4390) + * Correct Minor spelling error (#4394) + +## 3.0.5 / 2016-04-26 + + * Remove call to `#backwards_compatibilize` in `Configuration.from` (#4846) + +## 3.0.4 / 2016-04-18 + + * Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` (#4806) + * Configuration: allow users to specify a `collections.posts.permalink` directly without `permalink` clobbering it (#4753) + +## 3.0.3 / 2016-02-08 + +### Bug Fixes + + * Fix extension weirdness with folders (#4493) + * EntryFilter: only include 'excluded' log on excluded files (#4479) + * `Jekyll.sanitized_path`: escape tildes before sanitizing a questionable path (#4468) + * `LiquidRenderer#parse`: parse with line numbers (#4453) + * `Document#<=>`: protect against nil comparison in dates. (#4446) + +## 3.0.2 / 2016-01-20 + +### Bug Fixes + + * Document: throw a useful error when an invalid date is given (#4378) ## 3.0.1 / 2015-11-17 @@ -90,8 +2419,7 @@ * Perf: `Markdown#matches` should avoid regexp (#3321) * Perf: Use frozen regular expressions for `Utils#slugify` (#3321) * Split off Textile support into jekyll-textile-converter (#3319) - * Improve the navigation menu alignment in the site template on small - screens (#3331) + * Improve the navigation menu alignment in the site template on small screens (#3331) * Show the regeneration time after the initial generation (#3378) * Site template: Switch default font to Helvetica Neue (#3376) * Make the `include` tag a teensy bit faster. (#3391) @@ -123,8 +2451,7 @@ * Set log level to debug when verbose flag is set (#3665) * Added a mention on the Gemfile to complete the instructions (#3671) * Perf: Cache `Document#to_liquid` and invalidate where necessary (#3693) - * Perf: `Jekyll::Cleaner#existing_files`: Call `keep_file_regex` and - `keep_dirs` only once, not once per iteration (#3696) + * Perf: `Jekyll::Cleaner#existing_files`: Call `keep_file_regex` and `keep_dirs` only once, not once per iteration (#3696) * Omit jekyll/jekyll-help from list of resources. (#3698) * Add basic `jekyll doctor` test to detect fsnotify (OSX) anomalies. (#3704) * Added talk.jekyllrb.com to "Have questions?" (#3694) @@ -138,7 +2465,7 @@ * Internal: trigger hooks by owner symbol (#3871) * Update MIME types from mime-db (#3933) * Add header to site template `_config.yml` for clarity & direction (#3997) - * Site template: add timezone offset to post date frontmatter (#4001) + * Site template: add timezone offset to post date front matter (#4001) * Make a constant for the regex to find hidden files (#4032) * Site template: refactor github & twitter icons into includes (#4049) * Site template: add background to Kramdown Rouge-ified backtick code blocks (#4053) @@ -155,7 +2482,7 @@ * Fix nav items alignment when on multiple rows (#3264) * Highlight: Only Strip Newlines/Carriage Returns, not Spaces (#3278) * Find variables in front matter defaults by searching with relative file path. (#2774) - * Allow variables (e.g `:categories`) in YAML front matter permalinks (#3320) + * Allow variables (e.g `:categories`) in front matter permalinks (#3320) * Handle nil URL placeholders in permalinks (#3325) * Template: Fix nav items alignment when in "burger" mode (#3329) * Template: Remove `!important` from nav SCSS introduced in #3329 (#3375) @@ -172,7 +2499,7 @@ * Add WOFF2 font MIME type to Jekyll server MIME types (#3647) * Be smarter about extracting the extname in `StaticFile` (#3632) * Process metadata for all dependencies (#3608) - * Show error message if the YAML front matter on a page/post is invalid. (#3643) + * Show error message if the front matter on a page/post is invalid. (#3643) * Upgrade redcarpet to 3.2 (Security fix: OSVDB-120415) (#3652) * Create #mock_expects that goes directly to RSpec Mocks. (#3658) * Open `.jekyll-metadata` in binary mode to read binary Marshal data (#3713) @@ -183,7 +2510,7 @@ * Fixed an unclear code comment in site template SCSS (#3837) * Fix reading of binary metadata file (#3845) * Remove var collision with site template header menu iteration variable (#3838) - * Change non-existent `hl_linenos` to `hl_lines` to allow passthrough in safe mode (#3787) + * Change nonexistent `hl_linenos` to `hl_lines` to allow passthrough in safe mode (#3787) * Add missing flag to disable the watcher (#3820) * Update CI guide to include more direct explanations of the flow (#3891) * Set `future` to `false` in the default config (#3892) @@ -250,7 +2577,7 @@ * Add a Resources link to tutorial on building dynamic navbars (#3185) * Semantic structure improvements to the post and page layouts (#3251) * Add new AsciiDoc plugin to list of third-party plugins. (#3277) - * Specify that all transformable collection documents must contain YAML front matter (#3271) + * Specify that all transformable collection documents must contain front matter (#3271) * Assorted accessibility fixes (#3256) * Update configuration docs to mention `keep_files` for `destination` (#3288, #3296) * Break when we successfully generate nav link to save CPU cycles. (#3291) @@ -278,7 +2605,7 @@ * Add a link on all the docs pages to "Improve this page". (#3510) * Add jekyll-auto-image generator to the list of third-party plugins (#3489) * Replace link to the proposed `picture` element spec (#3530) - * Add frontmatter date formatting information (#3469) + * Add front matter date formatting information (#3469) * Improve consistency and clarity of plugins options note (#3546) * Add permalink warning to pagination docs (#3551) * Fix grammar in Collections docs API stability warning (#3560) @@ -290,7 +2617,7 @@ * Define the `install` step in the CI example `.travis.yml` (#3622) * Expand collections documentation. (#3638) * Add the "warning" note label to excluding `vendor` in the CI docs page (#3623) - * Upgrade pieces of the Ugrading guide for Jekyll 3 (#3607) + * Upgrade pieces of the Upgrading guide for Jekyll 3 (#3607) * Showing how to access specific data items (#3468) * Clarify pagination works from within HTML files (#3467) * Add note to `excerpt_separator` documentation that it can be set globally (#3667) @@ -341,7 +2668,7 @@ ### Site Enhancements - * Add `@alfredxing` to the `@jekyll/core` team. :tada: (#3218) + * Add @alfredxing to the @jekyll/core team. :tada: (#3218) * Document the `-q` option for the `build` and `serve` commands (#3149) * Fix some minor typos/flow fixes in documentation website content (#3165) * Add `keep_files` to configuration documentation (#3162) @@ -406,18 +2733,16 @@ * Strip newlines in site template `` description. (#2982) * Add link to atom feed in `head` of site template files (#2996) * Performance optimizations (#2994) - * Use `Hash#each_key` instead of `Hash#keys.each` to speed up iteration - over hash keys. (#3017) + * Use `Hash#each_key` instead of `Hash#keys.each` to speed up iteration over hash keys. (#3017) * Further minor performance enhancements. (#3022) * Add 'b' and 's' aliases for build and serve, respectively (#3065) ### Bug Fixes * Fix Rouge's RedCarpet plugin interface integration (#2951) - * Remove `--watch` from the site template blog post since it defaults - to watching in in 2.4.0 (#2922) + * Remove `--watch` from the site template blog post since it defaults to watching in in 2.4.0 (#2922) * Fix code for media query mixin in site template (#2946) - * Allow post URL's to have `.htm` extensions (#2925) + * Allow post URLs to have `.htm` extensions (#2925) * `Utils.slugify`: Don't create new objects when gsubbing (#2997) * The jsonify filter should deep-convert to Liquid when given an Array. (#3032) * Apply `jsonify` filter to Hashes deeply and effectively (#3063) @@ -443,7 +2768,7 @@ * Add Big Footnotes for Kramdown plugin to list of third-party plugins (#2916) * Remove warning regarding GHP use of singular types for front matter defaults (#2919) * Fix quote character typo in site documentation for templates (#2917) - * Point Liquid links to Liquid’s Github wiki (#2887) + * Point Liquid links to Liquid’s GitHub wiki (#2887) * Add HTTP Basic Auth (.htaccess) plugin to list of third-party plugins (#2931) * (Minor) Grammar & `_config.yml` filename fixes (#2911) * Added `mathml.rb` to the list of third-party plugins. (#2937) @@ -493,11 +2818,9 @@ * Document the `name` variable for collection permalinks (#2829) * Adds info about installing jekyll in current dir (#2839) - * Remove deprecated `jekyll-projectlist` plugin from list of third-party - plugins (#2742) - * Remove tag plugins that are built in to Jekyll (#2751) - * Add `markdown-writer` package for Atom Editor to list of third-party - plugins (#2763) + * Remove deprecated `jekyll-projectlist` plugin from list of third-party plugins (#2742) + * Remove tag plugins that are built into Jekyll (#2751) + * Add `markdown-writer` package for Atom Editor to list of third-party plugins (#2763) * Fix typo in site documentation for collections (#2764) * Fix minor typo on plugins docs page (#2765) * Replace markdown with HTML in `sass_dir` note on assets page (#2791) @@ -585,8 +2908,7 @@ ### Site Enhancements * Update Kramdown urls (#2588) - * Add `Jekyll::AutolinkEmail` and `Jekyll::GitMetadata` to the list of - third-party plugins (#2596) + * Add `Jekyll::AutolinkEmail` and `Jekyll::GitMetadata` to the list of third-party plugins (#2596) * Fix a bunch of broken links in the site (#2601) * Replace dead links with working links (#2611) * Add jekyll-hook to deployment methods (#2617) @@ -623,12 +2945,10 @@ * Allow subdirectories in `_data` (#2395) * Extract Pagination Generator into gem: `jekyll-paginate` (#2455) * Utilize `date_to_rfc822` filter in site template (#2437) - * Add categories, last build datetime, and generator to site template - feed (#2438) + * Add categories, last build datetime, and generator to site template feed (#2438) * Configurable, replaceable Logger-compliant logger (#2444) * Extract `gist` tag into a separate gem (#2469) - * Add `collection` attribute to `Document#to_liquid` to access the - document's collection label. (#2436) + * Add `collection` attribute to `Document#to_liquid` to access the document's collection label. (#2436) * Upgrade listen to `2.7.6 <= x < 3.0.0` (#2492) * Allow configuration of different Twitter and GitHub usernames in site template (#2485) * Bump Pygments to v0.6.0 (#2504) @@ -653,8 +2973,7 @@ * Allow front matter defaults to set post categories (#2373) * Fix command in subcommand deprecation warning (#2457) * Keep all parent directories of files/dirs in `keep_files` (#2458) - * When using RedCarpet and Rouge without Rouge installed, fixed erroneous - error which stated that redcarpet was missing, not rouge. (#2464) + * When using RedCarpet and Rouge without Rouge installed, fixed erroneous error which stated that redcarpet was missing, not rouge. (#2464) * Ignore *all* directories and files that merit it on auto-generation (#2459) * Before copying file, explicitly remove the old one (#2535) * Merge file system categories with categories from YAML. (#2531) @@ -683,8 +3002,7 @@ * Prevent table from extending parent width in permalink style table (#2424) * Add collections to info about pagination support (#2389) * Add `jekyll_github_sample` plugin to list of third-party plugins (#2463) - * Clarify documentation around front matter defaults and add details - about defaults for collections. (#2439) + * Clarify documentation around front matter defaults and add details about defaults for collections. (#2439) * Add Jekyll Project Version Tag to list of third-party plugins (#2468) * Use `https` for GitHub links across whole site (#2470) * Add StickerMule + Jekyll post (#2476) @@ -700,13 +3018,11 @@ ### Bug Fixes - * Properly prefix links in site template with URL or baseurl depending upon - need. (#2319) + * Properly prefix links in site template with URL or baseurl depending upon need. (#2319) * Update gist tag comments and error message to require username (#2326) * Fix `permalink` setting in site template (#2331) * Don't fail if any of the path objects are nil (#2325) - * Instantiate all descendants for converters and generators, not just - direct subclasses (#2334) + * Instantiate all descendants for converters and generators, not just direct subclasses (#2334) * Replace all instances of `site.name` with `site.title` in site template (#2324) * `Jekyll::Filters#time` now accepts UNIX timestamps in string or number form (#2339) * Use `item_property` for `where` filter so it doesn't break on collections (#2359) @@ -742,17 +3058,16 @@ ## 2.0.0 / 2014-05-06 ### Major Enhancements + * Add "Collections" feature (#2199) * Add gem-based plugin whitelist to safe mode (#1657) - * Replace the commander command line parser with a more robust - solution for our needs called `mercenary` (#1706) + * Replace the commander command line parser with a more robust solution for our needs called `mercenary` (#1706) * Remove support for Ruby 1.8.x (#1780) * Move to jekyll/jekyll from mojombo/jekyll (#1817) * Allow custom markdown processors (#1872) * Provide support for the Rouge syntax highlighter (#1859) * Provide support for Sass (#1932) - * Provide a 300% improvement when generating sites that use - `Post#next` or `Post#previous` (#1983) + * Provide a 300% improvement when generating sites that use `Post#next` or `Post#previous` (#1983) * Provide support for CoffeeScript (#1991) * Replace Maruku with Kramdown as Default Markdown Processor (#1988) * Expose `site.static_files` to Liquid (#2075) @@ -763,10 +3078,9 @@ * Exclude files based on prefix as well as `fnmatch?` (#2303) ### Minor Enhancements - * Move the EntryFilter class into the Jekyll module to avoid polluting the - global namespace (#1800) - * Add `group_by` Liquid filter create lists of items grouped by a common - property's value (#1788) + + * Move the EntryFilter class into the Jekyll module to avoid polluting the global namespace (#1800) + * Add `group_by` Liquid filter create lists of items grouped by a common property's value (#1788) * Add support for Maruku's `fenced_code_blocks` option (#1799) * Update Redcarpet dependency to ~> 3.0 (#1815) * Automatically sort all pages by name (#1848) @@ -777,12 +3091,10 @@ * Bump dependency `safe_yaml` to `~> 1.0` (#1886) * Allow sorting of content by custom properties (#1849) * Add `--quiet` flag to silence output during build and serve (#1898) - * Add a `where` filter to filter arrays based on a key/value pair - (#1875) + * Add a `where` filter to filter arrays based on a key/value pair (#1875) * Route 404 errors to a custom 404 page in development (#1899) * Excludes are now relative to the site source (#1916) - * Bring MIME Types file for `jekyll serve` to complete parity with GH Pages - servers (#1993) + * Bring MIME Types file for `jekyll serve` to complete parity with GH Pages servers (#1993) * Adding Breakpoint to make new site template more responsive (#2038) * Default to using the UTF-8 encoding when reading files. (#2031) * Update Redcarpet dependency to ~> 3.1 (#2044) @@ -800,13 +3112,11 @@ * Add support for unpublished drafts (#2164) * Add `force_polling` option to the `serve` command (#2165) * Clean up the `` in the site template (#2186) - * Permit YAML blocks to end with three dots to better conform with the - YAML spec (#2110) + * Permit YAML blocks to end with three dots to better conform with the YAML spec (#2110) * Use `File.exist?` instead of deprecated `File.exists?` (#2214) - * Require newline after start of YAML Front Matter header (#2211) + * Require newline after start of front matter header (#2211) * Add the ability for pages to be marked as `published: false` (#1492) - * Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy - looking up of variable values in a Liquid context. (#2253) + * Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy looking up of variable values in a Liquid context. (#2253) * Remove literal lang name from class (#2292) * Return `utf-8` encoding in header for webrick error page response (#2289) * Make template site easier to customize (#2268) @@ -815,13 +3125,12 @@ * Take into account missing values in the Liquid sort filter (#2299) ### Bug Fixes + * Don't allow nil entries when loading posts (#1796) - * Remove the scrollbar that's always displayed in new sites generated - from the site template (#1805) + * Remove the scrollbar that's always displayed in new sites generated from the site template (#1805) * Add `#path` to required methods in `Jekyll::Convertible` (#1866) * Default Maruku fenced code blocks to ON for 2.0.0-dev (#1831) - * Change short opts for host and port for `jekyll docs` to be consistent with - other subcommands (#1877) + * Change short opts for host and port for `jekyll docs` to be consistent with other subcommands (#1877) * Fix typos (#1910) * Lock Maruku at 0.7.0 to prevent bugs caused by Maruku 0.7.1 (#1958) * Fixes full path leak to source directory when using include tag (#1951) @@ -833,9 +3142,8 @@ * Patch a couple show-stopping security vulnerabilities (#1946) * Sanitize paths uniformly, in a Windows-friendly way (#2065, #2109) * Update gem build steps to work correctly on Windows (#2118) - * Remove obsolete `normalize_options` method call from `bin/jekyll` (#2121). - * Remove `+` characters from Pygments lexer names when adding as a CSS - class (#994) + * Remove obsolete `normalize_options` method call from `bin/jekyll` (#2121) + * Remove `+` characters from Pygments lexer names when adding as a CSS class (#994) * Remove some code that caused Ruby interpreter warnings (#2178) * Only strip the drive name if it begins the string (#2175) * Remove default post with invalid date from site template (#2200) @@ -850,14 +3158,14 @@ * Add `output` to `Document` liquid output hash (#2309) ### Development Fixes + * Add a link to the site in the README.md file (#1795) * Add in History and site changes from `v1-stable` branch (#1836) * Testing additions on the Excerpt class (#1893) * Fix the `highlight` tag feature (#1859) * Test Jekyll under Ruby 2.1.0 (#1900) * Add script/cibuild for fun and profit (#1912) - * Use `Forwardable` for delegation between `Excerpt` and `Post` - (#1927) + * Use `Forwardable` for delegation between `Excerpt` and `Post` (#1927) * Rename `read_things` to `read_content` (#1928) * Add `script/branding` script for ASCII art lovin' (#1936) * Update the README to reflect the repo move (#1943) @@ -885,11 +3193,11 @@ * Workaround for Travis bug (#2290) ### Site Enhancements + * Document Kramdown's GFM parser option (#1791) * Move CSS to includes & update normalize.css to v2.1.3 (#1787) * Minify CSS only in production (#1803) - * Fix broken link to installation of Ruby on Mountain Lion blog post on - Troubleshooting docs page (#1797) + * Fix broken link to installation of Ruby on Mountain Lion blog post on Troubleshooting docs page (#1797) * Fix issues with 1.4.1 release blog post (#1804) * Add note about deploying to OpenShift (#1812) * Collect all Windows-related docs onto one page (#1818) @@ -904,8 +3212,7 @@ * Add jekyll-compass to the plugin list (#1923) * Add note in Posts docs about stripping `

` tags from excerpt (#1933) * Add additional info about the new exclude behavior (#1938) - * Linkify 'awesome contributors' to point to the contributors graph on - GitHub (#1940) + * Linkify 'awesome contributors' to point to the contributors graph on GitHub (#1940) * Update `docs/sites.md` link to GitHub Training materials (#1949) * Update `master` with the release info from 1.4.3 (#1947) * Define docs nav in datafile (#1953) @@ -922,8 +3229,7 @@ * Update link to rack-jekyll on "Deployment Methods" page (#2047) * Fix typo in /docs/configuration (#2073) * Fix count in docs for `site.static_files` (#2077) - * Update configuration docs to indicate utf-8 is the default for 2.0.0 - and ASCII for 1.9.3 (#2074) + * Update configuration docs to indicate utf-8 is the default for 2.0.0 and ASCII for 1.9.3 (#2074) * Add info about unreleased feature to the site (#2061) * Add whitespace to liquid example in GitHub Pages docs (#2084) * Clarify the way Sass and CoffeeScript files are read in and output (#2067) @@ -940,8 +3246,7 @@ * Some HTML tidying (#2130) * Remove modernizr and use html5shiv.js directly for IE less than v9 (#2131) * Remove unused images (#2187) - * Use `array_to_sentence_string` filter when outputting news item - categories (#2191) + * Use `array_to_sentence_string` filter when outputting news item categories (#2191) * Add link to Help repo in primary navigation bar (#2177) * Switch to using an ico file for the shortcut icon (#2193) * Use numbers to specify font weights and only bring in font weights used (#2185) @@ -991,64 +3296,72 @@ ## 1.4.3 / 2014-01-13 ### Bug Fixes + * Patch show-stopping security vulnerabilities (#1944) ## 1.4.2 / 2013-12-16 ### Bug Fixes + * Turn on Maruku fenced code blocks by default (#1830) ## 1.4.1 / 2013-12-09 ### Bug Fixes + * Don't allow nil entries when loading posts (#1796) ## 1.4.0 / 2013-12-07 ### Major Enhancements + * Add support for TOML config files (#1765) ### Minor Enhancements + * Sort plugins as a way to establish a load order (#1682) * Update Maruku to 0.7.0 (#1775) ### Bug Fixes + * Add a space between two words in a Pagination warning message (#1769) * Upgrade `toml` gem to `v0.1.0` to maintain compat with Ruby 1.8.7 (#1778) ### Development Fixes + * Remove some whitespace in the code (#1755) * Remove some duplication in the reading of posts and drafts (#1779) ### Site Enhancements + * Fixed case of a word in the Jekyll v1.3.0 release post (#1762) * Fixed the mime type for the favicon (#1772) ## 1.3.1 / 2013-11-26 ### Minor Enhancements + * Add a `--prefix` option to passthrough for the importers (#1669) - * Push the paginator plugin lower in the plugin priority order so - other plugins run before it (#1759) + * Push the paginator plugin lower in the plugin priority order so other plugins run before it (#1759) ### Bug Fixes + * Fix the include tag when ran in a loop (#1726) * Fix errors when using `--watch` on 1.8.7 (#1730) - * Specify where the include is called from if an included file is - missing (#1746) + * Specify where the include is called from if an included file is missing (#1746) ### Development Fixes + * Extract `Site#filter_entries` into its own object (#1697) * Enable Travis' bundle caching (#1734) * Remove trailing whitespace in some files (#1736) * Fix a duplicate test name (#1754) ### Site Enhancements + * Update link to example Rakefile to point to specific commit (#1741) - * Fix drafts docs to indicate that draft time is based on file modification - time, not `Time.now` (#1695) - * Add `jekyll-monthly-archive-plugin` and `jekyll-category-archive-plugin` to - list of third-party plugins (#1693) + * Fix drafts docs to indicate that draft time is based on file modification time, not `Time.now` (#1695) + * Add `jekyll-monthly-archive-plugin` and `jekyll-category-archive-plugin` to list of third-party plugins (#1693) * Add `jekyll-asset-path-plugin` to list of third-party plugins (#1670) * Add `emoji-for-jekyll` to list of third-part plugins (#1708) * Fix previous section link on plugins page to point to pagination page (#1707) @@ -1060,44 +3373,40 @@ ## 1.3.0 / 2013-11-04 ### Major Enhancements - * Add support for adding data as YAML files under a site's `_data` - directory (#1003) + + * Add support for adding data as YAML files under a site's `_data` directory (#1003) * Allow variables to be used with `include` tags (#1495) * Allow using gems for plugin management (#1557) ### Minor Enhancements + * Decrease the specificity in the site template CSS (#1574) * Add `encoding` configuration option (#1449) - * Provide better error handling for Jekyll's custom Liquid tags - (#1514) - * If an included file causes a Liquid error, add the path to the - include file that caused the error to the error message (#1596) - * If a layout causes a Liquid error, change the error message so that - we know it comes from the layout (#1601) + * Provide better error handling for Jekyll's custom Liquid tags (#1514) + * If an included file causes a Liquid error, add the path to the include file that caused the error to the error message (#1596) + * If a layout causes a Liquid error, change the error message so that we know it comes from the layout (#1601) * Update Kramdown dependency to `~> 1.2` (#1610) * Update `safe_yaml` dependency to `~> 0.9.7` (#1602) * Allow layouts to be in subfolders like includes (#1622) * Switch to listen for site watching while serving (#1589) * Add a `json` liquid filter to be used in sites (#1651) - * Point people to the migration docs when the `jekyll-import` gem is - missing (#1662) + * Point people to the migration docs when the `jekyll-import` gem is missing (#1662) ### Bug Fixes - * Fix up matching against source and destination when the two - locations are similar (#1556) + + * Fix up matching against source and destination when the two locations are similar (#1556) * Fix the missing `pathname` require in certain cases (#1255) * Use `+` instead of `Array#concat` when building `Post` attribute list (#1571) * Print server address when launching a server (#1586) * Downgrade to Maruku `~> 0.6.0` in order to avoid changes in rendering (#1598) * Fix error with failing include tag when variable was file name (#1613) * Downcase lexers before passing them to pygments (#1615) - * Capitalize the short verbose switch because it conflicts with the - built-in Commander switch (#1660) + * Capitalize the short verbose switch because it conflicts with the built-in Commander switch (#1660) * Fix compatibility with 1.8.x (#1665) - * Fix an error with the new file watching code due to library version - incompatibilities (#1687) + * Fix an error with the new file watching code due to library version incompatibilities (#1687) ### Development Fixes + * Add coverage reporting with Coveralls (#1539) * Refactor the Liquid `include` tag (#1490) * Update launchy dependency to `~> 2.3` (#1608) @@ -1114,6 +3423,7 @@ * Improve comparisons of timestamps by ignoring the seconds (#1582) ### Site Enhancements + * Fix params for `JekyllImport::WordPress.process` arguments (#1554) * Add `jekyll-suggested-tweet` to list of third-party plugins (#1555) * Link to Liquid's docs for tags and filters (#1553) @@ -1121,8 +3431,7 @@ * Simplify/generalize pagination docs (#1577) * Add documentation for the new data sources feature (#1503) * Add more information on how to create generators (#1590, #1592) - * Improve the instructions for mimicking GitHub Flavored Markdown - (#1614) + * Improve the instructions for mimicking GitHub Flavored Markdown (#1614) * Add `jekyll-import` warning note of missing dependencies (#1626) * Fix grammar in the Usage section (#1635) * Add documentation for the use of gems as plugins (#1656) @@ -1134,21 +3443,25 @@ ## 1.2.1 / 2013-09-14 ### Minor Enhancements + * Print better messages for detached server. Mute output on detach. (#1518) * Disable reverse lookup when running `jekyll serve` (#1363) * Upgrade RedCarpet dependency to `~> 2.3.0` (#1515) * Upgrade to Liquid `>= 2.5.2, < 2.6` (#1536) ### Bug Fixes + * Fix file discrepancy in gemspec (#1522) * Force rendering of Include tag (#1525) ### Development Fixes + * Add a rake task to generate a new release post (#1404) * Mute LSI output in tests (#1531) * Update contributor documentation (#1537) ### Site Enhancements + * Fix a couple of validation errors on the site (#1511) * Make navigation menus reusable (#1507) * Fix link to History page from Release v1.2.0 notes post. @@ -1158,42 +3471,38 @@ ## 1.2.0 / 2013-09-06 ### Major Enhancements + * Disable automatically-generated excerpts when `excerpt_separator` is `""`. (#1386) * Add checking for URL conflicts when running `jekyll doctor` (#1389) ### Minor Enhancements + * Catch and fix invalid `paginate` values (#1390) - * Remove superfluous `div.container` from the default html template for - `jekyll new` (#1315) + * Remove superfluous `div.container` from the default html template for `jekyll new` (#1315) * Add `-D` short-form switch for the drafts option (#1394) * Update the links in the site template for Twitter and GitHub (#1400) * Update dummy email address to example.com domain (#1408) - * Update normalize.css to v2.1.2 and minify; add rake task to update - normalize.css with greater ease. (#1430) - * Add the ability to detach the server ran by `jekyll serve` from it's - controlling terminal (#1443) + * Update normalize.css to v2.1.2 and minify; add rake task to update normalize.css with greater ease. (#1430) + * Add the ability to detach the server ran by `jekyll serve` from it's controlling terminal (#1443) * Improve permalink generation for URLs with special characters (#944) - * Expose the current Jekyll version to posts and pages via a new - `jekyll.version` variable (#1481) + * Expose the current Jekyll version to posts and pages via a new `jekyll.version` variable (#1481) ### Bug Fixes + * Markdown extension matching matches only exact matches (#1382) * Fixed NoMethodError when message passed to `Stevenson#message` is nil (#1388) * Use binary mode when writing file (#1364) - * Fix 'undefined method `encoding` for "mailto"' errors w/ Ruby 1.8 and - Kramdown > 0.14.0 (#1397) + * Fix 'undefined method `encoding` for "mailto"' errors w/ Ruby 1.8 and Kramdown > 0.14.0 (#1397) * Do not force the permalink to be a dir if it ends on .html (#963) * When a Liquid Exception is caught, show the full path rel. to site source (#1415) - * Properly read in the config options when serving the docs locally - (#1444) + * Properly read in the config options when serving the docs locally (#1444) * Fixed `--layouts` option for `build` and `serve` commands (#1458) * Remove kramdown as a runtime dependency since it's optional (#1498) - * Provide proper error handling for invalid file names in the include - tag (#1494) + * Provide proper error handling for invalid file names in the include tag (#1494) ### Development Fixes - * Remove redundant argument to - Jekyll::Commands::New#scaffold_post_content (#1356) + + * Remove redundant argument to Jekyll::Commands::New#scaffold_post_content (#1356) * Add new dependencies to the README (#1360) * Fix link to contributing page in README (#1424) * Update TomDoc in Pager#initialize to match params (#1441) @@ -1203,6 +3512,7 @@ * Add Gem version and dependency badge to README (#1497) ### Site Enhancements + * Add info about new releases (#1353) * Update plugin list with jekyll-rss plugin (#1354) * Update the site list page with Ruby's official site (#1358) @@ -1227,59 +3537,59 @@ ## 1.1.2 / 2013-07-25 ### Bug Fixes + * Require Liquid 2.5.1 (#1349) ## 1.1.1 / 2013-07-24 ### Minor Enhancements + * Remove superfluous `table` selector from main.css in `jekyll new` template (#1328) * Abort with non-zero exit codes (#1338) ### Bug Fixes + * Fix up the rendering of excerpts (#1339) ### Site Enhancements + * Add Jekyll Image Tag to the plugins list (#1306) * Remove erroneous statement that `site.pages` are sorted alphabetically. - * Add info about the `_drafts` directory to the directory structure - docs (#1320) - * Improve the layout of the plugin listing by organizing it into - categories (#1310) + * Add info about the `_drafts` directory to the directory structure docs (#1320) + * Improve the layout of the plugin listing by organizing it into categories (#1310) * Add generator-jekyllrb and grunt-jekyll to plugins page (#1330) * Mention Kramdown as option for markdown parser on Extras page (#1318) * Update Quick-Start page to include reminder that all requirements must be installed (#1327) - * Change filename in `include` example to an HTML file so as not to indicate that Jekyll - will automatically convert them. (#1303) + * Change filename in `include` example to an HTML file so as not to indicate that Jekyll will automatically convert them. (#1303) * Add an RSS feed for commits to Jekyll (#1343) ## 1.1.0 / 2013-07-14 ### Major Enhancements + * Add `docs` subcommand to read Jekyll's docs when offline. (#1046) * Support passing parameters to templates in `include` tag (#1204) * Add support for Liquid tags to post excerpts (#1302) ### Minor Enhancements - * Search the hierarchy of pagination path up to site root to determine template page for - pagination. (#1198) + + * Search the hierarchy of pagination path up to site root to determine template page for pagination. (#1198) * Add the ability to generate a new Jekyll site without a template (#1171) - * Use redcarpet as the default markdown engine in newly generated - sites (#1245, #1247) - * Add `redcarpet` as a runtime dependency so `jekyll build` works out-of-the-box for new - sites. (#1247) - * In the generated site, remove files that will be replaced by a - directory (#1118) + * Use redcarpet as the default markdown engine in newly generated sites (#1245, #1247) + * Add `redcarpet` as a runtime dependency so `jekyll build` works out-of-the-box for new sites. (#1247) + * In the generated site, remove files that will be replaced by a directory (#1118) * Fail loudly if a user-specified configuration file doesn't exist (#1098) * Allow for all options for Kramdown HTML Converter (#1201) ### Bug Fixes + * Fix pagination in subdirectories. (#1198) - * Fix an issue with directories and permalinks that have a plus sign - (+) in them (#1215) + * Fix an issue with directories and permalinks that have a plus sign (+) in them (#1215) * Provide better error reporting when generating sites (#1253) * Latest posts first in non-LSI `related_posts` (#1271) ### Development Fixes + * Merge the theme and layout Cucumber steps into one step (#1151) * Restrict activesupport dependency to pre-4.0.0 to maintain compatibility with `<= 1.9.2` * Include/exclude deprecation handling simplification (#1284) @@ -1287,24 +3597,22 @@ * Refactor Jekyll::Site (#1144) ### Site Enhancements + * Add "News" section for release notes, along with an RSS feed (#1093, #1285, #1286) * Add "History" page. * Restructured docs sections to include "Meta" section. - * Add message to "Templates" page that specifies that Python must be installed in order - to use Pygments. (#1182) + * Add message to "Templates" page that specifies that Python must be installed in order to use Pygments. (#1182) * Update link to the official Maruku repo (#1175) * Add documentation about `paginate_path` to "Templates" page in docs (#1129) * Give the quick-start guide its own page (#1191) - * Update ProTip on Installation page in docs to point to all the info about Pygments and - the 'highlight' tag. (#1196) + * Update ProTip on Installation page in docs to point to all the info about Pygments and the 'highlight' tag. (#1196) * Run `site/img` through ImageOptim (thanks @qrush!) (#1208) * Added Jade Converter to `site/docs/plugins` (#1210) * Fix location of docs pages in Contributing pages (#1214) * Add ReadInXMinutes plugin to the plugin list (#1222) - * Remove plugins from the plugin list that have equivalents in Jekyll - proper (#1223) + * Remove plugins from the plugin list that have equivalents in Jekyll proper (#1223) * Add jekyll-assets to the plugin list (#1225) - * Add jekyll-pandoc-mulitple-formats to the plugin list (#1229) + * Add jekyll-pandoc-multiple-formats to the plugin list (#1229) * Remove dead link to "Using Git to maintain your blog" (#1227) * Tidy up the third-party plugins listing (#1228) * Update contributor information (#1192) @@ -1316,17 +3624,16 @@ * Add `jekyll-timeago` to list of third-party plugins. (#1260) * Add `jekyll-swfobject` to list of third-party plugins. (#1263) * Add `jekyll-picture-tag` to list of third-party plugins. (#1280) - * Update the GitHub Pages documentation regarding relative URLs - (#1291) + * Update the GitHub Pages documentation regarding relative URLs (#1291) * Update the S3 deployment documentation (#1294) * Add suggestion for Xcode CLT install to troubleshooting page in docs (#1296) * Add 'Working with drafts' page to docs (#1289) - * Add information about time zones to the documentation for a page's - date (#1304) + * Add information about time zones to the documentation for a page's date (#1304) ## 1.0.3 / 2013-06-07 ### Minor Enhancements + * Add support to gist tag for private gists. (#1189) * Fail loudly when Maruku errors out (#1190) * Move the building of related posts into their own class (#1057) @@ -1335,16 +3642,16 @@ * Convert IDs in the site template to classes (#1170) ### Bug Fixes + * Fix typo in Stevenson constant "ERROR". (#1166) * Rename Jekyll::Logger to Jekyll::Stevenson to fix inheritance issue (#1106) * Exit with a non-zero exit code when dealing with a Liquid error (#1121) - * Make the `exclude` and `include` options backwards compatible with - versions of Jekyll prior to 1.0 (#1114) + * Make the `exclude` and `include` options backwards compatible with versions of Jekyll prior to 1.0 (#1114) * Fix pagination on Windows (#1063) - * Fix the application of Pygments' Generic Output style to Go code - (#1156) + * Fix the application of Pygments' Generic Output style to Go code (#1156) ### Site Enhancements + * Add a Pro Tip to docs about front matter variables being optional (#1147) * Add changelog to site as History page in /docs/ (#1065) * Add note to Upgrading page about new config options in 1.0.x (#1146) @@ -1358,12 +3665,12 @@ * Fix logic for `relative_permalinks` instructions on Upgrading page (#1101) * Add docs for post excerpt (#1072) * Add docs for gist tag (#1072) - * Add docs indicating that Pygments does not need to be installed - separately (#1099, #1119) + * Add docs indicating that Pygments does not need to be installed separately (#1099, #1119) * Update the migrator docs to be current (#1136) * Add the Jekyll Gallery Plugin to the plugin list (#1143) ### Development Fixes + * Use Jekyll.logger instead of Jekyll::Stevenson to log things (#1149) * Fix pesky Cucumber infinite loop (#1139) * Do not write posts with timezones in Cucumber tests (#1124) @@ -1372,20 +3679,24 @@ ## 1.0.2 / 2013-05-12 ### Major Enhancements + * Add `jekyll doctor` command to check site for any known compatibility problems (#1081) * Backwards-compatibilize relative permalinks (#1081) ### Minor Enhancements + * Add a `data-lang=""` attribute to Redcarpet code blocks (#1066) * Deprecate old config `server_port`, match to `port` if `port` isn't set (#1084) * Update pygments.rb version to 0.5.0 (#1061) * Update Kramdown version to 1.0.2 (#1067) ### Bug Fixes + * Fix issue when categories are numbers (#1078) * Catching that Redcarpet gem isn't installed (#1059) ### Site Enhancements + * Add documentation about `relative_permalinks` (#1081) * Remove pygments-installation instructions, as pygments.rb is bundled with it (#1079) * Move pages to be Pages for realz (#985) @@ -1394,29 +3705,34 @@ ## 1.0.1 / 2013-05-08 ### Minor Enhancements + * Do not force use of `toc_token` when using `generate_tok` in RDiscount (#1048) * Add newer `language-` class name prefix to code blocks (#1037) * Commander error message now preferred over process abort with incorrect args (#1040) ### Bug Fixes + * Make Redcarpet respect the pygments configuration option (#1053) * Fix the index build with LSI (#1045) * Don't print deprecation warning when no arguments are specified. (#1041) * Add missing `

` to site template used by `new` subcommand, fixed typos in code (#1032) ### Site Enhancements + * Changed https to http in the GitHub Pages link (#1051) * Remove CSS cruft, fix typos, fix HTML errors (#1028) * Removing manual install of Pip and Distribute (#1025) * Updated URL for Markdown references plugin (#1022) ### Development Fixes + * Markdownify history file (#1027) * Update links on README to point to new jekyllrb.com (#1018) ## 1.0.0 / 2013-05-06 ### Major Enhancements + * Add `jekyll new` subcommand: generate a Jekyll scaffold (#764) * Refactored Jekyll commands into subcommands: build, serve, and migrate. (#690) * Removed importers/migrators from main project, migrated to jekyll-import sub-gem (#793) @@ -1424,6 +3740,7 @@ * Add ordinal date permalink style (/:categories/:year/:y_day/:title.html) (#928) ### Minor Enhancements + * Site template HTML5-ified (#964) * Use post's directory path when matching for the `post_url` tag (#998) * Loosen dependency on Pygments so it's only required when it's needed (#1015) @@ -1448,7 +3765,7 @@ * Adds excerpt attribute to posts which contains first paragraph of content (#837) * Accept custom configuration file via CLI (#863) * Load in GitHub Pages MIME Types on `jekyll serve` (#847, #871) - * Improve debugability of error message for a malformed highlight tag (#785) + * Improve debuggability of error message for a malformed highlight tag (#785) * Allow symlinked files in unsafe mode (#824) * Add 'gist' Liquid tag to core (#822, #861) * New format of Jekyll output (#795) @@ -1463,8 +3780,7 @@ * Massively accelerate LSI performance (#664) * Truncate post slugs when importing from Tumblr (#496) * Add glob support to include, exclude option (#743) - * Layout of Page or Post defaults to 'page' or 'post', respectively (#580) - REPEALED by (#977) + * Layout of Page or Post defaults to 'page' or 'post', respectively (#580) REPEALED by (#977) * "Keep files" feature (#685) * Output full path & name for files that don't parse (#745) * Add source and destination directory protection (#535) @@ -1476,7 +3792,7 @@ * Bullet-proof `limit_posts` option (#1004) * Read in YAML as UTF-8 to accept non-ASCII chars (#836) * Fix the CLI option `--plugins` to actually accept dirs and files (#993) - * Allow 'excerpt' in YAML front matter to override the extracted excerpt (#946) + * Allow 'excerpt' in front matter to override the extracted excerpt (#946) * Fix cascade problem with site.baseurl, site.port and site.host. (#935) * Filter out directories with valid post names (#875) * Fix symlinked static files not being correctly built in unsafe mode (#909) @@ -1488,16 +3804,16 @@ * Patch for multibyte URI problem with `jekyll serve` (#723) * Order plugin execution by priority (#864) * Fixed Page#dir and Page#url for edge cases (#536) - * Fix broken `post_url` with posts with a time in their YAML front matter (#831) + * Fix broken `post_url` with posts with a time in their front matter (#831) * Look for plugins under the source directory (#654) - * Tumblr Migrator: finds `_posts` dir correctly, fixes truncation of long - post names (#775) + * Tumblr Migrator: finds `_posts` dir correctly, fixes truncation of long post names (#775) * Force Categories to be Strings (#767) * Safe YAML plugin to prevent vulnerability (#777) * Add SVG support to Jekyll/WEBrick. (#407, #406) * Prevent custom destination from causing continuous regen on watch (#528, #820, #862) ### Site Enhancements + * Responsify (#860) * Fix spelling, punctuation and phrasal errors (#989) * Update quickstart instructions with `new` command (#966) @@ -1508,20 +3824,20 @@ * Redesigned site (#583) ### Development Fixes + * Exclude Cucumber 1.2.4, which causes tests to fail in 1.9.2 (#938) - * Added "features:html" rake task for debugging purposes, cleaned up - Cucumber profiles (#832) + * Added "features:html" rake task for debugging purposes, cleaned up Cucumber profiles (#832) * Explicitly require HTTPS rubygems source in Gemfile (#826) * Changed Ruby version for development to 1.9.3-p374 from p362 (#801) * Including a link to the GitHub Ruby style guide in CONTRIBUTING.md (#806) * Added script/bootstrap (#776) - * Running Simplecov under 2 conditions: ENV(COVERAGE)=true and with Ruby version - of greater than 1.9 (#771) + * Running Simplecov under 2 conditions: ENV(COVERAGE)=true and with Ruby version of greater than 1.9 (#771) * Switch to Simplecov for coverage report (#765) ## 0.12.1 / 2013-02-19 ### Minor Enhancements + * Update Kramdown version to 0.14.1 (#744) * Test Enhancements * Update Rake version to 10.0.3 (#744) @@ -1531,6 +3847,7 @@ ## 0.12.0 / 2012-12-22 ### Minor Enhancements + * Add ability to explicitly specify included files (#261) * Add `--default-mimetype` option (#279) * Allow setting of RedCloth options (#284) @@ -1550,10 +3867,12 @@ * Ensure front matter is at start of file (#562) ## 0.11.2 / 2011-12-27 + * Bug Fixes * Fix gemspec ## 0.11.1 / 2011-12-27 + * Bug Fixes * Fix extra blank line in highlight blocks (#409) * Update dependencies @@ -1561,12 +3880,14 @@ ## 0.11.0 / 2011-07-10 ### Major Enhancements + * Add command line importer functionality (#253) * Add Redcarpet Markdown support (#318) * Make markdown/textile extensions configurable (#312) * Add `markdownify` filter ### Minor Enhancements + * Switch to Albino gem * Bundler support * Use English library to avoid hoops (#292) @@ -1580,12 +3901,14 @@ * Secure additional path exploits ## 0.10.0 / 2010-12-16 + * Bug Fixes * Add `--no-server` option. ## 0.9.0 / 2010-12-15 ### Minor Enhancements + * Use OptionParser's `[no-]` functionality for better boolean parsing. * Add Drupal migrator (#245) * Complain about YAML and Liquid errors (#249) @@ -1595,6 +3918,7 @@ ## 0.8.0 / 2010-11-22 ### Minor Enhancements + * Add wordpress.com importer (#207) * Add `--limit-posts` cli option (#212) * Add `uri_escape` filter (#234) @@ -1609,12 +3933,14 @@ ## 0.7.0 / 2010-08-24 ### Minor Enhancements + * Add support for rdiscount extensions (#173) * Bug Fixes * Highlight should not be able to render local files * The site configuration may not always provide a 'time' setting (#184) ## 0.6.2 / 2010-06-25 + * Bug Fixes * Fix Rakefile 'release' task (tag pushing was missing origin) * Ensure that RedCloth is loaded when textilize filter is used (#183) @@ -1622,24 +3948,24 @@ * Fix `page.url` to include full relative path (#181) ## 0.6.1 / 2010-06-24 + * Bug Fixes * Fix Markdown Pygments prefix and suffix (#178) ## 0.6.0 / 2010-06-23 ### Major Enhancements + * Proper plugin system (#19, #100) * Add safe mode so unsafe converters/generators can be added - * Maruku is now the only processor dependency installed by default. - Other processors will be lazy-loaded when necessary (and prompt the - user to install them when necessary) (#57) + * Maruku is now the only processor dependency installed by default. Other processors will be lazy-loaded when necessary (and prompt the user to install them when necessary) (#57) ### Minor Enhancements + * Inclusion/exclusion of future dated posts (#59) * Generation for a specific time (#59) * Allocate `site.time` on render not per site_payload invocation (#59) - * Pages now present in the site payload and can be used through the - `site.pages` and `site.html_pages` variables + * Pages now present in the site payload and can be used through the `site.pages` and `site.html_pages` variables * Generate phase added to site#process and pagination is now a generator * Switch to RakeGem for build/test process * Only regenerate static files when they have changed (#142) @@ -1656,87 +3982,80 @@ ## 0.5.7 / 2010-01-12 ### Minor Enhancements + * Allow overriding of post date in the front matter (#62, #38) * Bug Fixes * Categories isn't always an array (#73) * Empty tags causes error in read_posts (#84) * Fix pagination to adhere to read/render/write paradigm * Test Enhancement - * Cucumber features no longer use site.posts.first where a better - alternative is available + * Cucumber features no longer use site.posts.first where a better alternative is available ## 0.5.6 / 2010-01-08 + * Bug Fixes * Require redcloth >= 4.2.1 in tests (#92) - * Don't break on triple dashes in yaml front matter (#93) + * Don't break on triple dashes in front matter (#93) ### Minor Enhancements + * Allow .mkd as markdown extension * Use $stdout/err instead of constants (#99) * Properly wrap code blocks (#91) * Add javascript mime type for webrick (#98) ## 0.5.5 / 2010-01-08 + * Bug Fixes * Fix pagination % 0 bug (#78) * Ensure all posts are processed first (#71) - -## NOTE - * After this point I will no longer be giving credit in the history; - that is what the commit log is for. + * After this point I will no longer be giving credit in the history; that is what the commit log is for. ## 0.5.4 / 2009-08-23 + * Bug Fixes * Do not allow symlinks (security vulnerability) ## 0.5.3 / 2009-07-14 + * Bug Fixes - * Solving the permalink bug where non-html files wouldn't work - (@jeffrydegrande) + * Solving the permalink bug where non-html files wouldn't work (@jeffrydegrande) ## 0.5.2 / 2009-06-24 + * Enhancements - * Added --paginate option to the executable along with a paginator object - for the payload (@calavera) - * Upgraded RedCloth to 4.2.1, which makes `` tags work once - again. - * Configuration options set in config.yml are now available through the - site payload (@vilcans) - * Posts can now have an empty YAML front matter or none at all - (@ bahuvrihi) + * Added --paginate option to the executable along with a paginator object for the payload (@calavera) + * Upgraded RedCloth to 4.2.1, which makes `` tags work once again. + * Configuration options set in config.yml are now available through the site payload (@vilcans) + * Posts can now have an empty front matter or none at all (@ bahuvrihi) * Bug Fixes - * Fixing Ruby 1.9 issue that requires `#to_s` on the err object - (@Chrononaut) + * Fixing Ruby 1.9 issue that requires `#to_s` on the err object (@Chrononaut) * Fixes for pagination and ordering posts on the same day (@ujh) - * Made pages respect permalinks style and permalinks in yml front matter - (@eugenebolshakov) - * Index.html file should always have index.html permalink - (@eugenebolshakov) - * Added trailing slash to pretty permalink style so Apache is happy - (@eugenebolshakov) - * Bad markdown processor in config fails sooner and with better message - (@ gcnovus) - * Allow CRLFs in yaml front matter (@juretta) + * Made pages respect permalinks style and permalinks in yml front matter (@eugenebolshakov) + * Index.html file should always have index.html permalink (@eugenebolshakov) + * Added trailing slash to pretty permalink style so Apache is happy (@eugenebolshakov) + * Bad markdown processor in config fails sooner and with better message (@ gcnovus) + * Allow CRLFs in front matter (@juretta) * Added Date#xmlschema for Ruby versions < 1.9 ## 0.5.1 / 2009-05-06 ### Major Enhancements + * Next/previous posts in site payload (@pantulis, @tomo) * Permalink templating system * Moved most of the README out to the GitHub wiki - * Exclude option in configuration so specified files won't be brought over - with generated site (@duritong) + * Exclude option in configuration so specified files won't be brought over with generated site (@duritong) * Bug Fixes * Making sure config.yaml references are all gone, using only config.yml * Fixed syntax highlighting breaking for UTF-8 code (@henrik) - * Worked around RDiscount bug that prevents Markdown from getting parsed - after highlight (@henrik) + * Worked around RDiscount bug that prevents Markdown from getting parsed after highlight (@henrik) * CGI escaped post titles (@Chrononaut) ## 0.5.0 / 2009-04-07 ### Minor Enhancements + * Ability to set post categories via YAML (@qrush) * Ability to set prevent a post from publishing via YAML (@qrush) * Add textilize filter (@willcodeforfoo) @@ -1756,6 +4075,7 @@ ## 0.4.1 ### Minor Enhancements + * Changed date format on wordpress converter (zeropadding) (@dysinger) * Bug Fixes * Add Jekyll binary as executable to gemspec (@dysinger) @@ -1763,9 +4083,11 @@ ## 0.4.0 / 2009-02-03 ### Major Enhancements + * Switch to Jeweler for packaging tasks ### Minor Enhancements + * Type importer (@codeslinger) * `site.topics` accessor (@baz) * Add `array_to_sentence_string` filter (@mchung) @@ -1784,55 +4106,62 @@ ## 0.3.0 / 2008-12-24 ### Major Enhancements - * Added `--server` option to start a simple WEBrick server on destination - directory (@johnreilly and @mchung) + + * Added `--server` option to start a simple WEBrick server on destination directory (@johnreilly and @mchung) ### Minor Enhancements + * Added post categories based on directories containing `_posts` (@mreid) * Added post topics based on directories underneath `_posts` * Added new date filter that shows the full month name (@mreid) - * Merge Post's YAML front matter into its to_liquid payload (@remi) + * Merge Post's front matter into its to_liquid payload (@remi) * Restrict includes to regular files underneath `_includes` * Bug Fixes - * Change YAML delimiter matcher so as to not chew up 2nd level markdown - headers (@mreid) - * Fix bug that meant page data (such as the date) was not available in - templates (@mreid) + * Change YAML delimiter matcher so as to not chew up 2nd level markdown headers (@mreid) + * Fix bug that meant page data (such as the date) was not available in templates (@mreid) * Properly reject directories in `_layouts` ## 0.2.1 / 2008-12-15 + * Major Changes * Use Maruku (pure Ruby) for Markdown by default (@mreid) * Allow use of RDiscount with `--rdiscount` flag ### Minor Enhancements + * Don't load directory_watcher unless it's needed (@pjhyett) ## 0.2.0 / 2008-12-14 + * Major Changes * related_posts is now found in `site.related_posts` ## 0.1.6 / 2008-12-13 + * Major Features * Include files in `_includes` with `{% include x.textile %}` ## 0.1.5 / 2008-12-12 ### Major Enhancements + * Code highlighting with Pygments if `--pygments` is specified * Disable true LSI by default, enable with `--lsi` ### Minor Enhancements + * Output informative message if RDiscount is not available (@JackDanger) * Bug Fixes * Prevent Jekyll from picking up the output directory as a source (@JackDanger) * Skip `related_posts` when there is only one post (@JackDanger) ## 0.1.4 / 2008-12-08 + * Bug Fixes * DATA does not work properly with rubygems ## 0.1.3 / 2008-12-06 + * Major Features * Markdown support (@vanpelt) * Mephisto and CSV converters (@vanpelt) @@ -1842,21 +4171,24 @@ * Accept both `\r\n` and `\n` in YAML header (@vanpelt) ## 0.1.2 / 2008-11-22 + * Major Features * Add a real "related posts" implementation using Classifier * Command Line Changes - * Allow cli to be called with 0, 1, or 2 args intuiting dir paths - if they are omitted + * Allow cli to be called with 0, 1, or 2 args intuiting dir paths if they are omitted ## 0.1.1 / 2008-11-22 + * Minor Additions * Posts now support introspectional data e.g. `{{ page.url }}` ## 0.1.0 / 2008-11-05 + * First release * Converts posts written in Textile * Converts regular site pages * Simple copy of binary files ## 0.0.0 / 2008-10-19 + * Birthday! diff --git a/LICENSE b/LICENSE index 527166b60b2..91e3192da85 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2008-2015 Tom Preston-Werner +Copyright (c) 2008-present Tom Preston-Werner and Jekyll contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.markdown b/README.markdown index b1dfae4a494..fe4ef808e05 100644 --- a/README.markdown +++ b/README.markdown @@ -1,52 +1,82 @@ -# [Jekyll](http://jekyllrb.com/) +# [Jekyll](https://jekyllrb.com/) -[![Gem Version](https://img.shields.io/gem/v/jekyll.svg)](https://rubygems.org/gems/jekyll) -[![Build Status](https://img.shields.io/travis/jekyll/jekyll/master.svg)](https://travis-ci.org/jekyll/jekyll) -[![Code Climate](https://img.shields.io/codeclimate/github/jekyll/jekyll.svg)](https://codeclimate.com/github/jekyll/jekyll) -[![Dependency Status](https://img.shields.io/gemnasium/jekyll/jekyll.svg)](https://gemnasium.com/jekyll/jekyll) -[![Security](https://hakiri.io/github/jekyll/jekyll/master.svg)](https://hakiri.io/github/jekyll/jekyll/master) +[![Gem Version](https://img.shields.io/gem/v/jekyll.svg)][ruby-gems] +[![Build Status](https://github.com/jekyll/jekyll/workflows/Continuous%20Integration/badge.svg)][ci-workflow] +[![Backers on Open Collective](https://opencollective.com/jekyll/backers/badge.svg)](#backers) +[![Sponsors on Open Collective](https://opencollective.com/jekyll/sponsors/badge.svg)](#sponsors) -By Tom Preston-Werner, Nick Quaranto, Parker Moore, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)! +[ruby-gems]: https://rubygems.org/gems/jekyll +[ci-workflow]: https://github.com/jekyll/jekyll/actions?query=workflow%3A%22Continuous+Integration%22+branch%3Amaster +[appveyor]: https://ci.appveyor.com/project/jekyll/jekyll/branch/master -Jekyll is a simple, blog-aware, static site generator perfect for personal, project, or organization sites. Think of it like a file-based CMS, without all the complexity. Jekyll takes your content, renders Markdown and Liquid templates, and spits out a complete, static website ready to be served by Apache, Nginx or another web server. Jekyll is the engine behind [GitHub Pages](http://pages.github.com), which you can use to host sites right from your GitHub repositories. +Jekyll is a simple, blog-aware, static site generator perfect for personal, project, or organization sites. Think of it like a file-based CMS, without all the complexity. Jekyll takes your content, renders Markdown and Liquid templates, and spits out a complete, static website ready to be served by Apache, Nginx or another web server. Jekyll is the engine behind [GitHub Pages](https://pages.github.com), which you can use to host sites right from your GitHub repositories. ## Philosophy Jekyll does what you tell it to do — no more, no less. It doesn't try to outsmart users by making bold assumptions, nor does it burden them with needless complexity and configuration. Put simply, Jekyll gets out of your way and allows you to concentrate on what truly matters: your content. -## Having trouble with OS X El Capitan? - -See: http://jekyllrb.com/docs/troubleshooting/#jekyll-amp-mac-os-x-1011 +See: [https://jekyllrb.com/philosophy](https://jekyllrb.com/philosophy) ## Getting Started -* [Install](http://jekyllrb.com/docs/installation/) the gem -* Read up about its [Usage](http://jekyllrb.com/docs/usage/) and [Configuration](http://jekyllrb.com/docs/configuration/) -* Take a gander at some existing [Sites](https://wiki.github.com/jekyll/jekyll/sites) -* Fork and [Contribute](http://jekyllrb.com/docs/contributing/) your own modifications -* Have questions? Check out our official forum community [Jekyll Talk](https://talk.jekyllrb.com/) or [`#jekyll` on irc.freenode.net](https://botbot.me/freenode/jekyll/) +* [Install](https://jekyllrb.com/docs/installation/) the gem +* Read up about its [Usage](https://jekyllrb.com/docs/usage/) and [Configuration](https://jekyllrb.com/docs/configuration/) +* Take a gander at some existing [Sites](https://github.com/jekyll/jekyll/wiki/sites) +* [Fork](https://github.com/jekyll/jekyll/fork) and [Contribute](https://jekyllrb.com/docs/contributing/) your own modifications +* Have questions? Check out our official forum community [Jekyll Talk](https://talk.jekyllrb.com/) and [`#jekyll` Channel on Libera IRC](https://libera.chat) + +## Diving In + +* [Migrate](https://import.jekyllrb.com/docs/home/) from your previous system +* Learn how [Front Matter](https://jekyllrb.com/docs/front-matter/) works +* Put information on your site with [Variables](https://jekyllrb.com/docs/variables/) +* Customize the [Permalinks](https://jekyllrb.com/docs/permalinks/) your posts are generated with +* Use the built-in [Liquid Extensions](https://jekyllrb.com/docs/templates/) to make your life easier +* Use custom [Plugins](https://jekyllrb.com/docs/plugins/) to generate content specific to your site +* Watch [video tutorials from Giraffe Academy](https://jekyllrb.com/tutorials/video-walkthroughs/) + +## Need help? + +If you don't find the answer to your problem in our [docs](https://jekyllrb.com/docs/), or in the [troubleshooting section](https://jekyllrb.com/docs/troubleshooting/), ask the [community](https://jekyllrb.com/docs/community/) for help. ## Code of Conduct In order to have a more open and welcoming community, Jekyll adheres to a -[code of conduct](CONDUCT.md) adapted from the Ruby on Rails code of +[code of conduct](https://jekyllrb.com/docs/conduct/) adapted from the Ruby on Rails code of conduct. Please adhere to this code of conduct in any interactions you have in the Jekyll community. It is strictly enforced on all official Jekyll repositories, websites, and resources. If you encounter someone violating -these terms, please let a maintainer (@parkr, @envygeeks, or @mattr-) know -and we will address it as soon as possible. +these terms, please let one of our [core team members](https://jekyllrb.com/team/#core-team) know and we will address it as soon as possible. -## Diving In +## Credits + +### Sponsors + +Support this project by becoming a sponsor. Your logo will show up in this README with a link to your website. [Become a sponsor!](https://opencollective.com/jekyll#sponsor) +[![Jekyll Sponsor 0](https://opencollective.com/jekyll/sponsor/0/avatar.svg)](https://opencollective.com/jekyll/sponsor/0/website) +[![Jekyll Sponsor 1](https://opencollective.com/jekyll/sponsor/1/avatar.svg)](https://opencollective.com/jekyll/sponsor/1/website) +[![Jekyll Sponsor 2](https://opencollective.com/jekyll/sponsor/2/avatar.svg)](https://opencollective.com/jekyll/sponsor/2/website) +[![Jekyll Sponsor 3](https://opencollective.com/jekyll/sponsor/3/avatar.svg)](https://opencollective.com/jekyll/sponsor/3/website) +[![Jekyll Sponsor 4](https://opencollective.com/jekyll/sponsor/4/avatar.svg)](https://opencollective.com/jekyll/sponsor/4/website) +[![Jekyll Sponsor 5](https://opencollective.com/jekyll/sponsor/5/avatar.svg)](https://opencollective.com/jekyll/sponsor/5/website) +[![Jekyll Sponsor 6](https://opencollective.com/jekyll/sponsor/6/avatar.svg)](https://opencollective.com/jekyll/sponsor/6/website) +[![Jekyll Sponsor 7](https://opencollective.com/jekyll/sponsor/7/avatar.svg)](https://opencollective.com/jekyll/sponsor/7/website) +[![Jekyll Sponsor 8](https://opencollective.com/jekyll/sponsor/8/avatar.svg)](https://opencollective.com/jekyll/sponsor/8/website) +[![Jekyll Sponsor 9](https://opencollective.com/jekyll/sponsor/9/avatar.svg)](https://opencollective.com/jekyll/sponsor/9/website) + +### Contributors + +This project exists thanks to all the people who contribute. +[![Jekyll Contributors](https://opencollective.com/jekyll/contributors.svg?width=890&&avatarHeight=24&limit=100&button=false)](../../graphs/contributors) + +### Backers + +Thank you to all our backers! 🙏 [Become a backer](https://opencollective.com/jekyll#backer) -* [Migrate](http://import.jekyllrb.com/docs/home/) from your previous system -* Learn how the [YAML Front Matter](http://jekyllrb.com/docs/frontmatter/) works -* Put information on your site with [Variables](http://jekyllrb.com/docs/variables/) -* Customize the [Permalinks](http://jekyllrb.com/docs/permalinks/) your posts are generated with -* Use the built-in [Liquid Extensions](http://jekyllrb.com/docs/templates/) to make your life easier -* Use custom [Plugins](http://jekyllrb.com/docs/plugins/) to generate content specific to your site +[![Jekyll Backers](https://opencollective.com/jekyll/backers.svg?width=890)](https://opencollective.com/jekyll#backers) ## License -See [LICENSE](https://github.com/jekyll/jekyll/blob/master/LICENSE). +See the [LICENSE](https://github.com/jekyll/jekyll/blob/master/LICENSE) file. diff --git a/Rakefile b/Rakefile index e189f0b947a..f215c225cbb 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,16 @@ -require 'rubygems' -require 'rake' -require 'rdoc' -require 'date' -require 'yaml' +# frozen_string_literal: true -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w[lib])) -require 'jekyll/version' +require "rubygems" +require "rake" +require "rdoc" +require "date" +require "yaml" + +$LOAD_PATH.unshift File.expand_path("lib", __dir__) +require "jekyll/version" +require "bundler/gem_tasks" + +Dir.glob("rake/**.rake").each { |f| import f } ############################################################################# # @@ -25,55 +30,60 @@ def docs_name "#{name}-docs" end +def docs_folder + "docs" +end + def gemspec_file "#{name}.gemspec" end def gem_file - "#{name}-#{Gem::Version.new(version).to_s}.gem" + "#{name}-#{Gem::Version.new(version)}.gem" end def normalize_bullets(markdown) - markdown.gsub(/\n\s{2}\*{1}/, "\n-") + # Normalize both old-style indented bullets (" *") and + # release-please-style non-indented bullets ("*") to "-" + markdown.gsub(%r!\n\s{0,2}\*{1}!, "\n-") end def linkify_prs(markdown) - markdown.gsub(/#(\d+)/) do |word| + # Match bare PR references like #1234 but skip those already linkified + # by release-please as [#1234](url) + markdown.gsub(%r{(? title, + "permalink" => "/docs/#{slug}/", + "note" => "This file is autogenerated. Edit /#{file} instead.", + }.merge(overrides_front_matter) + contents = "#{front_matter.to_yaml}---\n\n#{content_for(file)}" + File.write("#{docs_folder}/_docs/#{slug}.md", contents) +end + +def content_for(file) + contents = File.read(file) + case file + when "History.markdown" + converted_history(contents) + else + contents.gsub(%r!\A# .*\n\n?!, "") + end end ############################################################################# @@ -94,23 +135,23 @@ end multitask :default => [:test, :features] task :spec => :test -require 'rake/testtask' +require "rake/testtask" Rake::TestTask.new(:test) do |test| - test.libs << 'lib' << 'test' - test.pattern = 'test/**/test_*.rb' + test.libs << "lib" << "test" + test.pattern = "test/**/test_*.rb" test.verbose = true end -require 'rdoc/task' +require "rdoc/task" Rake::RDocTask.new do |rdoc| - rdoc.rdoc_dir = 'rdoc' + rdoc.rdoc_dir = "rdoc" rdoc.title = "#{name} #{version}" - rdoc.rdoc_files.include('README*') - rdoc.rdoc_files.include('lib/**/*.rb') + rdoc.rdoc_files.include("README*") + rdoc.rdoc_files.include("lib/**/*.rb") end begin - require 'cucumber/rake/task' + require "cucumber/rake/task" Cucumber::Rake::Task.new(:features) do |t| t.profile = "travis" end @@ -118,214 +159,13 @@ begin t.profile = "html_report" end rescue LoadError - desc 'Cucumber rake task not available' + desc "Cucumber rake task not available" task :features do - abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' + abort "Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin" end end desc "Open an irb session preloaded with this library" task :console do - sh "irb -rubygems -r ./lib/#{name}.rb" -end - -############################################################################# -# -# Site tasks - http://jekyllrb.com -# -############################################################################# - -namespace :site do - desc "Generate and view the site locally" - task :preview => [:history, :version_file] do - require "launchy" - require "jekyll" - - # Yep, it's a hack! Wait a few seconds for the Jekyll site to generate and - # then open it in a browser. Someday we can do better than this, I hope. - Thread.new do - sleep 4 - puts "Opening in browser..." - Launchy.open("http://localhost:4000") - end - - # Generate the site in server mode. - puts "Running Jekyll..." - options = { - "source" => File.expand_path("site"), - "destination" => File.expand_path("site/_site"), - "watch" => true, - "serving" => true - } - Jekyll::Commands::Build.process(options) - Jekyll::Commands::Serve.process(options) - end - - desc "Generate the site" - task :generate => [:history, :version_file] do - require "jekyll" - Jekyll::Commands::Build.process({ - "source" => File.expand_path("site"), - "destination" => File.expand_path("site/_site") - }) - end - - desc "Update normalize.css library to the latest version and minify" - task :update_normalize_css do - Dir.chdir("site/_sass") do - sh 'curl "http://necolas.github.io/normalize.css/latest/normalize.css" -o "normalize.scss"' - sh 'sass "normalize.scss":"_normalize.scss" --style compressed' - rm ['normalize.scss', Dir.glob('*.map')].flatten - end - end - - desc "Commit the local site to the gh-pages branch and publish to GitHub Pages" - task :publish => [:history, :version_file] do - # Ensure the gh-pages dir exists so we can generate into it. - puts "Checking for gh-pages dir..." - unless File.exist?("./gh-pages") - puts "Creating gh-pages dir..." - sh "git clone git@github.com:jekyll/jekyll gh-pages" - end - - # Ensure latest gh-pages branch history. - Dir.chdir('gh-pages') do - sh "git checkout gh-pages" - sh "git pull origin gh-pages" - end - - # Proceed to purge all files in case we removed a file in this release. - puts "Cleaning gh-pages directory..." - purge_exclude = %w[ - gh-pages/. - gh-pages/.. - gh-pages/.git - gh-pages/.gitignore - ] - FileList["gh-pages/{*,.*}"].exclude(*purge_exclude).each do |path| - sh "rm -rf #{path}" - end - - # Copy site to gh-pages dir. - puts "Building site into gh-pages branch..." - ENV['JEKYLL_ENV'] = 'production' - require "jekyll" - Jekyll::Commands::Build.process({ - "source" => File.expand_path("site"), - "destination" => File.expand_path("gh-pages"), - "sass" => { "style" => "compressed" } - }) - - File.open('gh-pages/.nojekyll', 'wb') { |f| f.puts(":dog: food.") } - - # Commit and push. - puts "Committing and pushing to GitHub Pages..." - sha = `git rev-parse HEAD`.strip - Dir.chdir('gh-pages') do - sh "git add ." - sh "git commit --allow-empty -m 'Updating to #{sha}.'" - sh "git push origin gh-pages" - end - puts 'Done.' - end - - desc "Create a nicely formatted history page for the jekyll site based on the repo history." - task :history do - if File.exist?("History.markdown") - history_file = File.read("History.markdown") - front_matter = { - "layout" => "docs", - "title" => "History", - "permalink" => "/docs/history/" - } - Dir.chdir('site/_docs/') do - File.open("history.md", "w") do |file| - file.write("#{front_matter.to_yaml}---\n\n") - file.write(converted_history(history_file)) - end - end - else - abort "You seem to have misplaced your History.markdown file. I can haz?" - end - end - - desc "Write the site latest_version.txt file" - task :version_file do - File.open('site/latest_version.txt', 'wb') { |f| f.puts(version) } unless version =~ /(beta|rc|alpha)/i - end - - namespace :releases do - desc "Create new release post" - task :new, :version do |t, args| - raise "Specify a version: rake site:releases:new['1.2.3']" unless args.version - today = Time.new.strftime('%Y-%m-%d') - release = args.version.to_s - filename = "site/_posts/#{today}-jekyll-#{release.split('.').join('-')}-released.markdown" - - File.open(filename, "wb") do |post| - post.puts("---") - post.puts("layout: news_item") - post.puts("title: 'Jekyll #{release} Released'") - post.puts("date: #{Time.new.strftime('%Y-%m-%d %H:%M:%S %z')}") - post.puts("author: ") - post.puts("version: #{release}") - post.puts("categories: [release]") - post.puts("---") - post.puts - post.puts - end - - puts "Created #{filename}" - end - end -end - -############################################################################# -# -# Packaging tasks -# -############################################################################# - -desc "Release #{name} v#{version}" -task :release => :build do - unless `git branch` =~ /^\* master$/ - puts "You must be on the master branch to release!" - exit! - end - sh "git commit --allow-empty -m 'Release :gem: #{version}'" - sh "git tag v#{version}" - sh "git push origin master" - sh "git push origin v#{version}" - sh "gem push pkg/#{name}-#{version}.gem" -end - -desc "Build #{name} v#{version} into pkg/" -task :build do - mkdir_p "pkg" - sh "gem build #{gemspec_file}" - sh "mv #{gem_file} pkg" -end - -############################################################################# -# -# Packaging tasks for jekyll-docs -# -############################################################################# - -namespace :docs do - desc "Release #{docs_name} v#{version}" - task :release => :build do - unless `git branch` =~ /^\* master$/ - puts "You must be on the master branch to release!" - exit! - end - sh "gem push pkg/#{docs_name}-#{version}.gem" - end - - desc "Build #{docs_name} v#{version} into pkg/" - task :build do - mkdir_p "pkg" - sh "gem build #{docs_name}.gemspec" - sh "mv #{docs_name}-#{version}.gem pkg" - end + sh "irb -r ./lib/#{name}.rb" end diff --git a/benchmark/capture-assign.rb b/benchmark/capture-assign.rb new file mode 100755 index 00000000000..7a127ad218a --- /dev/null +++ b/benchmark/capture-assign.rb @@ -0,0 +1,21 @@ +#!/usr/bin/env ruby +require "liquid" +require "benchmark/ips" + +puts "Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}" +puts "Liquid #{Liquid::VERSION}" + +template1 = '{% capture foobar %}foo{{ bar }}{% endcapture %}{{ foo }}{{ foobar }}' +template2 = '{% assign foobar = "foo" | append: bar %}{{ foobar }}' + +def render(template) + Liquid::Template.parse(template).render("bar" => "42") +end + +puts render(template1) +puts render(template2) + +Benchmark.ips do |x| + x.report('capture') { render(template1) } + x.report('assign') { render(template2) } +end diff --git a/benchmark/conditional_liquid.rb b/benchmark/conditional_liquid.rb new file mode 100755 index 00000000000..49d08271a13 --- /dev/null +++ b/benchmark/conditional_liquid.rb @@ -0,0 +1,101 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "liquid" +require "benchmark/ips" + +# Test if processing content string without any Liquid constructs, via Liquid, +# is slower than checking whether constructs exist ( using `String#include?` ) +# and return-ing the "plaintext" content string as is.. +# +# Ref: https://github.com/jekyll/jekyll/pull/6735 + +# Sample contents +WITHOUT_LIQUID = <<-TEXT.freeze +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at +pharetra tempus. Etiam bibendum magna et metus fermentum, eu cursus lorem +mattis. Curabitur vel dui et lacus rutrum suscipit et eget neque. + +Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper +ligula, at finibus eros laoreet id. Etiam sit amet est in libero efficitur +tristique. Ut nec magna augue. Quisque ut fringilla lacus, ac dictum enim. +Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis +aliquet. Sed ultrices placerat ultricies. +TEXT + +WITH_LIQUID = <<-LIQUID.freeze +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at +pharetra tempus. {{ author }} et metus fermentum, eu cursus lorem +mattis. Curabitur vel dui et lacus rutrum suscipit et eget neque. + +Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper +ligula, {% if author == "Jane Doe" %} at finibus eros laoreet id. {% else %} +Etiam sit amet est in libero efficitur.{% endif %} +tristique. Ut nec magna augue. Quisque ut fringilla lacus, ac dictum enim. +Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis +aliquet. Sed ultrices placerat ultricies. +LIQUID + +WITH_JUST_LIQUID_VAR = <<-LIQUID.freeze +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce auctor libero at +pharetra tempus. et metus fermentum, eu cursus lorem, ac dictum enim. +mattis. Curabitur vel dui et lacus rutrum suscipit et {{ title }} neque. + +Nullam luctus fermentum est id blandit. Phasellus consectetur ullamcorper +ligula, at finibus eros laoreet id. Etiam sit amet est in libero efficitur. +tristique. Ut nec magna augue. {{ author }} Quisque ut fringilla lacus +Aliquam vel ornare mauris. Suspendisse ornare diam tempor nulla facilisis +aliquet. Sed ultrices placerat ultricies. +LIQUID + +SUITE = { + :"plain text" => WITHOUT_LIQUID, + :"tags n vars" => WITH_LIQUID, + :"just vars" => WITH_JUST_LIQUID_VAR, +}.freeze + +# Mimic how Jekyll's LiquidRenderer would process a non-static file, with +# some dummy payload +def always_liquid(content) + Liquid::Template.error_mode = :warn + Liquid::Template.parse(content, :line_numbers => true).render( + "author" => "John Doe", + "title" => "FooBar" + ) +end + +# Mimic how the proposed change would first execute a couple of checks and +# proceed to process with Liquid if necessary +def conditional_liquid(content) + return content if content.nil? || content.empty? + return content unless content.include?("{%") || content.include?("{{") + always_liquid(content) +end + +# Test https://github.com/jekyll/jekyll/pull/6735#discussion_r165499868 +# ------------------------------------------------------------------------ +def check_with_regex(content) + !content.to_s.match?(%r!{[{%]!) +end + +def check_with_builtin(content) + content.include?("{%") || content.include?("{{") +end + +SUITE.each do |key, text| + Benchmark.ips do |x| + x.report("regex-check - #{key}") { check_with_regex(text) } + x.report("builtin-check - #{key}") { check_with_builtin(text) } + x.compare! + end +end +# ------------------------------------------------------------------------ + +# Let's roll! +SUITE.each do |key, text| + Benchmark.ips do |x| + x.report("always thru liquid - #{key}") { always_liquid(text) } + x.report("conditional liquid - #{key}") { conditional_liquid(text) } + x.compare! + end +end diff --git a/benchmark/end-with-vs-regexp b/benchmark/end-with-vs-regexp old mode 100644 new mode 100755 index cb849f42267..2ba5a3078c1 --- a/benchmark/end-with-vs-regexp +++ b/benchmark/end-with-vs-regexp @@ -1,13 +1,16 @@ +#!/usr/bin/env ruby require 'benchmark/ips' Benchmark.ips do |x| path_without_ending_slash = '/some/very/very/long/path/to/a/file/i/like' x.report('no slash regexp') { path_without_ending_slash =~ /\/$/ } x.report('no slash end_with?') { path_without_ending_slash.end_with?("/") } + x.report('no slash [-1, 1]') { path_without_ending_slash[-1, 1] == "/" } end Benchmark.ips do |x| path_with_ending_slash = '/some/very/very/long/path/to/a/file/i/like/' x.report('slash regexp') { path_with_ending_slash =~ /\/$/ } x.report('slash end_with?') { path_with_ending_slash.end_with?("/") } + x.report('slash [-1, 1]') { path_with_ending_slash[-1, 1] == "/" } end diff --git a/benchmark/file-dir-ensure-trailing-slash b/benchmark/file-dir-ensure-trailing-slash new file mode 100755 index 00000000000..aecfc039519 --- /dev/null +++ b/benchmark/file-dir-ensure-trailing-slash @@ -0,0 +1,54 @@ +#!/usr/bin/env ruby +require 'benchmark/ips' + +# For this pull request, which changes Page#dir +# https://github.com/jekyll/jekyll/pull/4403 + +FORWARD_SLASH = '/'.freeze + +def pre_pr(url) + url[-1, 1] == FORWARD_SLASH ? url : File.dirname(url) +end + +def pr(url) + if url.end_with?(FORWARD_SLASH) + url + else + url_dir = File.dirname(url) + url_dir.end_with?(FORWARD_SLASH) ? url_dir : "#{url_dir}/" + end +end + +def envygeeks(url) + return url if url.end_with?(FORWARD_SLASH) || url == FORWARD_SLASH + + url = File.dirname(url) + url == FORWARD_SLASH ? url : "#{url}/" +end + +# Just a slash +Benchmark.ips do |x| + path = '/' + x.report("pre_pr:#{path}") { pre_pr(path) } + x.report("pr:#{path}") { pr(path) } + x.report("envygeeks:#{path}") { pr(path) } + x.compare! +end + +# No trailing slash +Benchmark.ips do |x| + path = '/some/very/very/long/path/to/a/file/i/like' + x.report("pre_pr:#{path}") { pre_pr(path) } + x.report("pr:#{path}") { pr(path) } + x.report("envygeeks:#{path}") { pr(path) } + x.compare! +end + +# No trailing slash +Benchmark.ips do |x| + path = '/some/very/very/long/path/to/a/file/i/like/' + x.report("pre_pr:#{path}") { pre_pr(path) } + x.report("pr:#{path}") { pr(path) } + x.report("envygeeks:#{path}") { pr(path) } + x.compare! +end diff --git a/benchmark/find-filter-vs-where-first-filters.rb b/benchmark/find-filter-vs-where-first-filters.rb new file mode 100755 index 00000000000..f671c530e6f --- /dev/null +++ b/benchmark/find-filter-vs-where-first-filters.rb @@ -0,0 +1,49 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'benchmark/ips' +require_relative '../lib/jekyll' + +puts '' +print 'Setting up... ' + +SITE = Jekyll::Site.new( + Jekyll.configuration({ + "source" => File.expand_path("../docs", __dir__), + "destination" => File.expand_path("../docs/_site", __dir__), + "disable_disk_cache" => true, + "quiet" => true, + }) +) + +TEMPLATE_1 = Liquid::Template.parse(<<~HTML) + {%- assign doc = site.documents | where: 'url', '/docs/assets/' | first -%} + {{- doc.title -}} +HTML + +TEMPLATE_2 = Liquid::Template.parse(<<~HTML) + {%- assign doc = site.documents | find: 'url', '/docs/assets/' -%} + {{- doc.title -}} +HTML + +[:reset, :read, :generate].each { |phase| SITE.send(phase) } + +puts 'done.' +puts 'Testing... ' +puts " #{'where + first'.cyan} results in #{TEMPLATE_1.render(SITE.site_payload).inspect.green}" +puts " #{'find'.cyan} results in #{TEMPLATE_2.render(SITE.site_payload).inspect.green}" + +if TEMPLATE_1.render(SITE.site_payload) == TEMPLATE_2.render(SITE.site_payload) + puts 'Success! Proceeding to run benchmarks.'.green + puts '' +else + puts 'Something went wrong. Aborting.'.magenta + puts '' + return +end + +Benchmark.ips do |x| + x.report('where + first') { TEMPLATE_1.render(SITE.site_payload) } + x.report('find') { TEMPLATE_2.render(SITE.site_payload) } + x.compare! +end diff --git a/benchmark/flat-map b/benchmark/flat-map old mode 100644 new mode 100755 index 547bcee12de..18f0cfdbe03 --- a/benchmark/flat-map +++ b/benchmark/flat-map @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' enum = (0..50).to_a diff --git a/benchmark/hash-fetch b/benchmark/hash-fetch old mode 100644 new mode 100755 index 357083576ca..d7427d5364a --- a/benchmark/hash-fetch +++ b/benchmark/hash-fetch @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' h = {:bar => 'uco'} diff --git a/benchmark/jekyll-sanitize-path b/benchmark/jekyll-sanitize-path old mode 100644 new mode 100755 diff --git a/benchmark/local-require b/benchmark/local-require new file mode 100755 index 00000000000..96330667ae2 --- /dev/null +++ b/benchmark/local-require @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'benchmark/ips' +require 'jekyll' +require 'json' + +DATA = {"foo"=>"bar", "alpha"=>{"beta"=>"gamma"}, "lipsum"=>["lorem", "ipsum", "dolor"]} + +def local_require + require 'json' + JSON.pretty_generate(DATA) +end + +def global_require + JSON.pretty_generate(DATA) +end + +def graceful_require + Jekyll::External.require_with_graceful_fail("json") + JSON.pretty_generate(DATA) +end + +Benchmark.ips do |x| + x.report("local-require") { local_require } + x.report("global-require") { global_require } + x.report("graceful-require") { graceful_require } + x.compare! +end diff --git a/benchmark/native-vs-pathutil-relative b/benchmark/native-vs-pathutil-relative new file mode 100755 index 00000000000..c688100aa5a --- /dev/null +++ b/benchmark/native-vs-pathutil-relative @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby + +# ------------------------------------------------------------------- +# Benchmarking changes in https://github.com/jekyll/jekyll/pull/6767 +# ------------------------------------------------------------------- + +require 'benchmark/ips' +require 'pathutil' + +DOC_PATH = File.join(File.expand_path(__dir__), "_puppies", "rover.md") +COL_PATH = File.join(File.expand_path(__dir__), "_puppies") + + +def pathutil_relative + Pathutil.new(DOC_PATH).relative_path_from(COL_PATH).to_s +end + +def native_relative + DOC_PATH.sub("#{COL_PATH}/", "") +end + +if pathutil_relative == native_relative + Benchmark.ips do |x| + x.report("pathutil") { pathutil_relative } + x.report("native") { native_relative } + x.compare! + end +else + print "PATHUTIL: " + puts pathutil_relative + print "NATIVE: " + puts native_relative +end diff --git a/benchmark/parse-date b/benchmark/parse-date new file mode 100755 index 00000000000..9d1d1ed632d --- /dev/null +++ b/benchmark/parse-date @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby + +require_relative '../lib/jekyll' +require 'benchmark/ips' + +date = "2014-08-02 14:43:06 PDT".freeze +time = Time.parse(date) + +Benchmark.ips do |x| + x.report('Time.parse') do + Time.parse(date) + end + + x.report('localtime') do + Time.parse(date).localtime + end + + x.report('localtime parsed') do + time.localtime + end + + x.report('Utils.parse_date') do + Jekyll::Utils.parse_date(date) + end +end diff --git a/benchmark/parse-include-tag-params.rb b/benchmark/parse-include-tag-params.rb new file mode 100755 index 00000000000..c6670e0064a --- /dev/null +++ b/benchmark/parse-include-tag-params.rb @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# For pull request: https://github.com/jekyll/jekyll/pull/8192 + +require 'benchmark/ips' +require 'bundler/setup' +require 'memory_profiler' +require 'jekyll' + +CONTEXT = {"bar"=>"The quick brown fox"} +MARKUP_1 = %Q(foo=bar lorem="ipsum \\"dolor\\"" alpha='beta \\'gamma\\'').freeze +MARKUP_2 = %Q(foo=bar lorem="ipsum 'dolor'" alpha='beta "gamma"').freeze + +# + +def old_parse_params(markup) + params = {} + + while (match = Jekyll::Tags::IncludeTag::VALID_SYNTAX.match(markup)) + markup = markup[match.end(0)..-1] + + value = if match[2] + match[2].gsub('\\"', '"') + elsif match[3] + match[3].gsub("\\'", "'") + elsif match[4] + CONTEXT[match[4]] + end + + params[match[1]] = value + end + params +end + +def new_parse_params(markup) + params = {} + markup.scan(Jekyll::Tags::IncludeTag::VALID_SYNTAX) do |key, d_quoted, s_quoted, variable| + value = if d_quoted + d_quoted.include?('\\"') ? d_quoted.gsub('\\"', '"') : d_quoted + elsif s_quoted + s_quoted.include?("\\'") ? s_quoted.gsub("\\'", "'") : s_quoted + elsif variable + CONTEXT[variable] + end + + params[key] = value + end + params +end + +# + +def report(label, markup, color) + prof_report = MemoryProfiler.report { yield } + + allocated_memory = prof_report.scale_bytes(prof_report.total_allocated_memsize) + allocated_objects = prof_report.total_allocated + retained_memory = prof_report.scale_bytes(prof_report.total_retained_memsize) + retained_objects = prof_report.total_retained + + puts <<~MSG.send(color) + #{(label + " ").ljust(49, "-")} + + MARKUP: #{markup} + RESULT: #{yield} + + Total allocated: #{allocated_memory} (#{allocated_objects} objects) + Total retained: #{retained_memory} (#{retained_objects} objects) + MSG +end + +report('old w/ escaping', MARKUP_1, :magenta) { old_parse_params(MARKUP_1) } +report('new w/ escaping', MARKUP_1, :cyan) { new_parse_params(MARKUP_1) } + +report('old no escaping', MARKUP_2, :green) { old_parse_params(MARKUP_2) } +report('new no escaping', MARKUP_2, :yellow) { new_parse_params(MARKUP_2) } + +# + +Benchmark.ips do |x| + x.report("old + esc".magenta) { old_parse_params(MARKUP_1) } + x.report("new + esc".cyan) { new_parse_params(MARKUP_1) } + x.compare! +end + +Benchmark.ips do |x| + x.report("old - esc".green) { old_parse_params(MARKUP_2) } + x.report("new - esc".yellow) { new_parse_params(MARKUP_2) } + x.compare! +end diff --git a/benchmark/path-manager.rb b/benchmark/path-manager.rb new file mode 100644 index 00000000000..969949fdd2d --- /dev/null +++ b/benchmark/path-manager.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'benchmark/ips' +require 'jekyll' + +class FooPage + def initialize(dir:, name:) + @dir = dir + @name = name + end + + def slow_path + File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A/!, "") + end + + def fast_path + Jekyll::PathManager.join(@dir, @name).sub(%r!\A/!, "") + end +end + +nil_page = FooPage.new(:dir => nil, :name => nil) +empty_page = FooPage.new(:dir => "", :name => "") +root_page = FooPage.new(:dir => "", :name => "ipsum.md") +nested_page = FooPage.new(:dir => "lorem", :name => "ipsum.md") +slashed_page = FooPage.new(:dir => "/lorem/", :name => "/ipsum.md") + +if nil_page.slow_path == nil_page.fast_path + Benchmark.ips do |x| + x.report('nil_page slow') { nil_page.slow_path } + x.report('nil_page fast') { nil_page.fast_path } + x.compare! + end +end + +if empty_page.slow_path == empty_page.fast_path + Benchmark.ips do |x| + x.report('empty_page slow') { empty_page.slow_path } + x.report('empty_page fast') { empty_page.fast_path } + x.compare! + end +end + +if root_page.slow_path == root_page.fast_path + Benchmark.ips do |x| + x.report('root_page slow') { root_page.slow_path } + x.report('root_page fast') { root_page.fast_path } + x.compare! + end +end + +if nested_page.slow_path == nested_page.fast_path + Benchmark.ips do |x| + x.report('nested_page slow') { nested_page.slow_path } + x.report('nested_page fast') { nested_page.fast_path } + x.compare! + end +end + +if slashed_page.slow_path == slashed_page.fast_path + Benchmark.ips do |x| + x.report('slashed_page slow') { slashed_page.slow_path } + x.report('slashed_page fast') { slashed_page.fast_path } + x.compare! + end +end diff --git a/benchmark/proc-call-vs-yield b/benchmark/proc-call-vs-yield old mode 100644 new mode 100755 index 3d55979bab1..9b4ad3755ae --- a/benchmark/proc-call-vs-yield +++ b/benchmark/proc-call-vs-yield @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' def fast diff --git a/benchmark/regexp-vs-include.rb b/benchmark/regexp-vs-include.rb new file mode 100755 index 00000000000..b2a4eff4665 --- /dev/null +++ b/benchmark/regexp-vs-include.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +require 'benchmark/ips' + +# For this pull request, which changes Page#dir +# https://github.com/jekyll/jekyll/pull/4403 + +CONTENT_CONTAINING = <<-HTML.freeze + + + + + + Jemoji + + + + +

:+1:

+ + + +HTML +CONTENT_NOT_CONTAINING = <<-HTML.freeze + + + + + + Jemoji + + + + +

:+1:

+ + + +HTML + +Benchmark.ips do |x| + x.report("no body include?") { CONTENT_NOT_CONTAINING.include?(' A more efficient technique is to cache the sort keys (modification times in this case) +# > before the sort. Perl users often call this approach a Schwartzian transform, after +# > Randal Schwartz. We construct a temporary array, where each element is an array +# > containing our sort key along with the filename. We sort this array, and then extract +# > the filename from the result. +# > This is exactly what sort_by does internally. +# +# The well-documented efficiency of sort_by is a good reason to use it. However, when a property +# does not exist on an item being sorted, it can cause issues (no nil's allowed!) +# In Jekyll::Filters#sort_input, we extract the property in each iteration of #sort, +# which is quite inefficient! How inefficient? This benchmark will tell you just how, and how much +# it can be improved by using the Schwartzian transform. Thanks, Randall! + +require 'benchmark/ips' +require 'minitest' +require File.expand_path("../lib/jekyll", __dir__) + +def site + @site ||= Jekyll::Site.new( + Jekyll.configuration("source" => File.expand_path("../docs", __dir__)) + ).tap(&:reset).tap(&:read) +end + +def site_docs + site.collections["docs"].docs.dup +end + +def sort_by_property_directly(docs, meta_key) + docs.sort! do |apple, orange| + apple_property = apple[meta_key] + orange_property = orange[meta_key] + + if !apple_property.nil? && !orange_property.nil? + apple_property <=> orange_property + elsif !apple_property.nil? && orange_property.nil? + -1 + elsif apple_property.nil? && !orange_property.nil? + 1 + else + apple <=> orange + end + end +end + +def schwartzian_transform(docs, meta_key) + docs.collect! { |d| + [d[meta_key], d] + }.sort! { |apple, orange| + if !apple[0].nil? && !orange[0].nil? + apple.first <=> orange.first + elsif !apple[0].nil? && orange[0].nil? + -1 + elsif apple[0].nil? && !orange[0].nil? + 1 + else + apple[-1] <=> orange[-1] + end + }.collect! { |d| d[-1] } +end + +# Before we test efficiency, do they produce the same output? +class Correctness + include Minitest::Assertions + + require "pp" + define_method :mu_pp, &:pretty_inspect + + attr_accessor :assertions + + def initialize(docs, property) + @assertions = 0 + @docs = docs + @property = property + end + + def assert! + assert sort_by_property_directly(@docs, @property).is_a?(Array), "sort_by_property_directly must return an array" + assert schwartzian_transform(@docs, @property).is_a?(Array), "schwartzian_transform must return an array" + assert_equal sort_by_property_directly(@docs, @property), + schwartzian_transform(@docs, @property) + puts "Yeah, ok, correctness all checks out for property #{@property.inspect}" + end +end + +Correctness.new(site_docs, "redirect_from".freeze).assert! +Correctness.new(site_docs, "title".freeze).assert! + +def property(property, meta_key) + Benchmark.ips do |x| + x.config(time: 10, warmup: 5) + x.report("sort_by_property_directly with #{property} property") do + sort_by_property_directly(site_docs, meta_key) + end + x.report("schwartzian_transform with #{property} property") do + schwartzian_transform(site_docs, meta_key) + end + x.compare! + end +end + +# First, test with a property only a handful of documents have. +test_property('sparse', 'redirect_from') + +# Next, test with a property they all have. +test_property('non-sparse', 'title') diff --git a/benchmark/sequential-assignment b/benchmark/sequential-assignment old mode 100644 new mode 100755 index 945e982b25f..790e995c367 --- a/benchmark/sequential-assignment +++ b/benchmark/sequential-assignment @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' Benchmark.ips do |x| diff --git a/benchmark/static-drop-vs-forwarded.rb b/benchmark/static-drop-vs-forwarded.rb new file mode 100755 index 00000000000..9f8365d3c8f --- /dev/null +++ b/benchmark/static-drop-vs-forwarded.rb @@ -0,0 +1,83 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "forwardable" +require "colorator" +require "liquid" +require "benchmark/ips" +require "memory_profiler" + +# Set up (memory) profiler + +class Profiler + def self.run + yield new(ARGV[0] || 10_000) + end + + def initialize(count) + @count = count.to_i + end + + def report(label, color, &block) + prof_report = MemoryProfiler.report { @count.to_i.times(&block) } + + allocated_memory = prof_report.scale_bytes(prof_report.total_allocated_memsize) + allocated_objects = prof_report.total_allocated + retained_memory = prof_report.scale_bytes(prof_report.total_retained_memsize) + retained_objects = prof_report.total_retained + + puts <<~MSG.send(color) + With #{label} calls + + Total allocated: #{allocated_memory} (#{allocated_objects} objects) + Total retained: #{retained_memory} (#{retained_objects} objects) + MSG + end +end + +# Set up stage + +class Drop < Liquid::Drop + def initialize(obj) + @obj = obj + end +end + +class ForwardDrop < Drop + extend Forwardable + def_delegators :@obj, :name +end + +class StaticDrop < Drop + def name + @obj.name + end +end + +class Document + def name + "lipsum" + end +end + +# Set up actors + +document = Document.new +alpha = ForwardDrop.new(document) +beta = StaticDrop.new(document) +count = ARGV[0] || 10_000 + +# Run profilers +puts "\nMemory profiles for #{count} calls to invoke drop key:" +Profiler.run do |x| + x.report("forwarded", :cyan) { alpha["name"] } + x.report("static", :green) { beta["name"] } +end + +# Benchmark +puts "\nBenchmarking the two scenarios..." +Benchmark.ips do |x| + x.report("forwarded".cyan) { alpha["name"] } + x.report("static".green) { beta["name"] } + x.compare! +end diff --git a/benchmark/string-concat b/benchmark/string-concat old mode 100644 new mode 100755 index c4a9174836d..2020bb51567 --- a/benchmark/string-concat +++ b/benchmark/string-concat @@ -1,6 +1,7 @@ +#!/usr/bin/env ruby require 'benchmark/ips' -url = "http://jekyllrb.com" +url = "https://jekyllrb.com" Benchmark.ips do |x| x.report('+=') { url += '/' } diff --git a/benchmark/string-replacement b/benchmark/string-replacement old mode 100644 new mode 100755 index 36de613c31e..f522cfef517 --- a/benchmark/string-replacement +++ b/benchmark/string-replacement @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' def str diff --git a/benchmark/symbol-to-proc b/benchmark/symbol-to-proc old mode 100644 new mode 100755 index bc08b2f29a2..7b568c474f1 --- a/benchmark/symbol-to-proc +++ b/benchmark/symbol-to-proc @@ -1,3 +1,4 @@ +#!/usr/bin/env ruby require 'benchmark/ips' Benchmark.ips do |x| diff --git a/bin/jekyll b/bin/jekyll deleted file mode 100755 index 67705b515d7..00000000000 --- a/bin/jekyll +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env ruby -STDOUT.sync = true - -$:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib }) - -require 'jekyll' -require 'mercenary' - -Jekyll::External.require_if_present( - Jekyll::External.blessed_gems -) - -Jekyll::PluginManager.require_from_bundler - -Jekyll::Deprecator.process(ARGV) - -Mercenary.program(:jekyll) do |p| - p.version Jekyll::VERSION - p.description 'Jekyll is a blog-aware, static site generator in Ruby' - p.syntax 'jekyll [options]' - - p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)' - p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)' - p.option 'safe', '--safe', 'Safe mode (defaults to false)' - p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)' - p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)' - p.option 'profile', '--profile', 'Generate a Liquid rendering profile' - - Jekyll::Command.subclasses.each { |c| c.init_with_program(p) } - - p.action do |args, options| - if args.empty? - Jekyll.logger.error "A subcommand is required." - puts p - abort - else - unless p.has_command?(args.first) - Jekyll.logger.abort_with "Invalid command. Use --help for more information" - end - end - end -end diff --git a/site/.gitignore b/docs/.gitignore similarity index 77% rename from site/.gitignore rename to docs/.gitignore index 79bd74f7496..ab6b6662ffb 100644 --- a/site/.gitignore +++ b/docs/.gitignore @@ -1,4 +1,5 @@ _site/ +.idea/ *.swp pkg/ test/ diff --git a/site/CNAME b/docs/CNAME similarity index 100% rename from site/CNAME rename to docs/CNAME diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000000..935b293be85 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,65 @@ +--- +version: 4.4.1 +name: Jekyll • Simple, blog-aware, static sites +description: Transform your plain text into static websites and blogs +url: https://jekyllrb.com +repository: https://github.com/jekyll/jekyll +site_branch: master +timezone: America/Los_Angeles +twitter: + username: jekyllrb +logo: "/img/logo-2x.png" +google_analytics_id: UA-50755011-1 +google_site_verification: onQcXpAvtHBrUI5LlroHNE_FP0b2qvFyPq7VZw36iEY +cloudinary_url: https://res.cloudinary.com/jekyll/image/upload/f_auto,q_auto,w_404 +collections: + docs: + permalink: "/:collection/:path/" + output: true + posts: + permalink: "/news/:year/:month/:day/:title/" + output: true + tutorials: + permalink: "/:collection/:path/" + output: true +defaults: +- scope: + path: _docs + type: docs + values: + layout: docs +- scope: + path: _posts + type: posts + values: + layout: news_item +- scope: + path: _tutorials + type: tutorials + values: + layout: tutorials +- scope: + path: '' + values: + image: "/img/jekyll-og.png" +future: true +plugins: +- jekyll-avatar +- jekyll-feed +- jekyll-mentions +- jekyll-redirect-from +- jekyll-seo-tag +- jekyll-sitemap +- jemoji +feed: + categories: + - release +kramdown: + syntax_highlighter_opts: + default_lang: plaintext +sass: + style: compressed +strict_front_matter: true +exclude: +- icomoon-selection.json +- readme.md diff --git a/docs/_data/config_options/build.yml b/docs/_data/config_options/build.yml new file mode 100644 index 00000000000..a40f8625bbc --- /dev/null +++ b/docs/_data/config_options/build.yml @@ -0,0 +1,140 @@ +- name: Regeneration + description: Enable auto-regeneration of the site when files are modified. + flag: "-w, --[no-]watch" + + +- name: Configuration + description: >- + Specify config files instead of using _config.yml automatically. + Settings in later files override settings in earlier files. + flag: "--config FILE1[,FILE2,...]" + + +- name: Plugins + description: >- + Specify plugin directories instead of using _plugins/ automatically. + option: "plugins_dir: [ DIR1,... ]" + flag: "-p, --plugins DIR1[,DIR2,...]" + + +- name: Layouts + description: >- + Specify layout directory instead of using _layouts/ automatically. + option: "layouts_dir: DIR" + flag: --layouts DIR + + +- name: Drafts + description: Process and render draft posts. + option: "show_drafts: BOOL" + flag: -D, --drafts + + +- name: Environment + description: Use a specific environment value in the build. + flag: JEKYLL_ENV=production + + +- name: Future + description: Publish posts or collection documents with a future date. + option: "future: BOOL" + flag: --future + + +- name: Unpublished + description: Render posts that were marked as unpublished. + option: "unpublished: BOOL" + flag: --unpublished + + +- name: LSI + description: >- + Produce an index for related posts. Requires the + classifier-reborn plugin. + option: "lsi: BOOL" + flag: --lsi + + +- name: Limit posts + description: Limit the number of posts to parse and publish. + option: "limit_posts: NUM" + flag: --limit_posts NUM + + +- name: Force polling + description: Force watch to use polling. + option: "force_polling: BOOL" + flag: --force_polling + + +- name: Verbose output + description: Print verbose output. + option: "verbose: BOOL" + flag: -V, --verbose + + +- name: Silence output + description: Silence the normal output from Jekyll during a build. + option: "quiet: BOOL" + flag: -q, --quiet + + +- name: Log level + description: Specify a log level among debug, info, warn, or error. + flag: JEKYLL_LOG_LEVEL=info + + +- name: Incremental build + description: >- + Enable the experimental + incremental + build feature. Incremental build only re-builds posts and pages that + have changed, resulting in significant performance improvements for large + sites, but may also break site generation in certain cases. + option: "incremental: BOOL" + flag: -I, --incremental + + +- name: Disable bundle require + description: Disables the need to require gems in `:jekyll_plugins` Gemfile + flag: JEKYLL_NO_BUNDLER_REQUIRE=true + + +- name: Liquid profiler + description: Generate a Liquid rendering profile to help you identify performance bottlenecks. + option: "profile: BOOL" + flag: --profile + + +- name: Strict front matter + description: Cause a build to fail if there is a YAML syntax error in a page's front matter. + option: "strict_front_matter: BOOL" + flag: --strict_front_matter + + +- name: Web Domain URL + option: "url: SCHEME://HOST[:PORT]" + description: >- + The canonical URL of the root of your production deploy, composed of the following components:
+    •   Protocol scheme (e.g. http://)
+    •   Hostname or IP address (e.g. example.org)
+    •   (Optional) The port number of the server, prefixed with a colon + (e.g. :8080)
+ The value of this configuration option should NOT have a trailing slash. It will be appended + with the baseurl to form the full URL to your Jekyll site when using the + Liquid filter absolute_url.
+ NOTE: This setting is automatically configured to the localhost URL + when the jekyll serve command is invoked. + + +- name: Base URL + description: >- + Serve the website from the given base URL (the path between web-server or domain root and your landing + page). + option: "baseurl: /PATH/TO/SITE" + flag: -b, --baseurl /PATH/TO/SITE + + +- name: Trace + description: Show the full backtrace when an error occurs. + flag: -t, --trace diff --git a/docs/_data/config_options/global.yml b/docs/_data/config_options/global.yml new file mode 100644 index 00000000000..cd92a505a46 --- /dev/null +++ b/docs/_data/config_options/global.yml @@ -0,0 +1,108 @@ +- name: Site source + description: Change the directory where Jekyll will read files + option: "source: DIR" + flag: -s, --source DIR + + +- name: Site destination + description: Change the directory where Jekyll will write files + option: "destination: DIR" + flag: -d, --destination DIR + + +- name: Safe + description: >- + Disable non-whitelisted plugins, caching to disk, and ignore symbolic links. + option: "safe: BOOL" + flag: --safe + + +- name: Disable disk cache + version-badge: 4.1.0 + description: >- + Disable caching of content to disk in order to skip creating a .jekyll-cache or similar directory at + the source to avoid interference with virtual environments and third-party directory watchers. Caching to disk is + always disabled in safe mode. + option: "disable_disk_cache: BOOL" + flag: --disable-disk-cache + + +- name: Ignore theme configuration + version-badge: 4.1.0 + description: >- + Jekyll 4.0 started allowing themes to bundle a _config.yml to simplify theme-onboarding for new users. + In the unfortunate situation that importing a bundled theme configuration messes up the merged site-configuration, + the user can configure Jekyll to not import the theme-config entirely. + option: "ignore_theme_config: BOOL" + + +- name: Exclude + description: >- + Exclude directories and/or files from the conversion. These exclusions are relative to the site's source directory + and cannot be outside the source directory. +
+ This configuration option supports Ruby's + File.fnmatch filename globbing patterns to match multiple entries to exclude. For example, + you can exclude multiple README.md files in your source tree from being included in your site by specifying the + following exclude option entries: ["README.md", "**/README.md"]. +
+ In Jekyll 3, the exclude configuration option replaces the default exclusion list. +
+ In Jekyll 4, user-provided entries get added to the default exclusion list instead and the include + option can be used to override the default exclusion list entries. +
+ The default exclusions are found in _config.yml as created by jekyll new: +
    +
  • .sass-cache/
  • +
  • .jekyll-cache/
  • +
  • gemfiles/
  • +
  • Gemfile
  • +
  • Gemfile.lock
  • +
  • node_modules/
  • +
  • vendor/bundle/
  • +
  • vendor/cache/
  • +
  • vendor/gems/
  • +
  • vendor/ruby/
  • +
+ option: "exclude: [DIR, FILE, ...]" + + +- name: Include + description: >- + Force inclusion of directories and/or files in the conversion. .htaccess is a good example since + dotfiles are excluded by default. +
+ This configuration option supports Ruby's + File.fnmatch filename globbing patterns to match multiple entries to include, refer the + exclude configuration option for more information. +
+ With Jekyll 4, the include configuration option entries override the exclude option + entries. + option: "include: [DIR, FILE, ...]" + + +- name: Keep files + description: >- + When clobbering the site destination, keep the selected files. Useful for files that are not generated by jekyll; + e.g. files or assets that are generated by your build tool. The paths are relative to the destination. + option: "keep_files: [DIR, FILE, ...]" + + +- name: Time zone + description: >- + Set the time zone for site generation. This sets the TZ environment variable, which Ruby uses to handle + time and date creation and manipulation. Any entry from the + IANA Time Zone Database + is valid, e.g. America/New_York. A list of all available values can be found + here. + When serving on a local machine, the default time zone is set by your operating system. But when served on a remote + host/server, the default time zone depends on the server's setting or location. + option: "timezone: TIMEZONE" + + +- name: Encoding + description: >- + Set the encoding of files by name (only available for Ruby 1.9 or later). The default value is utf-8 + starting in 2.0.0, and nil before 2.0.0, which will yield the Ruby default of ASCII-8BIT. + Available encodings can be shown by the command ruby -e 'puts Encoding::list.join("\n")'. + option: "encoding: ENCODING" diff --git a/docs/_data/config_options/serve.yml b/docs/_data/config_options/serve.yml new file mode 100644 index 00000000000..2504045e03e --- /dev/null +++ b/docs/_data/config_options/serve.yml @@ -0,0 +1,80 @@ +- name: Local server port + description: Listen on the given port. The default is `4000`. + option: "port: PORT" + flag: "-P, --port PORT" + + +- name: Local server hostname + description: Listen at the given hostname. The default is `localhost`. + option: "host: HOSTNAME" + flag: "-H, --host HOSTNAME" + + +- name: Live reload + description: Reload a page automatically on the browser when its content is edited. + option: "livereload: BOOL" + flag: "-l, --livereload" + + +- name: Live reload ignore + description: >- + File glob patterns for LiveReload to ignore.

+ Ensure that patterns are quoted when passed via the command-line to deter your shell from + expanding them.

Note: The given glob patterns are matched against + the relative_path attribute of the processed resource. In the event Jekyll + reloads a relative_path matching the pattern in spite of being quoted, try listing + the pattern(s) under the config file option key. + option: "livereload_ignore: [ GLOB1,... ]" + flag: "--livereload-ignore GLOB1[,GLOB2,...]" + + +- name: Live reload min/max delay + description: Minimum/Maximum delay before automatically reloading page. + options: + - "livereload_min_delay: SECONDS" + - "livereload_max_delay: SECONDS" + flags: + - "--livereload-min-delay SECONDS" + - "--livereload-max-delay SECONDS" + + +- name: Live reload port + description: >- + Port for LiveReload to listen on.
Ability to override via config file introduced in + 4.4.0. + option: "livereload_port: PORT" + flag: "--livereload-port PORT" + + +- name: Open URL + description: Open the site's URL in the browser. + option: "open_url: BOOL" + flag: "-o, --open-url" + + +- name: Detach + description: Detach the server from the terminal. + option: "detach: BOOL" + flag: "-B, --detach" + + +- name: Skips the initial site build + description: Skips the initial site build which occurs before the server is started. + option: "skip_initial_build: BOOL" + flag: "--skip-initial-build" + + +- name: Show directory listing + description: Show a directory listing instead of loading your index file. + option: "show_dir_listing: BOOL" + flag: "--show-dir-listing" + + +- name: X.509 (SSL) private key + description: "SSL Private Key, stored or symlinked in the site source." + flag: "--ssl-key" + + +- name: X.509 (SSL) certificate + description: "SSL Public certificate, stored or symlinked in the site source." + flag: "--ssl-cert" diff --git a/docs/_data/docs_nav.yml b/docs/_data/docs_nav.yml new file mode 100644 index 00000000000..1e1af40a961 --- /dev/null +++ b/docs/_data/docs_nav.yml @@ -0,0 +1,37 @@ +- title: Getting Started + docs: + - link: /docs/ + - link: /docs/installation/ + - link: /docs/ruby-101/ + - link: /docs/community/ + - link: /docs/step-by-step/01-setup/ +- title: Build + docs: + - link: /docs/usage/ + - link: /docs/configuration/ + - link: /docs/rendering-process/ +- title: Content + docs: + - link: /docs/pages/ + - link: /docs/posts/ + - link: /docs/front-matter/ + - link: /docs/collections/ + - link: /docs/datafiles/ + - link: /docs/assets/ + - link: /docs/static-files/ +- title: Site Structure + docs: + - link: /docs/structure/ + - link: /docs/liquid/ + - link: /docs/variables/ + - link: /docs/includes/ + - link: /docs/layouts/ + - link: /docs/permalinks/ + - link: /docs/themes/ + - link: /docs/pagination/ +- title: Guides + docs: + - link: /docs/plugins/ + - link: /docs/migrations/ + - link: /docs/upgrading/ + - link: /docs/deployment/ diff --git a/docs/_data/jekyll_filters.yml b/docs/_data/jekyll_filters.yml new file mode 100644 index 00000000000..de052a54c72 --- /dev/null +++ b/docs/_data/jekyll_filters.yml @@ -0,0 +1,348 @@ +# +# --------------------------------------------------------------------------------------- +# List of Liquid Filters provided by Jekyll Core that will be utilized for their +# documentation. +# +# To document a new filter, create a new "list-item" below with the following keys: +# name: : [REQUIRED] A string label that identifies the filter +# description: : [REQUIRED] A short description of what to expect from the filter +# version_badge: : [OPTIONAL] Jekyll version that introduced the filter +# examples: : [REQUIRED] A 'nested list' comprised of inputs and outputs +# input: : [REQUIRED] The filter syntax and usage +# output: : [OPTIONAL] The output from the filter +# +# Tip: Use YAML Block notations to "fold" a long string, or to "break" a long string +# to the following line. Block notations can also be used to avoid having to use +# backslashes to escape quotes. +# --------------------------------------------------------------------------------------- +# +- name: Relative URL + description: >- + Prepend baseurl config value to the input to convert a URL path into a relative URL. + This is recommended for a site that is hosted on a subpath of a domain. + examples: + - input: '{{ "/assets/style.css" | relative_url }}' + output: '/my-baseurl/assets/style.css' + +# + +- name: Absolute URL + description: >- + Prepend url and baseurl values to the input to convert a URL path to an absolute URL. + examples: + - input: '{{ "/assets/style.css" | absolute_url }}' + output: 'http://example.com/my-baseurl/assets/style.css' + +# + +- name: Date to XML Schema + description: Convert a Date into XML Schema (ISO 8601) format. + examples: + - input: '{{ site.time | date_to_xmlschema }}' + output: '2008-11-07T13:07:54-08:00' + +# + +- name: Date to RFC-822 Format + description: Convert a Date into the RFC-822 format used for RSS feeds. + examples: + - input: '{{ site.time | date_to_rfc822 }}' + output: 'Mon, 07 Nov 2008 13:07:54 -0800' + +# + +- name: Date to String + description: Convert a date to short format. + examples: + - input: '{{ site.time | date_to_string }}' + output: '07 Nov 2008' + +# + +- name: Date to String in ordinal US style + description: 'Format a date to ordinal, US, short format.' + version_badge: 3.8.0 + examples: + - input: '{{ site.time | date_to_string: "ordinal", "US" }}' + output: 'Nov 7th, 2008' + +# + +- name: Date to Long String + description: Format a date to long format. + examples: + - input: '{{ site.time | date_to_long_string }}' + output: '07 November 2008' + +# + +- name: Date to Long String in ordinal UK style + description: 'Format a date to ordinal, UK, long format.' + version_badge: 3.8.0 + examples: + - input: '{{ site.time | date_to_long_string: "ordinal" }}' + output: '7th November 2008' + +# + +- name: Where + description: Select all the objects in an array where the key has the given value. + examples: + - input: '{{ site.members | where:"graduation_year","2014" }}' + output: + +# + +- name: Where Expression + description: Select all the objects in an array where the expression is true. + version_badge: 3.2.0 + examples: + - input: |- + {{ site.members | where_exp:"item", + "item.graduation_year == 2014" }} + output: + - input: |- + {{ site.members | where_exp:"item", + "item.graduation_year < 2014" }} + output: + - input: |- + {{ site.members | where_exp:"item", + "item.projects contains 'foo'" }} + output: + +# + +- name: Find + description: >- + Return the first object in an array for which the queried + attribute has the given value or return nil if no item in + the array satisfies the given criteria. + version_badge: 4.1.0 + examples: + - input: '{{ site.members | find: "graduation_year", "2014" }}' + output: + +# + +- name: Find Expression + description: >- + Return the first object in an array for which the given + expression evaluates to true or return nil if no item in + the array satisfies the evaluated expression. + version_badge: 4.1.0 + examples: + - input: |- + {{ site.members | find_exp:"item", + "item.graduation_year == 2014" }} + output: + - input: |- + {{ site.members | find_exp:"item", + "item.graduation_year < 2014" }} + output: + - input: |- + {{ site.members | find_exp:"item", + "item.projects contains 'foo'" }} + output: + +# + +- name: Group By + description: Group an array's items by a given property. + examples: + - input: '{{ site.members | group_by:"graduation_year" }}' + output: |- + [{"name"=>"2013", "items"=>[...]}, + {"name"=>"2014", "items"=>[...]}] + +# + +- name: Group By Expression + description: Group an array's items using a Liquid expression. + version_badge: 3.4.0 + examples: + - input: |- + {{ site.members | group_by_exp: "item", + "item.graduation_year | truncate: 3, ''" }} + output: |- + [{"name"=>"201", "items"=>[...]}, + {"name"=>"200", "items"=>[...]}] + +# + +- name: XML Escape + description: Escape some text for use in XML. + examples: + - input: '{{ page.content | xml_escape }}' + output: + +# + +- name: CGI Escape + description: >- + CGI escape a string for use in a URL. Replaces any special characters + with appropriate %XX replacements. CGI escape normally + replaces a space with a plus + sign. + examples: + - input: '{{ "foo, bar; baz?" | cgi_escape }}' + output: 'foo%2C+bar%3B+baz%3F' + +# + +- name: URI Escape + description: >- + Percent encodes any special characters in a URI. + URI escape normally replaces a space with %20. + Reserved characters + will not be escaped. + examples: + - input: '{{ "http://foo.com/?q=foo, \bar?" | uri_escape }}' + output: 'http://foo.com/?q=foo,%20%5Cbar?' + +# + +- name: Number of Words + description: >- + Count the number of words in some text.
+ From v4.1.0, this filter takes an optional + argument to control the handling of Chinese-Japanese-Korean (CJK) characters + in the input string.
+ Passing 'cjk' as the argument will count every CJK character + detected as one word irrespective of being separated by whitespace.
+ Passing 'auto' (auto-detect) works similar to 'cjk' + but is more performant if the filter is used on a variable string that may + or may not contain CJK chars. + examples: + - input: '{{ "Hello world!" | number_of_words }}' + output: 2 + - input: '{{ "你好hello世界world" | number_of_words }}' + output: 1 + - input: '{{ "你好hello世界world" | number_of_words: "cjk" }}' + output: 6 + - input: '{{ "你好hello世界world" | number_of_words: "auto" }}' + output: 6 + +# + +- name: Array to Sentence + description: >- + Convert an array into a sentence. Useful for listing tags. + Optional argument for connector. + examples: + - input: '{{ page.tags | array_to_sentence_string }}' + output: 'foo, bar, and baz' + - input: '{{ page.tags | array_to_sentence_string: "or" }}' + output: 'foo, bar, or baz' + +# + +- name: Markdownify + description: Convert a Markdown-formatted string into HTML. + examples: + - input: '{{ page.excerpt | markdownify }}' + output: + +# + +- name: Smartify + description: 'Convert "quotes" into “smart quotes.”' + examples: + - input: '{{ page.title | smartify }}' + output: + +# + +- name: Converting Sass/SCSS + description: Convert a Sass- or SCSS-formatted string into CSS. + examples: + - input: '{{ some_sass | sassify }}' + output: + - input: '{{ some_scss | scssify }}' + output: + +# + +- name: Slugify + description: Convert a string into a lowercase URL "slug". See below for options. + examples: + - input: '{{ "The _config.yml file" | slugify }}' + output: 'the-config-yml-file' + - input: '{{ "The _config.yml file" | slugify: "pretty" }}' + output: 'the-_config.yml-file' + - input: '{{ "The _cönfig.yml file" | slugify: "ascii" }}' + output: 'the-c-nfig-yml-file' + - input: '{{ "The cönfig.yml file" | slugify: "latin" }}' + output: 'the-config-yml-file' + +# + +- name: Data To JSON + description: Convert Hash or Array to JSON. + examples: + - input: '{{ site.data.projects | jsonify }}' + output: + +# + +- name: Normalize Whitespace + description: Replace any occurrence of whitespace with a single space. + examples: + - input: '{{ "a \n b" | normalize_whitespace }}' + output: + +# + +- name: Sort + description: >- + Sort an array. Optional arguments for hashes + 1. property name + 2. nils order (first or last). + examples: + - input: '{{ page.tags | sort }}' + output: + - input: '{{ site.posts | sort: "author" }}' + output: + - input: '{{ site.pages | sort: "title", "last" }}' + output: + +# + +- name: Sample + description: 'Pick a random value from an array. Optionally, pick multiple values.' + examples: + - input: '{{ site.pages | sample }}' + output: + - input: '{{ site.pages | sample: 2 }}' + output: + +# + +- name: To Integer + description: Convert a string or boolean to integer. + examples: + - input: '{{ some_var | to_integer }}' + output: + +# + +- name: Array Filters + description: >- + Push, pop, shift, and unshift elements from an Array. + These are NON-DESTRUCTIVE, i.e. they do not mutate the array, + but rather make a copy and mutate that. + examples: + - input: '{{ page.tags | push: "Spokane" }}' + output: '["Seattle", "Tacoma", "Spokane"]' + - input: '{{ page.tags | pop }}' + output: '["Seattle"]' + - input: '{{ page.tags | shift }}' + output: '["Tacoma"]' + - input: '{{ page.tags | unshift: "Olympia" }}' + output: '["Olympia", "Seattle", "Tacoma"]' + +# + +- name: Inspect + description: Convert an object into its String representation for debugging. + examples: + - input: '{{ some_var | inspect }}' + output: diff --git a/docs/_data/jekyll_variables.yml b/docs/_data/jekyll_variables.yml new file mode 100644 index 00000000000..cb0e13b34f7 --- /dev/null +++ b/docs/_data/jekyll_variables.yml @@ -0,0 +1,223 @@ +# Variables provided by Jekyll core +# +# name: : name of the variable +# description: : content returned by the variable + +global: + - name: site + description: >- + Site wide information + configuration settings from _config.yml. + See below for details. + - name: page + description: >- + Page specific information + the front matter. + Custom variables set via the front matter will be available here. See below for details. + - name: layout + description: >- + Layout specific information + the front matter. + Custom variables set via front matter in layouts will be available here. + - name: jekyll + description: >- + Jekyll-centric information will be available here. See below for details. + - name: theme + description: >- + Theme-gem specific information as defined in the theme's gemspec. Useful for rendering + information in the theme demo's "About" page, for example. See below for details. + - name: content + description: >- + In layout files, the rendered content of the Post or Page being wrapped. + Not defined in Post or Page files. + - name: paginator + description: >- + When the paginate configuration option is set, this variable becomes available + for use. See Pagination for details. + +site: + - name: site.time + description: >- + The current time (when you run the jekyll command). + - name: site.pages + description: >- + A list of all Pages. + - name: site.posts + description: >- + A reverse chronological list of all Posts. + - name: site.related_posts + description: >- + If the page being processed is a Post, this contains a list of up to ten related Posts. + By default, these are the ten most recent posts. For high quality but slow to compute + results, run the jekyll command with the --lsi + (latent semantic indexing) + option. Also note GitHub Pages does not support the + lsi option when generating sites. + - name: site.static_files + description: >- + A list of all static files (i.e. + files not processed by Jekyll's converters or the Liquid renderer). + Each file has five properties: path, modified_time, + name, basename and extname. + - name: site.html_pages + description: >- + A subset of site.pages listing those which end in .html. + - name: site.html_files + description: >- + A subset of site.static_files listing those which end in .html. + - name: site.collections + description: >- + A list of all the collections (including posts). + - name: site.data + description: >- + A list containing the data loaded from the YAML files located in the _data + directory. + - name: site.documents + description: >- + A list of all the documents in every collection. + - name: site.categories.CATEGORY + description: >- + The list of all Posts in category CATEGORY. + - name: site.tags.TAG + description: >- + The list of all Posts with tag TAG. + - name: site.url + description: >- + Contains the url of your site as it is configured in the _config.yml. + For example, if you have url: http://mysite.com in your configuration file, + then it will be accessible in Liquid as site.url. For the development + environment there is an + exception, if you are running jekyll serve in a development environment + site.url will be set to the value of host, port, + and SSL-related options. This defaults to url: http://localhost:4000. + - name: "site.[CONFIGURATION_DATA]" + description: >- + All the variables set via the command line and your _config.yml are available + through the site variable. For example, if you have foo: bar in + your configuration file, then it will be accessible in Liquid as site.foo. + Jekyll does not parse changes to _config.yml in + watch mode, you must restart Jekyll to see changes to variables. + +page: + - name: page.content + description: >- + The content of the Page, rendered or un-rendered depending upon what Liquid is being processed + and what page is. + - name: page.title + description: >- + The title of the Page or Document resource. + - name: page.excerpt + description: >- + The un-rendered excerpt of a Page or Document. Can be overridden in the + front matter. It can either be disabled atomically for + certain page or document by setting an empty string to an excerpt_separator key in + the front matter of desired resource or disabled site-wide by setting the same as a top-level + key in the config file. + - name: page.url + description: >- + The URL of the Post without the domain, but with a leading slash, e.g. + /2008/12/14/my-post.html + - name: page.date + description: >- + The Date assigned to the Post. This can be overridden in a Post's front matter by specifying + a new date/time in the format YYYY-MM-DD HH:MM:SS (assuming UTC), or + YYYY-MM-DD HH:MM:SS +/-TTTT (to specify a time zone using an offset from UTC. + e.g. 2008-12-14 10:30:00 +0900). Not applicable to Pages. + - name: page.id + description: >- + An identifier unique to a document in a Collection or a Post (useful in RSS feeds). e.g. + /2008/12/14/my-post/my-collection/my-document. Not applicable to + Pages. + - name: page.categories + description: >- + The list of categories to which this post belongs. Categories are derived from the directory + structure above the _posts directory. For example, a post at + /work/code/_posts/2008-12-24-closures.md would have this field set to + ['work', 'code']. These can also be specified in the + front matter. Note: Path-based categories may not work for + documents in user-defined collections. + - name: page.collection + description: >- + The label of the collection to which a Document belongs. e.g. posts for a post, or + puppies for a document at path _puppies/rover.md. If not part of a + collection, an empty string is returned. + - name: page.tags + description: >- + The list of tags to which this post belongs. These can be specified in the + front matter. + - name: page.dir + description: >- + The path between the source directory and the file of a page, e.g. /pages/ when the page + is at path pages/about.md relative to the source directory. This is derived from the + url attribute of the page and can therefore be overridden via the permalink + key in the front matter. NOTE: This variable is not applicable to + posts and documents in user-defined collections. Use the categories variable to get similar + info for posts. + - name: page.name + description: >- + The filename of the post or page, e.g. about.md + - name: page.path + description: >- + The path to the raw post or page, relative to the source directory. Example usage: Using a combination + of the repository's blob URL and this page variable to get the full URL to the file in the repository. + This can be overridden in the front matter. + - name: page.slug + description: >- + The filename of a Document resource without its extension (or date prefixes for a post). For example, + slug for a post at URL /2017/02/22/my-new-post.html, would be my-new-post. + Can be overridden in the front matter. + - name: page.ext + description: >- + The file extension of a Document resource. For example, .html. Can be overridden in the + front matter. + - name: page.next + description: >- + The next post relative to the position of the current post in site.posts. + Returns nil for the last entry. + - name: page.previous + description: >- + The previous post relative to the position of the current post in site.posts. + Returns nil for the first entry. + +jekyll: + - name: jekyll.version + description: Version of Jekyll used to build the site. + - name: jekyll.environment + description: Value assigned to environment variable JEKYLL_ENV during a build. + +theme: + - name: theme.root + description: >- + Absolute path to the theme-gem. Rendered only when environment variable JEKYLL_ENV + is set to development. + - name: theme.authors + description: Comma separated string composed of the authors of the theme-gem. + - name: theme.description + description: Description or summary of the theme-gem as specified in the theme gemspec. + - name: theme.version + description: The version string of current theme. + - name: theme.dependencies + description: List of runtime dependencies of the theme. + - name: theme.metadata + description: A mapping of key-value pairs as defined in the theme gemspec. + +paginator: + - name: paginator.page + description: The number of the current page + - name: paginator.per_page + description: Number of posts per page + - name: paginator.posts + description: Posts available for the current page + - name: paginator.total_posts + description: Total number of posts + - name: paginator.total_pages + description: Total number of pages + - name: paginator.previous_page + description: >- + The number of the previous page, or nil if no previous page exists + - name: paginator.previous_page_path + description: >- + The path to the previous page, or nil if no previous page exists + - name: paginator.next_page + description: >- + The number of the next page, or nil if no subsequent page exists + - name: paginator.next_page_path + description: >- + The path to the next page, or nil if no subsequent page exists diff --git a/docs/_data/jekyllconf-talks.yml b/docs/_data/jekyllconf-talks.yml new file mode 100644 index 00000000000..c386f814c0a --- /dev/null +++ b/docs/_data/jekyllconf-talks.yml @@ -0,0 +1,209 @@ +- speaker: Ben Balter + twitter_handle: BenBalter + youtube_id: Z-37y1qaoxc + topic: GitHub Pages behind the scenes + year: 2015 + +- speaker: Brandon Mathis + twitter_handle: imathis + youtube_id: KS6e4XxY2H4 + topic: What the heck is Octopress and why should I care? + year: 2015 + +- speaker: Brian Rinaldi + twitter_handle: remotesynth + youtube_id: vT7DhK5zbv0 + topic: Comparing Jekyll with the Competition + year: 2015 + +- speaker: Kyle Rush + twitter_handle: kylerush + youtube_id: ia8vsuiXiL0 + topic: Meet the Obama Campaign's $250 Million Fundraising Platform + year: 2015 + +- speaker: Michael Jovel + twitter_handle: mjovel + youtube_id: 8zSHG6XU_xY + topic: Building Living Style Guides with Jekyll + year: 2015 + +- speaker: Mike Neumegen + twitter_handle: mikeneumegen + youtube_id: NuChR_YdjrI + topic: A CMS for Jekyll + year: 2015 + +- speaker: Parker Moore + twitter_handle: parkr + youtube_id: y2SbOIQ5nSA + topic: Jekyll 3 and Beyond + year: 2015 + +- speaker: Tom Preston-Werner + twitter_handle: mojombo + youtube_id: BMve1OCKj6M + topic: Some crazy ideas I have for the future of static sites + year: 2015 + +- speaker: Allison Zadrozny + twitter_handle: allizad + youtube_id: Rsc0Mmp1qc8 + topic: Elasticsearch for Jekyll + year: 2016 + +- speaker: Amy Johnston + twitter_handle: AmyJohnstonXL + youtube_id: HR12JiUI2Zc + topic: Jekyll for Technical Documentation + year: 2016 + +- speaker: Bud Parr + twitter_handle: budparr + youtube_id: A1nTuNjoNbg + topic: Real World Content Strategy with Jekyll + year: 2016 + +- speaker: George Phillips + twitter_handle: gphillips_nz + youtube_id: skb_XWABEDc + topic: Building client-editable Jekyll sites + year: 2016 + +- speaker: Ire Aderinokun + twitter_handle: ireaderinokun + youtube_id: PRKV5IGKF2c + topic: Using Jekyll for Rapid CSS Testing + year: 2016 + +- speaker: Jon Chan + twitter_handle: JonHMChan + youtube_id: vDeKPs6xpOM + topic: Stack Overflow on Jekyll + year: 2016 + +- speaker: Julio Faerman + twitter_handle: juliodevrel + youtube_id: SOMonG8Iqak + topic: Jekyll on AWS + year: 2016 + +- speaker: Katy DeCorah + twitter_handle: katydecorah + youtube_id: s84wFRD8vfE + topic: Unconventional use cases for Jekyll + year: 2016 + +- speaker: David Darnes + twitter_handle: DavidDarnes + youtube_id: Y4qwpN40Dvg + topic: Doing a lot with a little + year: 2016 + +- speaker: Ronan Berder + twitter_handle: hunvreus + youtube_id: TteAQq25_Ns + topic: Designing fast websites with Jekyll + year: 2016 + +- speaker: David Von Lehman + twitter_handle: davidvlsea + youtube_id: wMlPlKCZfEk + topic: Continuous deployment of Jekyll sites powered by Docker + year: 2016 + +- speaker: David Jones + twitter_handle: d_jones + youtube_id: 4XxYQ7efk0E + topic: Building our agency site with Jekyll + year: 2016 + +- speaker: Scott Hewitt + twitter_handle: scotthewitt + youtube_id: qSd3pXQaPsE + topic: Jekyll For Every Case + year: 2016 + +- speaker: Tim Carry + twitter_handle: pixelastic + youtube_id: ivMML1J4ABY + topic: Algolia search on Jekyll sites + year: 2016 + +- speaker: Nils Borchers + twitter_handle: nilsbo + youtube_id: DtNMjuv6Rbo + topic: Building a living brand guide with Jekyll and Hologram + year: 2016 + +- speaker: Mike Neumegen + twitter_handle: mikeneumegen + youtube_id: rJ5EhVmTR7I + topic: Learning resources for the Jekyll community + year: 2016 + +- speaker: Oliver Pattison + twitter_handle: olivermakes + youtube_id: BIf6oNpGl74 + topic: Responsive srcset images with imgix + year: 2016 + +- speaker: Michael Lee + twitter_handle: michaelsoolee + youtube_id: F4bJRLEvXIc + topic: Jekyll, Your Website's Baseplate + year: 2016 + +- speaker: Paul Webb + twitter_handle: NetOpWibby + youtube_id: BRB5DgAE5nM + topic: Deploy Jekyll Like A Boss + year: 2016 + +- speaker: Tom Johnson + twitter_handle: tomjohnson + youtube_id: nq1AUB72GCQ + topic: Overcoming challenges in using Jekyll for documentation projects + year: 2016 + +- speaker: Pieter Roozen + twitter_handle: Pieter_Roozen + youtube_id: moQP0SqEPsw + topic: Jekyll As An API Endpoint + year: 2019 + +- speaker: Chen Hui Jing + twitter_handle: hj_chen + youtube_id: CERXESTZ5w4 + topic: Why I love Jekyll Data Files + year: 2019 + +- speaker: Chris Ferdinandi + twitter_handle: ChrisFerdinandi + youtube_id: vR1aI_kQ4-A + topic: The Lean Web + year: 2019 + +- speaker: Catherine Roebuck + twitter_handle: + youtube_id: zTAP1m1BaDM + topic: Jekyll For City Government + year: 2019 + +- speaker: Joost van der Schee + twitter_handle: jhvanderschee + youtube_id: ztJJ1GSlYgI + topic: "Jekyll Codex - Jekyll for front-end developers" + year: 2019 + +- speaker: Matthew Loberg + twitter_handle: mloberg + youtube_id: 6eiAjAtSGqw + topic: Leverage AWS S3 And CloudFront To Deploy Blazing Fast Jekyll Sites + year: 2019 + +- speaker: George Phillips + twitter_handle: gphillips_nz + youtube_id: nEvdOwFJBVc + topic: Structuring Jekyll Sites For Enterprise Design Systems + year: 2019 diff --git a/docs/_data/permalinks.yml b/docs/_data/permalinks.yml new file mode 100644 index 00000000000..1e548860877 --- /dev/null +++ b/docs/_data/permalinks.yml @@ -0,0 +1,139 @@ +placeholders: + - name: year + desc: >- + Year from the post's filename with four digits. May be overridden via the document's + date front matter. + - name: short_year + desc: >- + Year from the post's filename without the century. (00..99) May be overridden via the + document's date front matter. + - name: month + desc: >- + Month from the post's filename. (01..12) May be overridden via the document's + date front matter. + - name: i_month + desc: >- + Month without leading zeros from the post's filename. May be overridden via the document's + date front matter. + - name: short_month + desc: >- + Three-letter month abbreviation, e.g. "Jan". + - name: long_month + intro_ver: "4.0" + desc: >- + Full month name, e.g. "January". + - name: day + desc: >- + Day of the month from the post's filename. (01..31) May be overridden via the document's + date front matter. + - name: i_day + desc: >- + Day of the month without leading zeros from the post's filename. May be overridden via the + document's date front matter. + - name: y_day + desc: >- + Ordinal day of the year from the post's filename, with leading zeros. (001..366) + - name: w_year + intro_ver: "4.0" + desc: >- + Week year which may differ from the month year for up to three days at the start of January + and end of December + - name: week + intro_ver: "4.0" + desc: >- + Week number of the current year, starting with the first week having a majority of its days + in January. (01..53) + - name: w_day + intro_ver: "4.0" + desc: >- + Day of the week, starting with Monday. (1..7) + - name: short_day + intro_ver: "4.0" + desc: >- + Three-letter weekday abbreviation, e.g. "Sun". + - name: long_day + intro_ver: "4.0" + desc: >- + Weekday name, e.g. "Sunday". + - name: hour + desc: >- + Hour of the day, 24-hour clock, zero-padded from the post's date front matter. (00..23) + - name: minute + desc: >- + Minute of the hour from the post's date front matter. (00..59) + - name: second + desc: >- + Second of the minute from the post's date front matter. (00..59) + - name: title + desc: >- + Title from the document's filename. May be overridden via the document's + slug front matter. Preserves case from the source. + - name: slug + desc: >- + Slugified title from the document's filename (any character except numbers and letters is + replaced as hyphen). May be overridden via the document's slug front matter. + - name: categories + desc: >- + The specified categories for this post. If a post has multiple categories, Jekyll will create + a hierarchy (e.g. /category1/category2). Also Jekyll automatically parses out + double slashes in the URLs, so if no categories are present, it will ignore this. + - name: slugified_categories + intro_ver: "4.1" + desc: >- + The specified categories for this post but slugified. If a category is a composite of + multiple words, Jekyll will downcase all alphabets and replace any non-alphanumeric character + with a hyphen. (e.g. "Work 2 Progress" will be converted into + "work-2-progress"). If a post has multiple categories, Jekyll will create + a hierarchy (e.g. /work-2-progress/category2). Also Jekyll automatically parses + out double slashes in the URLs, so if no categories are present, it will ignore this. + - name: output_ext + desc: >- + Extension of the output file. (Included by default and usually unnecessary.) + +builtin_formats: + - name: date + format: "/:categories/:year/:month/:day/:title:output_ext" + - name: pretty + format: "/:categories/:year/:month/:day/:title/" + - name: ordinal + format: "/:categories/:year/:y_day/:title:output_ext" + - name: weekdate + intro_ver: "4.0" + format: "/:categories/:year/W:week/:short_day/:title:output_ext" + note: "W will be prefixed to the value of :week" + - name: none + format: "/:categories/:title:output_ext" + +types: + documents: + - name: collection + desc: >- + Label of the containing collection. + - name: path + desc: >- + Path to the document relative to the collection's directory, including base filename of the document. + However, does not include the file extension. + - name: name + desc: >- + The document's base filename but slugified: downcased and every sequence of non-alphanumeric character + (including spaces) replaced by a hyphen. + - name: title + desc: >- + Takes on the value of front matter key slug if defined for the document. Otherwise takes + on the string value generated from the document's base filename by piping through the slugify + filter method with pretty option.
+ Regardless of the value taken, the case of the alphabets are preserved instead of being replaced with + lowercase counterparts. + - name: output_ext + desc: >- + Extension of the output file. (Included by default and usually unnecessary.) + pages: + - name: path + desc: >- + Path between the source directory and the base filename of the page. + - name: basename + desc: >- + The page's base filename. + - name: output_ext + desc: >- + Extension of the output file. (Included by default and usually unnecessary.) diff --git a/docs/_data/primary_nav.yml b/docs/_data/primary_nav.yml new file mode 100644 index 00000000000..02ff6e99a79 --- /dev/null +++ b/docs/_data/primary_nav.yml @@ -0,0 +1,15 @@ +- title: Home + link: / + show_on_mobile: true +- title: Docs + link: /docs/ + show_on_mobile: true +- title: Resources + link: /resources/ + show_on_mobile: true +- title: Showcase + link: /showcase/ + show_on_mobile: false +- title: News + link: /news/ + show_on_mobile: true diff --git a/docs/_data/ruby.yml b/docs/_data/ruby.yml new file mode 100644 index 00000000000..423ff405648 --- /dev/null +++ b/docs/_data/ruby.yml @@ -0,0 +1,3 @@ +min_version: 2.7.0 +current_version: 3.4.1 +current_version_output: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) diff --git a/docs/_data/showcase.yml b/docs/_data/showcase.yml new file mode 100644 index 00000000000..6074f588759 --- /dev/null +++ b/docs/_data/showcase.yml @@ -0,0 +1,308 @@ +- name: Tom Preston Werner Blog + url: https://tom.preston-werner.com/ + image: tom-preston-werner.png + categories: + - personal + - blog + +# - name: White House Social and Behavioral Sciences Team +# url: https://sbst.gov/ +# image: sbst.png +# categories: +# - government + +- name: SiteLeaf + url: https://www.siteleaf.com/ + image: siteleaf.png + categories: + - software + - marketing-site + +- name: CloudCannon + url: https://cloudcannon.com/ + image: cloudcannon.png + categories: + - software + - marketing-site + +- name: Vesterheim Norwegian-American Museum + url: https://vesterheim.org/ + image: vesterheim.png + categories: + - marketing-site + +- name: KOTN + url: https://kotn.com/ + image: kotn.png + categories: + - marketing-site + +- name: MvvmCross + url: https://www.mvvmcross.com/ + image: mvvm.png + categories: + - software + - marketing-site + +- name: Vidgrid + url: https://www.vidgrid.com/ + image: vidgrid.png + categories: + - software + - marketing-site + +- name: Bitcoin + url: https://bitcoin.org/ + image: bitcoin.png + categories: + - software + - marketing-site + +- name: Mapwize + url: https://www.mapwize.io/ + image: mapwize.png + categories: + - software + - marketing-site + +- name: Auth0 Blog + url: https://auth0.com/blog/ + image: auth0-blog.png + categories: + - software + - blog + +- name: Freedom of Information Act + url: https://www.foia.gov/ + image: foia-gov.png + categories: + - government + +- name: "Art & About Sydney" + url: https://www.artandabout.com.au/ + image: art-sydney.png + categories: + - government + +- name: Passbolt Help + url: https://help.passbolt.com/ + image: passbolt-help.png + categories: + - knowledgebase + +- name: We are COLLINS + url: https://www.wearecollins.com/ + image: collins.png + categories: + - agency + +- name: Lightburn + url: https://lightburn.co/ + image: lightburn.png + categories: + - agency + +- name: italia.it + url: https://developers.italia.it/ + image: italia-it.png + categories: + - community + +- name: Sydney New Years Eve + url: https://www.sydneynewyearseve.com/ + image: nsw.png + categories: + - government + +- name: Login.gov + url: https://login.gov/ + image: login-gov.png + categories: + - government + +- name: plainlanguage.gov + url: https://plainlanguage.gov/ + image: plainlanguage-gov.png + categories: + - government + +- name: U.S. Web Design Standards + url: https://designsystem.digital.gov/ + image: uswds.png + categories: + - government + +- name: Grantmaker Search + url: https://www.grantmakers.io/ + image: grantmakers.png + categories: + - marketing-site + +- name: Rehan Butt + url: https://rehanbutt.com/ + image: rehn.png + categories: + - personal + - portfolio + +- name: The Markdown Guide + url: https://www.markdownguide.org/ + image: markdown-guide.png + categories: + - knowledgebase + +- name: Probot + url: https://probot.github.io/ + image: probot.png + categories: + - documentation + +- name: Matt Grey + url: https://himatt.com/ + image: matt-grey.png + categories: + - personal + - portfolio + +- name: Lattice + url: https://lattice.com/ + image: lattice.png + categories: + - software + - marketing-site + +- name: MailTape + url: https://www.mailta.pe/ + image: mailtape.png + categories: + - other + +- name: Digital Democracy + url: https://www.digital-democracy.org/ + image: digital-democracy.png + categories: + - other + +- name: HTML Reference + url: https://htmlreference.io/ + image: htmlreference.png + categories: + - documentation + +- name: CSS Reference + url: https://cssreference.io/ + image: cssreference.png + categories: + - documentation + +- name: Chain + url: https://www.chain.com/ + image: chain.png + categories: + - marketing-site + +- name: IBM MobileFirst Foundation + url: https://mobilefirstplatform.ibmcloud.com/ + image: ibm-mobile-foundation.png + categories: + - documentation + +- name: "18F" + url: https://18f.gsa.gov/ + image: 18f.png + categories: + - agency + - government + +- name: Development Seed + url: https://developmentseed.org/ + image: development-seed.png + categories: + - agency + +- name: Isomer - Singapore Government Static Websites + url: https://isomer.gov.sg/ + image: isomer.png + categories: + - government + +- name: French Government Digital Services + url: https://beta.gouv.fr/ + image: beta-gouv-fr.png + categories: + - government + +- name: Paris Call for Trust and Security in Cyberspace + url: https://pariscall.international/ + image: appel-de-paris.png + categories: + - government + +- name: TwitchCon + url: https://www.twitchcon.com/ + image: twitchcon.png + categories: + - marketing-site + - conference + +- name: UN World Statistics + url: https://worldstatisticsday.org/ + image: world-statistics-day.png + categories: + - government + +- name: Netflix Devices + url: https://devices.netflix.com/ + image: netflix.png + categories: + - marketing-site + +- name: Twitch Developer Documentation + url: https://dev.twitch.tv/ + image: twitch-developers.png + categories: + - marketing-site + - documentation + +- name: Yeoman + url: https://yeoman.io/ + image: yeoman.png + categories: + - open-source + - marketing-site + +- name: Release Management Blog + url: https://release.mozilla.org/ + image: mozilla-release-blog.png + categories: + - software + - blog + +- name: frame.ai + url: https://frame.ai/ + image: frame-ai.png + categories: + - software + - marketing-site + +- name: Spotify for Developers + url: https://developer.spotify.com + image: spotify-developers.png + categories: + - marketing-site + - documentation + - software + +- name: Sketch + url: https://www.sketch.com/ + image: sketch.png + categories: + - software + - marketing-site + +- name: Ruby on Rails + url: https://rubyonrails.org/ + image: ruby-on-rails.png + categories: + - marketing-site + - documentation diff --git a/docs/_data/tutorials.yml b/docs/_data/tutorials.yml new file mode 100644 index 00000000000..d0bdad2a597 --- /dev/null +++ b/docs/_data/tutorials.yml @@ -0,0 +1,14 @@ +- title: Tutorials + tutorials: + - home + - video-walkthroughs + - navigation + - orderofinterpretation + - custom-404-page + - convert-site-to-jekyll + - using-jekyll-with-bundler + - csv-to-table + +#- title: Another section +# tutorials: +# - sample diff --git a/site/_docs/assets.md b/docs/_docs/assets.md similarity index 64% rename from site/_docs/assets.md rename to docs/_docs/assets.md index 202ade0e58b..2cba9c95577 100644 --- a/site/_docs/assets.md +++ b/docs/_docs/assets.md @@ -1,22 +1,22 @@ --- -layout: docs title: Assets permalink: /docs/assets/ --- -Jekyll provides built-in support for Sass and can work with CoffeeScript via -a Ruby gem. In order to use them, you must first create a file with the -proper extension name (one of `.sass`, `.scss`, or `.coffee`) and start the -file with two lines of triple dashes, like this: +Jekyll provides built-in support for [Sass](https://sass-lang.com/) +and can work with [CoffeeScript](https://coffeescript.org/) via a Ruby gem. +In order to use them, you must first create a file with the proper extension +name (one of `.sass`, `.scss`, or `.coffee`) and +***start the file with two lines of triple dashes***, like this: -{% highlight sass %} +```sass --- --- // start content .my-definition font-size: 1.2em -{% endhighlight %} +``` Jekyll treats these files the same as a regular page, in that the output file will be placed in the same directory that it came from. For instance, if you @@ -26,9 +26,9 @@ will process it and put it in your site's destination folder under
Jekyll processes all Liquid filters and tags in asset files
-

If you are using Mustache +

If you are using Mustache or another JavaScript templating language that conflicts with - the Liquid template syntax, you + the Liquid template syntax, you will need to place {% raw %} and {% endraw %} tags around your code.

@@ -43,18 +43,17 @@ them to be in the output file, such as `/css`. For an example, take a look at [this example site using Sass support in Jekyll][example-sass]. If you are using Sass `@import` statements, you'll need to ensure that your -`sass_dir` is set to the base directory that contains your Sass files. You -can do that thusly: +`sass_dir` is set to the base directory that contains your Sass files: -{% highlight yaml %} +```yaml sass: sass_dir: _sass -{% endhighlight %} +``` The Sass converter will default the `sass_dir` configuration option to `_sass`. -[example-sass]: https://github.com/jekyll/jekyll-sass-converter/tree/master/example +[example-sass]: https://github.com/jekyll/jekyll-sass-converter/tree/master/docs
The sass_dir is only used by Sass
@@ -62,8 +61,8 @@ The Sass converter will default the `sass_dir` configuration option to Note that the sass_dir becomes the load path for Sass imports, nothing more. This means that Jekyll does not know about these files - directly, so any files here should not contain the YAML Front Matter as - described above nor will they be transformed as described above. This + directly. Any files here should not contain the empty front matter as + described above. If they do, they'll not be transformed as described above. This folder should only contain imports.

@@ -72,22 +71,24 @@ The Sass converter will default the `sass_dir` configuration option to You may also specify the output style with the `style` option in your `_config.yml` file: -{% highlight yaml %} +```yaml sass: style: compressed -{% endhighlight %} +``` These are passed to Sass, so any output style options Sass supports are valid here, too. +For more information on Sass configuration options, see the [Sass configuration]({{ '/docs/configuration/sass/' | relative_url }}) docs. ## Coffeescript -To enable Coffeescript in Jekyll 3.0 and up you must - * Install the `jekyll-coffeescript` gem - * Ensure that your `_config.yml` is up-to-date and includes the following +To enable Coffeescript in Jekyll 3.0 and up you must -{% highlight yaml %} -gems: - - jekyll-coffeescript -{% endhighlight %} +* Install the `jekyll-coffeescript` gem +* Ensure that your `_config.yml` is up-to-date and includes the following: + +```yaml +plugins: + - jekyll-coffeescript +``` diff --git a/docs/_docs/code_of_conduct.md b/docs/_docs/code_of_conduct.md new file mode 100644 index 00000000000..a0f529976d5 --- /dev/null +++ b/docs/_docs/code_of_conduct.md @@ -0,0 +1,82 @@ +--- +title: Code of Conduct +permalink: "/docs/code_of_conduct/" +note: This file is autogenerated. Edit /.github/CODE_OF_CONDUCT.markdown instead. +redirect_from: "/conduct/index.html" +editable: false +--- + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [olivia@jekyllrb.com](mailto:olivia@jekyllrb.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/docs/_docs/collections.md b/docs/_docs/collections.md new file mode 100644 index 00000000000..60813278999 --- /dev/null +++ b/docs/_docs/collections.md @@ -0,0 +1,392 @@ +--- +title: Collections +permalink: /docs/collections/ +--- + +Collections are a great way to group related content like members of a team or +talks at a conference. + +## Setup + +To use a Collection you first need to define it in your `_config.yml`. For +example here's a collection of staff members: + +```yaml +collections: + - staff_members +``` + +In this case `collections` is defined as a sequence (i.e., array) with no additional metadata defined for each collection. +You can optionally specify metadata for your collection by defining `collections` as a mapping (i.e., hashmap) instead of sequence, and then defining additional fields in it: + +```yaml +collections: + staff_members: + people: true +``` + +{: .note .info} +When defining a collection as a sequence, its pages will not be rendered by +default. To enable this, output: true must be specified on the +collection, which requires defining the collection as a mapping. For more +information, see the section Output. + +
+
Gather your collections {%- include docs_version_badge.html version="3.7.0" -%}
+ +

You can optionally specify a directory to store all your collections in the same place with collections_dir: my_collections.

+ +

Then Jekyll will look in my_collections/_books for the books collection, and + in my_collections/_recipes for the recipes collection.

+
+ +
+
Be sure to move drafts and posts into custom collections directory
+ +

If you specify a directory to store all your collections in the same place with collections_dir: my_collections, then you will need to move your _drafts and _posts directory to my_collections/_drafts and my_collections/_posts. Note that, the name of your collections directory cannot start with an underscore (`_`).

+
+ +## Add content + +Create a corresponding folder (e.g. `/_staff_members`) and add +documents. Front matter is processed if the front matter exists, and everything +after the front matter is pushed into the document's `content` attribute. If no front +matter is provided, Jekyll will consider it to be a [static file]({{ '/docs/static-files/' | relative_url }}) +and the contents will not undergo further processing. If front matter is provided, +Jekyll will process the file contents into the expected output. + +Regardless of whether front matter exists or not, Jekyll will write to the destination +directory (e.g. `_site`) only if `output: true` has been set in the collection's +metadata. + +For example here's how you would add a staff member to the collection set above. +The filename is `./_staff_members/jane.md` with the following content: + +```markdown +--- +name: Jane Doe +position: Developer +--- +Jane has worked on Jekyll for the past *five years*. +``` + + + Do note that in spite of being considered as a collection internally, the above + doesn't apply to [posts](/docs/posts/). Posts with a valid filename format will be + marked for processing even if they do not contain front matter. + + +
+
Be sure to name your directories correctly
+

+The folder must be named identically to the collection you defined in +your _config.yml file, with the addition of the preceding _ character. +

+
+ +## Output + +Now you can iterate over `site.staff_members` on a page and output the content +for each staff member. Similar to posts, the body of the document is accessed +using the `content` variable: + +{% raw %} +```liquid +{% for staff_member in site.staff_members %} +

{{ staff_member.name }} - {{ staff_member.position }}

+

{{ staff_member.content | markdownify }}

+{% endfor %} +``` +{% endraw %} + +If you'd like Jekyll to create a rendered page for each document in your +collection, you can set the `output` key to `true` in your collection +metadata in `_config.yml`: + +```yaml +collections: + staff_members: + output: true +``` + +You can link to the generated page using the `url` attribute: + +{% raw %} +```liquid +{% for staff_member in site.staff_members %} +

+ + {{ staff_member.name }} - {{ staff_member.position }} + +

+

{{ staff_member.content | markdownify }}

+{% endfor %} +``` +{% endraw %} + +## Future + +You can configure a collection to show future items by setting the `future` metadata to `true` in the collection's configuration. + +```yaml +collections: + staff_members: + future: true +``` + +## Permalinks + +There are special [permalink variables for collections]({{ '/docs/permalinks/#collections' | relative_url }}) to +help you control the output url for the entire collection. + +## Custom Sorting of Documents {%- include docs_version_badge.html version="4.0" -%} +{: #custom-sorting-of-documents} + +By default, two documents in a collection are sorted by their `date` attribute when both of them have the `date` key in their front matter. However, if either or both documents do not have the `date` key in their front matter, they are sorted by their respective paths. + +You can control this sorting via the collection's metadata. + +### Sort By Front Matter Key + +Documents can be sorted based on a front matter key by setting a `sort_by` metadata to the front matter key string. For example, +to sort a collection of tutorials based on key `lesson`, the configuration would be: + +```yaml +collections: + tutorials: + sort_by: lesson +``` + +The documents are arranged in the increasing order of the key's value. If a document does not have the front matter key defined +then that document is placed immediately after sorted documents. When multiple documents do not have the front matter key defined, +those documents are sorted by their dates or paths and then placed immediately after the sorted documents. + +### Manually Ordering Documents + +You can also manually order the documents by setting an `order` metadata with **the filenames listed** in the desired order. +For example, a collection of tutorials would be configured as: + +```yaml +collections: + tutorials: + order: + - hello-world.md + - introduction.md + - basic-concepts.md + - advanced-concepts.md +``` + +Any documents with filenames that do not match the list entry simply gets placed after the rearranged documents. If a document is +nested under subdirectories, include them in entries as well: + +```yaml +collections: + tutorials: + order: + - hello-world.md + - introduction.md + - concepts/basics.md + - concepts/advanced.md +``` + +If both metadata keys have been defined properly, `order` list takes precedence. + +## Liquid Attributes + +### Collections + +Collections are also available under `site.collections`, with the metadata +you specified in your `_config.yml` (if present) and the following information: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescription
+

label

+
+

+ The name of your collection, e.g. my_collection. +

+
+

docs

+
+

+ An array of documents. +

+
+

files

+
+

+ An array of static files in the collection. +

+
+

relative_directory

+
+

+ The path to the collection's source directory, relative to the site + source. +

+
+

directory

+
+

+ The full path to the collections's source directory. +

+
+

output

+
+

+ Whether the collection's documents will be output as individual + files. +

+
+
+ +
+
A Hard-Coded Collection
+

In addition to any collections you create yourself, the + posts collection is hard-coded into Jekyll. It exists whether + you have a _posts directory or not. This is something to note + when iterating through site.collections as you may need to + filter it out.

+

You may wish to use filters to find your collection: + {% raw %}{{ site.collections | where: "label", "myCollection" | first }}{% endraw %}

+
+ +
+
Collections and Time
+

Except for documents in hard-coded default collection posts, all documents in collections + you create, are accessible via Liquid irrespective of their assigned date, if any, and therefore renderable. +

+

Documents are attempted to be written to disk only if the concerned collection + metadata has output: true. Additionally, future-dated documents are only written if + site.future is also true. +

+

More fine-grained control over documents being written to disk can be exercised by setting + published: false (true by default) in the document's front matter. +

+
+ +### Documents + +In addition to any front matter provided in the document's corresponding +file, each document has the following attributes: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescription
+

content

+
+

+ The (unrendered) content of the document. If no front matter is + provided, Jekyll will not generate the file in your collection. If + front matter is used, then this is all the contents of the file + after the terminating + `---` of the front matter. +

+
+

output

+
+

+ The rendered output of the document, based on the + content. +

+
+

path

+
+

+ The full path to the document's source file. +

+
+

relative_path

+
+

+ The path to the document's source file relative to the site source. +

+
+

url

+
+

+ The URL of the rendered collection. The file is only written to the destination when the collection to which it belongs has output: true in the site's configuration. +

+
+

collection

+
+

+ The name of the document's collection. +

+
+

date

+
+

+ The date of the document's collection. +

+
+
diff --git a/docs/_docs/community/bug.md b/docs/_docs/community/bug.md new file mode 100644 index 00000000000..06d4ab5d8a8 --- /dev/null +++ b/docs/_docs/community/bug.md @@ -0,0 +1,8 @@ +--- +title: Report a bug +permalink: "/docs/community/bug/" +--- + +If you think you've found a bug within a Jekyll plugin, open an issue in that plugin's repository — First [look for the plugin on rubygems](https://rubygems.org/) then click on the `Homepage` link to access the plugin repository. + +If you think you've found a bug within Jekyll itself, [open an issue](https://github.com/jekyll/jekyll/issues/new). diff --git a/docs/_docs/community/community.md b/docs/_docs/community/community.md new file mode 100644 index 00000000000..59d365ad952 --- /dev/null +++ b/docs/_docs/community/community.md @@ -0,0 +1,44 @@ +--- +title: Community +permalink: /docs/community/ +redirect_from: "/help/index.html" +--- + +## Jekyll Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +Read the full [code of conduct]({{ '/docs/conduct/' | relative_url }}) + +## Reporting Security Vulnerabilities + +Find something in our codebase that could be exploited by malicious elements? + +Consult our [Security Policy]({{ '/docs/security/' | relative_url }}) to see if a product version is considered *outdated* and how to report +the situation responsibly. + +## Where to get support + +If you're looking for support for Jekyll, there are a lot of options: + +* Read the [Jekyll Documentation]({{ '/docs/' | relative_url }}) +* If you have a question about using Jekyll, start a discussion on the [Jekyll Forum](https://talk.jekyllrb.com/) or [StackOverflow](https://stackoverflow.com/questions/tagged/jekyll) +* Chat with Jekyllers — Join our [Gitter channel](https://gitter.im/jekyll/jekyll) or our IRC channel #jekyll on [Libera](irc://irc.libera.chat/#jekyll). + +There are a bunch of helpful community members on these services who are willing to point you in the right direction. + +**Reminder: Jekyll's issue tracker is not a support forum.** + +## Ways to contribute + +* [How to Contribute]({{ '/docs/contributing/' | relative_url }}) +* [How to file a bug]({{ '/docs/community/bug/' | relative_url }}) +* [Guide for maintaining Jekyll]({{ '/docs/maintaining/' | relative_url }}) + +## Jekyllconf + +[Watch videos]({{ '/jekyllconf/' | relative_url }}) from members of the Jekyll community speak about interesting use cases, tricks they’ve learned or meta Jekyll topics. + +## Jekyll on Twitter + +The [official Jekyll Twitter account](https://twitter.com/jekyllrb). diff --git a/docs/_docs/conduct.md b/docs/_docs/conduct.md new file mode 100644 index 00000000000..05f6b01538f --- /dev/null +++ b/docs/_docs/conduct.md @@ -0,0 +1,82 @@ +--- +title: Code of Conduct +permalink: "/docs/conduct/" +note: This file is autogenerated. Edit /CONDUCT.markdown instead. +redirect_from: "/conduct/index.html" +editable: false +--- + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at [olivia@jekyllrb.com](mailto:olivia@jekyllrb.com). All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +[https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/docs/_docs/configuration.md b/docs/_docs/configuration.md new file mode 100644 index 00000000000..6cf6685020e --- /dev/null +++ b/docs/_docs/configuration.md @@ -0,0 +1,19 @@ +--- +title: Configuration +permalink: /docs/configuration/ +--- + +Jekyll gives you a lot of flexibility to customize how it builds your site. These +options can either be specified in a `_config.yml` or `_config.toml` file placed +in your site’s root directory, or can be specified as flags for the `jekyll` +executable in the terminal. + +* [Configuration Options]({{ '/docs/configuration/options/' | relative_url }}) +* [Default Configuration]({{ '/docs/configuration/default/' | relative_url }}) +* [Front Matter Defaults]({{ '/docs/configuration/front-matter-defaults/' | relative_url }}) +* [Environments]({{ '/docs/configuration/environments/' | relative_url }}) +* [Markdown Options]({{ '/docs/configuration/markdown/' | relative_url }}) +* [Liquid Options]({{ '/docs/configuration/liquid/' | relative_url }}) +* [Sass/SCSS Options]({{ '/docs/configuration/sass/' | relative_url }}) +* [Webrick Options]({{ '/docs/configuration/webrick/' | relative_url }}) +* [Incremental Regeneration]({{ '/docs/configuration/incremental-regeneration/' | relative_url }}) diff --git a/docs/_docs/configuration/default.md b/docs/_docs/configuration/default.md new file mode 100644 index 00000000000..e96c5071e89 --- /dev/null +++ b/docs/_docs/configuration/default.md @@ -0,0 +1,89 @@ +--- +title: Default Configuration +permalink: "/docs/configuration/default/" +--- + +Jekyll runs with the following configuration options by default. Alternative +settings for these options can be explicitly specified in the configuration +file or on the command-line. + +
+
Be aware of directory paths
+

+ In general, make directory path values in configuration keys like plugins_dir relative to the current working directory, not the site source. The sass configuration key is an exception, where values must be relative to the site source. +

+
+ +```yaml +# Where things are +source : . +destination : ./_site +collections_dir : . +plugins_dir : _plugins # takes an array of strings and loads plugins in that order +layouts_dir : _layouts +data_dir : _data +includes_dir : _includes +sass: + sass_dir: _sass +collections: + posts: + output : true + +# Handling Reading +safe : false +include : [".htaccess"] +exclude : ["Gemfile", "Gemfile.lock", "node_modules", "vendor/bundle/", "vendor/cache/", "vendor/gems/", "vendor/ruby/"] +keep_files : [".git", ".svn"] +encoding : "utf-8" +markdown_ext : "markdown,mkdown,mkdn,mkd,md" +strict_front_matter : false + +# Filtering Content +show_drafts : null +limit_posts : 0 +future : false +unpublished : false + +# Plugins +whitelist : [] +plugins : [] + +# Conversion +markdown : kramdown +highlighter : rouge +lsi : false +excerpt_separator : "\n\n" +incremental : false + +# Serving +detach : false +port : 4000 +host : 127.0.0.1 +baseurl : "" # does not include hostname +show_dir_listing : false + +# Outputting +permalink : date +paginate_path : /page:num +timezone : null + +quiet : false +verbose : false +defaults : [] + +liquid: + error_mode : warn + strict_filters : false + strict_variables : false + +# Markdown Processors +kramdown: + auto_ids : true + entity_output : as_char + toc_levels : [1, 2, 3, 4, 5, 6] + smart_quotes : lsquo,rsquo,ldquo,rdquo + input : GFM + hard_wrap : false + footnote_nr : 1 + show_warnings : false +``` diff --git a/docs/_docs/configuration/environments.md b/docs/_docs/configuration/environments.md new file mode 100644 index 00000000000..6b06c84c75f --- /dev/null +++ b/docs/_docs/configuration/environments.md @@ -0,0 +1,49 @@ +--- +title: Environments +permalink: "/docs/configuration/environments/" +--- +In the `build` (or `serve`) arguments, you can specify a Jekyll environment +and value. The build will then apply this value in any conditional statements +in your content. + +For example, suppose you set this conditional statement in your code: + +{% raw %} +```liquid +{% if jekyll.environment == "production" %} + {% include disqus.html %} +{% endif %} +``` +{% endraw %} + +When you build your Jekyll site, the content inside the `if` statement won't be +run unless you also specify a `production` environment in the build command, +like this: + +```sh +JEKYLL_ENV=production jekyll build +``` + +Specifying an environment value allows you to make certain content available +only within specific environments. + +The default value for `JEKYLL_ENV` is `development`. Therefore if you omit +`JEKYLL_ENV` from the build arguments, the default value will be +`JEKYLL_ENV=development`. Any content inside +{% raw %}`{% if jekyll.environment == "development" %}`{% endraw %} tags will +automatically appear in the build. + +Your environment values can be anything you want (not just `development` or +`production`). Some elements you might want to hide in development +environments include Disqus comment forms or Google Analytics. Conversely, +you might want to expose an "Edit me in GitHub" button in a development +environment but not include it in production environments. + +By specifying the option in the build command, you avoid having to change +values in your configuration files when moving from one environment to another. + +{: .note} +To switch part of your config settings depending on the environment, use the +build command option, +for example --config _config.yml,_config_development.yml. Settings +in later files override settings in earlier files. diff --git a/docs/_docs/configuration/front-matter-defaults.md b/docs/_docs/configuration/front-matter-defaults.md new file mode 100644 index 00000000000..9f0aca81b7b --- /dev/null +++ b/docs/_docs/configuration/front-matter-defaults.md @@ -0,0 +1,153 @@ +--- +title: Front Matter Defaults +permalink: "/docs/configuration/front-matter-defaults/" +--- + +Using [front matter](/docs/front-matter/) is one way that you can specify configuration in the pages and posts for your site. Setting things like a default layout, or customizing the title, or specifying a more precise date/time for the post can all be added to your page or post front matter. + +Often times, you will find that you are repeating a lot of configuration options. Setting the same layout in each file, adding the same category - or categories - to a post, etc. You can even add custom variables like author names, which might be the same for the majority of posts on your blog. + +Instead of repeating this configuration each time you create a new post or page, Jekyll provides a way to set these defaults in the site configuration. To do this, you can specify site-wide defaults using the `defaults` key in the `_config.yml` file in your project's root directory. + +The `defaults` key holds an array of scope/values pairs that define what defaults should be set for a particular file path, and optionally, a file type in that path. + +Let's say that you want to add a default layout to all pages and posts in your site. You would add this to your `_config.yml` file: + +```yaml +defaults: + - + scope: + path: "" # an empty string here means all files in the project + values: + layout: "default" +``` + +
+
Stop and rerun `jekyll serve` command.
+

+ The _config.yml master configuration file contains global configurations + and variable definitions that are read once at execution time. Changes made to _config.yml + during automatic regeneration are not loaded until the next execution. +

+

+ Note Data Files are included and reloaded during automatic regeneration. +

+
+ +Here, we are scoping the `values` to any file that exists in the path `scope`. Since the path is set as an empty string, it will apply to **all files** in your project. You probably don't want to set a layout on every file in your project - like css files, for example - so you can also specify a `type` value under the `scope` key. + +```yaml +defaults: + - + scope: + path: "" # an empty string here means all files in the project + type: "posts" # previously `post` in Jekyll 2.2. + values: + layout: "default" +``` + +Now, this will only set the layout for files where the type is `posts`. +The different types that are available to you are `pages`, `posts`, `drafts` or any collection in your site. While `type` is optional, you must specify a value for `path` when creating a `scope/values` pair. + +As mentioned earlier, you can set multiple scope/values pairs for `defaults`. + +```yaml +defaults: + - + scope: + path: "" + type: "pages" + values: + layout: "my-site" + - + scope: + path: "projects" + type: "pages" # previously `page` in Jekyll 2.2. + values: + layout: "project" # overrides previous default layout + author: "Mr. Hyde" +``` + +With these defaults, all pages would use the `my-site` layout. Any html files that exist in the `projects/` +folder will use the `project` layout, if it exists. Those files will also have the `page.author` +[liquid variable]({{ '/docs/variables/' | relative_url }}) set to `Mr. Hyde`. + +```yaml +collections: + my_collection: + output: true + +defaults: + - + scope: + path: "" + type: "my_collection" # a collection in your site, in plural form + values: + layout: "default" +``` + +In this example, the `layout` is set to `default` inside the +[collection]({{ '/docs/collections/' | relative_url }}) with the name `my_collection`. + +### Glob patterns in Front Matter defaults + +It is also possible to use glob patterns (currently limited to patterns that contain `*`) when matching defaults. For example, it is possible to set specific layout for each `special-page.html` in any subfolder of `section` folder. {%- include docs_version_badge.html version="3.7.0" -%} + +```yaml +collections: + my_collection: + output: true + +defaults: + - + scope: + path: "section/*/special-page.html" + values: + layout: "specific-layout" +``` + +
+
Globbing and Performance
+

+ Please note that globbing a path is known to have a negative effect on + performance and is currently not optimized, especially on Windows. + Globbing a path will increase your build times in proportion to the size + of the associated collection directory. +

+
+ +### Precedence + +Jekyll will apply all of the configuration settings you specify in the `defaults` section of your `_config.yml` file. You can choose to override settings from other scope/values pair by specifying a more specific path for the scope. + +You can see that in the second to last example above. First, we set the default page layout to `my-site`. Then, using a more specific path, we set the default layout for pages in the `projects/` path to `project`. This can be done with any value that you would set in the page or post front matter. + +Finally, if you set defaults in the site configuration by adding a `defaults` section to your `_config.yml` file, you can override those settings in a post or page file. All you need to do is specify the settings in the post or page front matter. For example: + +```yaml +# In _config.yml +... +defaults: + - + scope: + path: "projects" + type: "pages" + values: + layout: "project" + author: "Mr. Hyde" + category: "project" +... +``` + +```yaml +# In projects/foo_project.md +--- +author: "John Smith" +layout: "foobar" +--- +The post text goes here... +``` + +The `projects/foo_project.md` would have the `layout` set to `foobar` instead +of `project` and the `author` set to `John Smith` instead of `Mr. Hyde` when +the site is built. diff --git a/docs/_docs/configuration/incremental-regeneration.md b/docs/_docs/configuration/incremental-regeneration.md new file mode 100644 index 00000000000..b538c374491 --- /dev/null +++ b/docs/_docs/configuration/incremental-regeneration.md @@ -0,0 +1,36 @@ +--- +title: Default Configuration +permalink: "/docs/configuration/incremental-regeneration/" +--- + +## Incremental Regeneration +
+
Incremental regeneration is still an experimental feature
+

+ While incremental regeneration will work for the most common cases, it will + not work correctly in every scenario. Please be extremely cautious when + using the feature, and report any problems not listed below by + opening an issue on GitHub. +

+
+ +Incremental regeneration helps shorten build times by only generating documents +and pages that were updated since the previous build. It does this by keeping +track of both file modification times and inter-document dependencies in the +`.jekyll-metadata` file. + +Under the current implementation, incremental regeneration will only generate a +document or page if either it, or one of its dependencies, is modified. Currently, +the only types of dependencies tracked are includes (using the +{% raw %}`{% include %}`{% endraw %} tag) and layouts. This means that plain +references to other documents (for example, the common case of iterating over +`site.posts` in a post listings page) will not be detected as a dependency. + +To remedy some of these shortfalls, putting `regenerate: true` in the front-matter +of a document will force Jekyll to regenerate it regardless of whether it has been +modified. Note that this will generate the specified document only; references +to other documents' contents will not work since they won't be re-rendered. + +Incremental regeneration can be enabled via the `--incremental` flag (`-I` for +short) from the command-line or by setting `incremental: true` in your +configuration file. diff --git a/docs/_docs/configuration/liquid.md b/docs/_docs/configuration/liquid.md new file mode 100644 index 00000000000..51096450960 --- /dev/null +++ b/docs/_docs/configuration/liquid.md @@ -0,0 +1,38 @@ +--- +title: Liquid Options +permalink: "/docs/configuration/liquid/" +--- +Liquid's response to errors can be configured by setting `error_mode`. The +options are + +- `lax` --- Ignore all errors. +- `warn` --- Output a warning on the console for each error. (default) +- `strict` --- Output an error message and stop the build. + +Within _config.yml, the default configuration is as follows: + +```yaml +liquid: + error_mode: warn +``` + +The above example depicts the "warn" value, which is already set by default- `error_mode: warn`. This results in any issues being called out during the build process however will continue to build if possible. + +You can also configure Liquid's renderer to catch non-assigned variables and +non-existing filters by setting `strict_variables` and / or `strict_filters` +to `true` respectively. {% include docs_version_badge.html version="3.8.0" %} + +Do note that while `error_mode` configures Liquid's parser, the `strict_variables` +and `strict_filters` options configure Liquid's renderer and are consequently +orthogonal. + +An example of setting these variables within _config.yml is as follows: + +```yaml +liquid: + error_mode: strict + strict_variables: true + strict_filters: true +``` + +Configuring as described above will stop your build/serve from happening and call out the offending error and halt. This is helpful when desiring to catch liquid-related issues by stopping the build or serve process and allowing you to deal with any issues. diff --git a/docs/_docs/configuration/markdown.md b/docs/_docs/configuration/markdown.md new file mode 100644 index 00000000000..9cd65a3381d --- /dev/null +++ b/docs/_docs/configuration/markdown.md @@ -0,0 +1,97 @@ +--- +title: Markdown Options +permalink: "/docs/configuration/markdown/" +--- +The various Markdown renderers supported by Jekyll sometimes have extra options +available. + +## Kramdown + +Kramdown is the default Markdown renderer for Jekyll, and often works well with no additional configuration. However, it does support many configuration options. + +### Kramdown Processor + +By default, Jekyll uses the [GitHub Flavored Markdown (GFM) processor](https://github.com/kramdown/parser-gfm) for Kramdown. (Specifying `input: GFM` is fine, but redundant.) GFM supports a couple additional Kramdown options, documented by [kramdown-parser-gfm](https://github.com/kramdown/parser-gfm). These options can be used directly in your Kramdown Jekyll config, like this: + +```yaml +kramdown: + gfm_quirks: [paragraph_end] +``` + +You can also change the processor used by Kramdown (as specified for the `input` key in the [Kramdown RDoc](https://kramdown.gettalong.org/rdoc/Kramdown/Document.html#method-c-new)). For example, to use the non-GFM Kramdown processor in Jekyll, add the following to your configuration. + +```yaml +kramdown: + input: Kramdown +``` + +Documentation for Kramdown parsers is available in the [Kramdown docs](https://kramdown.gettalong.org/parser/kramdown.html). If you use a Kramdown parser other than Kramdown or GFM, you'll need to add the gem for it. + +### Syntax Highlighting (CodeRay) + +To use the [CodeRay](http://coderay.rubychan.de/) syntax highlighter with Kramdown, you need to add a dependency on the `kramdown-syntax-coderay` gem. For example, `bundle add kramdown-syntax-coderay`. Then, you'll be able to specify CodeRay in your `syntax_highlighter` config: + +```yaml +kramdown: + syntax_highlighter: coderay +``` + +CodeRay supports several of its own configuration options, documented in the [kramdown-syntax-coderay docs](https://github.com/kramdown/syntax-coderay) which can be passed as `syntax_highlighter_opts` like this: + +```yaml +kramdown: + syntax_highlighter: coderay + syntax_highlighter_opts: + line_numbers: table + bold_every: 5 +``` + +### Advanced Kramdown Options + +Kramdown supports a variety of other relatively advanced options such as `header_offset` and `smart_quotes`. These are documented in the [Kramdown configuration documentation](https://kramdown.gettalong.org/options.html) and can be added to your Kramdown config like this: + +```yaml +kramdown: + header_offset: 2 +``` + +
+
There are several unsupported kramdown options
+

+ Please note that Jekyll uses Kramdown's HTML converter. Kramdown options used only by other converters, such as remove_block_html_tags (used by the RemoveHtmlTags converter), will not work. +

+
+ +## CommonMark + +[CommonMark](https://commonmark.org/) is a rationalized version of Markdown syntax, implemented in C and thus faster than default Kramdown implemented in Ruby. It [slightly differs](https://github.com/commonmark/CommonMark#differences-from-original-markdown) from original Markdown and does not support all the syntax elements implemented in Kramdown, like [Block Inline Attribute Lists](https://kramdown.gettalong.org/syntax.html#block-ials). + +It comes in two flavors: basic CommonMark with [jekyll-commonmark](https://github.com/jekyll/jekyll-commonmark) plugin and [GitHub Flavored Markdown supported by GitHub Pages](https://github.com/github/jekyll-commonmark-ghpages). + +### Custom Markdown Processors + +If you're interested in creating a custom markdown processor, you're in luck! Create a new class in the `Jekyll::Converters::Markdown` namespace: + +```ruby +class Jekyll::Converters::Markdown::MyCustomProcessor + def initialize(config) + require 'funky_markdown' + @config = config + rescue LoadError + STDERR.puts 'You are missing a library required for Markdown. Please run:' + STDERR.puts ' $ [sudo] gem install funky_markdown' + raise FatalException.new("Missing dependency: funky_markdown") + end + + def convert(content) + ::FunkyMarkdown.new(content).convert + end +end +``` + +Once you've created your class and have it properly set up either as a plugin +in the `_plugins` folder or as a gem, specify it in your `_config.yml`: + +```yaml +markdown: MyCustomProcessor +``` diff --git a/docs/_docs/configuration/options.md b/docs/_docs/configuration/options.md new file mode 100644 index 00000000000..7713f0ccc86 --- /dev/null +++ b/docs/_docs/configuration/options.md @@ -0,0 +1,162 @@ +--- +title: Configuration Options +permalink: "/docs/configuration/options/" +--- + +The tables below list the available settings for Jekyll, and the various options (specified in the configuration file) and flags (specified on the command-line) that control them. + +### Global Configuration + +
+ + + + + + + + + {% for setting in site.data.config_options.global %} + + + + + {% endfor %} + + + + + +
Setting + Options and Flags +
+

+ {{ setting.name }} + {% if setting.version-badge %} + {{ setting.version-badge }} + {% endif %} +

+

{{ setting.description }}

+
+

{{ setting.option }}

+ {% if setting.flag %} +

{{ setting.flag }}

+ {% endif %} +
+

Defaults

+

+ Set defaults for front matter + variables. +

+
+

see below

+
+
+ +
+
Destination folders are cleaned on site builds
+

+ The contents of <destination> are automatically + cleaned, by default, when the site is built. Files or folders that are not + created by your site will be removed. Some files could be retained + by specifying them within the <keep_files> configuration directive. +

+

+ Do not use an important location for <destination>; instead, use it as + a staging area and copy files from there to your web server. +

+
+ +### Build Command Options + +
+ + + + + + + + + {% for setting in site.data.config_options.build %} + + + + + {% endfor %} + +
SettingOptions and Flags
+

+ {{ setting.name }} + {% if setting.version-badge %} + {{ setting.version-badge }} + {% endif %} +

+

{{ setting.description }}

+
+ {% if setting.option %}

{{ setting.option }}

{% endif %} + {% if setting.flag %}

{{ setting.flag }}

{% endif %} +
+
+ +### Serve Command Options + +In addition to the options below, the `serve` sub-command can accept any of the options +for the `build` sub-command, which are then applied to the site build which occurs right +before your site is served. + +
+ + + + + + + + + {% for setting in site.data.config_options.serve %} + + + + + {% endfor %} + +
SettingOptions and Flags
+

+ {{ setting.name }} + {% if setting.version-badge %} + {{ setting.version-badge }} + {% endif %} +

+

{{ setting.description }}

+
+ {% if setting.option %} +

{{ setting.option }}

+ {% elsif setting.options %} +

+ {% for option in setting.options %} + {{ option }}
+ {% endfor %} +

+ {% endif %} + {% if setting.flag %} +

{{ setting.flag }}

+ {% elsif setting.flags %} +

+ {% for flag in setting.flags %} + {{ flag }}
+ {% endfor %} +

+ {% endif %} +
+
+ +
+
Do not use tabs in configuration files
+

+ This will either lead to parsing errors, or Jekyll will revert to the + default settings. Use spaces instead. +

+
diff --git a/docs/_docs/configuration/sass.md b/docs/_docs/configuration/sass.md new file mode 100644 index 00000000000..b11252d03d0 --- /dev/null +++ b/docs/_docs/configuration/sass.md @@ -0,0 +1,18 @@ +--- +title: Sass/SCSS Options +permalink: "/docs/configuration/sass/" +--- + +Jekyll comes bundled with [jekyll-sass-converter](https://github.com/jekyll/jekyll-sass-converter) plugin. By default, Jekyll will look for Sass partials in the `_sass` directory relative to your site's `source` directory. + +You can further configure the plugin by adding options to your Jekyll config under the `sass` attribute. See the [plugin's documentation](https://github.com/jekyll/jekyll-sass-converter#usage) for details and for its default values. + +{:.note .info} +If you see a warning in VSCode regarding `@import "main";`, you may ignore it as the same does not affect the functionality of the SCSS code in Jekyll. However, Jekyll 4 does not allow importing a `main` sass partial (`_sass/main.scss`) from a sass page of a same name, viz. `css/main.scss`. + +
+

+ Note that directory paths specified in the sass configuration + are resolved relative to your site's source, not relative to the location of the _config.yml file. +

+
diff --git a/docs/_docs/configuration/webrick.md b/docs/_docs/configuration/webrick.md new file mode 100644 index 00000000000..c760b850cf9 --- /dev/null +++ b/docs/_docs/configuration/webrick.md @@ -0,0 +1,20 @@ +--- +title: WEBrick Options +permalink: "/docs/configuration/webrick/" +--- +You can provide custom headers for your site by adding them to `_config.yml` + +```yaml +# File: _config.yml +webrick: + headers: + My-Header: My-Value + My-Other-Header: My-Other-Value +``` + +### Defaults + +Jekyll provides by default `Content-Type` and `Cache-Control` response +headers: one dynamic in order to specify the nature of the data being served, +the other static in order to disable caching so that you don't have to fight +with Chrome's aggressive caching when you are in development mode. diff --git a/docs/_docs/continuous-integration/buddyworks.md b/docs/_docs/continuous-integration/buddyworks.md new file mode 100644 index 00000000000..e342ca97f40 --- /dev/null +++ b/docs/_docs/continuous-integration/buddyworks.md @@ -0,0 +1,60 @@ +--- +title: "Buddy" +--- + +[Buddy][buddy-homepage] is a [Docker][docker-homepage]-based CI server that you can set up in 15-20 minutes to build, test, and deploy your Jekyll websites. It supports [GitHub][github-homepage], [Bitbucket][bitbucket-homepage], and [GitLab][gitlab-homepage] repositories, and can be installed on-premises or used in cloud. The following guide will show you how to set up a free environment to build and test your Jekyll project. + +[buddy-homepage]: https://buddy.works +[docker-homepage]: https://www.docker.com/ +[github-homepage]: https://github.com +[bitbucket-homepage]: https://bitbucket.org/ +[gitlab-homepage]: https://gitlab.com + +## 1. Getting started + +1. Log in at [https://buddy.works][buddy-homepage] with your GitHub/Bitbucket account or email +2. Choose your Git provider and select or push your Jekyll Project +3. Create a new pipeline and set the trigger mode to 'On every push' +4. Add and configure the Jekyll action and save the pipeline + +## 2. How it works + +Whenever you make a push to the selected branch, the Jekyll action runs `jekyll build` in an isolated [Jekyll Docker image][jekyll-docker-image]. The output is generated to the `/filesystem` directory, and can be further deployed to FTP/SFTP and IaaS services. You can add your own commands, install additional packages, attach services, and run Selenium tests, as well as add other actions down the pipeline, eg. a Slack notification or an SSH script that will restart your server. + +[jekyll-docker-image]: https://hub.docker.com/r/jekyll/jekyll/ + +## 3. Using YAML for configuration + +If you prefer configuration as code over GUI, you can generate a `buddy.yml` that will create a pipeline with the Jekyll action once you push it to the target branch: + +```yaml +- pipeline: "Build and Deploy Jekyll site" + trigger_mode: "ON_EVERY_PUSH" + ref_name: "master" + actions: + - action: "Execute: jekyll build" + type: "BUILD" + docker_image_name: "jekyll/jekyll" + docker_image_tag: "latest" + execute_commands: + - "chown jekyll:jekyll $WORKING_DIR" + - "jekyll build" +``` + +## 4. Setting up on-premises server + +The self-hosted version of Buddy can be installed on any type of server supporting Docker, including [Linux][bw-linux], [Mac][bw-mac], [AWS EC2][bw-aws-ec2], [DigitalOcean][bw-digitalocean], and [Microsoft Azure][bw-azure]. + +[bw-linux]: https://buddy.works/knowledge/standalone/installation-linux +[bw-mac]: https://buddy.works/knowledge/standalone/installation-mac-osx +[bw-aws-ec2]: https://buddy.works/knowledge/standalone/installation-amazon-ec2 +[bw-digitalocean]: https://buddy.works/knowledge/standalone/installation-digitalocean +[bw-azure]: https://buddy.works/knowledge/standalone/installation-azure + +## 5. Questions? + +This entire guide is open-source. Go ahead and [edit it][jekyll-docs-ci-buddy] if you want to expand it or have a fix or [ask for help][jekyll-help] if you run into trouble and need assistance. Buddy also has an [online community][buddy-forum] for help. + +[jekyll-docs-ci-buddy]: https://github.com/jekyll/jekyll/edit/master/docs/_docs/continuous-integration/buddyworks.md +[jekyll-help]: https://jekyllrb.com/help/ +[buddy-forum]: https://forum.buddy.works/ diff --git a/docs/_docs/continuous-integration/circleci.md b/docs/_docs/continuous-integration/circleci.md new file mode 100644 index 00000000000..d2e317df181 --- /dev/null +++ b/docs/_docs/continuous-integration/circleci.md @@ -0,0 +1,137 @@ +--- +title: "CircleCI" +--- + +Building, testing, and deploying your Jekyll-generated website can quickly be done with [CircleCI][0], a continuous integration & delivery tool. CircleCI supports [GitHub][1] and [Bitbucket][2], and you can get started for free using an open-source or private repository. + +[0]: https://circleci.com/ +[1]: https://github.com/ +[2]: https://bitbucket.org/ + +## 1. Follow Your Project on CircleCI + +To start building your project on CircleCI, all you need to do is 'follow' your project from CircleCI's website: + +1. Visit the 'Add Projects' page +1. From the GitHub or Bitbucket tab on the left, choose a user or organization. +1. Find your project in the list and click 'Build project' on the right. +1. The first build will start on its own. You can start telling CircleCI how to build your project by creating a [.circleci/config.yml][3] file in the root of your repository. + +[3]: https://circleci.com/docs/2.0/configuration-reference/ + +## 2. Dependencies + +The easiest way to manage dependencies for a Jekyll project (with or without CircleCI) is via a [Gemfile][4]. You'd want to have Jekyll, any Jekyll plugins, [HTML Proofer](#html-proofer), and any other gems that you are using in the `Gemfile`. Don't forget to version `Gemfile.lock` as well. Here's an example `Gemfile`: + +[4]: http://bundler.io/gemfile.html + +```ruby +source 'https://rubygems.org' + +ruby '2.7.4' + +gem "jekyll" +gem "html-proofer" +``` + +```yaml + - step: + run: bundle install +``` + +## 3. Testing + +The most basic test that can be run is seeing if `jekyll build` actually works. This is a blocker, a dependency if you will, for other tests you might run on the generate site. So we'll run Jekyll, via Bundler, in the `dependencies` phase. + +```yaml + - step: + run: bundle exec jekyll build +``` + +### HTML Proofer + +With your site built, it's useful to run tests to check for valid HTML, broken links, etc. There's a few tools out there but [HTML Proofer][5] is popular amongst Jekyll users. We'll run it in the `test` phase with a few preferred flags. Check out the `html-proofer` [README][6] for all available flags, or run `htmlproofer --help` locally. + +[5]: https://github.com/gjtorikian/html-proofer +[6]: https://github.com/gjtorikian/html-proofer/blob/master/README.md#configuration + +```yaml + - step: + run: bundle exec htmlproofer ./_site --check-html --disable-external +``` + +## Complete Example .circleci/config.yml File + +The example `.circleci/config.yml` below demonstrates how to +deploy your Jekyll project to AWS. In order for this to work you would first have to set the +`S3_BUCKET_NAME` [environment variable](https://circleci.com/docs/2.0/env-vars/). + +```yaml +workflows: + test-deploy: + jobs: + - build + - deploy: + requires: + - build + filters: + branches: + only: master +version: 2.1 +jobs: + build: + docker: + - image: cimg/ruby:2.7.4 + environment: + BUNDLE_PATH: ~/repo/vendor/bundle + steps: + - checkout + - restore_cache: + keys: + - rubygems-v1-{% raw %}{{ checksum "Gemfile.lock" }}{% endraw %} + - rubygems-v1-fallback + - run: + name: Bundle Install + command: bundle check || bundle install + - save_cache: + key: rubygems-v1-{% raw %}{{ checksum "Gemfile.lock" }}{% endraw %} + paths: + - vendor/bundle + - run: + name: Jekyll build + command: bundle exec jekyll build + - run: + name: HTMLProofer tests + command: | + bundle exec htmlproofer ./_site \ + --allow-hash-href \ + --check-favicon \ + --check-html \ + --disable-external + - persist_to_workspace: + root: ./ + paths: + - _site + deploy: + docker: + - image: cimg/python:3.9.1 + environment: + S3_BUCKET_NAME: <> + steps: + - attach_workspace: + at: ./ + - run: + name: Install AWS CLI + command: pip install awscli --upgrade --user + - run: + name: Upload to s3 + command: ~/.local/bin/aws s3 sync ./_site s3://$S3_BUCKET_NAME/ --delete --acl public-read +``` + +## Questions? + +This entire guide is open-source. Go ahead and [edit it][7] if you have a fix or [ask for help][8] if you run into trouble and need some help. CircleCI also has an [online community][9] for help. + +[7]: https://github.com/jekyll/jekyll/edit/master/docs/_docs/continuous-integration/circleci.md +[8]: https://jekyllrb.com/help/ +[9]: https://discuss.circleci.com diff --git a/docs/_docs/continuous-integration/github-actions.md b/docs/_docs/continuous-integration/github-actions.md new file mode 100644 index 00000000000..64d2ac89f19 --- /dev/null +++ b/docs/_docs/continuous-integration/github-actions.md @@ -0,0 +1,138 @@ +--- +title: GitHub Actions +--- + +When building a Jekyll site with GitHub Pages, Jekyll runs in an environment restricted for security +reasons, yet containing numerous [whitelisted plugins and themes][ghp-whitelist] to make it simpler +to get a site set up. + +The only workaround to have control over the build environment and gemset yet use GitHub Pages to +host the site was previously by building elsewhere and pushing the built directory contents to the +`gh-pages` branch on your repository. + +However, GitHub now provides you with the option to use their in-house CI/CD product named +*GitHub Actions* to *build and deploy (host)* your Jekyll site with complete control over the build +environment and gemset. + +## Advantages of using Actions + +### Control over gemset + +- **Jekyll version** --- Instead of using the classic GitHub Pages-provided version specified in + the [Dependency versions][ghp-whitelist] list, you can use any version of Jekyll you want. + For example `{{ site.version }}`, or point directly to the repository via the Gemfile. +- **Plugins** --- You can use any Jekyll plugins irrespective of them being whitelisted by GitHub, + including any `*.rb` files placed in the `_plugins` directory of your site. +- **Themes** --- While using a custom theme is possible without Actions, it is now possible to use + themes depending on features introduced in newer versions of Jekyll. + +{: .note .info} +If you are migrating from the classic flow but want to keep using a GitHub-hosted theme, you may use +the [jekyll-remote-theme][remote-theme] plugin, add any required dependencies of your theme +(previously bundled by default) into your `_config.yml` and `Gemfile` and set the +`remote_theme: /` theme repository slug correctly in your `_config.yml`. + +### Workflow Management + +- **Customization** --- By creating a workflow file to run Actions, you can specify custom build + steps, use environment variables. +- **Logging** --- The build log is visible and can be tweaked to be verbose, so it is much easier to + debug errors using Actions. +- **Caching** --- The `ruby/setup-ruby` action makes it possible to cache installed gems + automatically instead of having to download the bundle on each build. + +## Workspace setup + +The first and foremost requirement is a Jekyll project hosted at GitHub. Choose an existing Jekyll +project or follow the [quickstart]({{ '/docs/' | relative_url }}) and push the repository to GitHub +if it is not hosted there already. + +The Jekyll site we'll be using for the rest of this page, initially consists of just a `_config.yml`, +an `index.md` page and a `Gemfile`. The contents are respectively: + +```yaml +# _config.yml + +title: "Jekyll Actions Demo" +``` + +{% raw %} + +```liquid +--- +--- + +Welcome to My Home Page + +{% assign date = '2020-04-13T10:20:00Z' %} + +- Original date - {{ date }} +- With timeago filter - {{ date | timeago }} +``` + +{% endraw %} + +```ruby +# Gemfile + +source 'https://rubygems.org' + +gem "jekyll", "~> 4.2" + +group :jekyll_plugins do + gem "jekyll-timeago", "~> 0.13.1" +end +``` + +{: .note .info} +The demo site uses Jekyll 4 and a [third-party plugin][timeago-plugin], both of which are currently +not whitelisted for use on GitHub pages. The plugin will allow us to describe how far back a date +was from today. e.g. If we give a date as `2016-03-23T10:20:00Z` and the current date is +`2020-04-13T10:20:00Z`, then the output would be `4 years and 3 weeks ago`. + +{: .note .info} +The action we're using takes care of installing the Ruby gems and dependencies. While that keeps +the setup simple for the user, one may encounter issues if they also check-in `Gemfile.lock` if it +was generated with an old version of Bundler. + +### Setting up the Action + +1. Go to the **Settings** tab on your repository. + 1. Click **Pages** under **Code and automation**. + 2. Change **Source** under **Build and deployment** from **Deploy from a branch** to **GitHub Actions**. +2. Go to the **Actions** tab on your repository. + 1. Start a **New workflow** and search for **Jekyll**. + 2. Click **Configure** under the **Jekyll** workflow (not **GitHub Pages Jekyll** workflow). + 3. Review the change and click **Commit changes**. + +### Build and deploy + +On pushing any local changes onto the default branch, the action will be triggered and the build will +**start**. + +To watch the progress and see any build errors, check on the build **status** using one of the +following approaches: + +- **View by commit** + - Go to the repository level view in GitHub. Under the most recent commit (near the top) you’ll + see a **status symbol** next to the commit message as a tick or _X_. Hover over it and click + the **details** link. +- **Actions tab** + - Go to the repository's Actions tab. Click on the `jekyll` workflow tab. + +If all goes well, all steps will be green and the built assets will be uploaded to GitHub Pages. + +To see the **live site**, go to the **Deployments** tab on your repository, and click on the deployed +site URL. + +When you need to make further **changes** to the site, commit to the default branch and push. +The workflow will build and deploy your site again. + +## External links + +- [starter-workflows] is the official repository providing the workflow template used in this guide. + +[ghp-whitelist]: https://pages.github.com/versions/ +[remote-theme]: https://github.com/benbalter/jekyll-remote-theme +[timeago-plugin]: https://rubygems.org/gems/jekyll-timeago +[starter-workflows]: https://github.com/actions/starter-workflows/blob/main/pages/jekyll.yml diff --git a/docs/_docs/continuous-integration/razorops.md b/docs/_docs/continuous-integration/razorops.md new file mode 100644 index 00000000000..a7c17cf0fbe --- /dev/null +++ b/docs/_docs/continuous-integration/razorops.md @@ -0,0 +1,61 @@ +--- +title: "Razorops" +--- + +[Razorops][razorops-homepage] is a complete container native CI/CD solution handling all aspects of the software lifecycle from the moment a commit is created until it is deployed to production. +Razorops has all the capabilities that you would expect from a CI/CD platform such as +1. Code compilation/build +2. Artifact packaging +3. Testing Automation(unit, integration, acceptance etc.) +4. Faster builds and shipping to production + +Razorops is a single solution that implements the whole pipeline from start to deployment. + +With [Razorops][razorops-homepage] you can set up your Jekyll websites project's build, test, and deploy steps just in 15 min. It supports [GitHub][github-homepage], [Bitbucket][bitbucket-homepage], and [GitLab][gitlab-homepage] repositories. The following guide will show you how to set up a free environment to build, test and deploy your Jekyll project. + +[razorops-homepage]: https://razorops.com/ +[docker-homepage]: https://www.docker.com/ +[github-homepage]: https://github.com +[bitbucket-homepage]: https://bitbucket.org/ +[gitlab-homepage]: https://gitlab.com +[deploy-s3]: https://razorops.com/blog/how-to-deploy-a-static-website-to-aws-s3-with-razorops-ci-cd/ + +## 1. Getting started + +1. Log in at [https://razorops.com/][razorops-homepage] with your GitHub/Bitbucket or GitLab account +2. Create a pipeline, choose your Git provider and select your Jekyll Project +3. Add .razorops.yaml file in your root directory of your project +4. Add environment var and your deployment is ready +5. Add build and deployment steps as shown in this post [How to Deploy a Static Website to AWS S3 with Razorops CI/CD][deploy-s3] + +## 2. How it works + +Whenever you make a push to the selected branch, your steps auto runs as defined in .razorops.yaml file + +```yaml + tasks: + build-and-deploy: + steps: + - checkout + # commands to build jekyll website + - commands: + - bundle install + - JEKYLL_ENV=production bundle exec jekyll build + # Commands to upload static pages folder to AWS S3 or ftp + # Set AWS access key & secrets environment variables under + # Razorops dashboard project pipelines + - commands: + - aws s3 rm s3://$AWS_S3_BUCKET --recursive + - aws s3 cp _site s3://$AWS_S3_BUCKET --recursive + if: branch == 'main' + +``` + + + + Build step generates _site folder as Jekyll default and during deploy you will able to ship code to s3 or any ftp server you can define any command to ship your website code to server. + +Razorops is FREE for opensource projects, Try it Now +[https://razorops.com/][razorops-homepage] + + diff --git a/site/_docs/continuous-integration.md b/docs/_docs/continuous-integration/travis-ci.md similarity index 66% rename from site/_docs/continuous-integration.md rename to docs/_docs/continuous-integration/travis-ci.md index b98de42c1d6..16e58a76c7b 100644 --- a/site/_docs/continuous-integration.md +++ b/docs/_docs/continuous-integration/travis-ci.md @@ -1,77 +1,73 @@ --- -layout: docs -title: Continuous Integration -permalink: /docs/continuous-integration/ +title: "Travis CI" --- -You can easily test your website build against one or more versions of Ruby. +You can test your website build against one or more versions of Ruby. The following guide will show you how to set up a free build environment on -[Travis][0], with [GitHub][1] integration for pull requests. Paid -alternatives exist for private repositories. +[Travis][travis], with [GitHub][github] integration for pull requests. -[0]: https://travis-ci.org/ -[1]: https://github.com/ +[travis]: https://travis-ci.org/ +[github]: https://github.com/ ## 1. Enabling Travis and GitHub -Enabling Travis builds for your GitHub repository is pretty simple: +To enable Travis builds for your GitHub repository: 1. Go to your profile on travis-ci.org: https://travis-ci.org/profile/username 2. Find the repository for which you're interested in enabling builds. -3. Click the slider on the right so it says "ON" and is a dark grey. -4. Optionally configure the build by clicking on the wrench icon. Further - configuration happens in your `.travis.yml` file. More details on that - below. +3. Flick the repository switch on so that it turns blue. +4. Optionally configure the build by clicking on the gear icon. Further + configuration happens via your `.travis.yml` file. More details below. ## 2. The Test Script -The simplest test script simply runs `jekyll build` and ensures that Jekyll +The simplest test script runs `jekyll build` and ensures that Jekyll doesn't fail to build the site. It doesn't check the resulting site, but it does ensure things are built properly. -When testing Jekyll output, there is no better tool than [html-proofer][2]. +When testing Jekyll output, there is no better tool than [html-proofer][html-proofer]. This tool checks your resulting site to ensure all links and images exist. -Utilize it either with the convenient `htmlproof` command-line executable, +Utilize it either with the convenient `htmlproofer` command-line executable, or write a Ruby script which utilizes the gem. Save the commands you want to run and succeed in a file: `./script/cibuild` ### The HTML Proofer Executable -{% highlight bash %} +```bash #!/usr/bin/env bash set -e # halt script on error bundle exec jekyll build -bundle exec htmlproof ./_site -{% endhighlight %} +bundle exec htmlproofer ./_site +``` Some options can be specified via command-line switches. Check out the `html-proofer` README for more information about these switches, or run -`htmlproof --help` locally. +`htmlproofer --help` locally. For example to avoid testing external sites, use this command: -{% highlight bash %} -$ bundle exec htmlproof ./_site --disable-external -{% endhighlight %} +```sh +bundle exec htmlproofer ./_site --disable-external +``` ### The HTML Proofer Library You can also invoke `html-proofer` in Ruby scripts (e.g. in a Rakefile): -{% highlight ruby %} +```ruby #!/usr/bin/env ruby -require 'html/proofer' -HTML::Proofer.new("./_site").run -{% endhighlight %} +require 'html-proofer' +HTMLProofer.check_directory("./_site").run +``` Options are given as a second argument to `.new`, and are encoded in a symbol-keyed Ruby Hash. For more information about the configuration options, check out `html-proofer`'s README file. -[2]: https://github.com/gjtorikian/html-proofer +[html-proofer]: https://github.com/gjtorikian/html-proofer ## 3. Configuring Your Travis Builds @@ -80,21 +76,21 @@ with Ruby and requires RubyGems to install, we use the Ruby language build environment. Below is a sample `.travis.yml` file, followed by an explanation of each line. -**Note:** You will need a Gemfile as well, [Travis will automatically install](http://docs.travis-ci.com/user/languages/ruby/#Dependency-Management) the dependencies based on the referenced gems: +**Note:** You will need a Gemfile as well, [Travis will automatically install](https://docs.travis-ci.com/user/languages/ruby/#Dependency-Management) the dependencies based on the referenced gems. Here is an example `Gemfile` with two referenced gems, "jekyll" and "html-proofer": -{% highlight ruby %} +```ruby source "https://rubygems.org" gem "jekyll" gem "html-proofer" -{% endhighlight %} +``` Your `.travis.yml` file should look like this: -{% highlight yaml %} +```yaml language: ruby rvm: -- 2.1 + - 2.6.3 before_script: - chmod +x ./script/cibuild # or do this locally and commit @@ -109,42 +105,50 @@ branches: - gh-pages # test the gh-pages branch - /pages-(.*)/ # test every branch which starts with "pages-" -env: - global: - - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer -{% endhighlight %} +addons: + apt: + packages: + - libcurl4-openssl-dev + +cache: bundler # caching bundler gem packages will speed up build + +# Optional: disable email notifications about the outcome of your builds +notifications: + email: false +``` Ok, now for an explanation of each line: -{% highlight yaml %} +```yaml language: ruby -{% endhighlight %} +``` This line tells Travis to use a Ruby build container. It gives your script access to Bundler, RubyGems, and a Ruby runtime. -{% highlight yaml %} +```yaml rvm: -- 2.1 -{% endhighlight %} + - 2.6.3 +``` RVM is a popular Ruby Version Manager (like rbenv, chruby, etc). This directive tells Travis the Ruby version to use when running your test -script. +script. Use a [version which is pre-installed on the Travis build docker][5] +image to speed up the build. -{% highlight yaml %} +```yaml before_script: - chmod +x ./script/cibuild -{% endhighlight %} +``` The build script file needs to have the *executable* attribute set or Travis will fail with a permission denied error. You can also run this locally and commit the permissions directly, thus rendering this step irrelevant. -{% highlight yaml %} +```yaml script: ./script/cibuild -{% endhighlight %} +``` Travis allows you to run any arbitrary shell script to test your site. One convention is to put all scripts for your project in the `script` @@ -152,20 +156,20 @@ directory, and to call your test script `cibuild`. This line is completely customizable. If your script won't change much, you can write your test incantation here directly: -{% highlight yaml %} +```yaml install: gem install jekyll html-proofer -script: jekyll build && htmlproof ./_site -{% endhighlight %} +script: jekyll build && htmlproofer ./_site +``` The `script` directive can be absolutely any valid shell command. -{% highlight yaml %} +```yaml # branch whitelist, only for GitHub Pages branches: only: - gh-pages # test the gh-pages branch - /pages-(.*)/ # test every branch which starts with "pages-" -{% endhighlight %} +``` You want to ensure the Travis builds for your site are being run only on the branch or branches which contain your site. One means of ensuring this @@ -179,18 +183,6 @@ prefixed, exemplified above with the `/pages-(.*)/` regular expression. The `branches` directive is completely optional. Travis will build from every push to any branch of your repo if leave it out. -{% highlight yaml %} -env: - global: - - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer -{% endhighlight %} - -Using `html-proofer`? You'll want this environment variable. Nokogiri, used -to parse HTML files in your compiled site, comes bundled with libraries -which it must compile each time it is installed. Luckily, you can -dramatically decrease the install time of Nokogiri by setting the -environment variable `NOKOGIRI_USE_SYSTEM_LIBRARIES` to `true`. -
Be sure to exclude vendor from your _config.yml
@@ -198,9 +190,26 @@ environment variable `NOKOGIRI_USE_SYSTEM_LIBRARIES` to `true`. servers, which Jekyll will mistakenly read and explode on.

-{% highlight yaml %} +```yaml exclude: [vendor] -{% endhighlight %} +``` + +To speed up the build, you should cache the gem packages created by `bundler`. +Travis has a pre-defined [cache strategy for this tool][6] which should have +all the default configs to do exactly that. + +```yaml +cache: bundler +``` + +Optionally, if you are not interested in the build email notifications you +can disable them with this configuration. Travis supports a wide array of +notification services, you may find [another one more useful (e.g. slack)][7]. + +```yaml +notifications: + email: false +``` ### Troubleshooting @@ -217,5 +226,8 @@ an entry in the `.gitignore` file to avoid it from being checked in again. This entire guide is open-source. Go ahead and [edit it][3] if you have a fix or [ask for help][4] if you run into trouble and need some help. -[3]: https://github.com/jekyll/jekyll/edit/master/site/_docs/continuous-integration.md -[4]: http://jekyllrb.com/help/ +[3]: https://github.com/jekyll/jekyll/edit/master/docs/_docs/continuous-integration/travis-ci.md +[4]: https://jekyllrb.com/help/ +[5]: https://docs.travis-ci.com/user/languages/ruby/#Specifying-Ruby-versions-and-implementations +[6]: https://docs.travis-ci.com/user/caching/#Caching-directories-(Bundler%2C-dependencies) +[7]: https://docs.travis-ci.com/user/notifications/ diff --git a/docs/_docs/contributing.md b/docs/_docs/contributing.md new file mode 100644 index 00000000000..2caed814143 --- /dev/null +++ b/docs/_docs/contributing.md @@ -0,0 +1,162 @@ +--- +title: Contributing +permalink: "/docs/contributing/" +note: This file is autogenerated. Edit /.github/CONTRIBUTING.markdown instead. +--- + +Hi there! Interested in contributing to Jekyll? We'd love your help. Jekyll is an open source project, built one contribution at a time by users like you. + +## Where to get help or report a problem + +See the [support guidelines](https://jekyllrb.com/docs/support/) + +## Ways to contribute + +Whether you're a developer, a designer, or just a Jekyll devotee, there are lots of ways to contribute. Here's a few ideas: + +- [Install Jekyll on your computer](https://jekyllrb.com/docs/installation/) and kick the tires. Does it work? Does it do what you'd expect? If not, [open an issue](https://github.com/jekyll/jekyll/issues/new) and let us know. +- Comment on some of the project's [open issues](https://github.com/jekyll/jekyll/issues). Have you experienced the same problem? Know a workaround? Do you have a suggestion for how the feature could be better? +- Read through the [documentation](https://jekyllrb.com/docs/home/), and click the "improve this page" button, any time you see something confusing, or have a suggestion for something that could be improved. +- Browse through the [Jekyll discussion forum](https://talk.jekyllrb.com/), and lend a hand answering questions. There's a good chance you've already experienced what another user is experiencing. +- Find an [open issue](https://github.com/jekyll/jekyll/issues) (especially [those labeled `help-wanted`](https://github.com/jekyll/jekyll/issues?q=is%3Aopen+is%3Aissue+label%3Ahelp-wanted)), and submit a proposed fix. If it's your first pull request, we promise we won't bite, and are glad to answer any questions. +- Help evaluate [open pull requests](https://github.com/jekyll/jekyll/pulls), by testing the changes locally and reviewing what's proposed. + +## Submitting a pull request + +### Pull requests generally + +- The smaller the proposed change, the better. If you'd like to propose two unrelated changes, submit two pull requests. + +- The more information, the better. Make judicious use of the pull request body. Describe what changes were made, why you made them, and what impact they will have for users. + +- If this is your first pull request, it may help to [understand GitHub Flow](https://guides.github.com/introduction/flow/). + +- If you're submitting a code contribution, be sure to read the [code contributions](#code-contributions) section below. + +### Submitting a pull request via github.com + +Many small changes can be made entirely through the github.com web interface. + +1. Navigate to the file within [`jekyll/jekyll`](https://github.com/jekyll/jekyll) that you'd like to edit. +2. Click the pencil icon in the top right corner to edit the file +3. Make your proposed changes +4. Click "Propose file change" +5. Click "Create pull request" +6. Add a descriptive title and detailed description for your proposed change. The more information the better. +7. Click "Create pull request" + +That's it! You'll be automatically subscribed to receive updates as others review your proposed change and provide feedback. + +### Submitting a pull request via Git command line + +1. Fork the project by clicking "Fork" in the top right corner of [`jekyll/jekyll`](https://github.com/jekyll/jekyll). +2. Clone the repository locally `git clone https://github.com//jekyll`. +3. Create a new, descriptively named branch to contain your change ( `git checkout -b my-awesome-feature` ). +4. Hack away, add tests. Not necessarily in that order. +5. Make sure everything still passes by running `script/cibuild` (see the [tests section](#running-tests-locally) below) +6. Push the branch up ( `git push origin my-awesome-feature` ). +7. Create a pull request by visiting `https://github.com//jekyll` and following the instructions at the top of the screen. + +## Proposing updates to the documentation + +We want the Jekyll documentation to be the best it can be. We've open-sourced our docs and we welcome any pull requests if you find it lacking. + +### How to submit changes + +You can find the documentation for jekyllrb.com in the [docs](https://github.com/jekyll/jekyll/tree/master/docs) directory. See the section above, [submitting a pull request](#submitting-a-pull-request) for information on how to propose a change. + +One gotcha, all pull requests should be directed at the `master` branch (the default branch). + +### Updating FontAwesome iconset for jekyllrb.com + +We use a custom version of FontAwesome which contains just the icons we use. + +If you ever need to update our documentation with an icon that is not already available in our custom iconset, you'll have to regenerate the iconset using Icomoon's Generator: + +1. Go to . +2. Click `Import Icons` on the top-horizontal-bar and upload the existing `/docs/icomoon-selection.json`. +3. Click `Add Icons from Library..` further down on the page, and add 'Font Awesome'. +4. Select the required icon(s) from the Library (make sure its the 'FontAwesome' library instead of 'IcoMoon-Free' library). +5. Click `Generate Font` on the bottom-horizontal-bar. +6. Inspect the included icons and proceed by clicking `Download`. +7. Extract the font files and adapt the CSS to the paths we use in Jekyll: + +- Copy the entire `fonts` directory over and overwrite existing ones at `/docs/`. +- Copy the contents of `selection.json` and overwrite existing content inside `/docs/icomoon-selection.json`. +- Copy the entire `@font-face {}` declaration and only the **new-icon(s)' css declarations** further below, to update the + `/docs/_sass/_font-awesome.scss` sass partial. +- Fix paths in the `@font-face {}` declaration by adding `../` before `fonts/FontAwesome.*` like so: + `('../fonts/Fontawesome.woff?9h6hxj')`. + +### Adding plugins + +If you want to add your plugin to the [list of plugins](https://jekyllrb.com/docs/plugins/#available-plugins), please submit a pull request modifying the [plugins page source file](https://github.com/jekyll/jekyll/blob/master/docs/_docs/plugins.md) by adding a link to your plugin under the proper subheading depending upon its type. + +## Code Contributions + +Interested in submitting a pull request? Awesome. Read on. There's a few common gotchas that we'd love to help you avoid. + +### Tests and documentation + +Any time you propose a code change, you should also include updates to the documentation and tests within the same pull request. + +#### Documentation + +If your contribution changes any Jekyll behavior, make sure to update the documentation. Documentation lives in the `docs/_docs` folder (spoiler alert: it's a Jekyll site!). If the docs are missing information, please feel free to add it in. Great docs make a great project. Include changes to the documentation within your pull request, and once merged, `jekyllrb.com` will be updated. + +#### Tests + +- If you're creating a small fix or patch to an existing feature, a simple test is more than enough. You can usually copy/paste from an existing example in the `tests` folder, but if you need you can find out about our tests suites [Shoulda](https://github.com/thoughtbot/shoulda/tree/master) and [RSpec-Mocks](https://github.com/rspec/rspec-mocks). + +- If it's a brand new feature, create a new [Cucumber](https://github.com/cucumber/cucumber/) feature, reusing existing steps where appropriate. + +### Code contributions generally + +- Jekyll uses the [Rubocop](https://github.com/bbatsov/rubocop) static analyzer to ensure that contributions follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby). Please check your code using `script/fmt` and resolve any errors before pushing your branch. + +- Don't bump the Gem version in your pull request (if you don't know what that means, you probably didn't). + +- You can use the command `script/console` to start a REPL to explore the result of + Jekyll's methods. It also provides you with helpful methods to quickly create a + site or configuration. [Feel free to check it out!](https://github.com/jekyll/jekyll/blob/master/script/console) + +- Previously, we've used the WIP Probot app to help contributors determine whether their pull request is ready for review. Please use a [draft pull request](https://help.github.com/en/articles/about-pull-requests#draft-pull-requests) instead. When you're ready, [mark the pull request as ready for review](https://help.github.com/en/articles/changing-the-stage-of-a-pull-request) + +## Running tests locally + +### Test Dependencies + +To run the test suite and build the gem you'll need to install Jekyll's dependencies by running the following command: + +```sh +script/bootstrap +``` + +Before you make any changes, run the tests and make sure that they pass (to confirm your environment is configured properly): + +```sh +script/cibuild +``` + +If you are only updating a file in `test/`, you can use the command: + +```sh +script/test test/blah_test.rb +``` + +If you are only updating a `.feature` file, you can use the command: + +```sh +script/cucumber features/blah.feature +``` + +Both `script/test` and `script/cucumber` can be run without arguments to +run its entire respective suite. + +## Visual Studio Code Development Container + +If you've got [Visual Studio Code](https://code.visualstudio.com/) with the [Remote Development Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) installed then simply opening this repository in Visual Studio Code and following the prompts to "Re-open In A Development Container" will get you setup and ready to go with a fresh environment with all the requirements installed. + +## A thank you + +Thanks! Hacking on Jekyll should be fun. If you find any of this hard to figure out, let us know so we can improve our process or documentation! diff --git a/site/_docs/datafiles.md b/docs/_docs/datafiles.md similarity index 50% rename from site/_docs/datafiles.md rename to docs/_docs/datafiles.md index afa54b8fc67..e7ca78b7c79 100644 --- a/site/_docs/datafiles.md +++ b/docs/_docs/datafiles.md @@ -1,16 +1,14 @@ --- -layout: docs title: Data Files permalink: /docs/datafiles/ --- -In addition to the [built-in variables](../variables/) available from Jekyll, +In addition to the [built-in variables]({{'/docs/variables/' | relative_url }}) available from Jekyll, you can specify your own custom data that can be accessed via the [Liquid -templating system](https://wiki.github.com/shopify/liquid/liquid-for-designers). +templating system](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers). -Jekyll supports loading data from [YAML](http://yaml.org/), [JSON](http://www.json.org/), -and [CSV](https://en.wikipedia.org/wiki/Comma-separated_values) files located in the `_data` directory. -Note that CSV files *must* contain a header row. +Jekyll supports loading data from [YAML](https://yaml.org), [JSON](https://www.json.org/json-en.html), [CSV](https://en.wikipedia.org/wiki/Comma-separated_values), and [TSV](https://en.wikipedia.org/wiki/Tab-separated_values) files located in the `_data` directory. +Note that CSV and TSV files *must* contain a header row. This powerful feature allows you to avoid repetition in your templates and to set site specific options without changing `_config.yml`. @@ -19,10 +17,9 @@ Plugins/themes can also leverage Data Files to set configuration variables. ## The Data Folder -As explained on the [directory structure](../structure/) page, the `_data` -folder is where you can store additional data for Jekyll to use when generating -your site. These files must be YAML files -(using either the `.yml`, `.yaml`, `.json` or `csv` extension) and they will be +The `_data` folder is where you can store additional data for Jekyll to use when +generating your site. These files must be YAML, JSON, TSV or CSV files (using either +the `.yml`, `.yaml`, `.json`, `.tsv`, or `.csv` extension), and they will be accessible via `site.data`. ## Example: List of members @@ -32,33 +29,33 @@ of code in your Jekyll templates: In `_data/members.yml`: -{% highlight yaml %} -- name: Tom Preston-Werner - github: mojombo +```yaml +- name: Eric Mill + github: konklone - name: Parker Moore github: parkr - name: Liu Fengyun github: liufengyun -{% endhighlight %} +``` Or `_data/members.csv`: -{% highlight text %} +``` name,github -Tom Preston-Werner,mojombo +Eric Mill,konklone Parker Moore,parkr Liu Fengyun,liufengyun -{% endhighlight %} +``` -This data can be accessed via `site.data.members` (notice that the filename -determines the variable name). +This data can be accessed via `site.data.members` (notice that the file's *basename* determines the variable name and +therefore one should avoid having data files with the same basename but different extensions, in the same directory). You can now render the list of members in a template: -{% highlight html %} {% raw %} +```liquid
    {% for member in site.data.members %}
  • @@ -68,10 +65,10 @@ You can now render the list of members in a template:
  • {% endfor %}
+``` {% endraw %} -{% endhighlight %} -## Example: Organizations +## Subfolders Data files can also be placed in sub-folders of the `_data` folder. Each folder level will be added to a variable's namespace. The example below shows how @@ -80,7 +77,7 @@ folder: In `_data/orgs/jekyll.yml`: -{% highlight yaml %} +```yaml username: jekyll name: Jekyll members: @@ -89,23 +86,23 @@ members: - name: Parker Moore github: parkr -{% endhighlight %} +``` In `_data/orgs/doeorg.yml`: -{% highlight yaml %} +```yaml username: doeorg name: Doe Org members: - name: John Doe github: jdoe -{% endhighlight %} +``` The organizations can then be accessed via `site.data.orgs`, followed by the file name: -{% highlight html %} {% raw %} +```liquid
    {% for org_hash in site.data.orgs %} {% assign org = org_hash[1] %} @@ -117,24 +114,25 @@ file name: {% endfor %}
+``` {% endraw %} -{% endhighlight %} ## Example: Accessing a specific author Pages and posts can also access a specific data item. The example below shows how to access a specific item: `_data/people.yml`: -{% highlight yaml %} + +```yaml dave: name: David Smith twitter: DavidSilvaSmith -{% endhighlight %} +``` -The author can then be specified as a page variable in a post's frontmatter: +The author can then be specified as a page variable in a post's front matter: -{% highlight html %} {% raw %} +```liquid --- title: sample post author: dave @@ -142,10 +140,38 @@ author: dave {% assign author = site.data.people[page.author] %} - +``` {% endraw %} -{% endhighlight %} + +For information on how to build robust navigation for your site (especially if you have a documentation website or another type of Jekyll site with a lot of pages to organize), see [Navigation]({{ '/tutorials/navigation/' | relative_url }}). + +## CSV/TSV Parse Options + +The way Ruby parses CSV and TSV files can be customized with the `csv_reader` and `tsv_reader` +configuration options. Each configuration key exposes the same options: + +`converters`: What [CSV converters](https://ruby-doc.org/stdlib-2.5.0/libdoc/csv/rdoc/CSV.html#Converters) should be + used when parsing the file. Available options are `integer`, `float`, `numeric`, `date`, `date_time` and + `all`. By default, this list is empty. +`encoding`: What encoding the files are in. Defaults to the site `encoding` configuration option. +`headers`: Boolean field for whether to parse the first line of the file as headers. When `false`, it treats the + first row as data. Defaults to `true`. + +Examples: + +```yaml +csv_reader: + converters: + - numeric + - datetime + headers: true + encoding: utf-8 +tsv_reader: + converters: + - all + headers: false +``` diff --git a/docs/_docs/deployment.md b/docs/_docs/deployment.md new file mode 100644 index 00000000000..45722e4e93c --- /dev/null +++ b/docs/_docs/deployment.md @@ -0,0 +1,11 @@ +--- +title: Deployment +permalink: /docs/deployment/ +redirect_from: "/docs/deployment-methods/index.html" +--- + +Sites built using Jekyll can be deployed in a large number of ways due to the static nature of the generated output. Here's some of the most common ways: + +* [Manually]({{ '/docs/deployment/manual/' | relative_url }}) +* [Automated]({{ '/docs/deployment/automated/' | relative_url }}) +* [Third Party]({{ '/docs/deployment/third-party/' | relative_url }}) diff --git a/docs/_docs/deployment/automated.md b/docs/_docs/deployment/automated.md new file mode 100644 index 00000000000..8778a82310f --- /dev/null +++ b/docs/_docs/deployment/automated.md @@ -0,0 +1,70 @@ +--- +title: Automated Deployment +permalink: /docs/deployment/automated/ +--- +There are a number of ways to easily automate the deployment of a Jekyll site. + +## Continuous Integration Service + +One of the easiest ways to set up an automated deployment flow is by using a +CI. + +These services run a script when there's a commit on your Git repository. +You might want this script to build the site, run tests over the output then deploy it to the +service of your choice. + +We have guides for the following providers: + +* [GitHub Actions]({{ '/docs/continuous-integration/github-actions/' | relative_url }}) +* [Travis CI]({{ '/docs/continuous-integration/travis-ci/' | relative_url }}) +* [CircleCI]({{ '/docs/continuous-integration/circleci/' | relative_url }}) +* [Buddy]({{ '/docs/continuous-integration/buddyworks/' | relative_url }}) +* [Razorops CI/CD]({{ '/docs/continuous-integration/razorops/' | relative_url }}) + +## Git post-receive hook + +To have a remote server handle the deploy for you every time you push changes using Git, you can create a user account which has all the public keys that are authorized to deploy in its `authorized_keys` file. With that in place, setting up the post-receive hook is done as follows: + +```sh +laptop$ ssh deployer@example.com +server$ mkdir myrepo.git +server$ cd myrepo.git +server$ git --bare init +server$ cp hooks/post-receive.sample hooks/post-receive +server$ mkdir /var/www/myrepo +``` + +Next, add the following lines to hooks/post-receive and be sure Jekyll is +installed on the server: + +```bash +#!/bin/bash -l + +# Install Ruby Gems to ~/gems +export GEM_HOME=$HOME/gems +export PATH=$GEM_HOME/bin:$PATH + +TMP_GIT_CLONE=$HOME/tmp/myrepo +GEMFILE=$TMP_GIT_CLONE/Gemfile +PUBLIC_WWW=/var/www/myrepo + +git clone $GIT_DIR $TMP_GIT_CLONE +BUNDLE_GEMFILE=$GEMFILE bundle install +BUNDLE_GEMFILE=$GEMFILE bundle exec jekyll build -s $TMP_GIT_CLONE -d $PUBLIC_WWW +rm -Rf $TMP_GIT_CLONE +exit +``` + +Finally, run the following command on any users laptop that needs to be able to +deploy using this hook: + +```sh +laptops$ git remote add deploy deployer@example.com:~/myrepo.git +``` + +Deploying is now as easy as telling nginx or Apache to look at +`/var/www/myrepo` and running the following: + +```sh +laptops$ git push deploy master +``` diff --git a/docs/_docs/deployment/manual.md b/docs/_docs/deployment/manual.md new file mode 100644 index 00000000000..ed13b214fcc --- /dev/null +++ b/docs/_docs/deployment/manual.md @@ -0,0 +1,34 @@ +--- +title: Manual Deployment +permalink: /docs/deployment/manual/ +--- + +Jekyll generates your static site to the `_site` directory by default. You can +transfer the contents of this directory to almost any hosting provider to get +your site live. Here are some manual ways of achieving this: + +## rsync + +Rsync is similar to scp except it can be faster as it will only send changed +parts of files as opposed to the entire file. You can learn more about using +rsync in the [Digital Ocean tutorial](https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories-on-a-vps). + +## Amazon S3 + +If you want to host your site in Amazon S3, you can do so by +using the AWS cli client and pushing your rendered `_site` directory directly to +your S3 bucket. + +`aws s3 sync _site s3://.com --size-only --storage-class REDUCED_REDUNDANCY` + +## FTP + +Most traditional web hosting providers let you upload files to their servers over FTP. To upload a Jekyll site to a web host using FTP, run the `jekyll build` command and copy the contents of the generated `_site` folder to the root folder of your hosting account. This is most likely to be the `httpdocs` or `public_html` folder on most hosting providers. + +## scp + +If you have direct access to the deployment web server, the process is essentially the same, except you might have other methods available to you (such as `scp`, or even direct filesystem access) for transferring the files. Remember to make sure the contents of the generated `_site` folder get placed in the appropriate web root directory for your web server. + +## Rack-Jekyll + +[Rack-Jekyll](https://github.com/adaoraul/rack-jekyll/) allows you to deploy your site on any Rack server such as Amazon EC2, Slicehost, Heroku, and so forth. It also can run with [shotgun](https://github.com/rtomayko/shotgun/), [rackup](https://github.com/rack/rack), [mongrel](https://github.com/mongrel/mongrel), [unicorn](https://github.com/defunkt/unicorn/), and [others](https://github.com/adaoraul/rack-jekyll#readme). diff --git a/docs/_docs/deployment/third-party.md b/docs/_docs/deployment/third-party.md new file mode 100644 index 00000000000..e371f8301d0 --- /dev/null +++ b/docs/_docs/deployment/third-party.md @@ -0,0 +1,86 @@ +--- +title: 3rd Party +permalink: /docs/deployment/third-party/ +--- + + +## AWS Amplify + +The [AWS Amplify Console](https://console.amplify.aws) provides continuous deployment and hosting for modern web apps (single page apps and static site generators). Continuous deployment allows developers to deploy updates to their web app on every code commit to their Git repository. Hosting includes features such as globally available CDNs, 1-click custom domain setup + HTTPS, feature branch deployments, redirects, trailing slashes, and password protection. + +Read this [step-by-step guide](https://medium.com/@jameshamann/deploy-your-jekyll-site-using-aws-amplify-with-only-a-few-clicks-8f3dd8f26112) to deploy and host your Jekyll site on AWS Amplify. + +## CloudCannon + +[CloudCannon](https://cloudcannon.com) has everything you need to build, host +and update Jekyll websites. Take advantage of our global CDN, automated SSL, +continuous deployment and [more](https://cloudcannon.com/features/). + +## GitHub Pages + +Sites on GitHub Pages are powered by Jekyll behind the scenes, so if you’re looking for a zero-hassle, zero-cost solution, GitHub Pages are a great way to [host your Jekyll-powered website for free](/docs/github-pages/). + +## GitLab Pages + +[GitLab Pages](https://about.gitlab.com/stages-devops-lifecycle/pages/) offers free hosting with custom domains. [Get started with Jekyll](https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html) and a fully customizable pipeline. + +## KeyCDN + +[KeyCDN](https://www.keycdn.com) accelerates Jekyll-powered websites with a wide range of other features such as real time image processing including WebP transformation. +The [Jekyll hosting tutorial](https://www.keycdn.com/support/jekyll-hosting) provides various options to supercharge Jekyll sites with just a few steps. It combines best flexibility and excellent performance. + +## Kickster + +Use [Kickster](https://kickster.nielsenramon.com/) for automated deploys to GitHub Pages when using unsupported plugins on GitHub Pages. + +Kickster provides a basic Jekyll project setup packed with web best practices and useful optimization tools increasing your overall project quality. Kickster ships with automated and worry-free deployment scripts for GitHub Pages. + +Install the Kickster gem and you are good to go. More documentation can be found [here](https://github.com/nielsenramon/kickster#kickster). If you do not want to use the gem or start a new project you can just copy paste the deployment scripts for [Travis CI](https://github.com/nielsenramon/kickster/tree/master/snippets/travis) or [Circle CI](https://github.com/nielsenramon/kickster#automated-deployment-with-circle-ci). + +## Netlify + +Netlify provides Global CDN, Continuous Deployment, one click HTTPS and [much more](https://www.netlify.com/features/), providing developers a robust toolset for modern web projects, without added complexity. Netlify supports custom plugins for Jekyll and has a free plan for open source projects. + +Read this [Jekyll step-by-step guide](https://www.netlify.com/blog/2020/04/02/a-step-by-step-guide-jekyll-4.0-on-netlify/) to setup your Jekyll site on Netlify. + +## Render + +[Render](https://render.com) provides zero config continuous deployment for static sites. The service is free under 100GB monthly bandwidth. + +## Hostman + +[Hostman](https://hostman.com) allows you to host websites for free with no configurations. Read [this guide](https://hostman.com/docs/jekyll) to deploy your Jekyll site on Hostman. + +## Static Publisher + +[Static Publisher](https://github.com/static-publisher/static-publisher) is another automated deployment option with a server listening for webhook posts, though it's not tied to GitHub specifically. It has a one-click deploy to Heroku, it can watch multiple projects from one server, it has an easy to user admin interface and can publish to either S3 or to a git repository (e.g. gh-pages). + +## Vercel + +[Vercel](https://vercel.com/) provides zero config continuous deployment, HTTPS Custom domains, high performance smart CDN, you get instant static deploy for free. + +## 21YunBox + +[21YunBox](https://www.21yunbox.com) provides blazing fast Chinese CDN, Continuous Deployment, one click HTTPS and [much more](https://www.21yunbox.com/docs/), providing developers a hassle-free solution to launch their web projects in China. + +Read this [Jekyll step-by-step guide](https://www.21yunbox.com/docs/#/deploy-jekyll) to deploy your Jekyll site on 21YunBox. + +## Layer0 + +[Layer0](https://www.layer0.co) is an all-in-one platform to develop, deploy, preview, experiment on, monitor, and run your headless frontend. It is focused on large, dynamic websites and best-in-class performance through EdgeJS (a JavaScript-based Content Delivery Network), predictive prefetching, and performance monitoring. Layer0 offers a free tier. Get started in just a few minutes by following [Layer0's guide to deploying Jekyll](https://docs.layer0.co/guides/jekyll). + +## Kinsta Application Hosting + +[Kinsta Application Hosting](https://kinsta.com/application-hosting) is a Cloud Platform designed to help your company and dev teams ship web projects faster and more efficiently. You can host your apps, databases, and sites all in one place. Easily connect with GitHub and automate deployments and get 24/7 support for all your favorite languages and frameworks. + +Read [this guide](https://kinsta.com/docs/jekyll-static-site-example/) to learn how to deploy Jekyll site on Kinsta. + +## Supranode + +[Supranode](https://supranode.com) offers customizable continuous deployment for static websites, featuring automatic HTTPS, a high-performance CDN, secret management, deployment previews, password protection, and more. + +## Azion + +[Azion](https://www.azion.com/en/) is an web platform that provides a wide range of services. It allows you to host static sites, including Jekyll-powered websites, with features like automatic HTTPS, custom domains, and real-time analytics. Azion's platform is designed for performance and scalability, making it an excellent choice for hosting global websites. + +In [this guide](https://www.azion.com/en/documentation/products/guides/jekyll-boilerplate/) you can learn how to deploy a Jekyll site on Azion. diff --git a/site/_docs/frontmatter.md b/docs/_docs/front-matter.md similarity index 60% rename from site/_docs/frontmatter.md rename to docs/_docs/front-matter.md index c9a0292e873..7b88a15bc10 100644 --- a/site/_docs/frontmatter.md +++ b/docs/_docs/front-matter.md @@ -1,25 +1,24 @@ --- -layout: docs title: Front Matter -permalink: /docs/frontmatter/ +permalink: /docs/front-matter/ +redirect_from: /docs/frontmatter/index.html --- -The front matter is where Jekyll starts to get really cool. Any file that -contains a [YAML](http://yaml.org/) front matter block will be processed by -Jekyll as a special file. The front matter must be the first thing in the file -and must take the form of valid YAML set between triple-dashed lines. Here is a -basic example: +Any file that contains a [YAML](https://yaml.org/) front matter block will be +processed by Jekyll as a special file. The front matter must be the first thing +in the file and must take the form of valid YAML set between triple-dashed +lines. Here is a basic example: -{% highlight yaml %} +```yaml --- layout: post title: Blogging Like a Hacker --- -{% endhighlight %} +``` Between these triple-dashed lines, you can set predefined variables (see below for a reference) or even create custom ones of your own. These variables will -then be available to you to access using Liquid tags both further down in the +then be available for you to access using Liquid tags both further down in the file and also in any layouts or includes that the page or post in question relies on. @@ -29,14 +28,14 @@ relies on. If you use UTF-8 encoding, make sure that no BOM header characters exist in your files or very, very bad things will happen to Jekyll. This is especially relevant if you’re running - Jekyll on Windows. + Jekyll on Windows.

-
ProTip™: Front Matter Variables Are Optional
+
Front Matter Variables Are Optional

- If you want to use Liquid tags and variables + If you want to use Liquid tags and variables but don’t need anything in your front matter, just leave it empty! The set of triple-dashed lines with nothing in between will still get Jekyll to process your file. (This is useful for things like CSS and RSS feeds!) @@ -69,6 +68,20 @@ front matter of a page or post. _layouts directory.

+
    +
  • + Using null will produce a file without using a layout + file. This is overridden if the file is a post/document and has a + layout defined in the + front matter defaults. +
  • +
  • + Starting from version 3.5.0, using none in a post/document will + produce a file without using a layout file regardless of front matter defaults. + Using none in a page will cause Jekyll to attempt to + use a layout named "none". +
  • +
@@ -96,59 +109,33 @@ front matter of a page or post.

- - -

category

-

categories

- - -

- - Instead of placing posts inside of folders, you can specify one or - more categories that the post belongs to. When the site is generated - the post will act as though it had been set with these categories - normally. Categories (plural key) can be specified as a YAML list or a - comma-separated string. - -

- - - - -

tags

- - -

- - Similar to categories, one or multiple tags can be added to a post. - Also like categories, tags can be specified as a YAML list or a - comma-separated string. - -

- -
+
+
Render Posts Marked As Unpublished
+

+ To preview unpublished pages, run `jekyll serve` or `jekyll build` + with the `--unpublished` switch. Jekyll also has a handy drafts + feature tailored specifically for blog posts. +

+
## Custom Variables -Any variables in the front matter that are not predefined are mixed into the -data that is sent to the Liquid templating engine during the conversion. For -instance, if you set a title, you can use that in your layout to set the page -title: - -{% highlight html %} - - - - {% raw %}{{ page.title }}{% endraw %} - - - ... -{% endhighlight %} +You can also set your own front matter variables you can access in Liquid. For +instance, if you set a variable called `food`, you can use that in your page: + +{% raw %} +```liquid +--- +food: Pizza +--- + +

{{ page.food }}

+``` +{% endraw %} ## Predefined Variables for Posts @@ -176,15 +163,49 @@ These are available out-of-the-box to be used in the front matter for a post.

+ + +

category

+

categories

+ + +

+ + Instead of placing posts inside of folders, you can specify one or + more categories that the post belongs to. When the site is generated + the post will act as though it had been set with these categories + normally. Categories (plural key) can be specified as a YAML list or a + space-separated string. + +

+ + + + +

tags

+ + +

+ + Similar to categories, one or multiple tags can be added to a post. + Also like categories, tags can be specified as a YAML list or a + space-separated string. + +

+ +
-
ProTip™: Don't repeat yourself
+
Don't repeat yourself

If you don't want to repeat your frequently used front matter variables - over and over, just define defaults + over and over, define + defaults for them and only override them where necessary (or not at all). This works both for predefined and custom variables.

diff --git a/docs/_docs/github-pages.md b/docs/_docs/github-pages.md new file mode 100644 index 00000000000..298e4a8e1d3 --- /dev/null +++ b/docs/_docs/github-pages.md @@ -0,0 +1,131 @@ +--- +title: GitHub Pages +permalink: /docs/github-pages/ +--- + +[GitHub Pages](https://pages.github.com) are public web pages for users, +organizations, and repositories, that are freely hosted on GitHub's `github.io` +domain or on a custom domain name of your choice. GitHub Pages are powered by +Jekyll behind the scenes, so they're a great way to host your Jekyll-powered +website for free. + +Your site is automatically generated by GitHub Pages when you push your source +files. Note that GitHub Pages works equally well for regular HTML content, +simply because Jekyll treats files without front matter as static assets. +So if you only need to push generated HTML, you're good to go without any +further setup. + +The [GitHub Pages Documentation](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages) +is comprehensive and includes a [a guide to setting up a GitHub Pages site using +Jekyll](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/setting-up-a-github-pages-site-with-jekyll). +We recommend following this guide. + +This page contains some additional information which may be useful when working +on GitHub Pages sites with Jekyll. + +
+
GitHub Pages Documentation, Help, and Support
+

+ For more information about what you can do with GitHub Pages, as well as for + troubleshooting guides, you should check out + GitHub’s Pages Help section. + If all else fails, you should contact GitHub Support. +

+
+ +### Project Page URL Structure + +Sometimes it's nice to preview your Jekyll site before you push your `gh-pages` +branch to GitHub. The subdirectory-like URL structure GitHub uses for +Project Pages complicates the proper resolution of URLs. In order to assure your +site builds properly, use the handy [URL filters]({{ '/docs/liquid/filters/' | relative_url }}): + +{% raw %} +```liquid + + + +[{{ page.title }}]("{{ page.url | relative_url }}") +``` +{% endraw %} + +This way you can preview your site locally from the site root on localhost, +but when GitHub generates your pages from the `gh-pages` branch all the URLs +will resolve properly. + +## Deploying Jekyll to GitHub Pages + +GitHub Pages work by looking at certain branches of repositories on GitHub. +There are two basic types available: [user/organization and project pages](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites). +The way to deploy these two types of sites are nearly identical, except for a +few minor details. + +### User and Organization Pages + +User and organization pages live in a special GitHub repository dedicated to +only the GitHub Pages files. This repository must be named after the account +name. For example, [@mojombo’s user page repository](https://github.com/mojombo/mojombo.github.io) has the name +`mojombo.github.io`. + +Content from the `master` branch of your repository will be used to build and +publish the GitHub Pages site, so make sure your Jekyll site is stored there. + +
+
Custom domains do not affect repository names
+

+ GitHub Pages are initially configured to live under the + username.github.io subdomain, which is why repositories must + be named this way even if a custom domain is being used. +

+
+ +### Project Pages + +Unlike user and organization Pages, Project Pages are kept in the same +repository as the project they are for, except that the website content is +stored in a specially named `gh-pages` branch or in a `docs` folder on the +`master` branch. The content will be rendered using Jekyll, and the output +will become available under a subpath of your user pages subdomain, such as +`username.github.io/project` (unless a custom domain is specified). + +The Jekyll project repository itself is a perfect example of this branch +structure—the [master branch]({{ site.repository }}) contains the +actual software project for Jekyll, and the Jekyll website that you’re +looking at right now is contained in the [docs +folder]({{ site.repository }}/tree/master/docs) of the same repository. + +Please refer to GitHub official documentation on +[user, organization and project pages](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/about-github-pages#types-of-github-pages-sites) +to see more detailed examples. + +
+
Source files must be in the root directory
+

+ GitHub Pages overrides + the “Site Source” + configuration value, so if you locate your files anywhere other than the + root directory, your site may not build correctly. +

+
+ +
+
Installing the github-pages gem on Windows
+ +

+ While Windows is not officially supported, it is possible + to install the github-pages gem on Windows. + Special instructions can be found on our + Windows-specific docs page. +

+
+ +### Running and Testing Locally + +Once the project is configured with the github-pages environment, it's quite hard to switch back and forth with the local settings and the production-level settings. For that we can use certain CLI options to make the workflow hassle-free. + +```sh +bundle exec jekyll serve --baseurl="" +``` + +This will run the jekyll server on your local machine i.e. on `http://localhost:4000`. Refer server options for available options. + diff --git a/docs/_docs/history.md b/docs/_docs/history.md new file mode 100644 index 00000000000..9a3f8aa2964 --- /dev/null +++ b/docs/_docs/history.md @@ -0,0 +1,4659 @@ +--- +title: History +permalink: "/docs/history/" +note: This file is autogenerated. Edit /History.markdown instead. +--- + +## 4.4.1 / 2025-01-29 +{: #v4-4-1} + +### Bug Fixes +{: #bug-fixes-v4-4-1} + +- Restore globbed path behavior in front matter defaults ([#9762]({{ site.repository }}/issues/9762)) + + +## 4.4.0 / 2025-01-27 +{: #v4-4-0} + +### Minor Enhancements +{: #minor-enhancements-v4-4-0} + +- Allow marking specific highlighted lines via Liquid ([#9138]({{ site.repository }}/issues/9138)) +- Add gem `csv` to runtime dependency list ([#9522]({{ site.repository }}/issues/9522)) +- Bump the minimum ruby version to 2.7 ([#9525]({{ site.repository }}/issues/9525)) +- Acknowledge `livereload_port` from site config too ([#9606]({{ site.repository }}/issues/9606)) +- Add gem `base64` as runtime dependency ([#9740]({{ site.repository }}/issues/9740)) +- Add gem `json` as runtime_dependency ([#9671]({{ site.repository }}/issues/9671)) +- Remove unnecessary constraint on gem `mercenary` ([#9758]({{ site.repository }}/issues/9758)) + +### Bug Fixes +{: #bug-fixes-v4-4-0} + +- Optimize default front matter using `File.fnmatch?` ([#9185]({{ site.repository }}/issues/9185)) +- Remove totals in profile table properly ([#9186]({{ site.repository }}/issues/9186)) +- Optimize `Site#each_site_file` ([#9187]({{ site.repository }}/issues/9187)) +- Rename sass partial created for new blank site ([#9257]({{ site.repository }}/issues/9257)) +- Fix `jekyll serve --detach` with jekyll-sass-converter 3.x ([#9304]({{ site.repository }}/issues/9304)) +- Handle TypeError from `where` filter gracefully ([#9292]({{ site.repository }}/issues/9292)) +- Add support for upcoming logger 1.4.3 ([#9392]({{ site.repository }}/issues/9392)) +- Fix typo in devcontainer.json ([#9364]({{ site.repository }}/issues/9364)) +- Correct rubocop lint errors ([#9600]({{ site.repository }}/issues/9600)) +- Fix inexistent layout warning for the default 404 page ([#9589]({{ site.repository }}/issues/9589)) +- Relax version constraint on `wdm` in new Gemfile ([#9662]({{ site.repository }}/issues/9662)) +- Fix `--livereload-ignore` option ([#9570]({{ site.repository }}/issues/9570)) +- Render theme-gem root only in development ([#9680]({{ site.repository }}/issues/9680)) + +### Development Fixes +{: #development-fixes-v4-4-0} + +- Cleanup highlight tag ([#9177]({{ site.repository }}/issues/9177)) +- Run tests in utc ([#9168]({{ site.repository }}/issues/9168)) +- Lock Ruby in CI to v3.1.2 and bump JRuby to v9.4.0.0 ([#9196]({{ site.repository }}/issues/9196)) +- Update sass related tests for jekyll-sass-converter 3.x ([#9223]({{ site.repository }}/issues/9223)) +- Split `test/test_tags.rb` into multiple files ([#9230]({{ site.repository }}/issues/9230)) +- test: use hash explicitly for Struct initializer for ruby 3.2 ([#9237]({{ site.repository }}/issues/9237)) +- script/default-site: accept flags for `jekyll new` ([#9259]({{ site.repository }}/issues/9259)) +- Bump check-spelling/check-spelling from 0.0.20 to 0.0.21 ([#9205]({{ site.repository }}/issues/9205)) +- Use check-spelling/check-spelling@v0.0.21 ([#9199]({{ site.repository }}/issues/9199)) +- Bump RuboCop to v1.45.x ([#9305]({{ site.repository }}/issues/9305)) +- Bump Rubocop to version 1.48.x ([#9326]({{ site.repository }}/issues/9326)) +- Bump versions of ruby & nodejs in devcontainer ([#9360]({{ site.repository }}/issues/9360)) +- Bump rubocop version to 1.52.x ([#9361]({{ site.repository }}/issues/9361)) +- Upgrade RuboCop to 1.54 ([#9401]({{ site.repository }}/issues/9401)) +- Add CodeQL workflow ([#9397]({{ site.repository }}/issues/9397)) +- Bump actions/checkout from 3 to 4 ([#9442]({{ site.repository }}/issues/9442)) +- Test suite uses shoulda-context only. ([#9441]({{ site.repository }}/issues/9441)) +- Keep activesupport at version 7.0.x ([#9469]({{ site.repository }}/issues/9469)) +- Bump Rubocop to 1.56.4 ([#9459]({{ site.repository }}/issues/9459)) +- Configure dependabot to handle rubygems dependencies ([#9445]({{ site.repository }}/issues/9445)) +- Update rubocop gem ([#9476]({{ site.repository }}/issues/9476)) +- Fix Performance/StringIdentifierArgument violation in site.rb and allow activesupport 6 for windows tests ([#9512]({{ site.repository }}/issues/9512)) +- Add a few more emeritus team members ([#9535]({{ site.repository }}/issues/9535)) +- Make custom cop inherit `RuboCop::Cop::Base` ([#9597]({{ site.repository }}/issues/9597)) +- CI: Use JRuby 9.4.8.0 ([#9654]({{ site.repository }}/issues/9654)) +- Stop testing with Cucumber on JRuby ([#9661]({{ site.repository }}/issues/9661)) +- Windows CI on GitHub Actions ([#9659]({{ site.repository }}/issues/9659)) +- Run GitHub Actions only if needed ([#9664]({{ site.repository }}/issues/9664)) +- Format `.rubocop.yml` via a rake task ([#9687]({{ site.repository }}/issues/9687)) +- Configure some new cops ([#9688]({{ site.repository }}/issues/9688)) +- Fix expected markup per WAI-ARIA requirements ([#9737]({{ site.repository }}/issues/9737)) +- Add an optional `:rdoc` group of gems ([#9742]({{ site.repository }}/issues/9742)) +- Test `inspect` filter with custom object ([#9743]({{ site.repository }}/issues/9743)) +- Bump cucumber to v9 ([#9747]({{ site.repository }}/issues/9747)) +- Add Ruby 3.4 to CI matrix ([#9740]({{ site.repository }}/issues/9740)) +- Remove unnecessary runtime dependency ([#9753]({{ site.repository }}/issues/9753)) +- Bump `check-spelling/check-spelling` action ([#9756]({{ site.repository }}/issues/9756)) + +### Documentation + +- Fix Nested tree navigation with recursion example ([#9174]({{ site.repository }}/issues/9174)) +- Fix typo on website ([#9203]({{ site.repository }}/issues/9203)) +- Publish post on major release of sass-converter ([#9225]({{ site.repository }}/issues/9225)) +- Update Jekyll on macOS (macos.md) and current ruby version to 3.1.3 in ruby.yml ([#9195]({{ site.repository }}/issues/9195)) +- Add release post for v4.3.2 ([#9263]({{ site.repository }}/issues/9263)) +- Grammatical reordering in 3-to-4 upgrading docs ([#9245]({{ site.repository }}/issues/9245)) +- fixed grammatical mistake on "showcase" page ([#9264]({{ site.repository }}/issues/9264)) +- Mark `highlight` `mark_lines` feature as 4.4 in docs ([#9184]({{ site.repository }}/issues/9184)) +- Add v3.9.3 release history & post to `master` branch ([#9284]({{ site.repository }}/issues/9284)) +- Update S3 deployment to remove s3_website ([#9221]({{ site.repository }}/issues/9221)) +- Document Exclude behavior, Include overrides and the default exclusion list ([#9376]({{ site.repository }}/issues/9376)) +- Update macos.md, remove Catalina (macOS 10.15) ([#9405]({{ site.repository }}/issues/9405)) +- Update macos.md, add support for Ventura ([#9406]({{ site.repository }}/issues/9406)) +- Typo fix - update to hooks and 3rd party deployment and one other article ([#9411]({{ site.repository }}/issues/9411)) +- Update 07-assets.md ([#9393]({{ site.repository }}/issues/9393)) +- Mention the front matter requirement in pages.md ([#9423]({{ site.repository }}/issues/9423)) +- Point to the Rouge GitHub repo rather than broken website ([#9362]({{ site.repository }}/issues/9362)) +- Add new theme directory to themes resources ([#9356]({{ site.repository }}/issues/9356)) +- Adds Kinsta to 3rd party deployments ([#9331]({{ site.repository }}/issues/9331)) +- Update Fedora prerequisites to include g++ ([#9290]({{ site.repository }}/issues/9290)) +- Update convert-site-to-jekyll.md ([#9348]({{ site.repository }}/issues/9348)) +- Update github-actions documentation ([#9426]({{ site.repository }}/issues/9426)) +- Update resources.md ([#9449]({{ site.repository }}/issues/9449)) +- Add GitHub Pages helpful notes ([#9235]({{ site.repository }}/issues/9235)) +- Clarify which version of Jekyll needs 'jekyll-paginate' ([#9477]({{ site.repository }}/issues/9477)) +- chore: update showcases ([#9473]({{ site.repository }}/issues/9473)) +- Add FreeBSD installation instructions ([#9481]({{ site.repository }}/issues/9481)) +- Fix broken link for the security team page ([#9497]({{ site.repository }}/issues/9497)) +- Fix broken links for several Jekyll integrations ([#9496]({{ site.repository }}/issues/9496)) +- Add release post for v4.3.3 ([#9511]({{ site.repository }}/issues/9511)) +- Add docs version badge to page_excerpts feature ([#9520]({{ site.repository }}/issues/9520)) +- Improve accessibility of the docs ([#9338]({{ site.repository }}/issues/9338)) +- Fix gem quote consistency on docs ([#9517]({{ site.repository }}/issues/9517)) +- Make site search work again ([#9530]({{ site.repository }}/issues/9530)) +- Jekyll docs template typo - All pages show "Deployment" ([#9548]({{ site.repository }}/issues/9548)) +- Fixed: Wrong navigation style on the right side of news and docs pages ([#9586]({{ site.repository }}/issues/9586)) +- Add redirect for step-by-step tutorial ([#9593]({{ site.repository }}/issues/9593)) +- Add Jekyll 3.10.0 release post & history ([#9625]({{ site.repository }}/issues/9625)) +- Fix minor docs error ([#9641]({{ site.repository }}/issues/9641)) +- Update windows.md ([#9644]({{ site.repository }}/issues/9644)) +- Document keys of global variable {% raw %}`{{ jekyll }}`{% endraw %} ([#9653]({{ site.repository }}/issues/9653)) +- Fix incorrect and inconsistent variables in the permalinks page ([#9591]({{ site.repository }}/issues/9591)) +- Fix lapses in documentation of page variables ([#9667]({{ site.repository }}/issues/9667)) +- Add note about VSCode warning for SCSS files ([#9609]({{ site.repository }}/issues/9609)) +- docs: Fix incorrect parentheses ([#9629]({{ site.repository }}/issues/9629)) +- docs: Fix of a bug in the pagination section ([#8890]({{ site.repository }}/issues/8890)) +- Update current Ruby version renders and macOS docs ([#9614]({{ site.repository }}/issues/9614)) +- Improve docs around using GitHub Actions to build and deploy Jekyll sites ([#9682]({{ site.repository }}/issues/9682)) +- Fix grammar in the description of `page.excerpt` variable ([#9689]({{ site.repository }}/issues/9689)) +- Render HTML tables at `/docs/permalinks/` using a data file ([#9666]({{ site.repository }}/issues/9666)) +- Fix HTML attribute separation whitespace placement in the Navigation include code of Assets step of the Step by Step Tutorial ([#9695]({{ site.repository }}/issues/9695)) +- Fix missing glob matching pattern support description in the documentation of the `include` and `exclude` configuration options ([#9697]({{ site.repository }}/issues/9697)) +- Fix missing `url` configuration option documentation ([#9699]({{ site.repository }}/issues/9699)) +- Link to GitHub Pages Dependency versions page instead of explicitly specifying Jekyll version ([#9715]({{ site.repository }}/issues/9715)) +- Fix broken link on third-party.md ([#9704]({{ site.repository }}/issues/9704)) +- Fix: remove inaccessible links and their descriptions ([#9745]({{ site.repository }}/issues/9745)) +- Add release post for v4.4.0 ([#9759]({{ site.repository }}/issues/9759)) + +### Site Enhancements +{: #site-enhancements-v4-4-0} + +- Extract markup for `Improve this page` into an inclusion ([#9675]({{ site.repository }}/issues/9675)) + + +## 4.3.4 / 2024-09-16 +{: #v4-3-4} + +### Bug Fixes +{: #bug-fixes-v4-3-4} + +- Backport [#9662]({{ site.repository }}/issues/9662) for v4.3.x: Relax version constraint on wdm in new Gemfile ([#9683]({{ site.repository }}/issues/9683)) +- Backport [#9680]({{ site.repository }}/issues/9680) for v4.3.x: Render theme-gem root only in development ([#9684]({{ site.repository }}/issues/9684)) + +### Development Fixes +{: #development-fixes-v4-3-4} + +- Sync workflows with counterparts on `master` ([#9681]({{ site.repository }}/issues/9681)) + + +## 4.3.3 / 2023-12-27 +{: #v4-3-3} + +### Bug Fixes +{: #bug-fixes-v4-3-3} + +- Backport [#9392]({{ site.repository }}/issues/9392) for v4.3.x: Fix backward compatibility issues in the Logger ([#9510]({{ site.repository }}/issues/9510)) + +### Development Fixes +{: #development-fixes-v4-3-3} + +- Backport [#9237]({{ site.repository }}/issues/9237) for v4.3.x: Use Hash explicitly for Struct initializer ([#9285]({{ site.repository }}/issues/9285)) + + +## 3.10.0 / 2024-06-23 +{: #v3-10-0} + +### Minor Enhancements +{: #minor-enhancements-v3-10-0} + +- Backport add-csv-dependency from [#9522]({{ site.repository }}/issues/9522) to Jekyll 3 ([#9616]({{ site.repository }}/issues/9616)) +- 3.10-stable: Add webrick as a dependency ([#9620]({{ site.repository }}/issues/9620)) + + +## 3.9.5 / 2024-02-12 +{: #v3-9-5} + +### Minor Enhancements +{: #minor-enhancements-v3-9-5} + +- 3.9-stable: allow Pages to be Excerpted ([#9550]({{ site.repository }}/issues/9550)) + + +## 3.9.4 / 2023-12-28 +{: #v3-9-4} + +### Bug Fixes +{: #bug-fixes-v3-9-4} + +- Backport [#9392]({{ site.repository }}/issues/9392) for v3.9.x: Add support for Ruby 3.3 Logger ([#9513]({{ site.repository }}/issues/9513)) + + +## 3.9.3 / 2023-01-29 +{: #v3-9-3} + +### Bug Fixes +{: #bug-fixes-v3-9-3} + +- 3.9.x: Support i18n 1.x ([#9269]({{ site.repository }}/issues/9269)) +- Backport [#8880]({{ site.repository }}/issues/8880) for v3.9.x: Support both tzinfo v1 and v2 along with non-half hour offsets ([#9280]({{ site.repository }}/issues/9280)) + +### Development Fixes +{: #development-fixes-v3-9-3} + +- v3.9.x: test under Ruby 3.2 [#9272]({{ site.repository }}/issues/9272)) +- v3.9.x: fix rdiscount test ([#9277]({{ site.repository }}/issues/9277)) + + +## 4.3.2 / 2023-01-20 +{: #v4-3-2} + +### Bug Fixes +{: #bug-fixes-v4-3-2} + +- Backport [#9257]({{ site.repository }}/issues/9257) for v4.3.x: Rename sass partial created for new blank site ([#9262]({{ site.repository }}/issues/9262)) +- Backport [#9187]({{ site.repository }}/issues/9187) for v4.3.x: Optimize `Site#each_site_file` ([#9256]({{ site.repository }}/issues/9256)) +- Backport [#9186]({{ site.repository }}/issues/9186) for v4.3.x: Remove totals in profile table properly ([#9255]({{ site.repository }}/issues/9255)) + +### Development Fixes +{: #development-fixes-v4-3-2} + +- Backport [#9223]({{ site.repository }}/issues/9223) for 4.3.x: Update sass related tests for jekyll-sass-converter 3.x ([#9254]({{ site.repository }}/issues/9254)) + + +## 4.3.1 / 2022-10-26 +{: #v4-3-1} + +### Bug Fixes +{: #bug-fixes-v4-3-1} + +- Respect user-defined name attribute in documents ([#9167]({{ site.repository }}/issues/9167)) +- Revert "Incrementally rebuild when a data file is changed" ([#9170]({{ site.repository }}/issues/9170)) + +### Documentation + +- Release post for v4.3.1 ([#9171]({{ site.repository }}/issues/9171)) + + +## 4.3.0 / 2022-10-20 +{: #v4-3-0} + +### Minor Enhancements +{: #minor-enhancements-v4-3-0} + +- Add webrick as a dependency ([#8524]({{ site.repository }}/issues/8524)) +- Regenerate supported mime types ([#8542]({{ site.repository }}/issues/8542)) +- Update include tag to be more permissive ([#8618]({{ site.repository }}/issues/8618)) +- Optimize `Jekyll::Utils.parse_date` ([#8425]({{ site.repository }}/issues/8425)) +- Update rubocop from 1.12 to 1.18 and min ruby from 2.4 to 2.5 ([#8741]({{ site.repository }}/issues/8741)) +- Always hide cache-dir contents from Git ([#8798]({{ site.repository }}/issues/8798)) +- Remove the warning about auto-regeneration on Windows ([#8821]({{ site.repository }}/issues/8821)) +- Propagate _data folder from theme ([#8815]({{ site.repository }}/issues/8815)) +- Support both tzinfo v1 and v2 along with non-half hour offsets. ([#8880]({{ site.repository }}/issues/8880)) +- Run vendor-mimes to update mime.types ([#8940]({{ site.repository }}/issues/8940)) +- Expose collection static files via `site.static_files` ([#8961]({{ site.repository }}/issues/8961)) +- Expose `basename` from `document.rb` as `name` to Liquid templates ([#8761]({{ site.repository }}/issues/8761)) +- Allow Configurable Converters on CSV ([#8858]({{ site.repository }}/issues/8858)) +- Introduce `theme` drop to expose theme-gem details ([#9129]({{ site.repository }}/issues/9129)) +- Relax version constraint to allow Rouge 4.x ([#9134]({{ site.repository }}/issues/9134)) +- Incrementally rebuild when a data file is changed ([#8771]({{ site.repository }}/issues/8771)) +- Support jekyll-sass-converter 3.x ([#9132]({{ site.repository }}/issues/9132)) + +### Bug Fixes +{: #bug-fixes-v4-3-0} + +- fix: pin rubocop to 1.12 due to error with ruby 2.4 ([#8651]({{ site.repository }}/issues/8651)) +- Load Jekyll plugins from BUNDLE_GEMFILE location ([#8585]({{ site.repository }}/issues/8585)) +- fix(security): CVE-2021-28834 ([#8680]({{ site.repository }}/issues/8680)) +- Inject livereload script using `location.protocol` instead of `http:` ([#8718]({{ site.repository }}/issues/8718)) +- Respect collections_dir config within include tag ([#8756]({{ site.repository }}/issues/8756)) +- Fix regression in Convertible module from v4.2.0 ([#8786]({{ site.repository }}/issues/8786)) +- Revert [#7253]({{ site.repository }}/issues/7253): "Don't reset site.url to localhost:4000 by default" ([#8620]({{ site.repository }}/issues/8620)) +- Improve readability of CI logs ([#8877]({{ site.repository }}/issues/8877)) +- Fix deprecation message for missing doc method ([#8960]({{ site.repository }}/issues/8960)) +- Fix response header for content served via `jekyll serve` ([#8965]({{ site.repository }}/issues/8965)) +- Trigger livereload in sites without pages ([#8337]({{ site.repository }}/issues/8337)) +- Only enable BOM encoding option on UTF encodings ([#8363]({{ site.repository }}/issues/8363)) +- Ensure theme config is a `Jekyll::Configuration` object ([#8988]({{ site.repository }}/issues/8988)) +- Remove misleading totals row from `--profile` table ([#9039]({{ site.repository }}/issues/9039)) +- Unlock Psych dependency ([#9135]({{ site.repository }}/issues/9135)) +- Fix false positive conflicts for static files in a collection ([#9141]({{ site.repository }}/issues/9141)) + +### Development Fixes +{: #development-fixes-v4-3-0} + +- style: enable new cops ([#8538]({{ site.repository }}/issues/8538)) +- Allow dependabot to keep github actions up-to-date ([#8540]({{ site.repository }}/issues/8540)) +- Update actions/cache requirement to v2.1.3 ([#8543]({{ site.repository }}/issues/8543)) +- Pin rubocop version ([#8564]({{ site.repository }}/issues/8564)) +- style: add rubocop 1.9 cops ([#8567]({{ site.repository }}/issues/8567)) +- Cross Version Testing Locally and Faster CI ([#8610]({{ site.repository }}/issues/8610)) +- Use official Ruby setup GH action ([#8614]({{ site.repository }}/issues/8614)) +- Spell check action for markdown documentation ([#8675]({{ site.repository }}/issues/8675)) +- Update expect to cover docs/_posts ([#8677]({{ site.repository }}/issues/8677)) +- Bump check-spelling/check-spelling from 0.0.18 to 0.0.19 ([#8740]({{ site.repository }}/issues/8740)) +- Enable Rubocop accessor grouping, fix existing offenses ([#8293]({{ site.repository }}/issues/8293)) +- Tags:Highlight: Decomposed HTMLLegacy formatter ([#8623]({{ site.repository }}/issues/8623)) +- Relax Rubocop Dependency ([#8831]({{ site.repository }}/issues/8831)) +- Add a workflow to build gems consistently ([#8830]({{ site.repository }}/issues/8830)) +- Fix random test failures in TestExcerpt #to_liquid ([#8884]({{ site.repository }}/issues/8884)) +- Lock gem `psych` to `v3.x` ([#8918]({{ site.repository }}/issues/8918)) +- Fix typo in Bug Report template ([#8951]({{ site.repository }}/issues/8951)) +- Check symlink outside site_source without Pathutil ([#9015]({{ site.repository }}/issues/9015)) +- Stop testing with Rubies older than 2.7 on non-Windows ([#8955]({{ site.repository }}/issues/8955)) +- Bump actions/checkout from 2 to 3 ([#8986]({{ site.repository }}/issues/8986)) +- Remove git.io shortlinks from repo ([#9045]({{ site.repository }}/issues/9045)) +- Bump rubocop to 1.32 ([#9093]({{ site.repository }}/issues/9093)) +- Bump RuboCop to `1.36.x` ([#9125]({{ site.repository }}/issues/9125)) +- Use check-spelling/check-spelling@v0.0.20 ([#9111]({{ site.repository }}/issues/9111)) +- Disable pending cops when running rubocop ([#9136]({{ site.repository }}/issues/9136)) +- Relax RDoc version dependency ([#9142]({{ site.repository }}/issues/9142)) + +### Documentation + +- typo - do instead of don't ([#8518]({{ site.repository }}/issues/8518)) +- Document support for TSV files consistently ([#8488]({{ site.repository }}/issues/8488)) +- Add a disclaimer to tutorials involving Ruby code ([#8525]({{ site.repository }}/issues/8525)) +- Improve documentation on developing generators ([#8527]({{ site.repository }}/issues/8527)) +- Fixes typo in layouts_dir documentation ([#8532]({{ site.repository }}/issues/8532)) +- Fix i.e. typos in collections.md ([#8529]({{ site.repository }}/issues/8529)) +- Remove GitHub Pages content which is in GitHub docs ([#8533]({{ site.repository }}/issues/8533)) +- Step By Step Instructions Review ([#8399]({{ site.repository }}/issues/8399)) +- Fix typo in migrating from 3.0 to 4.0 page ([#8572]({{ site.repository }}/issues/8572)) +- Fix for important missing step in macOS Installation Docs: Add the Homebrew gems directory to the PATH ([#8496]({{ site.repository }}/issues/8496)) +- Use latest Jekyll-action configuration ([#8579]({{ site.repository }}/issues/8579)) +- docs: troubleshoot macOS with ARM64 architecture ([#8560]({{ site.repository }}/issues/8560)) +- docs: add overview of .jekyll-cache dir ([#8648]({{ site.repository }}/issues/8648)) +- docs: clarify where .jekyll-metadata comes from ([#8646]({{ site.repository }}/issues/8646)) +- Razorops CI/CD added ([#8656]({{ site.repository }}/issues/8656)) +- Specify default port and host for serve commands in docs ([#8624]({{ site.repository }}/issues/8624)) +- Update third-party.md ([#8652]({{ site.repository }}/issues/8652)) +- Add documentation for Sass configuration options ([#8587]({{ site.repository }}/issues/8587)) +- Add formcarry to forms section ([#8471]({{ site.repository }}/issues/8471)) +- Add step to set SDKROOT ([#8478]({{ site.repository }}/issues/8478)) +- Improve the "Markdown Options" Docs ([#8681]({{ site.repository }}/issues/8681)) +- Add 'webrick' warning note to "Quickstart" Docs ([#8727]({{ site.repository }}/issues/8727)) +- Update windows.md ([#8701]({{ site.repository }}/issues/8701)) +- IRC networks - Libera, Freenode ([#8706]({{ site.repository }}/issues/8706)) +- Improve GitHub Flavored Markdown Docs ([#8684]({{ site.repository }}/issues/8684)) +- Fixing URL in MacOS install for rbenv-doctor ([#8693]({{ site.repository }}/issues/8693)) +- Fix adjective in `troubleshooting.md` document ([#8777]({{ site.repository }}/issues/8777)) +- Goodbye Frank. We'll miss you. 💔 ([#8807]({{ site.repository }}/issues/8807)) +- Update index.html: Grammar fix. ([#8803]({{ site.repository }}/issues/8803)) +- Prefer Libera. Remove Freenode. ([#8811]({{ site.repository }}/issues/8811)) +- Update feature_request.md ([#8797]({{ site.repository }}/issues/8797)) +- Remove AWS Amplify from the showcase ([#8812]({{ site.repository }}/issues/8812)) +- Move Frank to Emeritus Core Team Members ([#8813]({{ site.repository }}/issues/8813)) +- Release post for v4.2.1 ([#8818]({{ site.repository }}/issues/8818)) +- Update CircleCI example ([#8829]({{ site.repository }}/issues/8829)) +- Fix typo ([#8835]({{ site.repository }}/issues/8835)) +- Added docs for running locally ([#8852]({{ site.repository }}/issues/8852)) +- Linting README.markdown ([#8900]({{ site.repository }}/issues/8900)) +- Remove text on GITHUB_TOKEN which is now built-in ([#8907]({{ site.repository }}/issues/8907)) +- Add Security Policy document ([#8823]({{ site.repository }}/issues/8823)) +- Manage repository meta documents consistently ([#8908]({{ site.repository }}/issues/8908)) +- docs: add Layer0 deployment guide ([#8915]({{ site.repository }}/issues/8915)) +- docs: Update README generated by `jekyll new-theme` ([#8919]({{ site.repository }}/issues/8919)) +- Update resources.md ([#8925]({{ site.repository }}/issues/8925)) +- Rewrite documentation on installing plugins ([#8921]({{ site.repository }}/issues/8921)) +- Improve maintainers guide on releasing a new version ([#8928]({{ site.repository }}/issues/8928)) +- Fix link for "CloudSh" ([#8934]({{ site.repository }}/issues/8934)) +- Recommend using `actions/cache` in GitHub Actions documentation ([#8948]({{ site.repository }}/issues/8948)) +- Remove references to EOL hakiri.io service ([#8946]({{ site.repository }}/issues/8946)) +- Release post for v4.2.2 ([#8982]({{ site.repository }}/issues/8982)) +- Document releasing off `*-stable` branches ([#8984]({{ site.repository }}/issues/8984)) +- Update document by fix yaml syntax error ([#8991]({{ site.repository }}/issues/8991)) +- Enhance option's case for Jekyll configuration ([#8992]({{ site.repository }}/issues/8992)) +- Fix typo in `_docs/deployment/manual.md` ([#8997]({{ site.repository }}/issues/8997)) +- Add quiet/verbose options ([#8996]({{ site.repository }}/issues/8996)) +- Update README.markdown re IRC Pointer ([#9005]({{ site.repository }}/issues/9005)) +- Remove Aerobatic ([#9007]({{ site.repository }}/issues/9007)) +- Add Jekyll 3.9.2 release post to 'master' branch ([#9013]({{ site.repository }}/issues/9013)) +- Simplify macOS installation docs ([#8993]({{ site.repository }}/issues/8993)) +- Improve document about GitHub Actions section ([#8853]({{ site.repository }}/issues/8853)) +- Update permalinks.md ([#9017]({{ site.repository }}/issues/9017)) +- Add clarity to docs on permalinks placeholders and built-ins ([#8995]({{ site.repository }}/issues/8995)) +- Remove Ionic Framework site from showcase ([#9057]({{ site.repository }}/issues/9057)) +- Windows: describe which option to choose ([#9049]({{ site.repository }}/issues/9049)) +- Improve links (http -> https) ([#9064]({{ site.repository }}/issues/9064)) +- Update ruby version for macos guide ([#9086]({{ site.repository }}/issues/9086)) +- Update posts.md ([#9151]({{ site.repository }}/issues/9151)) +- Release post for v4.3.0 ([#9157]({{ site.repository }}/issues/9157)) + +### Site Enhancements +{: #site-enhancements-v4-3-0} + +- Improvements to CSS ([#7834]({{ site.repository }}/issues/7834)) +- Slightly update lang `sh` code-block styling ([#8857]({{ site.repository }}/issues/8857)) + + +## 4.2.2 / 2022-03-03 +{: #v4-2-2} + +### Bug Fixes +{: #bug-fixes-v4-2-2} + +- Lock `http_parser.rb` gem to `v0.6.x` on JRuby. + +### Development Fixes +{: #development-fixes-v4-2-2} + +- Backport [#8830]({{ site.repository }}/issues/8830) for v4.2.x: Add a workflow to build gems consistently ([#8869]({{ site.repository }}/issues/8869)) +- Lock `rubocop-performance` to `v1.11.x`. + + +## 4.2.1 / 2021-09-27 +{: #v4-2-1} + +### Bug Fixes +{: #bug-fixes-v4-2-1} + +- Backport [#8620]({{ site.repository }}/issues/8620) for v4.2.x: Revert [#7253]({{ site.repository }}/issues/7253): "Don't reset site.url to localhost:4000 by default" ([#8808]({{ site.repository }}/issues/8808)) +- Backport [#8756]({{ site.repository }}/issues/8756) for v4.2.x: Respect collections_dir config within include tag ([#8794]({{ site.repository }}/issues/8794)) +- Backport [#8786]({{ site.repository }}/issues/8786) for v4.2.x: Fix regression in Convertible module from v4.2.0 ([#8793]({{ site.repository }}/issues/8793)) + + +## 4.2.0 / 2020-12-14 +{: #v4-2-0} + +### Minor Enhancements +{: #minor-enhancements-v4-2-0} + +- Warn on command-line with permalink conflict ([#8342]({{ site.repository }}/issues/8342)) +- Suppress warning issued for redirect pages ([#8347]({{ site.repository }}/issues/8347)) +- Enhance detection of conflicting destination URLs ([#8459]({{ site.repository }}/issues/8459)) +- Add `:post_convert` hook to modify HTML content before layout ([#8368]({{ site.repository }}/issues/8368)) +- Allow triggering `:post_convert` events atomically ([#8465]({{ site.repository }}/issues/8465)) +- Debug reading Page and Layout objects ([#8100]({{ site.repository }}/issues/8100)) +- Do not reset `site.url` to `http://localhost:4000` by default ([#7253]({{ site.repository }}/issues/7253)) +- Add custom debug strings for Jekyll objects ([#8473]({{ site.repository }}/issues/8473)) +- Debug reading data files in a site ([#8481]({{ site.repository }}/issues/8481)) + +### Bug Fixes +{: #bug-fixes-v4-2-0} + +- Replace nested conditional with guard clauses ([#8294]({{ site.repository }}/issues/8294)) +- Fix: security bump ([#8349]({{ site.repository }}/issues/8349)) +- Fix path matching regex in post_url Liquid tag ([#8375]({{ site.repository }}/issues/8375)) +- Enable `Performance/ChainArrayAllocation` cop ([#8404]({{ site.repository }}/issues/8404)) +- Enable Lint/NoReturnInBeginEndBlocks Cop ([#8457]({{ site.repository }}/issues/8457)) +- Generate items from `site.include` list only once ([#8463]({{ site.repository }}/issues/8463)) +- Explicitly return nil after site process phase ([#8472]({{ site.repository }}/issues/8472)) + +### Optimization Fixes +{: #optimization-fixes-v4-2-0} + +- Implement custom delegators for drop methods ([#8183]({{ site.repository }}/issues/8183)) +- Handle `nil` argument to `Jekyll.sanitized_path` ([#8415]({{ site.repository }}/issues/8415)) +- Cache `Jekyll.sanitized_path` ([#8424]({{ site.repository }}/issues/8424)) +- Memoize array of drop getter method names ([#8421]({{ site.repository }}/issues/8421)) +- Reduce string allocations from the `link` tag ([#8387]({{ site.repository }}/issues/8387)) +- Optimize parsing of parameters in `include` tag ([#8192]({{ site.repository }}/issues/8192)) +- Stash documents `write?` attribute in a variable ([#8389]({{ site.repository }}/issues/8389)) +- Reduce string allocations from generating doc URLs ([#8392]({{ site.repository }}/issues/8392)) +- Check if site is in incremental mode optimally ([#8401]({{ site.repository }}/issues/8401)) +- Utilize flexibility of `Site#in_dest_dir` ([#8403]({{ site.repository }}/issues/8403)) +- Reduce allocations from rendering item as liquid ([#8406]({{ site.repository }}/issues/8406)) +- Compute relative_path of pages using PathManager ([#8408]({{ site.repository }}/issues/8408)) +- Reduce allocation from `normalize_whitespace` filter ([#8400]({{ site.repository }}/issues/8400)) +- Use `Regexp#match?` when `MatchData` is not required ([#8427]({{ site.repository }}/issues/8427)) +- Check default front matter scope against symbols ([#8393]({{ site.repository }}/issues/8393)) +- Stash frequently used `Drop` setter keys for reuse ([#8394]({{ site.repository }}/issues/8394)) +- Memoize defaults computed for Convertibles ([#8451]({{ site.repository }}/issues/8451)) +- Reduce array allocations from merging categories ([#8453]({{ site.repository }}/issues/8453)) +- Memoize destination of pages, documents and staticfiles ([#8458]({{ site.repository }}/issues/8458)) +- Reduce allocations from computing item property ([#8485]({{ site.repository }}/issues/8485)) +- Optimize `Page#dir` with a private method ([#8489]({{ site.repository }}/issues/8489)) +- Stash attribute hash for Liquid computed for pages ([#8497]({{ site.repository }}/issues/8497)) + +### Development Fixes +{: #development-fixes-v4-2-0} + +- Update cucumber gem to version 4.1 ([#8278]({{ site.repository }}/issues/8278)) +- Move permalink styles data to constant ([#8282]({{ site.repository }}/issues/8282)) +- Update rubocop gem to 0.87.1 ([#8287]({{ site.repository }}/issues/8287)) +- Update RuboCop to-do file ([#8296]({{ site.repository }}/issues/8296)) +- Fix `rake console` generating LoadError ([#8312]({{ site.repository }}/issues/8312)) +- Configure Performance cops ([#8369]({{ site.repository }}/issues/8369)) +- Update rubocop gem to 0.90.0 ([#8313]({{ site.repository }}/issues/8313)) +- Refactor `Jekyll::Utils::Platforms` ([#7236]({{ site.repository }}/issues/7236)) +- Bump RuboCop to v0.91.x ([#8391]({{ site.repository }}/issues/8391)) +- Add workflow to build and profile third-party repo ([#8398]({{ site.repository }}/issues/8398)) +- Bump RuboCop to v0.92.x +- Update cucumber gem version to 5.1.2 ([#8413]({{ site.repository }}/issues/8413)) +- Fix test suite compatibility with JRuby ([#8418]({{ site.repository }}/issues/8418)) +- chore(deps): bump Rubocop to 0.93.0 ([#8430]({{ site.repository }}/issues/8430)) +- Use Ruby 2.7.1 in GitHub Actions ([#8444]({{ site.repository }}/issues/8444)) +- Test that Liquid expressions are not deeply evaled ([#8292]({{ site.repository }}/issues/8292)) +- Test rendering arbitrary Liquid variables by default ([#7414]({{ site.repository }}/issues/7414)) +- Migrate TravisCI jobs to GitHub Actions ([#8492]({{ site.repository }}/issues/8492)) + +### Documentation + +- Update pointer to special permalink variables for collections ([#8274]({{ site.repository }}/issues/8274)) +- Fix special treatment for 'page 1' in docs of pagination ([#8230]({{ site.repository }}/issues/8230)) +- Add Formcake to forms section ([#8283]({{ site.repository }}/issues/8283)) +- Add a note on the rendering process in the docs ([#8291]({{ site.repository }}/issues/8291)) +- Add refactoring type to PULL_REQUEST_TEMPLATE ([#8297]({{ site.repository }}/issues/8297)) +- Update resources.md ([#7864]({{ site.repository }}/issues/7864)) +- Extra apostrophes in an URL ([#8319]({{ site.repository }}/issues/8319)) +- Clarify target of subordinate clause ([#8320]({{ site.repository }}/issues/8320)) +- Cherry-pick commits from conflicting branch `docs-40` +- Update documentation on third party site ([#8352]({{ site.repository }}/issues/8352)) +- Update default.md with info requested in [#8314]({{ site.repository }}/issues/8314) ([#8353]({{ site.repository }}/issues/8353)) +- Clarify description of `safe` option ([#8354]({{ site.repository }}/issues/8354)) +- Simplifying the Git post-receive hook-example ([#8358]({{ site.repository }}/issues/8358)) +- Add missing doc for build and serve commands ([#8365]({{ site.repository }}/issues/8365)) +- Docs Review: Getting Started ([#8372]({{ site.repository }}/issues/8372)) +- Add note about rebooting system after installation ([#8359]({{ site.repository }}/issues/8359)) +- Use data file to render table at `/docs/configuration/options/#global-configuration` ([#8377]({{ site.repository }}/issues/8377)) +- Use data file(s) to render table(s) at `/docs/configuration/options/` ([#8380]({{ site.repository }}/issues/8380)) +- Improve maintainability of config option data ([#8383]({{ site.repository }}/issues/8383)) +- Remove CircleCI v1 docs ([#8410]({{ site.repository }}/issues/8410)) +- Remove `NOKOGIRI_USE_SYSTEM_LIBRARIES` from Travis CI docs ([#8409]({{ site.repository }}/issues/8409)) +- Add links to all Jekyll themes on GitHub tagged with #jekyll-theme ([#8447]({{ site.repository }}/issues/8447)) +- Document initializing project Gemfile from scratch ([#8450]({{ site.repository }}/issues/8450)) +- Document installation of additional dependencies for installing Jekyll on Fedora ([#8456]({{ site.repository }}/issues/8456)) +- Improve documentation on Hooks in Jekyll ([#8467]({{ site.repository }}/issues/8467)) +- Build docs site with GitHub Actions ([#8201]({{ site.repository }}/issues/8201)) +- Add link to Assets page from `_sass` section in `_docs/structure.md` ([#8486]({{ site.repository }}/issues/8486)) + +### Site Enhancements +{: #site-enhancements-v4-2-0} + +- Fix rendering of *showcase* images ([#8504]({{ site.repository }}/issues/8504)) + + +## 4.1.1 / 2020-06-24 +{: #v4-1-1} + +### Bug Fixes +{: #bug-fixes-v4-1-1} + +- Disable page excerpts by default ([#8222]({{ site.repository }}/issues/8222)) +- Revert introduction of PageDrop ([#8221]({{ site.repository }}/issues/8221)) +- Don't generate excerpts for non-html pages ([#8234]({{ site.repository }}/issues/8234)) +- Make page excerpts consistent with doc excerpts ([#8236]({{ site.repository }}/issues/8236)) + +### Documentation + +- Replace deprecated 'show' command with 'info' ([#8235]({{ site.repository }}/issues/8235)) +- Change name to ▲Vercel ([#8247]({{ site.repository }}/issues/8247)) +- Add language and examples to describe how to use the configuration op… ([#8249]({{ site.repository }}/issues/8249)) +- Fix missing yaml front matter colon and adjust/add clarifying language. ([#8250]({{ site.repository }}/issues/8250)) +- correct typo ([#8261]({{ site.repository }}/issues/8261)) +- Allow hyperlinks to specific filter documentation ([#8231]({{ site.repository }}/issues/8231)) +- Update link to Netlify step-by-step guide ([#8264]({{ site.repository }}/issues/8264)) +- Fix grammar in documentation section ([#8265]({{ site.repository }}/issues/8265)) + +### Site Enhancements +{: #site-enhancements-v4-1-1} + +- Including correct Sketch website ([#8241]({{ site.repository }}/issues/8241)) +- Release post for v4.1.1 ([#8243]({{ site.repository }}/issues/8243)) + +### Development Fixes +{: #development-fixes-v4-1-1} + +- Bump RuboCop to v0.85.x ([#8223]({{ site.repository }}/issues/8223)) +- Expect drive letter only on vanilla windows ([#8227]({{ site.repository }}/issues/8227)) + + +## 4.1.0 / 2020-05-27 +{: #v4-1-0} + +### Bug Fixes +{: #bug-fixes-v4-1-0} + +- Memoize `absolute_url` and `relative_url` filters ([#7793]({{ site.repository }}/issues/7793)) +- Fix documentation comment for `Jekyll::Converters::Identity` ([#7883]({{ site.repository }}/issues/7883)) +- Optimize `Jekyll::Filters#item_property` ([#7696]({{ site.repository }}/issues/7696)) +- Allow multiple binary operators in `where_exp` filter ([#8047]({{ site.repository }}/issues/8047)) +- Fix documents custom-ordering logic ([#8028]({{ site.repository }}/issues/8028)) +- Use `layout.path` when rendering the Liquid layout ([#8069]({{ site.repository }}/issues/8069)) +- Reduce array allocations from `StaticFile#path` ([#8083]({{ site.repository }}/issues/8083)) +- Simplify `Jekyll::Renderer#validate_layout` ([#8064]({{ site.repository }}/issues/8064)) +- Add static file's basename to its `url_placeholder` ([#7908]({{ site.repository }}/issues/7908)) +- Clear cached Liquid template scope before render ([#7967]({{ site.repository }}/issues/7967)) +- Cache `URLFilter` results of string inputs per site ([#7990]({{ site.repository }}/issues/7990)) +- Use `platforms` instead of `install_if` in Gemfile ([#8140]({{ site.repository }}/issues/8140)) +- Config include trailing slash ([#8113]({{ site.repository }}/issues/8113)) +- Improve path normalization in liquid_renderer ([#8075]({{ site.repository }}/issues/8075)) +- Switch slugify regex to support more Unicode character groups ([#8167]({{ site.repository }}/issues/8167)) +- Check if entry is a directory once per enumerator ([#8177]({{ site.repository }}/issues/8177)) +- Filter out exclusively excluded entries sooner ([#7482]({{ site.repository }}/issues/7482)) +- Return `relative_url` if site.url is an empty string ([#7988]({{ site.repository }}/issues/7988)) +- Configure kramdown toc_levels as array by default ([#8015]({{ site.repository }}/issues/8015)) +- Reduce `Pathname` objects from front matter defaults ([#8067]({{ site.repository }}/issues/8067)) +- Simplify `Jekyll::Hooks.trigger` logic ([#8044]({{ site.repository }}/issues/8044)) +- Quicker categories for documents without superdirs ([#7987]({{ site.repository }}/issues/7987)) +- Reduce `Jekyll::Renderer` instances during a build ([#7570]({{ site.repository }}/issues/7570)) +- Escape regex characters in paths to match ([#8138]({{ site.repository }}/issues/8138)) +- Provide invokables for common drop query keys ([#8165]({{ site.repository }}/issues/8165)) +- Optimize path sanitization of default front matter ([#8154]({{ site.repository }}/issues/8154)) +- Initialize static files' data hash only if needed ([#8188]({{ site.repository }}/issues/8188)) +- Initialize include-files as Jekyll objects ([#8158]({{ site.repository }}/issues/8158)) + +### Minor Enhancements +{: #minor-enhancements-v4-1-0} + +- serve: add support for ECC certificates ([#7768]({{ site.repository }}/issues/7768)) +- Update `item_property` to recognize integers ([#7878]({{ site.repository }}/issues/7878)) +- Include `_config.yml` in a new theme's gemspec ([#7865]({{ site.repository }}/issues/7865)) +- Add an option to easily disable disk-cache ([#7928]({{ site.repository }}/issues/7928)) +- Optimize markdown parsing with Kramdown by reusing the options and parser objects ([#8013]({{ site.repository }}/issues/8013)) +- Add `PageDrop` to provide Liquid templates with data ([#7992]({{ site.repository }}/issues/7992)) +- Optimize `Kramdown::JekyllDocument#to_html` calls ([#8041]({{ site.repository }}/issues/8041)) +- Configure default language for syntax-highlighting ([#8035]({{ site.repository }}/issues/8035)) +- Remove dev dependencies from new theme-gem gemspec ([#8042]({{ site.repository }}/issues/8042)) +- Allow disabling import of theme configuration ([#8131]({{ site.repository }}/issues/8131)) +- Allow excerpts to be generated for `Page` objects ([#7642]({{ site.repository }}/issues/7642)) +- Profile various stages of a site's build process ([#6760]({{ site.repository }}/issues/6760)) +- Add find filters to optimize where-first chains ([#8171]({{ site.repository }}/issues/8171)) +- Make `number_of_words` filter respect CJK characters ([#7813]({{ site.repository }}/issues/7813)) +- Allow extensionless document in a strict site ([#7950]({{ site.repository }}/issues/7950)) +- Add `:slugified_categories` URL placeholder ([#8094]({{ site.repository }}/issues/8094)) + +### Documentation + +- Add dropped 'title: Staff' to the code ([#7805]({{ site.repository }}/issues/7805)) +- Clarify docs for static files in collection ([#7812]({{ site.repository }}/issues/7812)) +- Rephrase the CircleCI v2 section ([#7815]({{ site.repository }}/issues/7815)) +- Update old GitHub wiki URL with new one ([#7823]({{ site.repository }}/issues/7823)) +- Update JekyllConf page with 2019 talks ([#7826]({{ site.repository }}/issues/7826)) +- link for memberships ([#7825]({{ site.repository }}/issues/7825)) +- Doc: minor fix, should be greater or equal to min version ([#7856]({{ site.repository }}/issues/7856)) +- Update third-party.md - Fix broken link ([#7857]({{ site.repository }}/issues/7857)) +- clarify _config.yml/collections type ([#7873]({{ site.repository }}/issues/7873)) +- Replace backticks with HTML tags in data file ([#7879]({{ site.repository }}/issues/7879)) +- add new theme source ([#7875]({{ site.repository }}/issues/7875)) +- fixed grammatical error (it's --> its) ([#7887]({{ site.repository }}/issues/7887)) +- Docs: Clarify organizing pages into subfolders ([#7896]({{ site.repository }}/issues/7896)) +- Disambiguate the placeholder of permalink ([#7906]({{ site.repository }}/issues/7906)) +- docs: add short serve command for livereload ([#7919]({{ site.repository }}/issues/7919)) +- docs: add options for watch and force polling ([#7918]({{ site.repository }}/issues/7918)) +- add install instructions for ArchLinux and openSUSE ([#7920]({{ site.repository }}/issues/7920)) +- Improve index page of Jekyll documentation ([#7926]({{ site.repository }}/issues/7926)) +- Include path in `jekyll new` commands (Usage docs) ([#7931]({{ site.repository }}/issues/7931)) +- Change `affect` to `effect` in the collections docs ([#7937]({{ site.repository }}/issues/7937)) +- Changed deprecated command in themes documentation ([#7941]({{ site.repository }}/issues/7941)) +- Adds some documentation for the `:clean`, `:on_obsolete` hook ([#7954]({{ site.repository }}/issues/7954)) +- docs: fix broken link ([#7955]({{ site.repository }}/issues/7955)) +- Corrected typo ([#7975]({{ site.repository }}/issues/7975)) +- docs: remove watch option in config ([#7940]({{ site.repository }}/issues/7940)) +- Correct a sentence in the documentation ([#7978]({{ site.repository }}/issues/7978)) +- Fix YAML representation of `group_by` result ([#7979]({{ site.repository }}/issues/7979)) +- Move `--baseurl` to build command options ([#7985]({{ site.repository }}/issues/7985)) +- Correct documentation of filters ([#7989]({{ site.repository }}/issues/7989)) +- Document sorting two documents by their `date` ([#7870]({{ site.repository }}/issues/7870)) +- Fix English grammar error ([#7994]({{ site.repository }}/issues/7994)) +- Update 03-front-matter.md ([#7996]({{ site.repository }}/issues/7996)) +- Add Kentico Kontent CMS integration to resources ([#8000]({{ site.repository }}/issues/8000)) +- Update 07-assets.md ([#7413]({{ site.repository }}/issues/7413)) +- Fix file references in Step by Step Tutorial's Assets step ([#8007]({{ site.repository }}/issues/8007)) +- docs: improve highlighting of code blocks ([#8017]({{ site.repository }}/issues/8017)) +- remove leading slash from Sass file location ([#8021]({{ site.repository }}/issues/8021)) +- [Docs] Fix asset link ref in step-by-step tutorial ([#8026]({{ site.repository }}/issues/8026)) +- Corrected command to modify PATH ([#8029]({{ site.repository }}/issues/8029)) +- Corrected command to modify PATH ([#8030]({{ site.repository }}/issues/8030)) +- Docs: Render full contents of just the latest post ([#8032]({{ site.repository }}/issues/8032)) +- docs: improvements for note boxes ([#8037]({{ site.repository }}/issues/8037)) +- Non-deprecated `vendor/bundle` path configuration ([#8048]({{ site.repository }}/issues/8048)) +- Update 09-collections.md ([#8060]({{ site.repository }}/issues/8060)) +- Remove extra paragraph tags ([#8063]({{ site.repository }}/issues/8063)) +- Add default front matter for tutorials collection ([#8081]({{ site.repository }}/issues/8081)) +- Create CSV to table tutorial ([#8090]({{ site.repository }}/issues/8090)) +- Add version badge for Custom Sorting of Documents ([#8098]({{ site.repository }}/issues/8098)) +- Docs: Fix grammar in `_docs/front-matter.md` ([#8097]({{ site.repository }}/issues/8097)) +- Update variables.md ([#8106]({{ site.repository }}/issues/8106)) +- Add help about Gentoo/Linux ([#8002]({{ site.repository }}/issues/8002)) +- Update documentation on third party site ([#8122]({{ site.repository }}/issues/8122)) +- Added Clear Linux ([#8132]({{ site.repository }}/issues/8132)) +- Added note about OS specific installation instructions. ([#8135]({{ site.repository }}/issues/8135)) +- Fix broken URL in the Resources Page on the Documentation Site ([#8136]({{ site.repository }}/issues/8136)) +- Docs: Deploy Jekyll site with GitHub Actions ([#8119]({{ site.repository }}/issues/8119)) +- Clarify `bundle config` in Bundler tutorial ([#8150]({{ site.repository }}/issues/8150)) +- docs: update your-first-plugin.md ([#8147]({{ site.repository }}/issues/8147)) +- Fix typo in documentation on GitHub Actions ([#8162]({{ site.repository }}/issues/8162)) +- Ease discovery of CLI commands (in their entirety) ([#8178]({{ site.repository }}/issues/8178)) +- Remove `sudo` from Travis CI tutorial ([#8187]({{ site.repository }}/issues/8187)) +- Add GitLab Pages to 3rd party list ([#8191]({{ site.repository }}/issues/8191)) +- docs: add 21yunbox for deployment ([#8193]({{ site.repository }}/issues/8193)) +- Improve documentation on tags and categories ([#8196]({{ site.repository }}/issues/8196)) + +### Development Fixes +{: #development-fixes-v4-1-0} + +- Ci/GitHub actions ([#7822]({{ site.repository }}/issues/7822)) +- Rubocop version upgrade ([#7846]({{ site.repository }}/issues/7846)) +- Split action steps to avoid using `&&` on Windows ([#7885]({{ site.repository }}/issues/7885)) +- Upgrade rake to use version 13 ([#7910]({{ site.repository }}/issues/7910)) +- Update dependency constraint to allow RuboCop v0.76 ([#7893]({{ site.repository }}/issues/7893)) +- Use bash executable consistently ([#7909]({{ site.repository }}/issues/7909)) +- Test with JRuby 9.2.9.0 ([#7779]({{ site.repository }}/issues/7779)) +- Bump RuboCop to v0.79.x ([#7970]({{ site.repository }}/issues/7970)) +- Remove post-install message from gemspec ([#7974]({{ site.repository }}/issues/7974)) +- Attain Ruby 3.0 compatibility ([#7948]({{ site.repository }}/issues/7948)) +- Test `where` filter handling numeric property values ([#7821]({{ site.repository }}/issues/7821)) +- chore(deps): rubocop 0.80.0 ([#8012]({{ site.repository }}/issues/8012)) +- Update unit tests for Kramdown-based converter ([#8014]({{ site.repository }}/issues/8014)) +- Add Visual Studio Code Development Container ([#8016]({{ site.repository }}/issues/8016)) +- chore: simplify require for `Jekyll::VERSION` ([#8057]({{ site.repository }}/issues/8057)) +- Remove version-constraint relaxation for i18n gem ([#8055]({{ site.repository }}/issues/8055)) +- Mirror `spec.homepage` as `metadata["homepage_uri"]` ([#8056]({{ site.repository }}/issues/8056)) +- Bump Ruby versions on Travis builds ([#8088]({{ site.repository }}/issues/8088)) +- chore(ci): cache dependencies ([#8168]({{ site.repository }}/issues/8168)) + +### Site Enhancements +{: #site-enhancements-v4-1-0} + +- Optimize rendering of the documentation site ([#8020]({{ site.repository }}/issues/8020)) +- Utilize `relative_url` filter in documentation site ([#8089]({{ site.repository }}/issues/8089)) +- Render tutorial metadata in documentation site ([#8092]({{ site.repository }}/issues/8092)) +- Improve syntax-highlighting in documentation site ([#8079]({{ site.repository }}/issues/8079)) +- Site: Filter through just the *docs* collection ([#8170]({{ site.repository }}/issues/8170)) + + +## 4.0.1 / 2020-05-08 +{: #v4-0-1} + +### Bug Fixes +{: #bug-fixes-v4-0-1} + +- Prevent console warning with Ruby 2.7 ([#8124]({{ site.repository }}/issues/8124)) +- Clear cached Liquid template scope before render ([#8141]({{ site.repository }}/issues/8141)) +- Add static file's basename to its url_placeholder ([#8142]({{ site.repository }}/issues/8142)) +- Update item_property to recognize integers ([#8160]({{ site.repository }}/issues/8160)) + +### Development Fixes +{: #development-fixes-v4-0-1} + +- Fix Kramdown converter based tests for v4.0.x ([#8143]({{ site.repository }}/issues/8143)) + + +## 3.9.2 / 2022-03-27 +{: #v3-9-2} + +### Bug Fixes +{: #bug-fixes-v3-9-2} + +- Lock `http_parser.rb` gem to `v0.6.x` on JRuby ([#8943]({{ site.repository }}/issues/8943)) +- Backport [#8756]({{ site.repository }}/issues/8756) for v3.9.x: Respect collections_dir config within include tag ([#8795]({{ site.repository }}/issues/8795)) +- Backport [#8965]({{ site.repository }}/issues/8965) for v3.9.x: Fix response header for content served via `jekyll serve` ([#8976]({{ site.repository }}/issues/8976)) + +### Development Fixes +{: #development-fixes-v3-9-2} + +- Update and fix CI for `3.9-stable` on Ruby 3.x ([#8942]({{ site.repository }}/issues/8942)) +- Fix CI for commits to `3.9-stable` branch ([#8788]({{ site.repository }}/issues/8788)) + + +## 3.9.1 / 2021-04-08 +{: #v3-9-1} + +### Bug Fixes +{: #bug-fixes-v3-9-1} + +- Backport [#8618]({{ site.repository }}/issues/8618) for v3.9.x: Update include tag to be more permissive ([#8629]({{ site.repository }}/issues/8629)) + + +## 3.9.0 / 2020-08-05 +{: #v3-9-0} + +### Minor Enhancements +{: #minor-enhancements-v3-9-0} + +- Allow use of kramdown v2 ([#8322]({{ site.repository }}/issues/8322)) +- Add default language for kramdown syntax highlighting ([#8325]({{ site.repository }}/issues/8325)) + + +## 3.8.7 / 2020-05-08 +{: #v3-8-7} + +### Bug Fixes +{: #bug-fixes-v3-8-7} + +- Prevent console warnings with Ruby 2.7 ([#8125]({{ site.repository }}/issues/8125)) + + +## 4.0.0 / 2019-08-19 +{: #v4-0-0} + +### Major Enhancements +{: #major-enhancements-v4-0-0} + +- Drop ruby 2.3 ([#7454]({{ site.repository }}/issues/7454)) +- Drop support for Ruby 2.1 and 2.2 ([#6560]({{ site.repository }}/issues/6560)) +- Drop support for older versions of Rouge ([#6978]({{ site.repository }}/issues/6978)) +- Drop support for pygments as syntax-highlighter ([#7118]({{ site.repository }}/issues/7118)) +- Drop support for Redcarpet ([#6987]({{ site.repository }}/issues/6987)) +- Drop support for rdiscount ([#6988]({{ site.repository }}/issues/6988)) +- Drop support for `jekyll-watch-1.4.0` and older ([#7287]({{ site.repository }}/issues/7287)) +- Incorporate `relative_url` filter in `link` tag ([#6727]({{ site.repository }}/issues/6727)) +- Upgrade kramdown dependency to v2.x ([#7492]({{ site.repository }}/issues/7492)) +- Upgrade jekyll-sass-converter to v2.x - Sassc + sourcemaps ([#7778]({{ site.repository }}/issues/7778)) +- Upgrade i18n to v1.x ([#6931]({{ site.repository }}/issues/6931)) +- Add `Jekyll::Cache` class to handle caching on disk ([#7169]({{ site.repository }}/issues/7169)) +- Cache converted markdown ([#7159]({{ site.repository }}/issues/7159)) +- Cache: Do not dump undumpable objects ([#7190]({{ site.repository }}/issues/7190)) +- Cache matched defaults sets for given parameters ([#6888]({{ site.repository }}/issues/6888)) +- Ignore cache directory ([#7184]({{ site.repository }}/issues/7184)) +- Add `Site#in_cache_dir` helper method ([#7160]({{ site.repository }}/issues/7160)) +- Remove 'cache_dir' during `jekyll clean` ([#7158]({{ site.repository }}/issues/7158)) +- Cache parsed Liquid templates in memory ([#7136]({{ site.repository }}/issues/7136)) +- Only read layouts from source_dir or theme_dir ([#6788]({{ site.repository }}/issues/6788)) +- Allow custom sorting of collection documents ([#7427]({{ site.repository }}/issues/7427)) +- Always exclude certain paths from being processed ([#7188]({{ site.repository }}/issues/7188)) +- Remove Jekyll::Utils#strip_heredoc in favor of a Ruby > 2.3 built in ([#7584]({{ site.repository }}/issues/7584)) +- Incorporate `relative_url` within `post_url` tag ([#7589]({{ site.repository }}/issues/7589)) +- Remove patch to modify config for kramdown ([#7699]({{ site.repository }}/issues/7699)) + +### Minor Enhancements +{: #minor-enhancements-v4-0-0} + +- Enhance `--blank` scaffolding ([#7310]({{ site.repository }}/issues/7310)) +- Use `jekyll-compose` if installed ([#6932]({{ site.repository }}/issues/6932)) +- Disable Liquid via front matter ([#6824]({{ site.repository }}/issues/6824)) +- Configure cache_dir ([#7232]({{ site.repository }}/issues/7232)) +- ISO week date drops ([#5981]({{ site.repository }}/issues/5981)) +- Fix custom 404 page for GitHub pages ([#7132]({{ site.repository }}/issues/7132)) +- Load config file from within current theme-gem ([#7304]({{ site.repository }}/issues/7304)) +- Suggest re-running command with `--trace` on fail ([#6551]({{ site.repository }}/issues/6551)) +- Support for binary operators in where_exp filter ([#6998]({{ site.repository }}/issues/6998)) +- Automatically load `_config.toml` ([#7299]({{ site.repository }}/issues/7299)) +- Add vendor folder to a newly installed site's .gitignore ([#6968]({{ site.repository }}/issues/6968)) +- Output Jekyll Version while debugging ([#7173]({{ site.repository }}/issues/7173)) +- Memoize computing excerpt's relative_path ([#6951]({{ site.repository }}/issues/6951)) +- Skip processing posts that can not be read ([#7302]({{ site.repository }}/issues/7302)) +- Memoize the return value of Site#documents ([#7273]({{ site.repository }}/issues/7273)) +- Cache globbed paths in front matter defaults ([#7345]({{ site.repository }}/issues/7345)) +- Cache computed item property ([#7301]({{ site.repository }}/issues/7301)) +- Cleanup Markdown converter ([#7519]({{ site.repository }}/issues/7519)) +- Do not process Liquid in post excerpt when disabled in front matter ([#7146]({{ site.repository }}/issues/7146)) +- Liquefied link tag ([#6269]({{ site.repository }}/issues/6269)) +- Update item_property to return numbers as numbers instead of strings ([#6608]({{ site.repository }}/issues/6608)) +- Use `.markdown` extension for page templates ([#7126]({{ site.repository }}/issues/7126)) +- Add support for `*.xhtml` files ([#6854]({{ site.repository }}/issues/6854)) +- Allow i18n v0.9.5 and higher ([#7044]({{ site.repository }}/issues/7044)) +- Ignore permission error of /proc/version ([#7267]({{ site.repository }}/issues/7267)) +- Strip extra slashes via `Jekyll.sanitized_path` ([#7182]({{ site.repository }}/issues/7182)) +- Site template: remove default config for markdown ([#7285]({{ site.repository }}/issues/7285)) +- Add a custom inspect string for StaticFile objects ([#7422]({{ site.repository }}/issues/7422)) +- Remind user to include gem in the Gemfile on error ([#7476]({{ site.repository }}/issues/7476)) +- Search Front matter defaults for Page objects with relative_path ([#7261]({{ site.repository }}/issues/7261)) +- Lock use of `tzinfo` gem to v1.x ([#7521]({{ site.repository }}/issues/7521), [#7562]({{ site.repository }}/issues/7562)) +- Utilize absolute paths of user-provided file paths ([#7450]({{ site.repository }}/issues/7450)) +- Detect `nil` and empty values in objects with `where` filter ([#7580]({{ site.repository }}/issues/7580)) +- Initialize mutations for Drops only if necessary ([#7657]({{ site.repository }}/issues/7657)) +- Reduce Array allocations via Jekyll::Cleaner ([#7659]({{ site.repository }}/issues/7659)) +- Encode and unencode urls only as required ([#7654]({{ site.repository }}/issues/7654)) +- Reduce string allocations with better alternatives ([#7643]({{ site.repository }}/issues/7643)) +- Reduce allocations from Jekyll::Document instances ([#7625]({{ site.repository }}/issues/7625)) +- Add `type` attribute to Document instances ([#7406]({{ site.repository }}/issues/7406)) +- Reduce allocations from where-filter ([#7653]({{ site.repository }}/issues/7653)) +- Memoize SiteDrop#documents to reduce allocations ([#7697]({{ site.repository }}/issues/7697)) +- Add PathManager class to cache interim paths ([#7732]({{ site.repository }}/issues/7732)) +- Remove warnings and fixes for deprecated config ([#7440]({{ site.repository }}/issues/7440)) +- Delegate --profile tabulation to `terminal-table` ([#7627]({{ site.repository }}/issues/7627)) + +### Bug Fixes +{: #bug-fixes-v4-0-0} + +- Security: fix `include` bypass of `EntryFilter#filter` symlink check ([#7226]({{ site.repository }}/issues/7226)) +- Theme gems: ensure directories aren't symlinks ([#7419]({{ site.repository }}/issues/7419)) +- Add call to unused method `validate_options` in `commands/serve.rb` ([#7122]({{ site.repository }}/issues/7122)) +- Check if scope applies to type before given path ([#7263]({{ site.repository }}/issues/7263)) +- Document two methods, simplify one of the methods ([#7270]({{ site.repository }}/issues/7270)) +- Check key in collections only if it isn't "posts" ([#7277]({{ site.repository }}/issues/7277)) +- Interpolate Jekyll::Page subclass on inspection ([#7203]({{ site.repository }}/issues/7203)) +- Measure the no. of times a template gets rendered ([#7316]({{ site.repository }}/issues/7316)) +- Reduce array traversal in Jekyll::Reader ([#7157]({{ site.repository }}/issues/7157)) +- Re-implement handling Liquid blocks in excerpts ([#7250]({{ site.repository }}/issues/7250)) +- Documents should be able to render their date ([#7404]({{ site.repository }}/issues/7404)) +- Fix Interpreter warning from Jekyll::Renderer ([#7448]({{ site.repository }}/issues/7448)) +- Loggers should accept both numbers and symbols ([#6967]({{ site.repository }}/issues/6967)) +- Replace regex arg to :gsub with a string arg ([#7189]({{ site.repository }}/issues/7189)) +- Dont write static files from unrendered collection ([#7410]({{ site.repository }}/issues/7410)) +- Excerpt handling of custom and intermediate tags ([#7382]({{ site.repository }}/issues/7382)) +- Change future post loglevel to warn to help user narrow down issues ([#7527]({{ site.repository }}/issues/7527)) +- Handle files with trailing dots in their basename ([#7315]({{ site.repository }}/issues/7315)) +- Fix unnecessary allocations via StaticFileReader ([#7572]({{ site.repository }}/issues/7572)) +- Don't check if site URL is absolute if it is nil ([#7498]({{ site.repository }}/issues/7498)) +- Avoid unnecessary duplication of pages array ([#7272]({{ site.repository }}/issues/7272)) +- Memoize Site#post_attr_hash ([#7276]({{ site.repository }}/issues/7276)) +- Memoize Document#excerpt_separator ([#7569]({{ site.repository }}/issues/7569)) +- Optimize Document::DATE_FILENAME_MATCHER to match valid filenames ([#7292]({{ site.repository }}/issues/7292)) +- Escape valid special chars in a site's path name ([#7568]({{ site.repository }}/issues/7568)) +- Replace `name` in Page#inspect with relative_path ([#7434]({{ site.repository }}/issues/7434)) +- Log a warning when the slug is empty ([#7357]({{ site.repository }}/issues/7357)) +- Push Markdown link refs to excerpt only as required ([#7577]({{ site.repository }}/issues/7577)) +- Fix broken include_relative usage in excerpt ([#7633]({{ site.repository }}/issues/7633)) +- Initialize and reset glob_cache only as necessary ([#7658]({{ site.repository }}/issues/7658)) +- Revert memoizing Site#docs_to_write and #documents ([#7684]({{ site.repository }}/issues/7684)) +- Backport [#7684]({{ site.repository }}/issues/7684) for v3.8.x: Revert memoizing Site#docs_to_write and refactor #documents ([#7689]({{ site.repository }}/issues/7689)) +- Backport [#7213]({{ site.repository }}/issues/7213) and [#7633]({{ site.repository }}/issues/7633) for v3.8.x: Fix broken include_relative usage in excerpt ([#7690]({{ site.repository }}/issues/7690)) +- Don't read symlinks in site.include in safe mode ([#7711]({{ site.repository }}/issues/7711)) +- Replace `String#=~` with `String#match?` ([#7723]({{ site.repository }}/issues/7723)) +- Update log output for an invalid theme directory ([#7679]({{ site.repository }}/issues/7679)) +- Remove configuration of theme sass files from Core ([#7290]({{ site.repository }}/issues/7290)) +- Actually conditionally include liquid-c ([#7792]({{ site.repository }}/issues/7792)) +- Test number_like regex on stringified property ([#7788]({{ site.repository }}/issues/7788)) + +### Development Fixes +{: #development-fixes-v4-0-0} + +- Upgrade liquid-c to v4.0 ([#7375]({{ site.repository }}/issues/7375)) +- Bump RuboCop to v0.71.0 ([#7687]({{ site.repository }}/issues/7687)) +- Target Ruby 2.4 syntax ([#7583]({{ site.repository }}/issues/7583)) +- Fix: RuboCop offenses ([#7769]({{ site.repository }}/issues/7769)) +- Use communicative method parameters ([#7566]({{ site.repository }}/issues/7566)) +- Scan `assert_equal` methods and rectify any offenses with a custom RuboCop cop ([#7130]({{ site.repository }}/issues/7130)) +- CI: Test with Ruby 2.6 ([#7438]({{ site.repository }}/issues/7438)) +- CI: Test with Ruby 2.6 on AppVeyor ([#7518]({{ site.repository }}/issues/7518)) +- CI: Update RuboCop config ([#7050]({{ site.repository }}/issues/7050)) +- CI: Add a script to profile docs ([#7540]({{ site.repository }}/issues/7540)) +- CI(Appveyor): shallow clone with 5 last commits ([#7312]({{ site.repository }}/issues/7312)) +- CI: Test with oldest and latest Ruby only ([#7412]({{ site.repository }}/issues/7412)) +- CI: Update excludes for CodeClimate Analyses ([#7365]({{ site.repository }}/issues/7365)) +- CI: Lock Travis to Bundler-1.16.2 ([#7144]({{ site.repository }}/issues/7144)) +- CI: Bump tested version of JRuby to 9.2.7.0 ([#7612]({{ site.repository }}/issues/7612)) +- CI: Do not install docs on updating gems on Travis ([#7706]({{ site.repository }}/issues/7706)) +- Update gemspec ([#7425]({{ site.repository }}/issues/7425)) +- deps: relax version constraint on classifier-reborn gem ([#7471]({{ site.repository }}/issues/7471)) +- deps: update yajl-ruby ([#7278]({{ site.repository }}/issues/7278)) +- deps: bump yajl-ruby to v1.4.0 ([#6976]({{ site.repository }}/issues/6976)) +- Create symlink only if target is accessible ([#7429]({{ site.repository }}/issues/7429)) +- Switch to `:install_if` for wdm gem ([#7372]({{ site.repository }}/issues/7372)) +- Add cucumber feature to test include_relative tag ([#7213]({{ site.repository }}/issues/7213)) +- Small benchmark refactoring ([#7211]({{ site.repository }}/issues/7211)) +- Fix incorrectly passed arguments to assert_equal ([#7134]({{ site.repository }}/issues/7134)) +- fix up refute_equal call ([#7133]({{ site.repository }}/issues/7133)) +- Fix RuboCop offences in test files ([#7128]({{ site.repository }}/issues/7128)) +- Use assert_include ([#7093]({{ site.repository }}/issues/7093)) +- Remember to release docs gem ([#7066]({{ site.repository }}/issues/7066)) +- Useless privates removed ([#6768]({{ site.repository }}/issues/6768)) +- Load Rouge for TestKramdown ([#7007]({{ site.repository }}/issues/7007)) +- Update instructions for releasing docs Gem ([#6975]({{ site.repository }}/issues/6975)) +- We are not using Ruby 2.2 anymore ([#6977]({{ site.repository }}/issues/6977)) +- Remove unnecessary Jekyll::Page constant ([#6770]({{ site.repository }}/issues/6770)) +- Remove unused error class ([#6511]({{ site.repository }}/issues/6511)) +- Add a Cucumber feature for post_url tag ([#7586]({{ site.repository }}/issues/7586)) +- Generate a "TOTAL" row for build-profile table ([#7614]({{ site.repository }}/issues/7614)) +- Refactor Jekyll::Cache ([#7532]({{ site.repository }}/issues/7532)) +- Store list of expected extnames in a constant ([#7638]({{ site.repository }}/issues/7638)) +- Profile allocations from a build session ([#7646]({{ site.repository }}/issues/7646)) +- Update small typo in contributing.md ([#7671]({{ site.repository }}/issues/7671)) +- Remove override to Jekyll::Document#respond_to? ([#7695]({{ site.repository }}/issues/7695)) +- Update TestTags in sync with Rouge v3.4 ([#7709]({{ site.repository }}/issues/7709)) +- Use regexp to filter special entries ([#7702]({{ site.repository }}/issues/7702)) +- Reduce Array objects generated from utility method ([#7749]({{ site.repository }}/issues/7749)) +- Update mime.types ([#7756]({{ site.repository }}/issues/7756)) +- Replace redundant Array#map with Array#each ([#7761]({{ site.repository }}/issues/7761)) +- Reduce allocations by using #each_with_object ([#7758]({{ site.repository }}/issues/7758)) +- Memoize fallback_data for Drop ([#7728]({{ site.repository }}/issues/7728)) +- Use String#end_with? to check if entry is a backup ([#7701]({{ site.repository }}/issues/7701)) + +### Documentation + +- Refactor docs ([#7205]({{ site.repository }}/issues/7205)) +- Add a link to Giraffe Academy's tutorial ([#7325]({{ site.repository }}/issues/7325)) +- Do not advise users to install Jekyll outside of Bundler ([#6927]({{ site.repository }}/issues/6927)) +- Remove documentation for using Redcarpet ([#6990]({{ site.repository }}/issues/6990)) +- Install Docs that Work on MacOS 10.14 ([#7561]({{ site.repository }}/issues/7561)) +- Add Installation Instructions for Ubuntu ([#6925]({{ site.repository }}/issues/6925)) +- Don't prompt for sudo when installing with Ubuntu WSL ([#6781]({{ site.repository }}/issues/6781)) +- Installation instructions for Fedora ([#7198]({{ site.repository }}/issues/7198)) +- Update Windows install docs ([#6926]({{ site.repository }}/issues/6926)) +- List all standard liquid filters ([#7333]({{ site.repository }}/issues/7333)) +- List all static files variables ([#7002]({{ site.repository }}/issues/7002)) +- Improve how to include Rouge stylesheets ([#7752]({{ site.repository }}/issues/7752)) +- Mention CommonMark plugins ([#7418]({{ site.repository }}/issues/7418)) +- Add TSV to list of supported _data files. ([#7168]({{ site.repository }}/issues/7168)) +- How to deploy using pre-push git hook ([#7179]({{ site.repository }}/issues/7179)) +- Hosting with AWS Amplify ([#7510]({{ site.repository }}/issues/7510)) +- CircleCI deployment through CircleCI v2 ([#7024]({{ site.repository }}/issues/7024)) +- GitHub Pages: use themes from other repos ([#7112]({{ site.repository }}/issues/7112)) +- Document page.dir and page.name ([#7373]({{ site.repository }}/issues/7373)) +- Document custom tag blocks ([#7359]({{ site.repository }}/issues/7359)) +- Document converter methods ([#7289]({{ site.repository }}/issues/7289)) +- Document {% raw %}`{{ page.collection }}`{% endraw %} ([#7430]({{ site.repository }}/issues/7430)) +- Document Jekyll Filters with YAML data ([#7335]({{ site.repository }}/issues/7335)) +- Document where Jekyll looks for layouts in a site ([#7564]({{ site.repository }}/issues/7564)) +- plugin: liquid tag jekyll-flickr ([#6946]({{ site.repository }}/issues/6946)) +- plugin: jekyll-target-blank ([#7046]({{ site.repository }}/issues/7046)) +- plugin: json-get. ([#7086]({{ site.repository }}/issues/7086)) +- plugin: `jekyll-info` ([#7091]({{ site.repository }}/issues/7091)) +- plugin: jekyll-xml-source ([#7114]({{ site.repository }}/issues/7114)) +- plugin: jekyll-firstimage filter ([#7127]({{ site.repository }}/issues/7127)) +- plugin: CAT ([#7011]({{ site.repository }}/issues/7011)) +- Resources: Statictastic ([#7593]({{ site.repository }}/issues/7593)) +- Resources: Bonsai Search ([#7543]({{ site.repository }}/issues/7543)) +- Resources: Formspark ([#7601]({{ site.repository }}/issues/7601)) +- Resources: Jekpack([#7598]({{ site.repository }}/issues/7598)) +- Resources: formX ([#7536]({{ site.repository }}/issues/7536)) +- Resources: 99inbound's Jekyll post ([#7348]({{ site.repository }}/issues/7348)) +- Resources: CloudSh ([#7497]({{ site.repository }}/issues/7497)) +- Community: DEV Community's Jekyll tag ([#7139]({{ site.repository }}/issues/7139)) +- Showcase: developer.spotify.com ([#7217]({{ site.repository }}/issues/7217)) +- Showcase: Isomer ([#7300]({{ site.repository }}/issues/7300)) +- Add version number for group_by_exp doc ([#6956]({{ site.repository }}/issues/6956)) +- Updated nginx configuration for custom-404-page documentation ([#6994]({{ site.repository }}/issues/6994)) +- Clarify definition of 'draft' ([#7037]({{ site.repository }}/issues/7037)) +- _drafts need to be contained within the custom collection directory ([#6985]({{ site.repository }}/issues/6985)) +- Updated to supported version ([#7031]({{ site.repository }}/issues/7031)) +- Add Hints for some Improved Travis Config in Doc ([#7049]({{ site.repository }}/issues/7049)) +- Update travis-ci.md to point out "this is an example Gemfile" ([#7089]({{ site.repository }}/issues/7089)) +- Instructions to view theme’s files under Linux ([#7095]({{ site.repository }}/issues/7095)) +- Use a real theme in the example ([#7125]({{ site.repository }}/issues/7125)) +- Update docs about post creation ([#7138]({{ site.repository }}/issues/7138)) +- Initialize upgrading doc for v4.0 ([#7140]({{ site.repository }}/issues/7140)) +- Add version badge for date filters with ordinal ([#7162]({{ site.repository }}/issues/7162)) +- Corrected sample usage of postfiles ([#7181]({{ site.repository }}/issues/7181)) +- Resolve "Unable to locate package ruby2.4" error ([#7196]({{ site.repository }}/issues/7196)) +- Correct stylesheet url in tutorial step 7 ([#7210]({{ site.repository }}/issues/7210)) +- Removes quotes from markdown for assets ([#7223]({{ site.repository }}/issues/7223)) +- Clarified front matter requirement ([#7234]({{ site.repository }}/issues/7234)) +- Explicit location of where to create blog.html ([#7241]({{ site.repository }}/issues/7241)) +- Reference the build command options that allows multiple config files ([#7266]({{ site.repository }}/issues/7266)) +- Add more issue template(s) and pull request template ([#7269]({{ site.repository }}/issues/7269)) +- Suggest sites use OpenSSL instead of GnuTLS for their site's CI ([#7010]({{ site.repository }}/issues/7010)) +- Fix broken Contributors link in README.markdown ([#7200]({{ site.repository }}/issues/7200)) +- Add title tag to item in RSS template ([#7282]({{ site.repository }}/issues/7282)) +- Add link tag to item in RSS template ([#7291]({{ site.repository }}/issues/7291)) +- Remove redundant instruction comment ([#7342]({{ site.repository }}/issues/7342)) +- Textile is only supported through a converter plugin ([#7003]({{ site.repository }}/issues/7003)) +- Add recursive navigation tutorial ([#7720]({{ site.repository }}/issues/7720)) +- Remove installation instructions with Homebrew ([#7381]({{ site.repository }}/issues/7381)) +- Fix dead link and misleading prose ([#7383]({{ site.repository }}/issues/7383)) +- Fix content management section ([#7385]({{ site.repository }}/issues/7385)) +- Apply ruby official guide documents ([#7393]({{ site.repository }}/issues/7393)) +- Fix group_by_exp filter example ([#7394]({{ site.repository }}/issues/7394)) +- Remove alt attribute from a tags ([#7407]({{ site.repository }}/issues/7407)) +- Fix BASH code-block in ubuntu.md ([#7420]({{ site.repository }}/issues/7420)) +- zlib is missing ([#7428]({{ site.repository }}/issues/7428)) +- Fixed unnecessary articles and pronouns ([#7466]({{ site.repository }}/issues/7466)) +- Store SSL key and cert in site source ([#7473]({{ site.repository }}/issues/7473)) +- Fix typo in tutorial for converting existing site ([#7524]({{ site.repository }}/issues/7524)) +- Check if var exists before include tag ([#7530]({{ site.repository }}/issues/7530)) +- Clarify docs on collections regarding the need for front matter ([#7538]({{ site.repository }}/issues/7538)) +- Fix incorrect Windows path in themes.md ([#7525]({{ site.repository }}/issues/7525)) +- Addresses bundle not found. ([#7351]({{ site.repository }}/issues/7351)) +- Update the contribution docs for draft pull requests ([#7619]({{ site.repository }}/issues/7619)) +- Data file section adds TSV ([#7640]({{ site.repository }}/issues/7640)) +- Indicate where the _sass folder is by default ([#7644]({{ site.repository }}/issues/7644)) +- Docs: add version tags to new placeholders ([#5981]({{ site.repository }}/issues/5981)) for permalinks ([#7647]({{ site.repository }}/issues/7647)) +- Solve "GitHub Page build failure" in 10-deployment.md ([#7648]({{ site.repository }}/issues/7648)) +- fix link to Site Source config ([#7708]({{ site.repository }}/issues/7708)) +- Introduce frontmatter in step 2 ([#7704]({{ site.repository }}/issues/7704)) +- Add @ashmaroli to Core Team listing ([#7398]({{ site.repository }}/issues/7398)) +- Link to Tidelift in site's footer ([#7377]({{ site.repository }}/issues/7377)) +- Link to OpenCollective backing ([#7378]({{ site.repository }}/issues/7378) +- Link to sponsor listing in README ([#7405]({{ site.repository }}/issues/7405)) +- Adjust team page listings ([#7395]({{ site.repository }}/issues/7395)) +- Updates to CODE OF CONDUCT (v1.4.0) ([#7105]({{ site.repository }}/issues/7105)) +- More inclusive writing ([#7283]({{ site.repository }}/issues/7283)) +- Update Ruby version used in Travis-CI example ([#7783]({{ site.repository }}/issues/7783)) +- Documentation for binary operators in where_exp ([#7786]({{ site.repository }}/issues/7786)) +- Adding SmartForms as Forms service ([#7794]({{ site.repository }}/issues/7794)) + +### Site Enhancements +{: #site-enhancements-v4-0-0} + +- Better Performance ([#7388]({{ site.repository }}/issues/7388)) +- Add some minor improvements to image loading in Showcase page ([#7214]({{ site.repository }}/issues/7214)) +- Simplify assigning classname to docs' aside-links ([#7609]({{ site.repository }}/issues/7609)) +- Simplify couple of includes in the docs site ([#7607]({{ site.repository }}/issues/7607)) +- Avoid generating empty classnames ([#7610]({{ site.repository }}/issues/7610)) +- Minimize rendering count ([#7343]({{ site.repository }}/issues/7343)) + +### Release + +- Jekyll v4.0 release ([#7782]({{ site.repository }}/issues/7782)) +- Release post for v4.0.0 beta1 ([#7716]({{ site.repository }}/issues/7716)) +- Release post for v4.0.0.pre.alpha1 ([#7574]({{ site.repository }}/issues/7574)) +- Release post for v3.8.0 ([#6849]({{ site.repository }}/issues/6849)) +- Release post for v3.6.3, v3.7.4 and v3.8.4 ([#7259]({{ site.repository }}/issues/7259)) +- Post: v4.0 development ([#6934]({{ site.repository }}/issues/6934)) + + +## 3.8.6 / 2019-07-02 +{: #v3-8-6} + +### Bug Fixes +{: #bug-fixes-v3-8-6} + +- Update log output for an invalid theme directory ([#7734]({{ site.repository }}/issues/7734)) +- Memoize `SiteDrop#documents` to reduce allocations ([#7722]({{ site.repository }}/issues/7722)) +- Excerpt handling of custom and intermediate tags ([#7467]({{ site.repository }}/issues/7467)) +- Escape valid special chars in a site's path name ([#7573]({{ site.repository }}/issues/7573)) +- Revert memoizing `Site#docs_to_write` and refactor `#documents` ([#7689]({{ site.repository }}/issues/7689)) +- Fix broken `include_relative` usage in excerpt ([#7690]({{ site.repository }}/issues/7690)) +- Install platform-specific gems as required (3c06609406) + +### Security Fixes +{: #security-fixes-v3-8-6} + +- Theme gems: ensure directories aren't symlinks ([#7424]({{ site.repository }}/issues/7424)) + + +## 3.8.5 / 2018-11-04 +{: #v3-8-5} + +### Bug Fixes +{: #bug-fixes-v3-8-5} + +- Re-implement handling Liquid blocks in excerpts ([#7250]({{ site.repository }}/issues/7250)) + + +## 3.8.4 / 2018-09-18 +{: #v3-8-4} + +### Bug Fixes +{: #bug-fixes-v3-8-4} + +- 3.8.x: security: fix `include` bypass of `EntryFilter#filter` symlink check ([#7228]({{ site.repository }}/issues/7228)) + + +## 3.8.3 / 2018-06-05 +{: #v3-8-3} + +### Bug Fixes +{: #bug-fixes-v3-8-3} + +- Fix --unpublished not affecting collection documents ([#7027]({{ site.repository }}/issues/7027)) + + +## 3.8.2 / 2018-05-18 +{: #v3-8-2} + +### Development Fixes +{: #development-fixes-v3-8-2} + +- Update rubocop version ([#7016]({{ site.repository }}/issues/7016)) + +### Bug Fixes +{: #bug-fixes-v3-8-2} + +- Add whitespace control to LIQUID_TAG_REGEX ([#7015]({{ site.repository }}/issues/7015)) + + +## 3.8.1 / 2018-05-01 +{: #v3-8-1} + +### Bug Fixes +{: #bug-fixes-v3-8-1} + +- Fix rendering Liquid constructs in excerpts ([#6945]({{ site.repository }}/issues/6945)) +- Liquify documents unless published == false ([#6959]({{ site.repository }}/issues/6959)) + + +## 3.8.0 / 2018-04-19 +{: #v3-8-0} + +### Development Fixes +{: #development-fixes-v3-8-0} + +- move duplicate code to a single private method ([#6593]({{ site.repository }}/issues/6593)) +- Test against Ruby 2.5 on AppVeyor ([#6668]({{ site.repository }}/issues/6668)) +- Replace simple regex with a native Ruby method ([#6732]({{ site.repository }}/issues/6732)) +- Codeclimate: exclude livereload.js ([#6776]({{ site.repository }}/issues/6776)) +- Add a cucumber feature to test link tag ([#6777]({{ site.repository }}/issues/6777)) +- Fix theme gem feature ([#6784]({{ site.repository }}/issues/6784)) +- Replace simple regex with equivalent Ruby methods ([#6736]({{ site.repository }}/issues/6736)) +- Rewrite `script/rubyprof` as a Ruby script ([#6813]({{ site.repository }}/issues/6813)) +- Add debug output to theme rendering ([#5195]({{ site.repository }}/issues/5195)) +- fix minitest deprecation warning in test ([#6839]({{ site.repository }}/issues/6839)) +- Memoize `Site#site_data` ([#6809]({{ site.repository }}/issues/6809)) +- Memoize document output extension ([#6814]({{ site.repository }}/issues/6814)) +- Access document permalink attribute efficiently ([#6740]({{ site.repository }}/issues/6740)) +- Minimize array allocations in the `where` filter ([#6860]({{ site.repository }}/issues/6860)) +- Bump JRuby ([#6878]({{ site.repository }}/issues/6878)) +- Assert existence of <collection>.files ([#6907]({{ site.repository }}/issues/6907)) +- Bump RuboCop to 0.54.x ([#6915]({{ site.repository }}/issues/6915)) +- Regenerate unconditionally unless its an incremental build ([#6917]({{ site.repository }}/issues/6917)) +- Centralize require statements ([#6910]({{ site.repository }}/issues/6910)) +- Bump to RuboCop 0.55 ([#6929]({{ site.repository }}/issues/6929)) +- Refactor private method `HighlightBlock#parse_options` ([#6822]({{ site.repository }}/issues/6822)) + +### Minor Enhancements +{: #minor-enhancements-v3-8-0} + +- Two massive performance improvements for large sites ([#6730]({{ site.repository }}/issues/6730)) +- Cache the list of documents to be written ([#6741]({{ site.repository }}/issues/6741)) +- Allow Jekyll Doctor to detect stray posts dir ([#6681]({{ site.repository }}/issues/6681)) +- Excerpt relative-path should match its path ([#6597]({{ site.repository }}/issues/6597)) +- Remind user to resolve conflict in `jekyll new` with `--force` ([#6801]({{ site.repository }}/issues/6801)) +- Memoize helper methods in site-cleaner ([#6808]({{ site.repository }}/issues/6808)) +- Compute document's relative_path faster ([#6767]({{ site.repository }}/issues/6767)) +- Create a single instance of PostReader per site ([#6759]({{ site.repository }}/issues/6759)) +- Allow date filters to output ordinal days ([#6773]({{ site.repository }}/issues/6773)) +- Change regex to sanitize and normalize filenames passed to LiquidRenderer ([#6610]({{ site.repository }}/issues/6610)) +- Allow passing :strict_variables and :strict_filters options to Liquid's renderer ([#6726]({{ site.repository }}/issues/6726)) +- Debug writing files during the build process ([#6696]({{ site.repository }}/issues/6696)) +- Improve regex usage in `Tags::IncludeTag` ([#6848]({{ site.repository }}/issues/6848)) +- Improve comment included in the starter index.md ([#6916]({{ site.repository }}/issues/6916)) +- Store and retrieve converter instances for Jekyll::Filters via a hash ([#6856]({{ site.repository }}/issues/6856)) +- Implement a cache within the `where` filter ([#6868]({{ site.repository }}/issues/6868)) +- Store regexp in a constant ([#6887]({{ site.repository }}/issues/6887)) +- Optimize computing filename in LiquidRenderer ([#6841]({{ site.repository }}/issues/6841)) + +### Documentation + +- Adding the jekyll-algolia plugin to the list of plugins ([#6737]({{ site.repository }}/issues/6737)) +- Added Premonition plugin to list of plugins ([#6750]({{ site.repository }}/issues/6750)) +- Add document on releasing a new version ([#6745]({{ site.repository }}/issues/6745)) +- Mention Talkyard, a new commenting system for Jekyll and others. ([#6752]({{ site.repository }}/issues/6752)) +- Add 'jekyll-fontello' to plugins ([#6757]({{ site.repository }}/issues/6757)) +- Install dh-autoreconf on Windows ([#6765]({{ site.repository }}/issues/6765)) +- Fix common typos ([#6764]({{ site.repository }}/issues/6764)) +- Fix documentation for {% raw %}`{{ page.excerpt }}`{% endraw %} ([#6779]({{ site.repository }}/issues/6779)) +- Update docs on permalink configuration ([#6775]({{ site.repository }}/issues/6775)) +- Propose fix some typos ([#6785]({{ site.repository }}/issues/6785)) +- Say hello to Jekyll's New Lead Developer ([#6790]({{ site.repository }}/issues/6790)) +- Add reference to Liquid to plugin docs ([#6794]({{ site.repository }}/issues/6794)) +- Draft a release post for v3.7.3 ([#6803]({{ site.repository }}/issues/6803)) +- add missing step for gem-based theme conversion ([#6802]({{ site.repository }}/issues/6802)) +- Update windows.md to explain an issue with jekyll new. ([#6838]({{ site.repository }}/issues/6838)) +- Add Bundler Installation Instructions ([#6828]({{ site.repository }}/issues/6828)) +- Docs: describe difference between tags and categories ([#6882]({{ site.repository }}/issues/6882)) +- Add `jekyll-random` plugin to docs ([#6833]({{ site.repository }}/issues/6833)) +- Fixed typo in description of categories and tags ([#6896]({{ site.repository }}/issues/6896)) +- Add missing ul-tag ([#6897]({{ site.repository }}/issues/6897)) +- doc: add liquid tag plugin jekyll-onebox for html previews ([#6898]({{ site.repository }}/issues/6898)) +- Add `jekyll-w2m` to plugins ([#6855]({{ site.repository }}/issues/6855)) +- Fix tutorials navigation HTML ([#6919]({{ site.repository }}/issues/6919)) +- add Arch Linux installation troubleshoot ([#6782]({{ site.repository }}/issues/6782)) +- Docs: Install Jekyll on macOS ([#6881]({{ site.repository }}/issues/6881)) +- Fix CodeClimate badges [ci skip] ([#6930]({{ site.repository }}/issues/6930)) +- Update index.md ([#6933]({{ site.repository }}/issues/6933)) + +### Site Enhancements +{: #site-enhancements-v3-8-0} + +- Remove links to Gists ([#6751]({{ site.repository }}/issues/6751)) +- Always load Google Fonts over HTTPS ([#6792]({{ site.repository }}/issues/6792)) +- always load analytics.js over HTTPS ([#6807]({{ site.repository }}/issues/6807)) + +### Bug Fixes +{: #bug-fixes-v3-8-0} + +- Append appropriate closing tag to Liquid block in an excerpt ### -minor ([#6724]({{ site.repository }}/issues/6724)) +- Bypass rendering via Liquid unless required ([#6735]({{ site.repository }}/issues/6735)) +- Delegated methods after `private` keyword are meant to be private ([#6819]({{ site.repository }}/issues/6819)) +- Improve handling non-default collection documents rendering and writing ([#6795]({{ site.repository }}/issues/6795)) +- Fix passing multiline params to include tag when using the variable syntax ([#6858]({{ site.repository }}/issues/6858)) +- `include_relative` tag should find related documents in collections gathered within custom `collections_dir` ([#6818]({{ site.repository }}/issues/6818)) +- Handle liquid tags in excerpts robustly ([#6891]({{ site.repository }}/issues/6891)) +- Allow front matter defaults to be applied properly to documents gathered under custom `collections_dir` ([#6885]({{ site.repository }}/issues/6885)) + + +## 3.7.4 / 2018-09-07 +{: #v3-7-4} + +### Bug Fixes +{: #bug-fixes-v3-7-4} + +- Security: fix `include` bypass of EntryFilter#filter symlink check ([#7224]({{ site.repository }}/issues/7224)) + + +## 3.7.3 / 2018-02-25 +{: #v3-7-3} + +### Bug Fixes +{: #bug-fixes-v3-7-3} + +- Do not hardcode locale unless certainly necessary ([#6791]({{ site.repository }}/issues/6791)) + + +## 3.7.2 / 2018-01-25 +{: #v3-7-2} + +### Development Fixes +{: #development-fixes-v3-7-2} + +- CI: Test against Ruby 2.5.0 ([#6664]({{ site.repository }}/issues/6664)) +- Bump rdoc to 6.0 ([#6600]({{ site.repository }}/issues/6600)) +- Lint file and bump theme dependencies ([#6698]({{ site.repository }}/issues/6698)) +- Write a Rubocop Cop to ensure no `#p` or `#puts` calls get committed to master. ([#6615]({{ site.repository }}/issues/6615)) +- Remove redgreen gem ([#6720]({{ site.repository }}/issues/6720)) + +### Site Enhancements +{: #site-enhancements-v3-7-2} + +- Display latest version in header ([#6676]({{ site.repository }}/issues/6676)) +- Update version in `config.yml` via YAML load / dump ([#6677]({{ site.repository }}/issues/6677)) + +### Documentation + +- Fix: Add note about posts in context of collections_dir ([#6680]({{ site.repository }}/issues/6680)) +- Update deploy-script in documentation ([#6666]({{ site.repository }}/issues/6666)) +- Add note about naming of collections_dir ([#6703]({{ site.repository }}/issues/6703)) +- Update installation.md ([#6694]({{ site.repository }}/issues/6694)) +- Add `jekyll-html` to plugins. ([#6654]({{ site.repository }}/issues/6654)) +- Update plugins.md ([#6716]({{ site.repository }}/issues/6716)) +- Release v3.7.1 ([#6695]({{ site.repository }}/issues/6695)) + +### Bug Fixes +{: #bug-fixes-v3-7-2} + +- inform that symlinks are not allowed in safe mode ([#6670]({{ site.repository }}/issues/6670)) +- Glob scope path only if configured with a pattern ([#6692]({{ site.repository }}/issues/6692)) +- Add gem "wdm" to all newly generated Gemfiles ([#6711]({{ site.repository }}/issues/6711)) +- Fix timezone inconsistencies between different ruby version ([#6697]({{ site.repository }}/issues/6697)) +- Refactor collections_dir feature for consistency ([#6685]({{ site.repository }}/issues/6685)) + +### Minor Enhancements +{: #minor-enhancements-v3-7-2} + +- Require external library only if necessary ([#6596]({{ site.repository }}/issues/6596)) + + +## 3.7.0 / 2018-01-02 +{: #v3-7-0} + +### Minor Enhancements +{: #minor-enhancements-v3-7-0} + +- Add LiveReload functionality to Jekyll. ([#5142]({{ site.repository }}/issues/5142)) +- Add Utils::Internet.connected? to determine whether host machine has internet connection. ([#5870]({{ site.repository }}/issues/5870)) +- Disable default layouts for Pages with a `layout: none` declaration ([#6182]({{ site.repository }}/issues/6182)) +- Scope path glob ([#6268]({{ site.repository }}/issues/6268)) +- Allow the user to set collections_dir to put all collections under one subdirectory ([#6331]({{ site.repository }}/issues/6331)) +- Upgrade to Rouge 3 ([#6381]({{ site.repository }}/issues/6381)) +- Allow URL filters to work directly with documents ([#6478]({{ site.repository }}/issues/6478)) +- filter relative_url should keep absolute urls with scheme/authority ([#6490]({{ site.repository }}/issues/6490)) +- `.sass-cache` doesn't *always* land in `options['source']` ([#6500]({{ site.repository }}/issues/6500)) +- Allow plugins to modify the obsolete files. ([#6502]({{ site.repository }}/issues/6502)) +- Add latin mode to `slugify` ([#6509]({{ site.repository }}/issues/6509)) +- Log Kramdown warnings if log level is WARN ([#6522]({{ site.repository }}/issues/6522)) +- Add an option to configure kramdown warning output ([#6554]({{ site.repository }}/issues/6554)) +- Add `json` extension to list of directory indices ([#6550]({{ site.repository }}/issues/6550)) +- Dependency: Bump jekyll-watch to 2.0 ([#6589]({{ site.repository }}/issues/6589)) +- Remove paginate check ([#6606]({{ site.repository }}/issues/6606)) +- update classifier-reborn to 2.2.0 ([#6631]({{ site.repository }}/issues/6631)) +- Switch to an actively-maintained TOML parser. ([#6652]({{ site.repository }}/issues/6652)) +- Do not coerce layout paths in theme-gem to the source directory ([#6603]({{ site.repository }}/issues/6603)) + +### Bug Fixes +{: #bug-fixes-v3-7-0} + +- Raise when theme root directory is not available ([#6455]({{ site.repository }}/issues/6455)) +- Avoid block parser warning in SmartyPants ([#6565]({{ site.repository }}/issues/6565)) +- Fail gracefully if "sass" gem cannot be loaded ([#6573]({{ site.repository }}/issues/6573)) +- return correct file in dir if dir has same name as file ([#6569]({{ site.repository }}/issues/6569)) +- Register reload hooks in Server#process ([#6605]({{ site.repository }}/issues/6605)) +- Memoize path to metadata file ([#6602]({{ site.repository }}/issues/6602)) +- Use `require_relative` to load Jekyll classes ([#6609]({{ site.repository }}/issues/6609)) + +### Development Fixes +{: #development-fixes-v3-7-0} + +- Added direct collection access to future collection item feature test([#6151]({{ site.repository }}/issues/6151)) +- add failing test for non-utf8 encoding ([#6339]({{ site.repository }}/issues/6339)) +- Upgrade to Cucumber 3.0 ([#6395]({{ site.repository }}/issues/6395)) +- Provide a better default hash for tracking liquid stats ([#6417]({{ site.repository }}/issues/6417)) +- Add configuration for first-timers bot ([#6431]({{ site.repository }}/issues/6431)) +- Do not linkify escaped characters as PRs in History ([#6468]({{ site.repository }}/issues/6468)) +- Rely on jekyll-mentions for linking usernames ([#6469]({{ site.repository }}/issues/6469)) +- Update first-timers-issue-template.md ([#6472]({{ site.repository }}/issues/6472)) +- Enable `Lint/RescueWithoutErrorClass` Cop ([#6482]({{ site.repository }}/issues/6482)) +- Clean up Rubocop config ([#6495]({{ site.repository }}/issues/6495)) +- Use Gem to discover the location of bundler ([#6499]({{ site.repository }}/issues/6499)) +- Remove unnecessary encoding comment ([#6513]({{ site.repository }}/issues/6513)) +- Suggest using Rubocop to automatically fix errors ([#6514]({{ site.repository }}/issues/6514)) +- Assert raising Psych::SyntaxError when`"strict_front_matter"=>true` ([#6520]({{ site.repository }}/issues/6520)) +- Use Kernel#Array instead of explicit Array check ([#6525]({{ site.repository }}/issues/6525)) +- RuboCop: Enable `Style/UnneededCapitalW` cop ([#6526]({{ site.repository }}/issues/6526)) +- Refactor method to reduce ABC Metric size ([#6529]({{ site.repository }}/issues/6529)) +- Remove parentheses around arguments to raise ([#6532]({{ site.repository }}/issues/6532)) +- Use double-quotes around gem name ([#6535]({{ site.repository }}/issues/6535)) +- Dependencies: upgrade to toml 0.2.0 ([#6541]({{ site.repository }}/issues/6541)) +- Lock to cucumber 3.0.1 on Ruby 2.1 ([#6546]({{ site.repository }}/issues/6546)) +- Bump JRuby version in Travis config ([#6561]({{ site.repository }}/issues/6561)) +- Rescue from Psych::SyntaxError instead of SyntaxError after parsing YAML([#5828]({{ site.repository }}/issues/5828)) +- Drop forwarding to private methods by exposing those methods as public([#6577]({{ site.repository }}/issues/6577)) +- Upgrade pygments to v1.x ([#5937]({{ site.repository }}/issues/5937)) +- Bump yajl-ruby ([#6582]({{ site.repository }}/issues/6582)) +- Cleanup test_redcarpet.rb ([#6584]({{ site.repository }}/issues/6584)) +- Add PageWithoutAFile class from jekyll plugins ([#6556]({{ site.repository }}/issues/6556)) +- Cleanup LiveReloadReactor ([#6607]({{ site.repository }}/issues/6607)) + +### Documentation + +- Add formester to the list of saas form backend ([#6059]({{ site.repository }}/issues/6059)) +- GitHub Pages instructions ([#6384]({{ site.repository }}/issues/6384)) +- Improve documentation for theme-gem installation ([#6387]({{ site.repository }}/issues/6387)) +- Fix diff syntax-highlighting ([#6388]({{ site.repository }}/issues/6388)) +- Update instructions ([#6396]({{ site.repository }}/issues/6396)) +- Fix code-block highlighting in docs ([#6398]({{ site.repository }}/issues/6398)) +- Filtering Posts with categories, tags, or other variables ([#6399]({{ site.repository }}/issues/6399)) +- Fixes formatting on pre-formatted text. ([#6405]({{ site.repository }}/issues/6405)) +- Added new tutorial to tutorials section on docs ([#6406]({{ site.repository }}/issues/6406)) +- Updates ([#6407]({{ site.repository }}/issues/6407)) +- Fix `collections_dir` example ([#6408]({{ site.repository }}/issues/6408)) +- Renaming duplicate of "Scenario 6" to "Scenario 7" ([#6411]({{ site.repository }}/issues/6411)) +- Mark `collection_dir` as unreleased ([#6412]({{ site.repository }}/issues/6412)) +- Fix link to SUPPORT ([#6415]({{ site.repository }}/issues/6415)) +- Fix list appearance by adding missing `ol` tag ([#6421]({{ site.repository }}/issues/6421)) +- Explain how to override output collection index page ([#6424]({{ site.repository }}/issues/6424)) +- Added github-cards to the list of plugins ([#6425]({{ site.repository }}/issues/6425)) +- CoC violation correspondents ([#6429]({{ site.repository }}/issues/6429)) +- Add a note about Liquid and syntax highlighting ([#6466]({{ site.repository }}/issues/6466)) +- Remove `sudo` from macOS troubleshooting instructions ([#6486]({{ site.repository }}/issues/6486)) +- Add a note on `:jekyll_plugins` group in the docs ([#6488]({{ site.repository }}/issues/6488)) +- Updated custom-404-page.md ([#6489]({{ site.repository }}/issues/6489)) +- Fix a few minor issues in the docs ([#6494]({{ site.repository }}/issues/6494)) +- Add jekyll-pwa-plugin ([#6533]({{ site.repository }}/issues/6533)) +- Remove Jekyll-Smartify from plugins directory ([#6548]({{ site.repository }}/issues/6548)) +- Updated Jekyll-Pug listing to include official website ([#6555]({{ site.repository }}/issues/6555)) +- Remove link to severely outdated asset plugin ([#6613]({{ site.repository }}/issues/6613)) +- Default time zone depends upon server ([#6617]({{ site.repository }}/issues/6617)) +- Add `disqus-for-jekyll` to plugins. ([#6618]({{ site.repository }}/issues/6618)) +- Update "Requirements" for Ruby version ([#6623]({{ site.repository }}/issues/6623)) +- Fix: Update link to i18n_filter plugin ([#6638]({{ site.repository }}/issues/6638)) +- Correct WordPress capitalization ([#6645]({{ site.repository }}/issues/6645)) +- Add Tweetsert, Stickyposts, Paginate::Content ([#6651]({{ site.repository }}/issues/6651)) +- Post: Jekyll 3.7.0 released ([#6634]({{ site.repository }}/issues/6634)) + +### Site Enhancements +{: #site-enhancements-v3-7-0} + +- Add special styling for code-blocks run in shell ([#6389]({{ site.repository }}/issues/6389)) +- Add post about diversity ([#6447]({{ site.repository }}/issues/6447)) +- Update list of files excluded from Docs site ([#6457]({{ site.repository }}/issues/6457)) +- Update site History ([#6460]({{ site.repository }}/issues/6460)) +- Add default twitter card image ([#6476]({{ site.repository }}/issues/6476)) +- Update normalize.css to v7.0.0 ([#6491]({{ site.repository }}/issues/6491)) +- Optimize images ([#6519]({{ site.repository }}/issues/6519)) +- Back to original main navigation ([#6544]({{ site.repository }}/issues/6544)) +- Styles: mobile-docs select element ([#6545]({{ site.repository }}/issues/6545)) +- Search with DocSearch by @Algolia ([#6557]({{ site.repository }}/issues/6557)) +- Site header redesign ([#6567]({{ site.repository }}/issues/6567)) +- Move logo above site navigation on small screens ([#6570]({{ site.repository }}/issues/6570)) +- Docs: Include version badge for latest features ([#6574]({{ site.repository }}/issues/6574)) +- Use version-badge on an existing feature intro ([#6575]({{ site.repository }}/issues/6575)) +- Add jekyll-category-pages plugin ([#6632]({{ site.repository }}/issues/6632)) +- Improve docs styling for code to be run in shell ([#6641]({{ site.repository }}/issues/6641)) +- Fix permalink icon markup in news-item layout ([#6639]({{ site.repository }}/issues/6639)) + + +## 3.6.3 / 2018-09-18 +{: #v3-6-3} + +### Bug Fixes +{: #bug-fixes-v3-6-3} + +- 3.6.x: security: fix `include` bypass of `EntryFilter#filter` symlink check ([#7229]({{ site.repository }}/issues/7229)) + + +## 3.6.2 / 2017-10-21 +{: #v3-6-2} + +### Development Fixes +{: #development-fixes-v3-6-2} + +- Update Rubocop to 0.51.0 ([#6444]({{ site.repository }}/issues/6444)) +- Add test for layout as string ([#6445]({{ site.repository }}/issues/6445)) + +### Bug Fixes +{: #bug-fixes-v3-6-2} + +- Problematic UTF+bom files ([#6322]({{ site.repository }}/issues/6322)) +- Always treat `data.layout` as a string ([#6442]({{ site.repository }}/issues/6442)) + + +## 3.6.1 / 2017-10-20 +{: #v3-6-1} + +### Documentation + +- Doc y_day in docs/permalinks ([#6244]({{ site.repository }}/issues/6244)) +- Update frontmatter.md ([#6371]({{ site.repository }}/issues/6371)) +- Elaborate on excluding items from processing ([#6136]({{ site.repository }}/issues/6136)) +- Style lists in tables ([#6379]({{ site.repository }}/issues/6379)) +- Remove duplicate "available" ([#6380]({{ site.repository }}/issues/6380)) + +### Development Fixes +{: #development-fixes-v3-6-1} + +- Bump rubocop to use `v0.50.x` ([#6368]({{ site.repository }}/issues/6368)) + + +## 3.6.0 / 2017-09-21 +{: #v3-6-0} + +### Minor Enhancements +{: #minor-enhancements-v3-6-0} + +- Ignore final newline in folded YAML string ([#6054]({{ site.repository }}/issues/6054)) +- Add URL checks to Doctor ([#5760]({{ site.repository }}/issues/5760)) +- Fix serving files that clash with directories ([#6222]({{ site.repository }}/issues/6222)) ([#6231]({{ site.repository }}/issues/6231)) +- Bump supported Ruby version to `>= 2.1.0` ([#6220]({{ site.repository }}/issues/6220)) +- set `LiquidError#template_name` for errors in included file ([#6206]({{ site.repository }}/issues/6206)) +- Access custom config array throughout session ([#6200]({{ site.repository }}/issues/6200)) +- Add support for Rouge 2, in addition to Rouge 1 ([#5919]({{ site.repository }}/issues/5919)) +- Allow `yield` to logger methods & bail early on no-op messages ([#6315]({{ site.repository }}/issues/6315)) +- Update mime-types. ([#6336]({{ site.repository }}/issues/6336)) +- Use a Schwartzian transform with custom sorting ([#6342]({{ site.repository }}/issues/6342)) +- Alias `Drop#invoke_drop` to `Drop#[]` ([#6338]({{ site.repository }}/issues/6338)) + +### Bug Fixes +{: #bug-fixes-v3-6-0} + +- `Deprecator`: fix typo for `--serve` command ([#6229]({{ site.repository }}/issues/6229)) +- `Reader#read_directories`: guard against an entry not being a directory ([#6226]({{ site.repository }}/issues/6226)) +- kramdown: symbolize keys in-place ([#6247]({{ site.repository }}/issues/6247)) +- Call `to_s` on site.url before attempting to concatenate strings ([#6253]({{ site.repository }}/issues/6253)) +- Enforce Style/FrozenStringLiteralComment ([#6265]({{ site.repository }}/issues/6265)) +- Update theme-template README to note 'assets' directory ([#6257]({{ site.repository }}/issues/6257)) +- Memoize the return value of `Document#url` ([#6266]({{ site.repository }}/issues/6266)) +- delegate `StaticFile#to_json` to `StaticFile#to_liquid` ([#6273]({{ site.repository }}/issues/6273)) +- Fix `Drop#key?` so it can handle a nil argument ([#6281]({{ site.repository }}/issues/6281)) +- Guard against type error in absolute url ([#6280]({{ site.repository }}/issues/6280)) +- Mutable drops should fallback to their own methods when a mutation isn't present ([#6350]({{ site.repository }}/issues/6350)) +- Skip adding binary files as posts ([#6344]({{ site.repository }}/issues/6344)) +- Don't break if bundler is not installed ([#6377]({{ site.repository }}/issues/6377)) + +### Documentation + +- Fix a typo in `custom-404-page.md` ([#6218]({{ site.repository }}/issues/6218)) +- Docs: fix links to issues in History.markdown ([#6255]({{ site.repository }}/issues/6255)) +- Update deprecated gems key to plugins. ([#6262]({{ site.repository }}/issues/6262)) +- Fixes minor typo in post text ([#6283]({{ site.repository }}/issues/6283)) +- Execute build command using bundle. ([#6274]({{ site.repository }}/issues/6274)) +- name unification - buddy details ([#6317]({{ site.repository }}/issues/6317)) +- name unification - application index ([#6318]({{ site.repository }}/issues/6318)) +- trim and relocate plugin info across docs ([#6311]({{ site.repository }}/issues/6311)) +- update Jekyll's README ([#6321]({{ site.repository }}/issues/6321)) +- add SUPPORT file for GitHub ([#6324]({{ site.repository }}/issues/6324)) +- Rename CODE_OF_CONDUCT to show in banner ([#6325]({{ site.repository }}/issues/6325)) +- Docs : illustrate page.id for a collection's document ([#6329]({{ site.repository }}/issues/6329)) +- Docs: post's date can be overridden in front matter ([#6334]({{ site.repository }}/issues/6334)) +- Docs: `site.url` behavior on development and production environments ([#6270]({{ site.repository }}/issues/6270)) +- Fix typo in site.url section of variables.md :-[ ([#6337]({{ site.repository }}/issues/6337)) +- Docs: updates ([#6343]({{ site.repository }}/issues/6343)) +- Fix precedence docs ([#6346]({{ site.repository }}/issues/6346)) +- add note to contributing docs about `script/console` ([#6349]({{ site.repository }}/issues/6349)) +- Docs: Fix permalink example ([#6375]({{ site.repository }}/issues/6375)) + +### Site Enhancements +{: #site-enhancements-v3-6-0} + +- Adding DevKit helpers ([#6225]({{ site.repository }}/issues/6225)) +- Customizing url in collection elements clarified ([#6264]({{ site.repository }}/issues/6264)) +- Plugins is the new gems ([#6326]({{ site.repository }}/issues/6326)) + +### Development Fixes +{: #development-fixes-v3-6-0} + +- Strip unnecessary leading whitespace in template ([#6228]({{ site.repository }}/issues/6228)) +- Users should be installing patch versions. ([#6198]({{ site.repository }}/issues/6198)) +- Fix tests ([#6240]({{ site.repository }}/issues/6240)) +- Define path with `__dir__` ([#6087]({{ site.repository }}/issues/6087)) +- exit site.process sooner ([#6239]({{ site.repository }}/issues/6239)) +- make flakey test more robust ([#6277]({{ site.repository }}/issues/6277)) +- Add a quick test for DataReader ([#6284]({{ site.repository }}/issues/6284)) +- script/backport-pr: commit message no longer includes the `#` ([#6289]({{ site.repository }}/issues/6289)) +- Add CODEOWNERS file to help automate reviews. ([#6320]({{ site.repository }}/issues/6320)) +- Fix builds on codeclimate ([#6333]({{ site.repository }}/issues/6333)) +- Bump rubies on Travis ([#6366]({{ site.repository }}/issues/6366)) + + +## 3.5.2 / 2017-08-12 +{: #v3-5-2} + +### Bug Fixes +{: #bug-fixes-v3-5-2} + +- Backport [#6281]({{ site.repository }}/issues/6281) for v3.5.x: Fix `Drop#key?` so it can handle a nil argument ([#6288]({{ site.repository }}/issues/6288)) +- Backport [#6280]({{ site.repository }}/issues/6280) for v3.5.x: Guard against type error in `absolute_url` ([#6287]({{ site.repository }}/issues/6287)) +- Backport [#6266]({{ site.repository }}/issues/6266) for v3.5.x: Memoize the return value of `Document#url` ([#6301]({{ site.repository }}/issues/6301)) +- Backport [#6273]({{ site.repository }}/issues/6273) for v3.5.x: delegate `StaticFile#to_json` to `StaticFile#to_liquid` ([#6302]({{ site.repository }}/issues/6302)) +- Backport [#6226]({{ site.repository }}/issues/6226) for v3.5.x: `Reader#read_directories`: guard against an entry not being a directory ([#6304]({{ site.repository }}/issues/6304)) +- Backport [#6247]({{ site.repository }}/issues/6247) for v3.5.x: kramdown: symbolize keys in-place ([#6303]({{ site.repository }}/issues/6303)) + + +## 3.5.1 / 2017-07-17 +{: #v3-5-1} + +### Minor Enhancements +{: #minor-enhancements-v3-5-1} + +- Use Warn for deprecation messages ([#6192]({{ site.repository }}/issues/6192)) +- site template: Use plugins key instead of gems ([#6045]({{ site.repository }}/issues/6045)) + +### Bug Fixes +{: #bug-fixes-v3-5-1} + +- Backward compatibilize URLFilters module ([#6163]({{ site.repository }}/issues/6163)) +- Static files contain front matter default keys when `to_liquid`'d ([#6162]({{ site.repository }}/issues/6162)) +- Always normalize the result of the `relative_url` filter ([#6185]({{ site.repository }}/issues/6185)) + +### Documentation + +- Update reference to trouble with OS X/macOS ([#6139]({{ site.repository }}/issues/6139)) +- added BibSonomy plugin ([#6143]({{ site.repository }}/issues/6143)) +- add plugins for multiple page pagination ([#6055]({{ site.repository }}/issues/6055)) +- Update minimum Ruby version in installation.md ([#6164]({{ site.repository }}/issues/6164)) +- Add information about finding a collection in `site.collections` ([#6165]({{ site.repository }}/issues/6165)) +- Add {% raw %}`{% raw %}`{% endraw %} to Liquid example on site ([#6179]({{ site.repository }}/issues/6179)) +- Added improved Pug plugin - removed 404 Jade plugin ([#6174]({{ site.repository }}/issues/6174)) +- Linking the link ([#6210]({{ site.repository }}/issues/6210)) +- Small correction in documentation for includes ([#6193]({{ site.repository }}/issues/6193)) +- Fix docs site page margin ([#6214]({{ site.repository }}/issues/6214)) + +### Development Fixes +{: #development-fixes-v3-5-1} + +- Add jekyll doctor to GitHub Issue Template ([#6169]({{ site.repository }}/issues/6169)) +- Test with Ruby 2.4.1-1 on AppVeyor ([#6176]({{ site.repository }}/issues/6176)) +- set minimum requirement for jekyll-feed ([#6184]({{ site.repository }}/issues/6184)) + + +## 3.5.0 / 2017-06-18 +{: #v3-5-0} + +### Minor Enhancements +{: #minor-enhancements-v3-5-0} + +- Upgrade to Liquid v4 ([#4362]({{ site.repository }}/issues/4362)) +- Convert StaticFile liquid representation to a Drop & add front matter defaults support to StaticFiles ([#5871]({{ site.repository }}/issues/5871)) +- Add support for Tab-Separated Values data files (`*.tsv`) ([#5985]({{ site.repository }}/issues/5985)) +- Specify version constraint in subcommand error message. ([#5974]({{ site.repository }}/issues/5974)) +- Add a template for custom 404 page ([#5945]({{ site.repository }}/issues/5945)) +- Require `runtime_dependencies` of a Gem-based theme from its `.gemspec` file ([#5914]({{ site.repository }}/issues/5914)) +- Don't raise an error if URL contains a colon ([#5889]({{ site.repository }}/issues/5889)) +- Date filters should never raise an exception ([#5722]({{ site.repository }}/issues/5722)) +- add `plugins` config key as replacement for `gems` ([#5130]({{ site.repository }}/issues/5130)) +- create configuration from options only once in the boot process ([#5487]({{ site.repository }}/issues/5487)) +- Add option to fail a build with front matter syntax errors ([#5832]({{ site.repository }}/issues/5832)) +- Disable default layouts for documents with a `layout: none` declaration ([#5933]({{ site.repository }}/issues/5933)) +- In `jekyll new`, make copied site template user-writable ([#6072]({{ site.repository }}/issues/6072)) +- Add top-level `layout` liquid variable to Documents ([#6073]({{ site.repository }}/issues/6073)) +- Address reading non-binary static files in themes ([#5918]({{ site.repository }}/issues/5918)) +- Allow filters to sort & select based on subvalues ([#5622]({{ site.repository }}/issues/5622)) +- Add strip_index filter ([#6075]({{ site.repository }}/issues/6075)) + +### Documentation + +- Install troubleshooting on Ubuntu ([#5817]({{ site.repository }}/issues/5817)) +- Add Termux section on troubleshooting ([#5837]({{ site.repository }}/issues/5837)) +- fix ial css classes in theme doc ([#5876]({{ site.repository }}/issues/5876)) +- Update installation.md ([#5880]({{ site.repository }}/issues/5880)) +- Update Aerobatic docs ([#5883]({{ site.repository }}/issues/5883)) +- Add note to collections doc on hard-coded collections. ([#5882]({{ site.repository }}/issues/5882)) +- Makes uri_escape template docs more specific. ([#5887]({{ site.repository }}/issues/5887)) +- Remove duplicate footnote_nr from default config ([#5891]({{ site.repository }}/issues/5891)) +- Fixed tutorial for publishing gem to include repo. ([#5900]({{ site.repository }}/issues/5900)) +- update broken links ([#5905]({{ site.repository }}/issues/5905)) +- Fix typo in contribution information ([#5910]({{ site.repository }}/issues/5910)) +- update plugin repo URL to reflect repo move ([#5916]({{ site.repository }}/issues/5916)) +- Update exclude array in configuration.md ([#5947]({{ site.repository }}/issues/5947)) +- Fixed path in "Improve this page" link in Tutorials section ([#5951]({{ site.repository }}/issues/5951)) +- Corrected permalink ([#5949]({{ site.repository }}/issues/5949)) +- Included more details about adding defaults to static files ([#5971]({{ site.repository }}/issues/5971)) +- Create buddyworks ([#5962]({{ site.repository }}/issues/5962)) +- added (buddyworks) to ci list ([#5965]({{ site.repository }}/issues/5965)) +- Add a tutorial on serving custom Error 404 page ([#5946]({{ site.repository }}/issues/5946)) +- add custom 404 to tutorial navigation ([#5978]({{ site.repository }}/issues/5978)) +- Add link to order of interpretation tutorial in Tutorials nav ([#5952]({{ site.repository }}/issues/5952)) +- Document Jekyll's Philosophy ([#5792]({{ site.repository }}/issues/5792)) +- Require Ruby > 2.1.0 ([#5983]({{ site.repository }}/issues/5983)) +- Fix broken link ([#5994]({{ site.repository }}/issues/5994)) +- Default options for script/proof ([#5995]({{ site.repository }}/issues/5995)) +- Mention Bash on Ubuntu on Windows ([#5960]({{ site.repository }}/issues/5960)) +- Document `--unpublished` flag introduced in 91e9ecf ([#5959]({{ site.repository }}/issues/5959)) +- Update upgrading.md to mention usage of `bundle update` ([#5604]({{ site.repository }}/issues/5604)) +- Fix missing quotation mark ([#6002]({{ site.repository }}/issues/6002)) +- New tutorial: Convert an HTML site to Jekyll ([#5881]({{ site.repository }}/issues/5881)) +- Revamp Permalink section ([#5912]({{ site.repository }}/issues/5912)) +- Fixup tutorial on creating theme from existing HTML templates ([#6006]({{ site.repository }}/issues/6006)) +- Standardise on "URLs" without apostrophe in docs ([#6018]({{ site.repository }}/issues/6018)) +- Added txtpen in tutorial ([#6021]({{ site.repository }}/issues/6021)) +- fix typo using past participle ([#6026]({{ site.repository }}/issues/6026)) +- changed formatting to fit the style of the documentation ([#6027]({{ site.repository }}/issues/6027)) +- doc fix typo word usage ([#6028]({{ site.repository }}/issues/6028)) +- corrected reference to layout in index.md ([#6032]({{ site.repository }}/issues/6032)) +- (Minor) Update MathJax CDN ([#6013]({{ site.repository }}/issues/6013)) +- Add MvvmCross to samples ([#6035]({{ site.repository }}/issues/6035)) +- Update travis-ci.md to correct procedure ([#6043]({{ site.repository }}/issues/6043)) +- fix sentence in documentation ([#6048]({{ site.repository }}/issues/6048)) +- rephrase a sentence in posts.md to be more direct ([#6049]({{ site.repository }}/issues/6049)) +- Compress Website Sass output ([#6009]({{ site.repository }}/issues/6009)) +- doc correct spelling error ([#6050]({{ site.repository }}/issues/6050)) +- adjusted date-format in sitemap ([#6053]({{ site.repository }}/issues/6053)) +- Typo fix (welcomed change -> welcome change). ([#6070]({{ site.repository }}/issues/6070)) +- Fixed documentation inconsistency ([#6068]({{ site.repository }}/issues/6068)) +- Add own plugin -> Jekyll Brand Social Wall ([#6064]({{ site.repository }}/issues/6064)) +- Added plugin jekyll-analytics ([#6042]({{ site.repository }}/issues/6042)) +- Use more precise language when explaining links ([#6078]({{ site.repository }}/issues/6078)) +- Update plugins.md ([#6088]({{ site.repository }}/issues/6088)) +- windows 10 tutorial ([#6100]({{ site.repository }}/issues/6100)) +- Explain how to override theme styles ([#6107]({{ site.repository }}/issues/6107)) +- updated Bash on Ubuntu on Windows link in tutorial ([#6111]({{ site.repository }}/issues/6111)) +- Fix wording in `_docs/templates.md` links section ([#6114]({{ site.repository }}/issues/6114)) +- Update windows.md ([#6115]({{ site.repository }}/issues/6115)) +- Added windows to docs.yml ([#6109]({{ site.repository }}/issues/6109)) +- Be more specific on what to upload ([#6119]({{ site.repository }}/issues/6119)) +- Remove Blank Newlines from "Jekyll on Windows" Page ([#6126]({{ site.repository }}/issues/6126)) +- Link the troubleshooting page in the quickstart page ([#6134]({{ site.repository }}/issues/6134)) +- add documentation about the "pinned" label ([#6147]({{ site.repository }}/issues/6147)) +- docs(JekyllOnWindows): Add a new Installation way ([#6141]({{ site.repository }}/issues/6141)) +- corrected windows.md ([#6149]({{ site.repository }}/issues/6149)) +- Refine documentation for Windows ([#6153]({{ site.repository }}/issues/6153)) + +### Development Fixes +{: #development-fixes-v3-5-0} + +- Rubocop: add missing comma ([#5835]({{ site.repository }}/issues/5835)) +- Appease classifier-reborn ([#5934]({{ site.repository }}/issues/5934)) +- Allow releases & development on `*-stable` branches ([#5926]({{ site.repository }}/issues/5926)) +- Add script/backport-pr ([#5925]({{ site.repository }}/issues/5925)) +- Prefer .yaml over .toml ([#5966]({{ site.repository }}/issues/5966)) +- Fix Appveyor with DST-aware cucumber steps ([#5961]({{ site.repository }}/issues/5961)) +- Use Rubocop v0.47.1 till we're ready for v0.48 ([#5989]({{ site.repository }}/issues/5989)) +- Test against Ruby 2.4.0 ([#5687]({{ site.repository }}/issues/5687)) +- rubocop: lib/jekyll/renderer.rb complexity fixes ([#5052]({{ site.repository }}/issues/5052)) +- Use yajl-ruby 1.2.2 (now with 2.4 support) ([#6007]({{ site.repository }}/issues/6007)) +- Bump Rubocop to v0.48 ([#5997]({{ site.repository }}/issues/5997)) +- doc use example.com ([#6031]({{ site.repository }}/issues/6031)) +- fix typo ([#6040]({{ site.repository }}/issues/6040)) +- Fix CI ([#6044]({{ site.repository }}/issues/6044)) +- Remove `ruby RUBY_VERSION` from generated Gemfile ([#5803]({{ site.repository }}/issues/5803)) +- Test if hidden collections output a document with a future date ([#6103]({{ site.repository }}/issues/6103)) +- Add test for uri_escape on reserved characters ([#6086]({{ site.repository }}/issues/6086)) +- Allow you to specify the rouge version via an environment variable for testing ([#6138]({{ site.repository }}/issues/6138)) +- Bump Rubocop to 0.49.1 ([#6093]({{ site.repository }}/issues/6093)) +- Lock nokogiri to 1.7.x for Ruby 2.1 ([#6140]({{ site.repository }}/issues/6140)) + +### Site Enhancements +{: #site-enhancements-v3-5-0} + +- Corrected date for version 3.4.0 ([#5842]({{ site.repository }}/issues/5842)) +- Add the correct year to the 3.4.0 release date ([#5858]({{ site.repository }}/issues/5858)) +- Add documentation about order of interpretation ([#5834]({{ site.repository }}/issues/5834)) +- Documentation on how to build navigation ([#5698]({{ site.repository }}/issues/5698)) +- Navigation has been moved out from docs ([#5927]({{ site.repository }}/issues/5927)) +- Make links in sidebar for current page more prominent ([#5820]({{ site.repository }}/issues/5820)) +- Update normalize.css to v6.0.0 ([#6008]({{ site.repository }}/issues/6008)) +- Docs: rename `gems` to `plugins` ([#6082]({{ site.repository }}/issues/6082)) +- plugins -> gems ([#6110]({{ site.repository }}/issues/6110)) +- Document difference between cgi_escape and uri_escape [#5970]({{ site.repository }}/issues/5970) ([#6081]({{ site.repository }}/issues/6081)) + +### Bug Fixes +{: #bug-fixes-v3-5-0} + +- Exclude Gemfile by default ([#5860]({{ site.repository }}/issues/5860)) +- Convertible#validate_permalink!: ensure the return value of `data["permalink"]` is a string before asking if it is empty ([#5878]({{ site.repository }}/issues/5878)) +- Allow abbreviated post dates ([#5920]({{ site.repository }}/issues/5920)) +- Remove dependency on include from default about.md ([#5903]({{ site.repository }}/issues/5903)) +- Allow colons in `uri_escape` filter ([#5957]({{ site.repository }}/issues/5957)) +- Re-surface missing public methods in `Jekyll::Document` ([#5975]({{ site.repository }}/issues/5975)) +- absolute_url should not mangle URL if called more than once ([#5789]({{ site.repository }}/issues/5789)) +- patch URLFilters to prevent `//` ([#6058]({{ site.repository }}/issues/6058)) +- add test to ensure variables work in `where_exp` condition ([#5315]({{ site.repository }}/issues/5315)) +- Read explicitly included dot-files in collections. ([#6092]({{ site.repository }}/issues/6092)) +- Default `baseurl` to `nil` instead of empty string ([#6137]({{ site.repository }}/issues/6137)) +- Filters#time helper: Duplicate time before calling #localtime. ([#5996]({{ site.repository }}/issues/5996)) + + +## 3.4.5 / 2017-06-30 +{: #v3-4-5} + +- Backport [#6185]({{ site.repository }}/issues/6185) for v3.4.x: Always normalize the result of the `relative_url` filter ([#6186]({{ site.repository }}/issues/6186)) + + +## 3.4.4 / 2017-06-17 +{: #v3-4-4} + +- Backport [#6137]({{ site.repository }}/issues/6137) for v3.4.x: Default `baseurl` to `nil` instead of empty string ([#6146]({{ site.repository }}/issues/6146)) + + +## 3.4.3 / 2017-03-21 +{: #v3-4-3} + +- Backport [#5957]({{ site.repository }}/issues/5957) for v3.4.x: Allow colons in `uri_escape` filter ([#5968]({{ site.repository }}/issues/5968)) + + +## 3.4.2 / 2017-03-09 +{: #v3-4-2} + +- Backport [#5871]({{ site.repository }}/issues/5871) for v3.4.x: Convert StaticFile liquid representation to a Drop & add front matter defaults support to StaticFiles ([#5940]({{ site.repository }}/issues/5940)) + + +## 3.4.1 / 2017-03-02 +{: #v3-4-1} + +- Backport [#5920]({{ site.repository }}/issues/5920) for v3.4.x: Allow abbreviated post dates ([#5924]({{ site.repository }}/issues/5924)) + + +## 3.4.0 / 2017-01-27 +{: #v3-4-0} + +### Minor Enhancements +{: #minor-enhancements-v3-4-0} + +- Add connector param to `array_to_sentence_string` filter ([#5597]({{ site.repository }}/issues/5597)) +- Adds `group_by_exp` filter ([#5513]({{ site.repository }}/issues/5513)) +- Use Addressable instead of URI to decode ([#5726]({{ site.repository }}/issues/5726)) +- throw IncludeTagError if error occurs in included file ([#5767]({{ site.repository }}/issues/5767)) +- Write Jekyll::Utils::Exec.run for running shell commands. ([#5640]({{ site.repository }}/issues/5640)) +- Use the current year for the LICENSE of theme ([#5712]({{ site.repository }}/issues/5712)) +- Update License ([#5713]({{ site.repository }}/issues/5713)) + +### Bug Fixes +{: #bug-fixes-v3-4-0} + +- Escaped regular expressions when using `post_url`. ([#5605]({{ site.repository }}/issues/5605)) +- fix date parsing in file names to be stricter ([#5609]({{ site.repository }}/issues/5609)) +- Add a module to re-define `ENV["TZ"]` in Windows ([#5612]({{ site.repository }}/issues/5612)) +- Use each instead of map to actually return nothing ([#5668]({{ site.repository }}/issues/5668)) +- include: fix 'no implicit conversion of nil to String' ([#5750]({{ site.repository }}/issues/5750)) +- Don't include the theme's includes_path if it is nil. ([#5780]({{ site.repository }}/issues/5780)) +- test double slash when input = '/' ([#5542]({{ site.repository }}/issues/5542)) +- use logger.info for related posts ([#5822]({{ site.repository }}/issues/5822)) + +### Site Enhancements +{: #site-enhancements-v3-4-0} + +- Use only the used Font Awesome icons. ([#5530]({{ site.repository }}/issues/5530)) +- Switch to `https` when possible. ([#5611]({{ site.repository }}/issues/5611)) +- Update `_font-awesome.scss` to move .woff file before .ttf ([#5614]({{ site.repository }}/issues/5614)) +- Update documentation on updating FontAwesome Iconset ([#5655]({{ site.repository }}/issues/5655)) +- Use defaults for docs and news-items ([#5744]({{ site.repository }}/issues/5744)) +- Sort gems in `docs/_config.yml` ([#5746]({{ site.repository }}/issues/5746)) +- Add missing class ([#5791]({{ site.repository }}/issues/5791)) +- Improve template docs ([#5694]({{ site.repository }}/issues/5694)) + +### Development Fixes +{: #development-fixes-v3-4-0} + +- clean unit-test names in `test/test_tags.rb` ([#5608]({{ site.repository }}/issues/5608)) +- Add cucumber feature to test for bonafide theme gems ([#5384]({{ site.repository }}/issues/5384)) +- Use `assert_nil` instead of `assert_equal nil` ([#5652]({{ site.repository }}/issues/5652)) +- Rubocop -a on lib/jekyll ([#5666]({{ site.repository }}/issues/5666)) +- Bump to rake 12.0 ([#5670]({{ site.repository }}/issues/5670)) +- Rubocop Gemfile ([#5671]({{ site.repository }}/issues/5671)) +- update Classifier-Reborn to 2.1.0 ([#5711]({{ site.repository }}/issues/5711)) +- Rubocop: fix Rakefile and gemspec ([#5745]({{ site.repository }}/issues/5745)) +- Use `assert_nil` ([#5725]({{ site.repository }}/issues/5725)) +- Sort gems in `jekyll.gemspec` ([#5746]({{ site.repository }}/issues/5746)) +- Rubocop: Require consistent comma in multiline literals ([#5761]({{ site.repository }}/issues/5761)) +- Bump rubocop ([#5765]({{ site.repository }}/issues/5765)) +- New rubocop security checks ([#5768]({{ site.repository }}/issues/5768)) +- test/helper: fix flaky plugin path test by removing calls to Dir.chdir without a block ([#5779]({{ site.repository }}/issues/5779)) +- Use latest jemoji gem ([#5782]({{ site.repository }}/issues/5782)) +- Bump htmlproofer ([#5781]({{ site.repository }}/issues/5781)) +- Bump rubies we test against ([#5784]({{ site.repository }}/issues/5784)) +- Bump rdoc to v5.0 ([#5797]({{ site.repository }}/issues/5797)) +- Bump codeclimate-test-reporter to v1.0.5 ([#5798]({{ site.repository }}/issues/5798)) + +### Documentation + +- Improve quickstart docs ([#5689]({{ site.repository }}/issues/5689)) +- Add Jekyll-Post to list of plugins ([#5705]({{ site.repository }}/issues/5705)) +- Add jekyll-numbered-headings ([#5688]({{ site.repository }}/issues/5688)) +- Docs: move permalinks from documents into config ([#5544]({{ site.repository }}/issues/5544)) +- Improve collections docs ([#5691]({{ site.repository }}/issues/5691)) +- Fix [#5730]({{ site.repository }}/issues/5730): add gcc and make to the list of requirements ([#5731]({{ site.repository }}/issues/5731)) +- Remove instructions to install Jekyll 2 on Windows ([#5582]({{ site.repository }}/issues/5582)) +- Fix example URL inconsistency ([#5592]({{ site.repository }}/issues/5592)) +- Replace backticks within HTML blocks with HTML tags ([#5435]({{ site.repository }}/issues/5435)) +- Add jekyll-migrate-permalink ([#5600]({{ site.repository }}/issues/5600)) +- Fix bad config YAML in collections example ([#5587]({{ site.repository }}/issues/5587)) +- Bring documentation on 'Directory Structure' up-to-date ([#5573]({{ site.repository }}/issues/5573)) +- Fixed typo ([#5632]({{ site.repository }}/issues/5632)) +- use backticks for Gemfile for consistency since in the next sentence … ([#5641]({{ site.repository }}/issues/5641)) +- Update Core team list in the README file ([#5643]({{ site.repository }}/issues/5643)) +- Improve Permalinks documentation. ([#5653]({{ site.repository }}/issues/5653)) +- Fix typo in Variables doc page ([#5657]({{ site.repository }}/issues/5657)) +- Fix a couple of typos in the docs ([#5658]({{ site.repository }}/issues/5658)) +- Update windows.md ([#5683]({{ site.repository }}/issues/5683)) +- Improve permalinks docs ([#5693]({{ site.repository }}/issues/5693)) +- Document --unpublished build option ([#5720]({{ site.repository }}/issues/5720)) +- Improve pages docs ([#5692]({{ site.repository }}/issues/5692)) +- Added new includes.md topic to docs ([#5696]({{ site.repository }}/issues/5696)) +- Replace a dead link with a web-archived one ([#5738]({{ site.repository }}/issues/5738)) +- Remove duplicate paragraph. ([#5740]({{ site.repository }}/issues/5740)) +- Addition of a sample "typical post" ([#5473]({{ site.repository }}/issues/5473)) +- Fix a minor grammatical mistake on themes' document ### -dev ([#5748]({{ site.repository }}/issues/5748)) +- Correct comments in data_reader.rb ([#5621]({{ site.repository }}/issues/5621)) +- Add jekyll-pre-commit to plugins list ([#5752]({{ site.repository }}/issues/5752)) +- Update quickstart.md ([#5758]({{ site.repository }}/issues/5758)) +- Correct minor typo ([#5764]({{ site.repository }}/issues/5764)) +- Fix a markdown link to look properly on the web ([#5769]({{ site.repository }}/issues/5769)) +- Info about the help command usage ([#5312]({{ site.repository }}/issues/5312)) +- Add missing merge labels for jekyllbot ([#5753]({{ site.repository }}/issues/5753)) +- Fix broken links in documentation ([#5736]({{ site.repository }}/issues/5736)) +- Docs: add `match_regex` and `replace_regex` filters ([#5799]({{ site.repository }}/issues/5799)) +- Got that diaper money? ([#5810]({{ site.repository }}/issues/5810)) +- Sort content by popularity using Google Analytics ([#5812]({{ site.repository }}/issues/5812)) +- Rework CI doc to include multiple providers. ([#5815]({{ site.repository }}/issues/5815)) +- Improve theme docs ([#5690]({{ site.repository }}/issues/5690)) +- Add mention of classifier-reborn for LSI ([#5811]({{ site.repository }}/issues/5811)) +- Added note about --blank flag ([#5802]({{ site.repository }}/issues/5802)) +- Fixed inaccuracy in "Built-in permalink styles" docs ([#5819]({{ site.repository }}/issues/5819)) + + +## 3.3.1 / 2016-11-14 +{: #v3-3-1} + +### Minor Enhancements +{: #minor-enhancements-v3-3-1} + +- Collapse `gsub` for performance ([#5494]({{ site.repository }}/issues/5494)) +- URL: warn if key doesn't exist in url drop ([#5524]({{ site.repository }}/issues/5524)) + +### Bug Fixes +{: #bug-fixes-v3-3-1} + +- Fix typo in `theme_template` README ([#5472]({{ site.repository }}/issues/5472)) +- Do not swallow all exceptions on render ([#5495]({{ site.repository }}/issues/5495)) +- Site template: fixed `_config.yml` comment typo ([#5511]({{ site.repository }}/issues/5511)) +- `jekyll new-theme` should specify Jekyll as a runtime dependency for the theme ([#5457]({{ site.repository }}/issues/5457)) +- Be much more specific about ignoring specific vendored directories. ([#5564]({{ site.repository }}/issues/5564)) +- Only warn about auto-regeneration bug on Bash On Windows. ([#5464]({{ site.repository }}/issues/5464)) +- Allow permalink template to have underscores ([#5572]({{ site.repository }}/issues/5572)) + +### Site Enhancements +{: #site-enhancements-v3-3-1} + +- Documentation: `link` Liquid tag ([#5449]({{ site.repository }}/issues/5449)) +- Updating install instruction link for Jekyll 3 on Windows ([#5475]({{ site.repository }}/issues/5475)) +- Update normalize.css to v5.0.0 ([#5471]({{ site.repository }}/issues/5471)) +- Add jekyll-data to the list of plugins ([#5491]({{ site.repository }}/issues/5491)) +- Add info about checking version + updating ([#5497]({{ site.repository }}/issues/5497)) +- Add jekyll-include-absolute-plugin to list of third-party plugins ([#5492]({{ site.repository }}/issues/5492)) +- Remove jekyll-hook from deployment methods ([#5502]({{ site.repository }}/issues/5502)) +- Update deployment-methods.md ([#5504]({{ site.repository }}/issues/5504)) +- Ubuntu users should install ruby2.3-dev ([#5512]({{ site.repository }}/issues/5512)) +- Remove Glynn as deployment option ([#5519]({{ site.repository }}/issues/5519)) +- Fix broken forum link ([#5466]({{ site.repository }}/issues/5466)) +- Move documentation to docs folder ([#5459]({{ site.repository }}/issues/5459)) +- Fix broken links in CONTRIBUTING ([#5533]({{ site.repository }}/issues/5533)) +- Update documentation on jekyllrb.com ([#5540]({{ site.repository }}/issues/5540)) +- Fix HTML rendering ([#5536]({{ site.repository }}/issues/5536)) +- Remove outdated deployment information ([#5557]({{ site.repository }}/issues/5557)) +- no more invalid US-ASCII on lines 30 and 97 ([#5520]({{ site.repository }}/issues/5520)) +- Add permalinks to docs in '/maintaining/' ([#5532]({{ site.repository }}/issues/5532)) +- Add jekyll-pinboard to list of third-party plugins ([#5514]({{ site.repository }}/issues/5514)) +- Fix formatting in 2-to-3.md ([#5507]({{ site.repository }}/issues/5507)) +- Add two plugins to the plugins page ([#5493]({{ site.repository }}/issues/5493)) +- Use site.baseurl before link and post_url tags ([#5559]({{ site.repository }}/issues/5559)) +- Fix link to jekyll-pinboard plugin ([#5570]({{ site.repository }}/issues/5570)) +- mention `docs` folder as a way to deploy on GitHub Pages ([#5571]({{ site.repository }}/issues/5571)) + +### Development Fixes +{: #development-fixes-v3-3-1} + +- fix rubocop errors on testing with Rubocop 0.44 ([#5489]({{ site.repository }}/issues/5489)) +- script/test: add missing whitespace ([#5479]({{ site.repository }}/issues/5479)) +- Restrict Rubocop version ([#5496]({{ site.repository }}/issues/5496)) +- include a hashbang for all benchmark scripts & make them executable ([#5505]({{ site.repository }}/issues/5505)) +- Update source in script/proof ([#5538]({{ site.repository }}/issues/5538)) +- Collections.feature: conditional steps to have it pass on Windows ([#5546]({{ site.repository }}/issues/5546)) +- Fix tests to get script/test to pass on Windows ([#5526]({{ site.repository }}/issues/5526)) + + +## 3.3.0 / 2016-10-06 +{: #v3-3-0} + +### Minor Enhancements +{: #minor-enhancements-v3-3-0} + +- Colorize interpolated output in logger.info ([#5239]({{ site.repository }}/issues/5239)) +- Site template: exclude Gemfile and Gemfile.lock in site config ([#5293]({{ site.repository }}/issues/5293)) +- Fix [#5233]({{ site.repository }}/issues/5233): Increase our ability to detect Windows. ([#5235]({{ site.repository }}/issues/5235)) +- update gitignore template to ignore theme gems built by user ([#5326]({{ site.repository }}/issues/5326)) +- Adds ability to link to all files ([#5199]({{ site.repository }}/issues/5199)) +- Exclude vendor by default ([#5361]({{ site.repository }}/issues/5361)) +- Add ThemeAssetsReader which reads assets from a theme ([#5364]({{ site.repository }}/issues/5364)) +- Add bundle install to jekyll new command ([#5237]({{ site.repository }}/issues/5237)) +- Add absolute_url and relative_url filters. ([#5399]({{ site.repository }}/issues/5399)) +- Site template: remove `css/` from new site scaffolding ([#5402]({{ site.repository }}/issues/5402)) +- Site template: Move contents of the index.html page to the 'home' layout ([#5420]({{ site.repository }}/issues/5420)) +- Exclude node_modules by default ([#5210]({{ site.repository }}/issues/5210)) +- Run hooks in priority order. ([#5157]({{ site.repository }}/issues/5157)) +- Add `static_file.name` and `.basename` Liquid attributes ([#5264]({{ site.repository }}/issues/5264)) +- set site.url in dev environment to `http://localhost:4000` ([#5431]({{ site.repository }}/issues/5431)) +- Add support for indented link references on excerpt ([#5212]({{ site.repository }}/issues/5212)) + +### Bug Fixes +{: #bug-fixes-v3-3-0} + +- Use jekyll-feed to generate the default site's RSS feed ([#5196]({{ site.repository }}/issues/5196)) +- Site#configure_theme: do not set theme unless it's a string ([#5189]({{ site.repository }}/issues/5189)) +- Convertible: set self.output in #render_all_layouts and #do_layout ([#5337]({{ site.repository }}/issues/5337)) +- Only complain about `kramdown.coderay` if it is actually in the config ([#5380]({{ site.repository }}/issues/5380)) +- Clarify documentation in theme gem's README template ([#5376]({{ site.repository }}/issues/5376)) +- Allow underscore in highlighter language ([#5375]({{ site.repository }}/issues/5375)) +- Site template: set empty url in config file by default ([#5338]({{ site.repository }}/issues/5338)) +- Site template config: prepend 'jekyll serve' with 'bundle exec' ([#5430]({{ site.repository }}/issues/5430)) +- Don't call `File.utime` for StaticFiles if it's a symlink ([#5427]({{ site.repository }}/issues/5427)) +- Fix handling of non-ASCII characters in new `*_url` filters ([#5410]({{ site.repository }}/issues/5410)) +- Remove autoload of Draft which no longer exists. ([#5441]({{ site.repository }}/issues/5441)) +- Fix issue where Windows drive name is stripped from Jekyll.sanitized_path incorrectly ([#5256]({{ site.repository }}/issues/5256)) +- Fix bug where `post_url` tag matched incorrect post with subdirectory ([#4873]({{ site.repository }}/issues/4873)) +- Fix loading data from subdir with a period in name ([#5433]({{ site.repository }}/issues/5433)) +- Revert Commands::Serve#server_address signature change. ([#5456]({{ site.repository }}/issues/5456)) + +### Site Enhancements +{: #site-enhancements-v3-3-0} + +- Document `to_integer` and `inspect` filters ([#5185]({{ site.repository }}/issues/5185)) +- Fix path in the prompt ([#5194]({{ site.repository }}/issues/5194)) +- need subcommand build ([#5190]({{ site.repository }}/issues/5190)) +- Add the Jekyll Cloudinary plugin ([#5183]({{ site.repository }}/issues/5183)) +- Documentation : `new-theme` command ([#5205]({{ site.repository }}/issues/5205)) +- Document `link` Liquid tag ([#5182]({{ site.repository }}/issues/5182)) +- Remove mention of page for link tag in release post ([#5214]({{ site.repository }}/issues/5214)) +- fixed typo ([#5226]({{ site.repository }}/issues/5226)) +- Add missing comma ([#5222]({{ site.repository }}/issues/5222)) +- Maintain aspect ratio with `height: auto;` ([#5254]({{ site.repository }}/issues/5254)) +- Fix a link in deployment-methods.md ([#5244]({{ site.repository }}/issues/5244)) +- Documentation: improve highlight in `Creating a theme` ([#5249]({{ site.repository }}/issues/5249)) +- Bundler isn't installed by default ([#5258]({{ site.repository }}/issues/5258)) +- Update troubleshooting documentation to include fix for issue with vendored gems ([#5271]({{ site.repository }}/issues/5271)) +- Link `--lsi` option's description to Wikipedia docs on LSI ([#5274]({{ site.repository }}/issues/5274)) +- Document `--profile` option on the configuration page ([#5279]({{ site.repository }}/issues/5279)) +- Update homepage to sync with merge of [#5258]({{ site.repository }}/issues/5258) ([#5287]({{ site.repository }}/issues/5287)) +- Add post about Jekyll Admin initial release ([#5291]({{ site.repository }}/issues/5291)) +- Replace liquid highlight tag with backticks ([#5262]({{ site.repository }}/issues/5262)) +- Word update ([#5294]({{ site.repository }}/issues/5294)) +- Site documentation section links always point to https://jekyllrb.com ([#5281]({{ site.repository }}/issues/5281)) +- Missing `:site, :post_render` payload documentation on site ([#5280]({{ site.repository }}/issues/5280)) +- Site: exclude README.md and .gitignore ([#5304]({{ site.repository }}/issues/5304)) +- Add link to Staticman ([#5224]({{ site.repository }}/issues/5224)) +- Update url for OpenShift ([#5320]({{ site.repository }}/issues/5320)) +- Add help for missing static_file e.g. on heroku ([#5334]({{ site.repository }}/issues/5334)) +- Add a line about updating theme-gems in the docs ([#5318]({{ site.repository }}/issues/5318)) +- Explain how to copy a theme's files ([#5335]({{ site.repository }}/issues/5335)) +- .md as default extension in examples ([#5316]({{ site.repository }}/issues/5316)) +- Fix small typo in docs ([#5347]({{ site.repository }}/issues/5347)) +- Add missing period to sentence in first paragraph. ([#5372]({{ site.repository }}/issues/5372)) +- added jekyll-spotify plugin ([#5369]({{ site.repository }}/issues/5369)) +- Add jekyll-menus to the list of plugins. ([#5397]({{ site.repository }}/issues/5397)) +- macOS and one grammar fix ([#5403]({{ site.repository }}/issues/5403)) +- Add documentation for `relative_url` and `absolute_url` ([#5405]({{ site.repository }}/issues/5405)) +- Bugfix on logo in JSON-LD ([#5421]({{ site.repository }}/issues/5421)) +- Fix Travis.ci documentation ([#5413]({{ site.repository }}/issues/5413)) +- Update documentation regarding `bundle install` after `jekyll new` ([#5428]({{ site.repository }}/issues/5428)) +- Replace classic box-sizing reset with inheritance reset ([#5411]({{ site.repository }}/issues/5411)) +- Update Wikipedia YAML list link ([#5452]({{ site.repository }}/issues/5452)) +- Add Jekyll 3.3 release post ([#5442]({{ site.repository }}/issues/5442)) + +### Development Fixes +{: #development-fixes-v3-3-0} + +- Update appveyor.yml and fix optional deps for Ruby x64 ([#5180]({{ site.repository }}/issues/5180)) +- Improve tests for Jekyll::PluginManager ([#5167]({{ site.repository }}/issues/5167)) +- Update Ruby versions in travis.yml ([#5221]({{ site.repository }}/issues/5221)) +- Avoid installing unnecessary gems for site testing ([#5272]({{ site.repository }}/issues/5272)) +- Proposal: Affinity teams and their captains ([#5273]({{ site.repository }}/issues/5273)) +- Replace duplicate with positive local test in issue template ([#5286]({{ site.repository }}/issues/5286)) +- Update AppVeyor config. ([#5240]({{ site.repository }}/issues/5240)) +- Execute jekyll from clone instead of defined binary when running 'script/default-site' ([#5295]({{ site.repository }}/issues/5295)) +- rubocop: lib/jekyll/document.rb complexity fixes ([#5045]({{ site.repository }}/issues/5045)) +- Proxy a number of Convertible methods to Renderer ([#5308]({{ site.repository }}/issues/5308)) +- Run executable for Cucumber via Ruby instead of Shell ([#5383]({{ site.repository }}/issues/5383)) +- Appease Rubocop ([#5381]({{ site.repository }}/issues/5381)) +- remove features' directories on windows with proper access ([#5389]({{ site.repository }}/issues/5389)) +- `site_configuration.feature`: use UTC format in timezone ([#5416]({{ site.repository }}/issues/5416)) +- swallow bundle output from `jekyll new` while in CI ([#5408]({{ site.repository }}/issues/5408)) +- Add .editorconfig ([#5412]({{ site.repository }}/issues/5412)) + + +## 3.2.1 / 2016-08-02 +{: #v3-2-1} + +### Bug Fixes +{: #bug-fixes-v3-2-1} + +- Include theme directories in default gemspec ([#5152]({{ site.repository }}/issues/5152)) +- Fix for symlinked themes ([#5156]({{ site.repository }}/issues/5156)) +- Layout: set `relative_path` without using Pathname ([#5164]({{ site.repository }}/issues/5164)) + +### Development Fixes +{: #development-fixes-v3-2-1} + +- Add test to build the default site ([#5154]({{ site.repository }}/issues/5154)) +- script/default-site: specify `BUNDLE_GEMFILE` for new site ([#5178]({{ site.repository }}/issues/5178)) +- script/default-site: read Jekyll source from local clone ([#5188]({{ site.repository }}/issues/5188)) + +### Site Enhancements +{: #site-enhancements-v3-2-1} + +- Enable site excerpts ([#5150]({{ site.repository }}/issues/5150)) +- Initial 404 page ([#5143]({{ site.repository }}/issues/5143)) +- Remove the "this feature is unreleased" warning from the theme docs ([#5158]({{ site.repository }}/issues/5158)) +- Future True on GitHub Pages note ([#5173]({{ site.repository }}/issues/5173)) +- Minor updates and corrections ([#5177]({{ site.repository }}/issues/5177)) +- index.html: update instructions to require bundler ([#5169]({{ site.repository }}/issues/5169)) +- docs/quickstart: update instructions to require bundler ([#5168]({{ site.repository }}/issues/5168)) + + +## 3.2.0 / 2016-07-26 +{: #v3-2-0} + +### Minor Enhancements +{: #minor-enhancements-v3-2-0} + +- Stop testing with Ruby 2.0.x EOL ([#4381]({{ site.repository }}/issues/4381)) +- Allow collections to have documents that have no file extension ([#4545]({{ site.repository }}/issues/4545)) +- Add size property to `group_by` result ([#4557]({{ site.repository }}/issues/4557)) +- Site Template: Removed unnecessary nesting from `_base.scss` ([#4637]({{ site.repository }}/issues/4637)) +- Adding a debug log statement for skipped future documents. ([#4558]({{ site.repository }}/issues/4558)) +- Site Template: Changed main `
` to `
` and added accessibility info ([#4636]({{ site.repository }}/issues/4636)) +- Add array support to `where` filter ([#4555]({{ site.repository }}/issues/4555)) +- 'jekyll clean': also remove .sass-cache ([#4652]({{ site.repository }}/issues/4652)) +- Clean up `Tags::PostUrl` a bit, including better errors and date parsing ([#4670]({{ site.repository }}/issues/4670)) +- Use `String#encode` for `xml_escape` filter instead of `CGI.escapeHTML` ([#4694]({{ site.repository }}/issues/4694)) +- Add `show_dir_listing` option for serve command and fix index file names ([#4533]({{ site.repository }}/issues/4533)) +- Site Template: write a Gemfile which is educational to the new site ([#4542]({{ site.repository }}/issues/4542)) +- Site template: add explanation of site variables in the example `_config.yml` ([#4704]({{ site.repository }}/issues/4704)) +- Adds `link` Liquid tag to make generation of URLs easier ([#4624]({{ site.repository }}/issues/4624)) +- Allow static files to be symlinked in unsafe mode or non-prod environments ([#4640]({{ site.repository }}/issues/4640)) +- Add `:after_init` hook & add `Site#config=` to make resetting config easy ([#4703]({{ site.repository }}/issues/4703)) +- DocumentDrop: add `#<=>` which sorts by date (falling back to path) ([#4741]({{ site.repository }}/issues/4741)) +- Add a `where_exp` filter for filtering by expression ([#4478]({{ site.repository }}/issues/4478)) +- Globalize Jekyll's Filters. ([#4792]({{ site.repository }}/issues/4792)) +- Gem-based themes ([#4595]({{ site.repository }}/issues/4595)) +- Allow symlinks if they point to stuff inside `site.source` ([#4710]({{ site.repository }}/issues/4710)) +- Update colorator dependency to v1.x ([#4855]({{ site.repository }}/issues/4855)) +- Move EntryFilter to use Pathutil & fix `glob_include?` ([#4859]({{ site.repository }}/issues/4859)) +- Add 'jekyll new-theme' command to help users get up and running creating a theme ([#4848]({{ site.repository }}/issues/4848)) +- `markdownify` and `smartify` should convert input to string before conversion ([#4958]({{ site.repository }}/issues/4958)) +- Run `Site#generate` for 'jekyll doctor' to catch plugin issues ([#5005]({{ site.repository }}/issues/5005)) +- Add `normalize_whitespace` filter ([#4917]({{ site.repository }}/issues/4917)) +- Move bin/jekyll to exe/jekyll to prevent collision with binstubs ([#5014]({{ site.repository }}/issues/5014)) +- Cleaning up site template & theme updates. ([#4922]({{ site.repository }}/issues/4922)) +- Add fetch method to Drops ([#5056]({{ site.repository }}/issues/5056)) +- Extract tag name to class method ([#5063]({{ site.repository }}/issues/5063)) +- check if relative URL contains a colon ([#5069]({{ site.repository }}/issues/5069)) +- Enable strict (or lax) liquid parsing via a config variable. ([#5053]({{ site.repository }}/issues/5053)) +- Add filter: `to_integer` ([#5101]({{ site.repository }}/issues/5101)) +- watcher: pass site instance to watch plugin ([#5109]({{ site.repository }}/issues/5109)) +- Show liquid warnings. ([#5129]({{ site.repository }}/issues/5129)) +- Add `--baseurl` to `build` subcommand ([#5135]({{ site.repository }}/issues/5135)) + +### Bug Fixes +{: #bug-fixes-v3-2-0} + +- Site Template: Added a default lang attribute ([#4633]({{ site.repository }}/issues/4633)) +- Site template: Escape title and description where it is used in HTML ([#4606]({{ site.repository }}/issues/4606)) +- `Document#date`: drafts which have no date should use source file mtime ([#4611]({{ site.repository }}/issues/4611)) +- `Filters#time`: clone an input Time so as to be non-destructive ([#4590]({{ site.repository }}/issues/4590)) +- Doctor: fix issue where `--config` wasn't a recognized flag ([#4598]({{ site.repository }}/issues/4598)) +- Ensures `related_posts` are only set for a post ([#4620]({{ site.repository }}/issues/4620)) +- `EntryFilter#special?`: ignore filenames which begin with `~` ([#4491]({{ site.repository }}/issues/4491)) +- Cleaner: `keep_files` should only apply to the beginning of paths, not substrings with index > 0 ([#3849]({{ site.repository }}/issues/3849)) +- Use SSLEnable instead of EnableSSL and make URL HTTPS. ([#4693]({{ site.repository }}/issues/4693)) +- convertible: use `Document::YAML_FRONT_MATTER_REGEXP` to parse transformable files ([#4786]({{ site.repository }}/issues/4786)) +- Example in the site template should be IANA-approved example.com ([#4793]({{ site.repository }}/issues/4793)) +- 3.2.x/master: Fix defaults for Documents (posts/collection docs) ([#4808]({{ site.repository }}/issues/4808)) +- Don't rescue LoadError or bundler load errors for Bundler. ([#4857]({{ site.repository }}/issues/4857)) +- `Serve.process` should receive same config as `Build.process` ([#4953]({{ site.repository }}/issues/4953)) +- Prevent reset of page in Liquid payload right before rendering layouts ([#5009]({{ site.repository }}/issues/5009)) +- Add missing fields to ExcerptDrop ([#5067]({{ site.repository }}/issues/5067)) +- Stringify configuration overrides before first use ([#5060]({{ site.repository }}/issues/5060)) +- hooks: move `after_init` hook call at the end of `Site#initialize` ([#5106]({{ site.repository }}/issues/5106)) +- filters: raise error if no input given to date filters ([#5127]({{ site.repository }}/issues/5127)) +- `where_exp` filter should filter posts ([#4860]({{ site.repository }}/issues/4860)) + +### Forward Ports +{: #forward-ports-v3-2-0} + +- From v3.1.4: Add ExcerptDrop and remove excerpt's ability to refer to itself in Liquid ([#4941]({{ site.repository }}/issues/4941)) +- From v3.1.4: Configuration permalink fix and addition of Configuration.from and sorting `site.collections` by label ([#4942]({{ site.repository }}/issues/4942)) +- From v3.1.4: Fix {% raw %}`{{ layout }}`{% endraw %} oddities (proper inheritance & fixing overflow of old data) ([#4943]({{ site.repository }}/issues/4943)) +- From v3.1.5: Sort the results of the `require_all` glob ([#4944]({{ site.repository }}/issues/4944)) +- From v3.1.6: Add ability to render drops as JSON ([#4945]({{ site.repository }}/issues/4945)) + +### Development Fixes +{: #development-fixes-v3-2-0} + +- Add project maintainer profile links ([#4591]({{ site.repository }}/issues/4591)) +- Fix state leakage in Kramdown test ([#4618]({{ site.repository }}/issues/4618)) +- Unify method for copying special files from repo to site ([#4601]({{ site.repository }}/issues/4601)) +- Refresh the contributing file ([#4596]({{ site.repository }}/issues/4596)) +- change smartify doc from copy/paste of markdownify doc ([#4653]({{ site.repository }}/issues/4653)) +- Update Rake & disable warnings when running tests ([#4720]({{ site.repository }}/issues/4720)) +- Fix many warnings ([#4537]({{ site.repository }}/issues/4537)) +- Don't blindly assume the last system when determining "open" cmd ([#4717]({{ site.repository }}/issues/4717)) +- Fix "locally" typo in contributing documentation ([#4756]({{ site.repository }}/issues/4756)) +- Update Rubocop rules ([#4886]({{ site.repository }}/issues/4886)) +- Flesh out the issue template to be much more detailed ([#4849]({{ site.repository }}/issues/4849)) +- Fixing rubocop offenses in lib/jekyll/cleaner.rb ([#4892]({{ site.repository }}/issues/4892)) +- Update `jekyll/commands*` to pass rubocop rules ([#4888]({{ site.repository }}/issues/4888)) +- Clean up many test files to pass Rubocop rules ([#4902]({{ site.repository }}/issues/4902)) +- Rubocop cleanup for some utils and further test files ([#4916]({{ site.repository }}/issues/4916)) +- Rubocop: Low hanging fruit ([#4936]({{ site.repository }}/issues/4936)) +- Rubocop: `Drop` changes from v3.1 forward-ports ([#4949]({{ site.repository }}/issues/4949)) +- Rubocop: cleanup for misc files ([#4946]({{ site.repository }}/issues/4946)) +- Rubocop: Stevenson ([#4951]({{ site.repository }}/issues/4951)) +- Rubocop: lib/jekyll/entry_filter.rb ([#4950]({{ site.repository }}/issues/4950)) +- Rubocop: `test/*` ([#4947]({{ site.repository }}/issues/4947)) +- Rubocop: features ([#4934]({{ site.repository }}/issues/4934)) +- Rubocop: Liquid renderer ([#4933]({{ site.repository }}/issues/4933)) +- Rubocop: converters ([#4931]({{ site.repository }}/issues/4931)) +- Rubocop: Site Drop ([#4948]({{ site.repository }}/issues/4948)) +- Rubocop: tags ([#4938]({{ site.repository }}/issues/4938)) +- Rubocop: Readers ([#4932]({{ site.repository }}/issues/4932)) +- rubocop: jekyll/lib/frontmatter_defaults.rb ([#4974]({{ site.repository }}/issues/4974)) +- rubocop: features/step_definitions.rb ([#4956]({{ site.repository }}/issues/4956)) +- Rubocop theme and url jekyll libs ([#4959]({{ site.repository }}/issues/4959)) +- Rubocop jekyll.rb ([#4966]({{ site.repository }}/issues/4966)) +- Rubocop: use %r for all regular expressions. ([#4979]({{ site.repository }}/issues/4979)) +- Cleanup and make misc files compliant with Rubocop. ([#4940]({{ site.repository }}/issues/4940)) +- Rubocop: jekyll/lib/site.rb ([#4973]({{ site.repository }}/issues/4973)) +- Add timings for each scenario in cucumber & print worst offenders ([#4908]({{ site.repository }}/issues/4908)) +- rubocop: jekyll/lib/filters.rb ([#4993]({{ site.repository }}/issues/4993)) +- Fix rubocop offenses in exe/jekyll ([#5017]({{ site.repository }}/issues/5017)) +- Rubocop: lib/jekyll/command.rb ([#5018]({{ site.repository }}/issues/5018)) +- rubocop: lib/jekyll/static_file.rb ([#5019]({{ site.repository }}/issues/5019)) +- rubocop: lib/jekyll/utils.rb ([#5026]({{ site.repository }}/issues/5026)) +- rubocop: lib/jekyll/regenerator.rb ([#5025]({{ site.repository }}/issues/5025)) +- rubocop: lib/jekyll/configuration.rb ([#5024]({{ site.repository }}/issues/5024)) +- rubocop: lib/jekyll/renderer.rb style fixes ([#5032]({{ site.repository }}/issues/5032)) +- rubocop: lib/jekyll/convertible.rb style fixes ([#5031]({{ site.repository }}/issues/5031)) +- rubocop: lib/jekyll/document.rb style fixes ([#5030]({{ site.repository }}/issues/5030)) +- Remove ruby-head from Travis matrix & fix jruby failures ([#5015]({{ site.repository }}/issues/5015)) +- Remove useless statement from Configuration test ([#5065]({{ site.repository }}/issues/5065)) +- Change baseurl to example.com for some test cases ([#5068]({{ site.repository }}/issues/5068)) +- use activesupport < 5 if we are on a Ruby < 2.2.2 ([#5100]({{ site.repository }}/issues/5100)) +- Internal documentation for working on Jekyll ([#5011]({{ site.repository }}/issues/5011)) +- rubocop: lib/jekyll/collection.rb ([#5022]({{ site.repository }}/issues/5022)) +- tests: Typo fixes. ([#5114]({{ site.repository }}/issues/5114)) +- Normalize yml files. ([#5116]({{ site.repository }}/issues/5116)) +- Whitespace cleanup. ([#5113]({{ site.repository }}/issues/5113)) +- Add AppVeyor support. ([#5115]({{ site.repository }}/issues/5115)) +- appveyor.yml: drop Ruby 2.0.0. ([#5119]({{ site.repository }}/issues/5119)) +- Fix indentation in benchmark ([#5124]({{ site.repository }}/issues/5124)) +- Style fixes for Rubocop 0.42.0 - var == 0 becomes var.zero? - when defining method_missing, also define respond_to_missing? ([#5137]({{ site.repository }}/issues/5137)) + +### Site Enhancements +{: #site-enhancements-v3-2-0} + +- Add jekyll-seo-tag, jekyll-avatar, and jekyll-sitemap to the site ([#4553]({{ site.repository }}/issues/4553)) +- Add Google search query to /docs/help/ ([#4589]({{ site.repository }}/issues/4589)) +- Upgrading, documentation ([#4597]({{ site.repository }}/issues/4597)) +- Add 'view source' entry ([#4602]({{ site.repository }}/issues/4602)) +- Add jekyll-video-embed to list of third-party plugins. ([#4621]({{ site.repository }}/issues/4621)) +- Adding Aerobatic to list of deployment options ([#4630]({{ site.repository }}/issues/4630)) +- Update documentation: HTMLProofer CLI command ([#4641]({{ site.repository }}/issues/4641)) +- Document that subdirectories of `_posts` are no longer categories ([#4639]({{ site.repository }}/issues/4639)) +- Update continuous-integration docs with sudo: false information ([#4628]({{ site.repository }}/issues/4628)) +- Blog post on refreshed contributing file and new affinity teams ([#4645]({{ site.repository }}/issues/4645)) +- Fixes typo on collections ([#4647]({{ site.repository }}/issues/4647)) +- Documentation: future option also works for collections ([#4682]({{ site.repository }}/issues/4682)) +- Additional package needed for Fedora 23 Workspace ([#4685]({{ site.repository }}/issues/4685)) +- Fix typo on Chocolatey name in Windows documentation ([#4686]({{ site.repository }}/issues/4686)) +- Use the correct URL, Fixes [#4698]({{ site.repository }}/issues/4698) ([#4699]({{ site.repository }}/issues/4699)) +- Add jekyll-paspagon plugin ([#4700]({{ site.repository }}/issues/4700)) +- Bold-italicize note in assets documentation about needing front matter ([#4706]({{ site.repository }}/issues/4706)) +- Highlight the `script/` calls in the Contributing documentation ([#4712]({{ site.repository }}/issues/4712)) +- Add Hawkins to the list of third-party plugins ([#4755]({{ site.repository }}/issues/4755)) +- Fix a typo in pagination doc ([#4763]({{ site.repository }}/issues/4763)) +- Switch second GitHub Pages link to HTTPS ([#4760]({{ site.repository }}/issues/4760)) +- Explain data file format requirements more clearly in documentation ([#4781]({{ site.repository }}/issues/4781)) +- Add jekyll-i18n_tags to list of third-party plugins ([#4775]({{ site.repository }}/issues/4775)) +- Remove Leonard Lamprecht's website from Sites page ([#4771]({{ site.repository }}/issues/4771)) +- Updates documentation for collections to include `date` property ([#4769]({{ site.repository }}/issues/4769)) +- Added an explicit rerun note to configuration.md, defaults section ([#4734]({{ site.repository }}/issues/4734)) +- Update Rack-Jekyll Heroku deployment blog post url ([#4789]({{ site.repository }}/issues/4789)) +- Added missing single quote on rsync client side command ([#4813]({{ site.repository }}/issues/4813)) +- Organize Form Platforms-as-a-Service into unified list & add FormSpree.io ([#4754]({{ site.repository }}/issues/4754)) +- Fixed typo on Configuration page ([#4804]({{ site.repository }}/issues/4804)) +- Update FormKeep URL on the Resources doc ([#4844]({{ site.repository }}/issues/4844)) +- site: use liquid & reduce some whitespace noise ([#4854]({{ site.repository }}/issues/4854)) +- Add jekyll-breadcrumbs to list of third-party plugins ([#4874]({{ site.repository }}/issues/4874)) +- Added Pug converter to list of third-party plugins ([#4872]({{ site.repository }}/issues/4872)) +- Add jekyll-ideal-image-slider to list of third-party plugins ([#4863]({{ site.repository }}/issues/4863)) +- Add Jekyll Tips and the Cheatsheet to the list of resources ([#4887]({{ site.repository }}/issues/4887)) +- Removed extra `

` from `site/_docs/permalinks.md` ([#4890]({{ site.repository }}/issues/4890)) +- Add pubstorm deployment instructions to docs ([#4881]({{ site.repository }}/issues/4881)) +- Corrected pagination docs for hidden: true feature ([#4903]({{ site.repository }}/issues/4903)) +- Remove a Broken Link for Refheap Plugin ([#4971]({{ site.repository }}/issues/4971)) +- Instructions on how to install github-gem on Windows ([#4975]({{ site.repository }}/issues/4975)) +- Minor tweak to fix missing apostrophe ([#4962]({{ site.repository }}/issues/4962)) +- Instructions on how to install github-gem on Windows (v2) ([#4977]({{ site.repository }}/issues/4977)) +- Fix inaccurate HTTP response header field name ([#4976]({{ site.repository }}/issues/4976)) +- Add post about GSoC project ([#4980]({{ site.repository }}/issues/4980)) +- Link to the HTML page instead of Markdown ([#4985]({{ site.repository }}/issues/4985)) +- Update normalize.css to v4.0.0. ([#4989]({{ site.repository }}/issues/4989)) +- Add jekyll-tags-list-plugin to list of third-party plugins ([#5000]({{ site.repository }}/issues/5000)) +- Windows docs: Command needs to be called from blog path ([#5006]({{ site.repository }}/issues/5006)) +- Update text to be consistent with example ([#5010]({{ site.repository }}/issues/5010)) +- Update template links to point to core Liquid site ([#5012]({{ site.repository }}/issues/5012)) +- Add generator-jekyllized to third-party plugins ([#5027]({{ site.repository }}/issues/5027)) +- Add Jekyll Art Gallery generator plugin to list of third-party plugins ([#5043]({{ site.repository }}/issues/5043)) +- Add Formingo to the list of Jekyll form SaaS ([#5054]({{ site.repository }}/issues/5054)) +- Highlight help nav item when navigated to. ([#5058]({{ site.repository }}/issues/5058)) +- Update normalize.css to v4.2.0. ([#5096]({{ site.repository }}/issues/5096)) +- Updates html-proofer code ([#5098]({{ site.repository }}/issues/5098)) +- Jekyll Community ([#5097]({{ site.repository }}/issues/5097)) +- Typo in documentation file templates.md ([#5117]({{ site.repository }}/issues/5117)) +- Slightly, improve PNG compression. ([#5112]({{ site.repository }}/issues/5112)) +- docs: add jekyll-maps plugin reference ([#5123]({{ site.repository }}/issues/5123)) +- docs: fix link to plugins page source ([#5122]({{ site.repository }}/issues/5122)) +- Update the configuration docs to match the code ([#5131]({{ site.repository }}/issues/5131)) +- Removed confusing word repetition. ([#5139]({{ site.repository }}/issues/5139)) +- Add a note about script/fmt ([#5138]({{ site.repository }}/issues/5138)) + + +## 3.1.6 / 2016-05-19 +{: #v3-1-6} + +### Bug Fixes +{: #bug-fixes-v3-1-6} + +- Add ability to `jsonify` Drops such that, e.g. `site | jsonify`, works. ([#4914]({{ site.repository }}/issues/4914)) + + +## 3.1.5 / 2016-05-18 +{: #v3-1-5} + +### Bug Fixes +{: #bug-fixes-v3-1-5} + +- Sort the results of the `require_all` glob (affects Linux only). ([#4912]({{ site.repository }}/issues/4912)) + + +## 3.1.4 / 2016-05-18 +{: #v3-1-4} + +### Bug Fixes +{: #bug-fixes-v3-1-4} + +- Add `ExcerptDrop` and remove excerpt's ability to refer to itself in Liquid ([#4907]({{ site.repository }}/issues/4907)) +- Configuration permalink fix where `collections.posts.permalink` inherits properly from `permalink` only when it doesn't exist ([#4910]({{ site.repository }}/issues/4910)) +- Add `Configuration.from` to make it easier to build configs from just a hash +- Sorting `site.collections` in Liquid by label ([#4910]({{ site.repository }}/issues/4910)) +- Fix bug where `layout` in Liquid would inherit from previously-rendered layouts' metadatas ([#4909]({{ site.repository }}/issues/4909)) +- Fix bug where `layout` in Liquid would override in the wrong direction (more-specific layouts' data were overwritten by their parent layouts' data; this has now been reversed) ([#4909]({{ site.repository }}/issues/4909)) + + +## 3.1.3 / 2016-04-18 +{: #v3-1-3} + +- Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` ([#4807]({{ site.repository }}/issues/4807)) +- Use SSLEnable instead of EnableSSL and make URL HTTPS (WEBrick) ([#4693]({{ site.repository }}/issues/4693)) + + +## 3.1.2 / 2016-02-19 +{: #v3-1-2} + +### Minor Enhancements +{: #minor-enhancements-v3-1-2} + +- Include `.rubocop.yml` in Gem ([#4437]({{ site.repository }}/issues/4437)) +- `LiquidRenderer#parse`: parse with line numbers. ([#4452]({{ site.repository }}/issues/4452)) +- Add consistency to the no-subcommand deprecation message ([#4505]({{ site.repository }}/issues/4505)) + +### Bug Fixes +{: #bug-fixes-v3-1-2} + +- Fix syntax highlighting in kramdown by making `@config` accessible in the Markdown converter. ([#4428]({{ site.repository }}/issues/4428)) +- `Jekyll.sanitized_path`: sanitizing a questionable path should handle tildes ([#4492]({{ site.repository }}/issues/4492)) +- Fix `titleize` so already capitalized words are not dropped ([#4525]({{ site.repository }}/issues/4525)) +- Permalinks which end in a slash should always output HTML ([#4546]({{ site.repository }}/issues/4546)) + +### Development Fixes +{: #development-fixes-v3-1-2} + +- Require at least cucumber version 2.1.0 ([#4514]({{ site.repository }}/issues/4514)) + +### Site Enhancements +{: #site-enhancements-v3-1-2} + +- Add jekyll-toc plugin ([#4429]({{ site.repository }}/issues/4429)) +- Docs: Quickstart - added documentation about the `--force` option ([#4410]({{ site.repository }}/issues/4410)) +- Fix broken links to the Code of Conduct ([#4436]({{ site.repository }}/issues/4436)) +- Upgrade notes: mention trailing slash in permalink; fixes [#4440]({{ site.repository }}/issues/4440) ([#4455]({{ site.repository }}/issues/4455)) +- Add hooks to the plugin categories toc ([#4463]({{ site.repository }}/issues/4463)) +- Jekyll 3 requires newer version of Ruby. ([#4461]({{ site.repository }}/issues/4461)) +- Fix typo in upgrading docs ([#4473]({{ site.repository }}/issues/4473)) +- Add note about upgrading documentation on jekyllrb.com/help/ ([#4484]({{ site.repository }}/issues/4484)) +- Update Rake link ([#4496]({{ site.repository }}/issues/4496)) +- Update & prune the short list of example sites ([#4374]({{ site.repository }}/issues/4374)) +- Added amp-jekyll plugin to plugins docs ([#4517]({{ site.repository }}/issues/4517)) +- A few grammar fixes ([#4512]({{ site.repository }}/issues/4512)) +- Correct a couple mistakes in structure.md ([#4522]({{ site.repository }}/issues/4522)) + + +## 3.1.1 / 2016-01-29 +{: #v3-1-1} + +### Meta + +- Update the Code of Conduct to the latest version ([#4402]({{ site.repository }}/issues/4402)) + +### Bug Fixes +{: #bug-fixes-v3-1-1} + +- `Page#dir`: ensure it ends in a slash ([#4403]({{ site.repository }}/issues/4403)) +- Add `Utils.merged_file_read_opts` to unify reading & strip the BOM ([#4404]({{ site.repository }}/issues/4404)) +- `Renderer#output_ext`: honor folders when looking for ext ([#4401]({{ site.repository }}/issues/4401)) + +### Development Fixes +{: #development-fixes-v3-1-1} + +- Suppress stdout in liquid profiling test ([#4409]({{ site.repository }}/issues/4409)) + + +## 3.1.0 / 2016-01-23 +{: #v3-1-0} + +### Minor Enhancements +{: #minor-enhancements-v3-1-0} + +- Use `Liquid::Drop`s instead of `Hash`es in `#to_liquid` ([#4277]({{ site.repository }}/issues/4277)) +- Add 'sample' Liquid filter Equivalent to Array#sample functionality ([#4223]({{ site.repository }}/issues/4223)) +- Cache parsed include file to save liquid parsing time. ([#4120]({{ site.repository }}/issues/4120)) +- Slightly speed up url sanitization and handle multiples of ///. ([#4168]({{ site.repository }}/issues/4168)) +- Print debug message when a document is skipped from reading ([#4180]({{ site.repository }}/issues/4180)) +- Include tag should accept multiple variables in the include name ([#4183]({{ site.repository }}/issues/4183)) +- Add `-o` option to serve command which opens server URL ([#4144]({{ site.repository }}/issues/4144)) +- Add CodeClimate platform for better code quality. ([#4220]({{ site.repository }}/issues/4220)) +- General improvements for WEBrick via jekyll serve such as SSL & custom headers ([#4224]({{ site.repository }}/issues/4224), [#4228]({{ site.repository }}/issues/4228)) +- Add a default charset to content-type on webrick. ([#4231]({{ site.repository }}/issues/4231)) +- Switch `PluginManager` to use `require_with_graceful_fail` for better UX ([#4233]({{ site.repository }}/issues/4233)) +- Allow quoted date in front matter defaults ([#4184]({{ site.repository }}/issues/4184)) +- Add a Jekyll doctor warning for URLs that only differ by case ([#3171]({{ site.repository }}/issues/3171)) +- drops: create one base Drop class which can be set as mutable or not ([#4285]({{ site.repository }}/issues/4285)) +- drops: provide `#to_h` to allow for hash introspection ([#4281]({{ site.repository }}/issues/4281)) +- Shim subcommands with indication of gem possibly required so users know how to use them ([#4254]({{ site.repository }}/issues/4254)) +- Add smartify Liquid filter for SmartyPants ([#4323]({{ site.repository }}/issues/4323)) +- Raise error on empty permalink ([#4361]({{ site.repository }}/issues/4361)) +- Refactor Page#permalink method ([#4389]({{ site.repository }}/issues/4389)) + +### Bug Fixes +{: #bug-fixes-v3-1-0} + +- Pass build options into `clean` command ([#4177]({{ site.repository }}/issues/4177)) +- Allow users to use .htm and .xhtml (XHTML5.) ([#4160]({{ site.repository }}/issues/4160)) +- Prevent Shell Injection. ([#4200]({{ site.repository }}/issues/4200)) +- Convertible should make layout data accessible via `layout` instead of `page` ([#4205]({{ site.repository }}/issues/4205)) +- Avoid using `Dir.glob` with absolute path to allow special characters in the path ([#4150]({{ site.repository }}/issues/4150)) +- Handle empty config files ([#4052]({{ site.repository }}/issues/4052)) +- Rename `@options` so that it does not impact Liquid. ([#4173]({{ site.repository }}/issues/4173)) +- utils/drops: update Drop to support `Utils.deep_merge_hashes` ([#4289]({{ site.repository }}/issues/4289)) +- Make sure jekyll/drops/drop is loaded first. ([#4292]({{ site.repository }}/issues/4292)) +- Convertible/Page/Renderer: use payload hash accessor & setter syntax for backwards-compatibility ([#4311]({{ site.repository }}/issues/4311)) +- Drop: fix hash setter precedence ([#4312]({{ site.repository }}/issues/4312)) +- utils: `has_yaml_header?` should accept files with extraneous spaces ([#4290]({{ site.repository }}/issues/4290)) +- Escape html from site.title and page.title in site template ([#4307]({{ site.repository }}/issues/4307)) +- Allow custom file extensions if defined in `permalink` front matter ([#4314]({{ site.repository }}/issues/4314)) +- Fix deep_merge_hashes! handling of drops and hashes ([#4359]({{ site.repository }}/issues/4359)) +- Page should respect output extension of its permalink ([#4373]({{ site.repository }}/issues/4373)) +- Disable auto-regeneration when running server detached ([#4376]({{ site.repository }}/issues/4376)) +- Drop#: only use public_send for keys in the content_methods array ([#4388]({{ site.repository }}/issues/4388)) +- Extract title from filename successfully when no date. ([#4195]({{ site.repository }}/issues/4195)) + +### Development Fixes +{: #development-fixes-v3-1-0} + +- `jekyll-docs` should be easily release-able ([#4152]({{ site.repository }}/issues/4152)) +- Allow use of Cucumber 2.1 or greater ([#4181]({{ site.repository }}/issues/4181)) +- Modernize Kramdown for Markdown converter. ([#4109]({{ site.repository }}/issues/4109)) +- Change TestDoctorCommand to JekyllUnitTest... ([#4263]({{ site.repository }}/issues/4263)) +- Create namespaced rake tasks in separate `.rake` files under `lib/tasks` ([#4282]({{ site.repository }}/issues/4282)) +- markdown: refactor for greater readability & efficiency ([#3771]({{ site.repository }}/issues/3771)) +- Fix many Rubocop style errors ([#4301]({{ site.repository }}/issues/4301)) +- Fix spelling of "GitHub" in docs and history ([#4322]({{ site.repository }}/issues/4322)) +- Reorganize and cleanup the Gemfile, shorten required depends. ([#4318]({{ site.repository }}/issues/4318)) +- Remove script/rebund. ([#4341]({{ site.repository }}/issues/4341)) +- Implement codeclimate platform ([#4340]({{ site.repository }}/issues/4340)) +- Remove ObjectSpace dumping and start using inherited, it's faster. ([#4342]({{ site.repository }}/issues/4342)) +- Add script/travis so all people can play with Travis-CI images. ([#4338]({{ site.repository }}/issues/4338)) +- Move Cucumber to using RSpec-Expectations and furthering JRuby support. ([#4343]({{ site.repository }}/issues/4343)) +- Rearrange Cucumber and add some flair. ([#4347]({{ site.repository }}/issues/4347)) +- Remove old FIXME ([#4349]({{ site.repository }}/issues/4349)) +- Clean up the Gemfile (and keep all the necessary dependencies) ([#4350]({{ site.repository }}/issues/4350)) + +### Site Enhancements +{: #site-enhancements-v3-1-0} + +- Add three plugins to directory ([#4163]({{ site.repository }}/issues/4163)) +- Add upgrading docs from 2.x to 3.x ([#4157]({{ site.repository }}/issues/4157)) +- Add `protect_email` to the plugins index. ([#4169]({{ site.repository }}/issues/4169)) +- Add `jekyll-deploy` to list of third-party plugins ([#4179]({{ site.repository }}/issues/4179)) +- Clarify plugin docs ([#4154]({{ site.repository }}/issues/4154)) +- Add Kickster to deployment methods in documentation ([#4190]({{ site.repository }}/issues/4190)) +- Add DavidBurela's tutorial for Windows to Windows docs page ([#4210]({{ site.repository }}/issues/4210)) +- Change GitHub code block to highlight tag to avoid it overlaps parent div ([#4121]({{ site.repository }}/issues/4121)) +- Update FormKeep link to be something more specific to Jekyll ([#4243]({{ site.repository }}/issues/4243)) +- Remove example Roger Chapman site, as the domain doesn't exist ([#4249]({{ site.repository }}/issues/4249)) +- Added configuration options for `draft_posts` to configuration docs ([#4251]({{ site.repository }}/issues/4251)) +- Fix checklist in `_assets.md` ([#4259]({{ site.repository }}/issues/4259)) +- Add Markdown examples to Pages docs ([#4275]({{ site.repository }}/issues/4275)) +- Add jekyll-paginate-category to list of third-party plugins ([#4273]({{ site.repository }}/issues/4273)) +- Add `jekyll-responsive_image` to list of third-party plugins ([#4286]({{ site.repository }}/issues/4286)) +- Add `jekyll-commonmark` to list of third-party plugins ([#4299]({{ site.repository }}/issues/4299)) +- Add documentation for incremental regeneration ([#4293]({{ site.repository }}/issues/4293)) +- Add note about removal of relative permalink support in upgrading docs ([#4303]({{ site.repository }}/issues/4303)) +- Add Pro Tip to use front matter variable to create clean URLs ([#4296]({{ site.repository }}/issues/4296)) +- Fix grammar in the documentation for posts. ([#4330]({{ site.repository }}/issues/4330)) +- Add documentation for smartify Liquid filter ([#4333]({{ site.repository }}/issues/4333)) +- Fixed broken link to blog on using mathjax with jekyll ([#4344]({{ site.repository }}/issues/4344)) +- Documentation: correct reference in Precedence section of Configuration docs ([#4355]({{ site.repository }}/issues/4355)) +- Add @jmcglone's guide to github-pages doc page ([#4364]({{ site.repository }}/issues/4364)) +- Added the Wordpress2Jekyll Wordpress plugin ([#4377]({{ site.repository }}/issues/4377)) +- Add Contentful Extension to list of third-party plugins ([#4390]({{ site.repository }}/issues/4390)) +- Correct Minor spelling error ([#4394]({{ site.repository }}/issues/4394)) + + +## 3.0.5 / 2016-04-26 +{: #v3-0-5} + +- Remove call to `#backwards_compatibilize` in `Configuration.from` ([#4846]({{ site.repository }}/issues/4846)) + + +## 3.0.4 / 2016-04-18 +{: #v3-0-4} + +- Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` ([#4806]({{ site.repository }}/issues/4806)) +- Configuration: allow users to specify a `collections.posts.permalink` directly without `permalink` clobbering it ([#4753]({{ site.repository }}/issues/4753)) + + +## 3.0.3 / 2016-02-08 +{: #v3-0-3} + +### Bug Fixes +{: #bug-fixes-v3-0-3} + +- Fix extension weirdness with folders ([#4493]({{ site.repository }}/issues/4493)) +- EntryFilter: only include 'excluded' log on excluded files ([#4479]({{ site.repository }}/issues/4479)) +- `Jekyll.sanitized_path`: escape tildes before sanitizing a questionable path ([#4468]({{ site.repository }}/issues/4468)) +- `LiquidRenderer#parse`: parse with line numbers ([#4453]({{ site.repository }}/issues/4453)) +- `Document#<=>`: protect against nil comparison in dates. ([#4446]({{ site.repository }}/issues/4446)) + + +## 3.0.2 / 2016-01-20 +{: #v3-0-2} + +### Bug Fixes +{: #bug-fixes-v3-0-2} + +- Document: throw a useful error when an invalid date is given ([#4378]({{ site.repository }}/issues/4378)) + + +## 3.0.1 / 2015-11-17 +{: #v3-0-1} + +### Bug Fixes +{: #bug-fixes-v3-0-1} + +- Document: only superdirectories of the collection are categories ([#4110]({{ site.repository }}/issues/4110)) +- `Convertible#render_liquid` should use `render!` to cause failure on bad Liquid ([#4077]({{ site.repository }}/issues/4077)) +- Don't generate `.jekyll-metadata` in non-incremental build ([#4079]({{ site.repository }}/issues/4079)) +- Set `highlighter` config val to `kramdown.syntax_highlighter` ([#4090]({{ site.repository }}/issues/4090)) +- Align hooks implementation with documentation ([#4104]({{ site.repository }}/issues/4104)) +- Fix the deprecation warning in the doctor command ([#4114]({{ site.repository }}/issues/4114)) +- Fix case in `:title` and add `:slug` which is downcased ([#4100]({{ site.repository }}/issues/4100)) + +### Development Fixes +{: #development-fixes-v3-0-1} + +- Fix test warnings when doing rake {test,spec} or script/test ([#4078]({{ site.repository }}/issues/4078)) + +### Site Enhancements +{: #site-enhancements-v3-0-1} + +- Update normalize.css to v3.0.3. ([#4085]({{ site.repository }}/issues/4085)) +- Update Font Awesome to v4.4.0. ([#4086]({{ site.repository }}/issues/4086)) +- Adds a note about installing the jekyll-gist gem to make gist tag work ([#4101]({{ site.repository }}/issues/4101)) +- Align hooks documentation with implementation ([#4104]({{ site.repository }}/issues/4104)) +- Add Jekyll Flickr Plugin to the list of third party plugins ([#4111]({{ site.repository }}/issues/4111)) +- Remove link to now-deleted blog post ([#4125]({{ site.repository }}/issues/4125)) +- Update the liquid syntax in the pagination docs ([#4130]({{ site.repository }}/issues/4130)) +- Add jekyll-language-plugin to plugins.md ([#4134]({{ site.repository }}/issues/4134)) +- Updated to reflect feedback in [#4129]({{ site.repository }}/issues/4129) ([#4137]({{ site.repository }}/issues/4137)) +- Clarify assets.md based on feedback of [#4129]({{ site.repository }}/issues/4129) ([#4142]({{ site.repository }}/issues/4142)) +- Re-correct the liquid syntax in the pagination docs ([#4140]({{ site.repository }}/issues/4140)) + + +## 3.0.0 / 2015-10-26 +{: #v3-0-0} + +### Major Enhancements +{: #major-enhancements-v3-0-0} + +- Liquid profiler (i.e. know how fast or slow your templates render) ([#3762]({{ site.repository }}/issues/3762)) +- Incremental regeneration ([#3116]({{ site.repository }}/issues/3116)) +- Add Hooks: a new kind of plugin ([#3553]({{ site.repository }}/issues/3553)) +- Upgrade to Liquid 3.0.0 ([#3002]({{ site.repository }}/issues/3002)) +- `site.posts` is now a Collection instead of an Array ([#4055]({{ site.repository }}/issues/4055)) +- Add basic support for JRuby (commit: 0f4477) +- Drop support for Ruby 1.9.3. ([#3235]({{ site.repository }}/issues/3235)) +- Support Ruby v2.2 ([#3234]({{ site.repository }}/issues/3234)) +- Support RDiscount 2 ([#2767]({{ site.repository }}/issues/2767)) +- Remove most runtime deps ([#3323]({{ site.repository }}/issues/3323)) +- Move to Rouge as default highlighter ([#3323]({{ site.repository }}/issues/3323)) +- Mimic GitHub Pages `.html` extension stripping behavior in WEBrick ([#3452]({{ site.repository }}/issues/3452)) +- Always include file extension on output files ([#3490]({{ site.repository }}/issues/3490)) +- Improved permalinks for pages and collections ([#3538]({{ site.repository }}/issues/3538)) +- Sunset (i.e. remove) Maruku ([#3655]({{ site.repository }}/issues/3655)) +- Remove support for relative permalinks ([#3679]({{ site.repository }}/issues/3679)) +- Iterate over `site.collections` as an array instead of a hash. ([#3670]({{ site.repository }}/issues/3670)) +- Adapt StaticFile for collections, config defaults ([#3823]({{ site.repository }}/issues/3823)) +- Add a Code of Conduct for the Jekyll project ([#3925]({{ site.repository }}/issues/3925)) +- Added permalink time variables ([#3990]({{ site.repository }}/issues/3990)) +- Add `--incremental` flag to enable incremental regen (disabled by default) ([#4059]({{ site.repository }}/issues/4059)) + +### Minor Enhancements +{: #minor-enhancements-v3-0-0} + +- Deprecate access to Document#data properties and Collection#docs methods ([#4058]({{ site.repository }}/issues/4058)) +- Sort static files just once, and call `site_payload` once for all collections ([#3204]({{ site.repository }}/issues/3204)) +- Separate `jekyll docs` and optimize external gem handling ([#3241]({{ site.repository }}/issues/3241)) +- Improve `Site#getConverterImpl` and call it `Site#find_converter_instance` ([#3240]({{ site.repository }}/issues/3240)) +- Use relative path for `path` Liquid variable in Documents for consistency ([#2908]({{ site.repository }}/issues/2908)) +- Generalize `Utils#slugify` for any scripts ([#3047]({{ site.repository }}/issues/3047)) +- Added basic microdata to post template in site template ([#3189]({{ site.repository }}/issues/3189)) +- Store log messages in an array of messages. ([#3244]({{ site.repository }}/issues/3244)) +- Allow collection documents to override `output` property in front matter ([#3172]({{ site.repository }}/issues/3172)) +- Keep file modification times between builds for static files ([#3220]({{ site.repository }}/issues/3220)) +- Only downcase mixed-case categories for the URL ([#2571]({{ site.repository }}/issues/2571)) +- Added per post `excerpt_separator` functionality ([#3274]({{ site.repository }}/issues/3274)) +- Allow collections YAML to end with three dots ([#3134]({{ site.repository }}/issues/3134)) +- Add mode parameter to `slugify` Liquid filter ([#2918]({{ site.repository }}/issues/2918)) +- Perf: `Markdown#matches` should avoid regexp ([#3321]({{ site.repository }}/issues/3321)) +- Perf: Use frozen regular expressions for `Utils#slugify` ([#3321]({{ site.repository }}/issues/3321)) +- Split off Textile support into jekyll-textile-converter ([#3319]({{ site.repository }}/issues/3319)) +- Improve the navigation menu alignment in the site template on small screens ([#3331]({{ site.repository }}/issues/3331)) +- Show the regeneration time after the initial generation ([#3378]({{ site.repository }}/issues/3378)) +- Site template: Switch default font to Helvetica Neue ([#3376]({{ site.repository }}/issues/3376)) +- Make the `include` tag a teensy bit faster. ([#3391]({{ site.repository }}/issues/3391)) +- Add `pkill -f jekyll` to ways to kill. ([#3397]({{ site.repository }}/issues/3397)) +- Site template: collapsed, variable-driven font declaration ([#3360]({{ site.repository }}/issues/3360)) +- Site template: Don't always show the scrollbar in code blocks ([#3419]({{ site.repository }}/issues/3419)) +- Site template: Remove undefined `text` class from `p` element ([#3440]({{ site.repository }}/issues/3440)) +- Site template: Optimize text rendering for legibility ([#3382]({{ site.repository }}/issues/3382)) +- Add `draft?` method to identify if Post is a Draft & expose to Liquid ([#3456]({{ site.repository }}/issues/3456)) +- Write regeneration metadata even on full rebuild ([#3464]({{ site.repository }}/issues/3464)) +- Perf: Use `String#end_with?("/")` instead of regexp when checking paths ([#3516]({{ site.repository }}/issues/3516)) +- Docs: document 'ordinal' built-in permalink style ([#3532]({{ site.repository }}/issues/3532)) +- Upgrade liquid-c to 3.x ([#3531]({{ site.repository }}/issues/3531)) +- Use consistent syntax for deprecation warning ([#3535]({{ site.repository }}/issues/3535)) +- Added build --destination and --source flags ([#3418]({{ site.repository }}/issues/3418)) +- Site template: remove unused `page.meta` attribute ([#3537]({{ site.repository }}/issues/3537)) +- Improve the error message when sorting null objects ([#3520]({{ site.repository }}/issues/3520)) +- Added liquid-md5 plugin ([#3598]({{ site.repository }}/issues/3598)) +- Documentation: RR replaced with RSpec Mocks ([#3600]({{ site.repository }}/issues/3600)) +- Documentation: Fix subpath. ([#3599]({{ site.repository }}/issues/3599)) +- Create 'tmp' dir for test_tags if it doesn't exist ([#3609]({{ site.repository }}/issues/3609)) +- Extract reading of data from `Site` to reduce responsibilities. ([#3545]({{ site.repository }}/issues/3545)) +- Removed the word 'Jekyll' a few times from the comments ([#3617]({{ site.repository }}/issues/3617)) +- `bin/jekyll`: with no args, exit with exit code 1 ([#3619]({{ site.repository }}/issues/3619)) +- Incremental build if destination file missing ([#3614]({{ site.repository }}/issues/3614)) +- Static files `mtime` liquid should return a `Time` obj ([#3596]({{ site.repository }}/issues/3596)) +- Use `Jekyll::Post`s for both LSI indexing and lookup. ([#3629]({{ site.repository }}/issues/3629)) +- Add `charset=utf-8` for HTML and XML pages in WEBrick ([#3649]({{ site.repository }}/issues/3649)) +- Set log level to debug when verbose flag is set ([#3665]({{ site.repository }}/issues/3665)) +- Added a mention on the Gemfile to complete the instructions ([#3671]({{ site.repository }}/issues/3671)) +- Perf: Cache `Document#to_liquid` and invalidate where necessary ([#3693]({{ site.repository }}/issues/3693)) +- Perf: `Jekyll::Cleaner#existing_files`: Call `keep_file_regex` and `keep_dirs` only once, not once per iteration ([#3696]({{ site.repository }}/issues/3696)) +- Omit jekyll/jekyll-help from list of resources. ([#3698]({{ site.repository }}/issues/3698)) +- Add basic `jekyll doctor` test to detect fsnotify (OSX) anomalies. ([#3704]({{ site.repository }}/issues/3704)) +- Added talk.jekyllrb.com to "Have questions?" ([#3694]({{ site.repository }}/issues/3694)) +- Performance: Sort files only once ([#3707]({{ site.repository }}/issues/3707)) +- Performance: Marshal metadata ([#3706]({{ site.repository }}/issues/3706)) +- Upgrade highlight wrapper from `div` to `figure` ([#3779]({{ site.repository }}/issues/3779)) +- Upgrade mime-types to `~> 2.6` ([#3795]({{ site.repository }}/issues/3795)) +- Update windows.md with Ruby version info ([#3818]({{ site.repository }}/issues/3818)) +- Make the directory for includes configurable ([#3782]({{ site.repository }}/issues/3782)) +- Rename directory configurations to match `*_dir` convention for consistency ([#3782]({{ site.repository }}/issues/3782)) +- Internal: trigger hooks by owner symbol ([#3871]({{ site.repository }}/issues/3871)) +- Update MIME types from mime-db ([#3933]({{ site.repository }}/issues/3933)) +- Add header to site template `_config.yml` for clarity & direction ([#3997]({{ site.repository }}/issues/3997)) +- Site template: add timezone offset to post date front matter ([#4001]({{ site.repository }}/issues/4001)) +- Make a constant for the regex to find hidden files ([#4032]({{ site.repository }}/issues/4032)) +- Site template: refactor github & twitter icons into includes ([#4049]({{ site.repository }}/issues/4049)) +- Site template: add background to Kramdown Rouge-ified backtick code blocks ([#4053]({{ site.repository }}/issues/4053)) + +### Bug Fixes +{: #bug-fixes-v3-0-0} + +- `post_url`: fix access deprecation warning & fix deprecation msg ([#4060]({{ site.repository }}/issues/4060)) +- Perform jekyll-paginate deprecation warning correctly. ([#3580]({{ site.repository }}/issues/3580)) +- Make permalink parsing consistent with pages ([#3014]({{ site.repository }}/issues/3014)) +- `time()`pre-filter method should accept a `Date` object ([#3299]({{ site.repository }}/issues/3299)) +- Remove unneeded end tag for `link` in site template ([#3236]({{ site.repository }}/issues/3236)) +- Kramdown: Use `enable_coderay` key instead of `use_coderay` ([#3237]({{ site.repository }}/issues/3237)) +- Unescape `Document` output path ([#2924]({{ site.repository }}/issues/2924)) +- Fix nav items alignment when on multiple rows ([#3264]({{ site.repository }}/issues/3264)) +- Highlight: Only Strip Newlines/Carriage Returns, not Spaces ([#3278]({{ site.repository }}/issues/3278)) +- Find variables in front matter defaults by searching with relative file path. ([#2774]({{ site.repository }}/issues/2774)) +- Allow variables (e.g `:categories`) in front matter permalinks ([#3320]({{ site.repository }}/issues/3320)) +- Handle nil URL placeholders in permalinks ([#3325]({{ site.repository }}/issues/3325)) +- Template: Fix nav items alignment when in "burger" mode ([#3329]({{ site.repository }}/issues/3329)) +- Template: Remove `!important` from nav SCSS introduced in [#3329]({{ site.repository }}/issues/3329) ([#3375]({{ site.repository }}/issues/3375)) +- The `:title` URL placeholder for collections should be the filename slug. ([#3383]({{ site.repository }}/issues/3383)) +- Trim the generate time diff to just 3 places past the decimal place ([#3415]({{ site.repository }}/issues/3415)) +- The highlight tag should only clip the newlines before and after the *entire* block, not in between ([#3401]({{ site.repository }}/issues/3401)) +- highlight: fix problem with linenos and rouge. ([#3436]({{ site.repository }}/issues/3436)) +- `Site#read_data_file`: read CSV's with proper file encoding ([#3455]({{ site.repository }}/issues/3455)) +- Ignore `.jekyll-metadata` in site template ([#3496]({{ site.repository }}/issues/3496)) +- Template: Point documentation link to the documentation pages ([#3502]({{ site.repository }}/issues/3502)) +- Removed the trailing slash from the example `/blog` baseurl comment ([#3485]({{ site.repository }}/issues/3485)) +- Clear the regenerator cache every time we process ([#3592]({{ site.repository }}/issues/3592)) +- Readd (bring back) minitest-profile ([#3628]({{ site.repository }}/issues/3628)) +- Add WOFF2 font MIME type to Jekyll server MIME types ([#3647]({{ site.repository }}/issues/3647)) +- Be smarter about extracting the extname in `StaticFile` ([#3632]({{ site.repository }}/issues/3632)) +- Process metadata for all dependencies ([#3608]({{ site.repository }}/issues/3608)) +- Show error message if the front matter on a page/post is invalid. ([#3643]({{ site.repository }}/issues/3643)) +- Upgrade redcarpet to 3.2 (Security fix: OSVDB-120415) ([#3652]({{ site.repository }}/issues/3652)) +- Create #mock_expects that goes directly to RSpec Mocks. ([#3658]({{ site.repository }}/issues/3658)) +- Open `.jekyll-metadata` in binary mode to read binary Marshal data ([#3713]({{ site.repository }}/issues/3713)) +- Incremental regeneration: handle deleted, renamed, and moved dependencies ([#3717]({{ site.repository }}/issues/3717)) +- Fix typo on line 19 of pagination.md ([#3760]({{ site.repository }}/issues/3760)) +- Fix it so that 'blog.html' matches 'blog.html' ([#3732]({{ site.repository }}/issues/3732)) +- Remove occasionally-problematic `ensure` in `LiquidRenderer` ([#3811]({{ site.repository }}/issues/3811)) +- Fixed an unclear code comment in site template SCSS ([#3837]({{ site.repository }}/issues/3837)) +- Fix reading of binary metadata file ([#3845]({{ site.repository }}/issues/3845)) +- Remove var collision with site template header menu iteration variable ([#3838]({{ site.repository }}/issues/3838)) +- Change nonexistent `hl_linenos` to `hl_lines` to allow passthrough in safe mode ([#3787]({{ site.repository }}/issues/3787)) +- Add missing flag to disable the watcher ([#3820]({{ site.repository }}/issues/3820)) +- Update CI guide to include more direct explanations of the flow ([#3891]({{ site.repository }}/issues/3891)) +- Set `future` to `false` in the default config ([#3892]({{ site.repository }}/issues/3892)) +- filters: `where` should compare stringified versions of input & comparator ([#3935]({{ site.repository }}/issues/3935)) +- Read build options for `jekyll clean` command ([#3828]({{ site.repository }}/issues/3828)) +- Fix [#3970]({{ site.repository }}/issues/3970): Use Gem::Version to compare versions, not `>`. +- Abort if no subcommand. Fixes confusing message. ([#3992]({{ site.repository }}/issues/3992)) +- Whole-post excerpts should match the post content ([#4004]({{ site.repository }}/issues/4004)) +- Change default font weight to 400 to fix bold/strong text issues ([#4050]({{ site.repository }}/issues/4050)) +- Document: Only auto-generate the excerpt if it's not overridden ([#4062]({{ site.repository }}/issues/4062)) +- Utils: `deep_merge_hashes` should also merge `default_proc` (45f69bb) +- Defaults: compare paths in `applies_path?` as `String`s to avoid confusion (7b81f00) + +### Development Fixes +{: #development-fixes-v3-0-0} + +- Remove loader.rb and "modernize" `script/test`. ([#3574]({{ site.repository }}/issues/3574)) +- Improve the grammar in the documentation ([#3233]({{ site.repository }}/issues/3233)) +- Update the LICENSE text to match the MIT license exactly ([#3253]({{ site.repository }}/issues/3253)) +- Update rake task `site:publish` to fix minor bugs. ([#3254]({{ site.repository }}/issues/3254)) +- Switch to shields.io for the README badges. ([#3255]({{ site.repository }}/issues/3255)) +- Use `FileList` instead of `Dir.glob` in `site:publish` rake task ([#3261]({{ site.repository }}/issues/3261)) +- Fix test script to be platform-independent ([#3279]({{ site.repository }}/issues/3279)) +- Instead of symlinking `/tmp`, create and symlink a local `tmp` in the tests ([#3258]({{ site.repository }}/issues/3258)) +- Fix some spacing ([#3312]({{ site.repository }}/issues/3312)) +- Fix comment typo in `lib/jekyll/frontmatter_defaults.rb` ([#3322]({{ site.repository }}/issues/3322)) +- Move all `regenerate?` checking to `Regenerator` ([#3326]({{ site.repository }}/issues/3326)) +- Factor out a `read_data_file` call to keep things clean ([#3380]({{ site.repository }}/issues/3380)) +- Proof the site with CircleCI. ([#3427]({{ site.repository }}/issues/3427)) +- Update LICENSE to 2015. ([#3477]({{ site.repository }}/issues/3477)) +- Upgrade tests to use Minitest ([#3492]({{ site.repository }}/issues/3492)) +- Remove trailing whitespace ([#3497]({{ site.repository }}/issues/3497)) +- Use `fixture_site` for Document tests ([#3511]({{ site.repository }}/issues/3511)) +- Remove adapters deprecation warning ([#3529]({{ site.repository }}/issues/3529)) +- Minor fixes to `url.rb` to follow GitHub style guide ([#3544]({{ site.repository }}/issues/3544)) +- Minor changes to resolve deprecation warnings ([#3547]({{ site.repository }}/issues/3547)) +- Convert remaining textile test documents to markdown ([#3528]({{ site.repository }}/issues/3528)) +- Migrate the tests to use rspec-mocks ([#3552]({{ site.repository }}/issues/3552)) +- Remove `activesupport` ([#3612]({{ site.repository }}/issues/3612)) +- Added tests for `Jekyll:StaticFile` ([#3633]({{ site.repository }}/issues/3633)) +- Force minitest version to 5.5.1 ([#3657]({{ site.repository }}/issues/3657)) +- Update the way cucumber accesses Minitest assertions ([#3678]({{ site.repository }}/issues/3678)) +- Add `script/rubyprof` to generate cachegrind callgraphs ([#3692]({{ site.repository }}/issues/3692)) +- Upgrade cucumber to 2.x ([#3795]({{ site.repository }}/issues/3795)) +- Update Kramdown. ([#3853]({{ site.repository }}/issues/3853)) +- Updated the scripts shebang for portability ([#3858]({{ site.repository }}/issues/3858)) +- Update JRuby testing to 9K ([3ab386f](https://github.com/jekyll/jekyll/commit/3ab386f1b096be25a24fe038fc70fd0fb08d545d)) +- Organize dependencies into dev and test groups. ([#3852]({{ site.repository }}/issues/3852)) +- Contributing.md should refer to `script/cucumber` ([#3894]({{ site.repository }}/issues/3894)) +- Update contributing documentation to reflect workflow updates ([#3895]({{ site.repository }}/issues/3895)) +- Add script to vendor mime types ([#3933]({{ site.repository }}/issues/3933)) +- Ignore .bundle dir in SimpleCov ([#4033]({{ site.repository }}/issues/4033)) + +### Site Enhancements +{: #site-enhancements-v3-0-0} + +- Add 'info' labels to certain notes in collections docs ([#3601]({{ site.repository }}/issues/3601)) +- Remove extra spaces, make the last sentence less awkward in permalink docs ([#3603]({{ site.repository }}/issues/3603)) +- Update the permalinks documentation to reflect the updates for 3.0 ([#3556]({{ site.repository }}/issues/3556)) +- Add blog post announcing Jekyll Help ([#3523]({{ site.repository }}/issues/3523)) +- Add Jekyll Talk to Help page on site ([#3518]({{ site.repository }}/issues/3518)) +- Change Ajax pagination resource link to use HTTPS ([#3570]({{ site.repository }}/issues/3570)) +- Fixing the default host on docs ([#3229]({{ site.repository }}/issues/3229)) +- Add `jekyll-thumbnail-filter` to list of third-party plugins ([#2790]({{ site.repository }}/issues/2790)) +- Add link to 'Adding Ajax pagination to Jekyll' to Resources page ([#3186]({{ site.repository }}/issues/3186)) +- Add a Resources link to tutorial on building dynamic navbars ([#3185]({{ site.repository }}/issues/3185)) +- Semantic structure improvements to the post and page layouts ([#3251]({{ site.repository }}/issues/3251)) +- Add new AsciiDoc plugin to list of third-party plugins. ([#3277]({{ site.repository }}/issues/3277)) +- Specify that all transformable collection documents must contain front matter ([#3271]({{ site.repository }}/issues/3271)) +- Assorted accessibility fixes ([#3256]({{ site.repository }}/issues/3256)) +- Update configuration docs to mention `keep_files` for `destination` ([#3288]({{ site.repository }}/issues/3288), [#3296]({{ site.repository }}/issues/3296)) +- Break when we successfully generate nav link to save CPU cycles. ([#3291]({{ site.repository }}/issues/3291)) +- Update usage docs to mention `keep_files` and a warning about `destination` cleaning ([#3295]({{ site.repository }}/issues/3295)) +- Add logic to automatically generate the `next_section` and `prev_section` navigation items ([#3292]({{ site.repository }}/issues/3292)) +- Some small fixes for the Plugins TOC. ([#3306]({{ site.repository }}/issues/3306)) +- Added versioning comment to configuration file ([#3314]({{ site.repository }}/issues/3314)) +- Add `jekyll-minifier` to list of third-party plugins ([#3333]({{ site.repository }}/issues/3333)) +- Add blog post about the Jekyll meet-up ([#3332]({{ site.repository }}/issues/3332)) +- Use `highlight` Liquid tag instead of the four-space tabs for code ([#3336]({{ site.repository }}/issues/3336)) +- 3.0.0.beta1 release post ([#3346]({{ site.repository }}/issues/3346)) +- Add `twa` to the list of third-party plugins ([#3384]({{ site.repository }}/issues/3384)) +- Remove extra spaces ([#3388]({{ site.repository }}/issues/3388)) +- Fix small grammar errors on a couple pages ([#3396]({{ site.repository }}/issues/3396)) +- Fix typo on Templates docs page ([#3420]({{ site.repository }}/issues/3420)) +- s/three/four for plugin type list ([#3424]({{ site.repository }}/issues/3424)) +- Release jekyllrb.com as a locally-compiled site. ([#3426]({{ site.repository }}/issues/3426)) +- Add a jekyllrb.com/help page which elucidates places from which to get help ([#3428]({{ site.repository }}/issues/3428)) +- Remove extraneous dash on Plugins doc page which caused a formatting error ([#3431]({{ site.repository }}/issues/3431)) +- Fix broken link to Jordan Thornquest's website. ([#3438]({{ site.repository }}/issues/3438)) +- Change the link to an extension ([#3457]({{ site.repository }}/issues/3457)) +- Fix Twitter link on the help page ([#3466]({{ site.repository }}/issues/3466)) +- Fix wording in code snippet highlighting section ([#3475]({{ site.repository }}/issues/3475)) +- Add a `/` to `paginate_path` in the Pagination documentation ([#3479]({{ site.repository }}/issues/3479)) +- Add a link on all the docs pages to "Improve this page". ([#3510]({{ site.repository }}/issues/3510)) +- Add jekyll-auto-image generator to the list of third-party plugins ([#3489]({{ site.repository }}/issues/3489)) +- Replace link to the proposed `picture` element spec ([#3530]({{ site.repository }}/issues/3530)) +- Add front matter date formatting information ([#3469]({{ site.repository }}/issues/3469)) +- Improve consistency and clarity of plugins options note ([#3546]({{ site.repository }}/issues/3546)) +- Add permalink warning to pagination docs ([#3551]({{ site.repository }}/issues/3551)) +- Fix grammar in Collections docs API stability warning ([#3560]({{ site.repository }}/issues/3560)) +- Restructure `excerpt_separator` documentation for clarity ([#3550]({{ site.repository }}/issues/3550)) +- Fix accidental line break in collections docs ([#3585]({{ site.repository }}/issues/3585)) +- Add information about the `.jekyll-metadata` file ([#3597]({{ site.repository }}/issues/3597)) +- Document addition of variable parameters to an include ([#3581]({{ site.repository }}/issues/3581)) +- Add `jekyll-files` to the list of third-party plugins. ([#3586]({{ site.repository }}/issues/3586)) +- Define the `install` step in the CI example `.travis.yml` ([#3622]({{ site.repository }}/issues/3622)) +- Expand collections documentation. ([#3638]({{ site.repository }}/issues/3638)) +- Add the "warning" note label to excluding `vendor` in the CI docs page ([#3623]({{ site.repository }}/issues/3623)) +- Upgrade pieces of the Upgrading guide for Jekyll 3 ([#3607]({{ site.repository }}/issues/3607)) +- Showing how to access specific data items ([#3468]({{ site.repository }}/issues/3468)) +- Clarify pagination works from within HTML files ([#3467]({{ site.repository }}/issues/3467)) +- Add note to `excerpt_separator` documentation that it can be set globally ([#3667]({{ site.repository }}/issues/3667)) +- Fix some names on Troubleshooting page ([#3683]({{ site.repository }}/issues/3683)) +- Add `remote_file_content` tag plugin to list of third-party plugins ([#3691]({{ site.repository }}/issues/3691)) +- Update the Redcarpet version on the Configuration page. ([#3743]({{ site.repository }}/issues/3743)) +- Update the link in the welcome post to point to Jekyll Talk ([#3745]({{ site.repository }}/issues/3745)) +- Update link for navbars with data attributes tutorial ([#3728]({{ site.repository }}/issues/3728)) +- Add `jekyll-asciinema` to list of third-party plugins ([#3750]({{ site.repository }}/issues/3750)) +- Update pagination example to be agnostic to first pagination dir ([#3763]({{ site.repository }}/issues/3763)) +- Detailed instructions for rsync deployment method ([#3848]({{ site.repository }}/issues/3848)) +- Add Jekyll Portfolio Generator to list of plugins ([#3883]({{ site.repository }}/issues/3883)) +- Add `site.html_files` to variables docs ([#3880]({{ site.repository }}/issues/3880)) +- Add Static Publisher tool to list of deployment methods ([#3865]({{ site.repository }}/issues/3865)) +- Fix a few typos. ([#3897]({{ site.repository }}/issues/3897)) +- Add `jekyll-youtube` to the list of third-party plugins ([#3931]({{ site.repository }}/issues/3931)) +- Add Views Router plugin ([#3950]({{ site.repository }}/issues/3950)) +- Update install docs (Core dependencies, Windows reqs, etc) ([#3769]({{ site.repository }}/issues/3769)) +- Use Jekyll Feed for jekyllrb.com ([#3736]({{ site.repository }}/issues/3736)) +- Add jekyll-umlauts to plugins.md ($3966) +- Troubleshooting: fix broken link, add other mac-specific info ([#3968]({{ site.repository }}/issues/3968)) +- Add a new site for learning purposes ([#3917]({{ site.repository }}/issues/3917)) +- Added documentation for Jekyll environment variables ([#3989]({{ site.repository }}/issues/3989)) +- Fix broken configuration documentation page ([#3994]({{ site.repository }}/issues/3994)) +- Add troubleshooting docs for installing on El Capitan ([#3999]({{ site.repository }}/issues/3999)) +- Add Lazy Tweet Embedding to the list of third-party plugins ([#4015]({{ site.repository }}/issues/4015)) +- Add installation instructions for 2 of 3 options for plugins ([#4013]({{ site.repository }}/issues/4013)) +- Add alternative jekyll gem installation instructions ([#4018]({{ site.repository }}/issues/4018)) +- Fix a few typos and formatting problems. ([#4022]({{ site.repository }}/issues/4022)) +- Fix pretty permalink example ([#4029]({{ site.repository }}/issues/4029)) +- Note that `_config.yml` is not reloaded during regeneration ([#4034]({{ site.repository }}/issues/4034)) +- Apply code block figure syntax to blocks in CONTRIBUTING ([#4046]({{ site.repository }}/issues/4046)) +- Add jekyll-smartify to the list of third-party plugins ([#3572]({{ site.repository }}/issues/3572)) + + +## 2.5.3 / 2014-12-22 +{: #v2-5-3} + +### Bug Fixes +{: #bug-fixes-v2-5-3} + +- When checking a Markdown extname, include position of the `.` ([#3147]({{ site.repository }}/issues/3147)) +- Fix `jsonify` Liquid filter handling of boolean values ([#3154]({{ site.repository }}/issues/3154)) +- Add comma to value of `viewport` meta tag ([#3170]({{ site.repository }}/issues/3170)) +- Set the link type for the RSS feed to `application/rss+xml` ([#3176]({{ site.repository }}/issues/3176)) +- Refactor `#as_liquid` ([#3158]({{ site.repository }}/issues/3158)) + +### Development Fixes +{: #development-fixes-v2-5-3} + +- Exclude built-in bundles from being added to coverage report ([#3180]({{ site.repository }}/issues/3180)) + +### Site Enhancements +{: #site-enhancements-v2-5-3} + +- Add @alfredxing to the @jekyll/core team. :tada: ([#3218]({{ site.repository }}/issues/3218)) +- Document the `-q` option for the `build` and `serve` commands ([#3149]({{ site.repository }}/issues/3149)) +- Fix some minor typos/flow fixes in documentation website content ([#3165]({{ site.repository }}/issues/3165)) +- Add `keep_files` to configuration documentation ([#3162]({{ site.repository }}/issues/3162)) +- Repeat warning about cleaning of the `destination` directory ([#3161]({{ site.repository }}/issues/3161)) +- Add jekyll-500px-embed to list of third-party plugins ([#3163]({{ site.repository }}/issues/3163)) +- Simplified platform detection in Gemfile example for Windows ([#3177]({{ site.repository }}/issues/3177)) +- Add the `jekyll-jalali` plugin added to the list of third-party plugins. ([#3198]({{ site.repository }}/issues/3198)) +- Add Table of Contents to Troubleshooting page ([#3196]({{ site.repository }}/issues/3196)) +- Add `inline_highlight` plugin to list of third-party plugins ([#3212]({{ site.repository }}/issues/3212)) +- Add `jekyll-mermaid` plugin to list of third-party plugins ([#3222]({{ site.repository }}/issues/3222)) + + +## 2.5.2 / 2014-11-17 +{: #v2-5-2} + +### Minor Enhancements +{: #minor-enhancements-v2-5-2} + +- `post_url` should match `post.name` instead of slugs and dates ([#3058]({{ site.repository }}/issues/3058)) + +### Bug Fixes +{: #bug-fixes-v2-5-2} + +- Fix bundle require for `:jekyll_plugins` ([#3119]({{ site.repository }}/issues/3119)) +- Remove duplicate regexp phrase: `^\A` ([#3089]({{ site.repository }}/issues/3089)) +- Remove duplicate `Conversion error:` message in `Convertible` ([#3088]({{ site.repository }}/issues/3088)) +- Print full conversion error message in `Renderer#convert` ([#3090]({{ site.repository }}/issues/3090)) + +### Site Enhancements +{: #site-enhancements-v2-5-2} + +- Change variable names in Google Analytics script ([#3093]({{ site.repository }}/issues/3093)) +- Mention CSV files in the docs for data files ([#3101]({{ site.repository }}/issues/3101)) +- Add trailing slash to `paginate_path` example. ([#3091]({{ site.repository }}/issues/3091)) +- Get rid of noifniof (`excerpt_separator`) ([#3094]({{ site.repository }}/issues/3094)) +- Sass improvements, around nesting mostly. ([#3123]({{ site.repository }}/issues/3123)) +- Add webmentions.io plugin to the list of third-party plugins ([#3127]({{ site.repository }}/issues/3127)) +- Add Sass mixins and use them. ([#2904]({{ site.repository }}/issues/2904)) +- Slightly compress jekyll-sticker.jpg. ([#3133]({{ site.repository }}/issues/3133)) +- Update gridism and separate out related but custom styles. ([#3132]({{ site.repository }}/issues/3132)) +- Add remote-include plugin to list of third-party plugins ([#3136]({{ site.repository }}/issues/3136)) + + +## 2.5.1 / 2014-11-09 +{: #v2-5-1} + +### Bug Fixes +{: #bug-fixes-v2-5-1} + +- Fix path sanitation bug related to Windows drive names ([#3077]({{ site.repository }}/issues/3077)) + +### Development Fixes +{: #development-fixes-v2-5-1} + +- Add development time dependencies on minitest and test-unit to gemspec for cygwin ([#3064]({{ site.repository }}/issues/3064)) +- Use Travis's built-in caching. ([#3075]({{ site.repository }}/issues/3075)) + + +## 2.5.0 / 2014-11-06 +{: #v2-5-0} + +### Minor Enhancements +{: #minor-enhancements-v2-5-0} + +- Require gems in `:jekyll_plugins` Gemfile group unless `JEKYLL_NO_BUNDLER_REQUIRE` is specified in the environment. ([#2865]({{ site.repository }}/issues/2865)) +- Centralize path sanitation in the `Site` object ([#2882]({{ site.repository }}/issues/2882)) +- Allow placeholders in permalinks ([#3031]({{ site.repository }}/issues/3031)) +- Allow users to specify the log level via `JEKYLL_LOG_LEVEL`. ([#3067]({{ site.repository }}/issues/3067)) +- Fancy Indexing with WEBrick ([#3018]({{ site.repository }}/issues/3018)) +- Allow Enumerables to be used with `where` filter. ([#2986]({{ site.repository }}/issues/2986)) +- Meta descriptions in the site template now use `page.excerpt` if it's available ([#2964]({{ site.repository }}/issues/2964)) +- Change indentation in `head.html` of site template to 2 spaces from 4 ([#2973]({{ site.repository }}/issues/2973)) +- Use a `$content-width` variable instead of a fixed value in the site template CSS ([#2972]({{ site.repository }}/issues/2972)) +- Strip newlines in site template `` description. ([#2982]({{ site.repository }}/issues/2982)) +- Add link to atom feed in `head` of site template files ([#2996]({{ site.repository }}/issues/2996)) +- Performance optimizations ([#2994]({{ site.repository }}/issues/2994)) +- Use `Hash#each_key` instead of `Hash#keys.each` to speed up iteration over hash keys. ([#3017]({{ site.repository }}/issues/3017)) +- Further minor performance enhancements. ([#3022]({{ site.repository }}/issues/3022)) +- Add 'b' and 's' aliases for build and serve, respectively ([#3065]({{ site.repository }}/issues/3065)) + +### Bug Fixes +{: #bug-fixes-v2-5-0} + +- Fix Rouge's RedCarpet plugin interface integration ([#2951]({{ site.repository }}/issues/2951)) +- Remove `--watch` from the site template blog post since it defaults to watching in in 2.4.0 ([#2922]({{ site.repository }}/issues/2922)) +- Fix code for media query mixin in site template ([#2946]({{ site.repository }}/issues/2946)) +- Allow post URLs to have `.htm` extensions ([#2925]({{ site.repository }}/issues/2925)) +- `Utils.slugify`: Don't create new objects when gsubbing ([#2997]({{ site.repository }}/issues/2997)) +- The jsonify filter should deep-convert to Liquid when given an Array. ([#3032]({{ site.repository }}/issues/3032)) +- Apply `jsonify` filter to Hashes deeply and effectively ([#3063]({{ site.repository }}/issues/3063)) +- Use `127.0.0.1` as default host instead of `0.0.0.0` ([#3053]({{ site.repository }}/issues/3053)) +- In the case that a Gemfile does not exist, ensure Jekyll doesn't fail on requiring the Gemfile group ([#3066]({{ site.repository }}/issues/3066)) + +### Development Fixes +{: #development-fixes-v2-5-0} + +- Fix a typo in the doc block for `Jekyll::URL.escape_path` ([#3052]({{ site.repository }}/issues/3052)) +- Add integration test for `jekyll new --blank` in TestUnit ([#2913]({{ site.repository }}/issues/2913)) +- Add unit test for `jekyll new --force` logic ([#2929]({{ site.repository }}/issues/2929)) +- Update outdated comment for `Convertible#transform` ([#2957]({{ site.repository }}/issues/2957)) +- Add Hakiri badge to README. ([#2953]({{ site.repository }}/issues/2953)) +- Add some simple benchmarking tools. ([#2993]({{ site.repository }}/issues/2993)) + +### Site Enhancements +{: #site-enhancements-v2-5-0} + +- `NOKOGIRI_USE_SYSTEM_LIBRARIES=true` **decreases** installation time. ([#3040]({{ site.repository }}/issues/3040)) +- Add FormKeep to resources as Jekyll form backend ([#3010]({{ site.repository }}/issues/3010)) +- Fixing a mistake in the name of the new Liquid tag ([#2969]({{ site.repository }}/issues/2969)) +- Update Font Awesome to v4.2.0. ([#2898]({{ site.repository }}/issues/2898)) +- Fix link to [#2895]({{ site.repository }}/issues/2895) in 2.4.0 release post. ([#2899]({{ site.repository }}/issues/2899)) +- Add Big Footnotes for Kramdown plugin to list of third-party plugins ([#2916]({{ site.repository }}/issues/2916)) +- Remove warning regarding GHP use of singular types for front matter defaults ([#2919]({{ site.repository }}/issues/2919)) +- Fix quote character typo in site documentation for templates ([#2917]({{ site.repository }}/issues/2917)) +- Point Liquid links to Liquid’s GitHub wiki ([#2887]({{ site.repository }}/issues/2887)) +- Add HTTP Basic Auth (.htaccess) plugin to list of third-party plugins ([#2931]({{ site.repository }}/issues/2931)) +- (Minor) Grammar & `_config.yml` filename fixes ([#2911]({{ site.repository }}/issues/2911)) +- Added `mathml.rb` to the list of third-party plugins. ([#2937]({{ site.repository }}/issues/2937)) +- Add `--force_polling` to the list of configuration options ([#2943]({{ site.repository }}/issues/2943)) +- Escape unicode characters in site CSS ([#2906]({{ site.repository }}/issues/2906)) +- Add note about using the github-pages gem via pages.github.com/versions.json ([#2939]({{ site.repository }}/issues/2939)) +- Update usage documentation to reflect 2.4 auto-enabling of `--watch`. ([#2954]({{ site.repository }}/issues/2954)) +- Add `--skip-initial-build` to configuration docs ([#2949]({{ site.repository }}/issues/2949)) +- Fix a minor typo in Templates docs page ([#2959]({{ site.repository }}/issues/2959)) +- Add a ditaa-ditaa plugin under Other section on the Plugins page ([#2967]({{ site.repository }}/issues/2967)) +- Add `build/serve -V` option to configuration documentation ([#2948]({{ site.repository }}/issues/2948)) +- Add 'Jekyll Twitter Plugin' to list of third-party plugins ([#2979]({{ site.repository }}/issues/2979)) +- Docs: Update normalize.css to v3.0.2. ([#2981]({{ site.repository }}/issues/2981)) +- Fix typo in Continuous Integration documentation ([#2984]({{ site.repository }}/issues/2984)) +- Clarify behavior of `:categories` in permalinks ([#3011]({{ site.repository }}/issues/3011)) + + +## 2.4.0 / 2014-09-09 +{: #v2-4-0} + +### Minor Enhancements +{: #minor-enhancements-v2-4-0} + +- Support a new `relative_include` tag ([#2870]({{ site.repository }}/issues/2870)) +- Auto-enable watch on 'serve' ([#2858]({{ site.repository }}/issues/2858)) +- Render Liquid in CoffeeScript files ([#2830]({{ site.repository }}/issues/2830)) +- Array Liquid filters: `push`, `pop`, `unshift`, `shift` ([#2895]({{ site.repository }}/issues/2895)) +- Add `:title` to collection URL template fillers ([#2864]({{ site.repository }}/issues/2864)) +- Add support for CSV files in the `_data` directory ([#2761]({{ site.repository }}/issues/2761)) +- Add the `name` variable to collection permalinks ([#2799]({{ site.repository }}/issues/2799)) +- Add `inspect` liquid filter. ([#2867]({{ site.repository }}/issues/2867)) +- Add a `slugify` Liquid filter ([#2880]({{ site.repository }}/issues/2880)) + +### Bug Fixes +{: #bug-fixes-v2-4-0} + +- Use `Jekyll.sanitized_path` when adding static files to Collections ([#2849]({{ site.repository }}/issues/2849)) +- Fix encoding of `main.scss` in site template ([#2771]({{ site.repository }}/issues/2771)) +- Fix orientation bugs in default site template ([#2862]({{ site.repository }}/issues/2862)) + +### Development Fixes +{: #development-fixes-v2-4-0} + +- Update simplecov gem to 0.9 ([#2748]({{ site.repository }}/issues/2748)) +- Remove `docs/` dir ([#2768]({{ site.repository }}/issues/2768)) +- add class `<< self` idiom to `New` command ([#2817]({{ site.repository }}/issues/2817)) +- Allow Travis to 'parallelize' our tests ([#2859]({{ site.repository }}/issues/2859)) +- Fix test for Liquid rendering in Sass ([#2856]({{ site.repository }}/issues/2856)) +- Fixing "vertycal" typo in site template's `_base.scss` ([#2889]({{ site.repository }}/issues/2889)) + +### Site Enhancements +{: #site-enhancements-v2-4-0} + +- Document the `name` variable for collection permalinks ([#2829]({{ site.repository }}/issues/2829)) +- Adds info about installing jekyll in current dir ([#2839]({{ site.repository }}/issues/2839)) +- Remove deprecated `jekyll-projectlist` plugin from list of third-party plugins ([#2742]({{ site.repository }}/issues/2742)) +- Remove tag plugins that are built into Jekyll ([#2751]({{ site.repository }}/issues/2751)) +- Add `markdown-writer` package for Atom Editor to list of third-party plugins ([#2763]({{ site.repository }}/issues/2763)) +- Fix typo in site documentation for collections ([#2764]({{ site.repository }}/issues/2764)) +- Fix minor typo on plugins docs page ([#2765]({{ site.repository }}/issues/2765)) +- Replace markdown with HTML in `sass_dir` note on assets page ([#2791]({{ site.repository }}/issues/2791)) +- Fixed "bellow" typo in datafiles docs ([#2879]({{ site.repository }}/issues/2879)) +- Fix code/markdown issue in documentation for variables ([#2877]({{ site.repository }}/issues/2877)) +- Remove Good Include third-party plugin from plugins page ([#2881]({{ site.repository }}/issues/2881)) +- Add some more docs on `include_relative` ([#2884]({{ site.repository }}/issues/2884)) + + +## 2.3.0 / 2014-08-10 +{: #v2-3-0} + +### Minor Enhancements +{: #minor-enhancements-v2-3-0} + +- Allow Convertibles to be converted by >= 1 converters ([#2704]({{ site.repository }}/issues/2704)) +- Allow Sass files to be rendered in Liquid, but never place them in layouts. ([#2733]({{ site.repository }}/issues/2733)) +- Add `jekyll help` command ([#2707]({{ site.repository }}/issues/2707)) +- Use `.scss` for `site_template` styles. ([#2667]({{ site.repository }}/issues/2667)) +- Don't require the `scope` key in front matter defaults ([#2659]({{ site.repository }}/issues/2659)) +- No longer set `permalink: pretty` in the `_config.yml` for the site template ([#2680]({{ site.repository }}/issues/2680)) +- Rework site template to utilize Sass ([#2687]({{ site.repository }}/issues/2687)) +- Notify the user when auto-regeneration is disabled. ([#2696]({{ site.repository }}/issues/2696)) +- Allow partial variables in include tag filename argument ([#2693]({{ site.repository }}/issues/2693)) +- Move instances of `Time.parse` into a Utils method ([#2682]({{ site.repository }}/issues/2682)) +- Ignore subfolders in the `_posts` folder ([#2705]({{ site.repository }}/issues/2705)) REVERTS ([#2633]({{ site.repository }}/issues/2633)) +- Front Matter default types should always be pluralized ([#2732]({{ site.repository }}/issues/2732)) +- Read in static files into `collection.files` as `StaticFile`s ([#2737]({{ site.repository }}/issues/2737)) +- Add `sassify` and `scssify` Liquid filters ([#2739]({{ site.repository }}/issues/2739)) +- Replace `classifier` gem with `classifier-reborn` ([#2721]({{ site.repository }}/issues/2721)) + +### Bug Fixes +{: #bug-fixes-v2-3-0} + +- Use only the last extname when multiple converters exist ([#2722]({{ site.repository }}/issues/2722)) +- Call `#to_liquid` before calling `#to_json` in jsonify filter ([#2729]({{ site.repository }}/issues/2729)) +- Use non padded config in `strftime` to avoid parse string twice ([#2673]({{ site.repository }}/issues/2673)) +- Replace deprecated Ruby methods with undeprecated ones ([#2664]({{ site.repository }}/issues/2664)) +- Catch errors when parsing Post `date` front matter value & produce nice error message ([#2649]({{ site.repository }}/issues/2649)) +- Allow static files in Collections ([#2615]({{ site.repository }}/issues/2615)) +- Fixed typo in `Deprecator#gracefully_require` error message ([#2694]({{ site.repository }}/issues/2694)) +- Remove preemptive loading of the 'classifier' gem. ([#2697]({{ site.repository }}/issues/2697)) +- Use case-insensitive checking for the file extensions when loading config files ([#2718]({{ site.repository }}/issues/2718)) +- When Reading Documents, Respect `encoding` Option ([#2720]({{ site.repository }}/issues/2720)) +- Refactor based on jekyll-watch clean-up. ([#2716]({{ site.repository }}/issues/2716)) +- `Document#to_s` should produce just the content of the document ([#2731]({{ site.repository }}/issues/2731)) + +### Development Fixes +{: #development-fixes-v2-3-0} + +- Only include lib files in the gem ([#2671]({{ site.repository }}/issues/2671)) +- Fix `git diff` command in `proof` script ([#2672]({{ site.repository }}/issues/2672)) +- Make default rake task a multitask so tests run in parallel ([#2735]({{ site.repository }}/issues/2735)) + +### Site Enhancements +{: #site-enhancements-v2-3-0} + +- Use Sass and a Docs Collection ([#2651]({{ site.repository }}/issues/2651)) +- Add `latest_version.txt` file to the site ([#2740]({{ site.repository }}/issues/2740)) +- Be more ambiguous about `page.content`. But more transparent. ([#2522]({{ site.repository }}/issues/2522)) +- Streamlining front matter wording (instead of front-matter/frontmatter) ([#2674]({{ site.repository }}/issues/2674)) +- Add note that source directory cannot be modified in GitHub Pages ([#2669]({{ site.repository }}/issues/2669)) +- Fix links from [#2669]({{ site.repository }}/issues/2669) to be actual HTML. Whoops. ([#2679]({{ site.repository }}/issues/2679)) +- Add link to `jekyll-slim` in list of third-party plugins ([#2689]({{ site.repository }}/issues/2689)) +- Add Barry Clark's Smashing Magazine tutorial to resources page ([#2688]({{ site.repository }}/issues/2688)) +- Reorganize and update default configuration settings ([#2456]({{ site.repository }}/issues/2456)) +- Fixing indentation in the configuration docs about Redcarpet exts ([#2717]({{ site.repository }}/issues/2717)) +- Use `null` in YAML instead of `nil` in default config list ([#2719]({{ site.repository }}/issues/2719)) +- Fix typo in Continuous Integration docs ([#2708]({{ site.repository }}/issues/2708)) + + +## 2.2.0 / 2014-07-29 +{: #v2-2-0} + +### Minor Enhancements +{: #minor-enhancements-v2-2-0} + +- Throw a warning if the specified layout does not exist ([#2620]({{ site.repository }}/issues/2620)) +- Whitelist Pygments options in safe mode ([#2642]({{ site.repository }}/issues/2642)) + +### Bug Fixes +{: #bug-fixes-v2-2-0} + +- Remove unnecessary `Jekyll::Tags::IncludeTag#blank?` method ([#2625]({{ site.repository }}/issues/2625)) +- Categories in the path are ignored ([#2633]({{ site.repository }}/issues/2633)) + +### Development Fixes +{: #development-fixes-v2-2-0} + +- Refactoring Errors & Requires of Third-Party stuff ([#2591]({{ site.repository }}/issues/2591)) +- Add further tests for categories ([#2584]({{ site.repository }}/issues/2584)) +- Proof site with html-proofer on change ([#2605]({{ site.repository }}/issues/2605)) +- Fix up bug in [#2605]({{ site.repository }}/issues/2605) which caused proofing the site not to function ([#2608]({{ site.repository }}/issues/2608)) +- Use `bundle exec` in `script/proof` ([#2610]({{ site.repository }}/issues/2610)) + +### Site Enhancements +{: #site-enhancements-v2-2-0} + +- Update Kramdown urls ([#2588]({{ site.repository }}/issues/2588)) +- Add `Jekyll::AutolinkEmail` and `Jekyll::GitMetadata` to the list of third-party plugins ([#2596]({{ site.repository }}/issues/2596)) +- Fix a bunch of broken links in the site ([#2601]({{ site.repository }}/issues/2601)) +- Replace dead links with working links ([#2611]({{ site.repository }}/issues/2611)) +- Add jekyll-hook to deployment methods ([#2617]({{ site.repository }}/issues/2617)) +- Added kramdown-with-pygments plugin to the list of third-party plugins ([#2623]({{ site.repository }}/issues/2623)) +- Update outdated "Extras" page and remove duplicate documentation ([#2622]({{ site.repository }}/issues/2622)) +- Add co2 plugin to list of third-party plugins ([#2639]({{ site.repository }}/issues/2639)) +- Attempt to clarify the way Sass imports happen ([#2642]({{ site.repository }}/issues/2642)) + + +## 2.1.1 / 2014-07-01 +{: #v2-1-1} + +### Bug Fixes +{: #bug-fixes-v2-1-1} + +- Patch read vulnerabilities for data & confirm none for layouts ([#2563]({{ site.repository }}/issues/2563)) +- Update Maruku dependency to allow use of the latest version ([#2576]({{ site.repository }}/issues/2576)) +- Remove conditional assignment from document URL to prevent stale urls ([#2575]({{ site.repository }}/issues/2575)) + +### Site Enhancements +{: #site-enhancements-v2-1-1} + +- Add vertical margin to `highlight` to separate code blocks ([#2558]({{ site.repository }}/issues/2558)) +- Add `html_pages` to Variables docs ([#2567]({{ site.repository }}/issues/2567)) +- Fixed broken link to Permalinks page ([#2572]({{ site.repository }}/issues/2572)) +- Update link to Windows installation guide ([#2578]({{ site.repository }}/issues/2578)) + + +## 2.1.0 / 2014-06-28 +{: #v2-1-0} + +### Minor Enhancements +{: #minor-enhancements-v2-1-0} + +- Bump to the latest Liquid version, 2.6.1 ([#2495]({{ site.repository }}/issues/2495)) +- Add support for JSON files in the `_data` directory ([#2369]({{ site.repository }}/issues/2369)) +- Allow subclasses to override `EXCERPT_ATTRIBUTES_FOR_LIQUID` ([#2408]({{ site.repository }}/issues/2408)) +- Add `Jekyll.env` and `jekyll.environment` (the Liquid var) ([#2417]({{ site.repository }}/issues/2417)) +- Use `_config.yaml` or `_config.yml` (`.yml` takes precedence) ([#2406]({{ site.repository }}/issues/2406)) +- Override collection url template ([#2418]({{ site.repository }}/issues/2418)) +- Allow subdirectories in `_data` ([#2395]({{ site.repository }}/issues/2395)) +- Extract Pagination Generator into gem: `jekyll-paginate` ([#2455]({{ site.repository }}/issues/2455)) +- Utilize `date_to_rfc822` filter in site template ([#2437]({{ site.repository }}/issues/2437)) +- Add categories, last build datetime, and generator to site template feed ([#2438]({{ site.repository }}/issues/2438)) +- Configurable, replaceable Logger-compliant logger ([#2444]({{ site.repository }}/issues/2444)) +- Extract `gist` tag into a separate gem ([#2469]({{ site.repository }}/issues/2469)) +- Add `collection` attribute to `Document#to_liquid` to access the document's collection label. ([#2436]({{ site.repository }}/issues/2436)) +- Upgrade listen to `2.7.6 <= x < 3.0.0` ([#2492]({{ site.repository }}/issues/2492)) +- Allow configuration of different Twitter and GitHub usernames in site template ([#2485]({{ site.repository }}/issues/2485)) +- Bump Pygments to v0.6.0 ([#2504]({{ site.repository }}/issues/2504)) +- Front matter defaults for documents in collections ([#2419]({{ site.repository }}/issues/2419)) +- Include files with a url which ends in `/` in the `site.html_pages` list ([#2524]({{ site.repository }}/issues/2524)) +- Make `highlight` tag use `language-` prefix in CSS class ([#2511]({{ site.repository }}/issues/2511)) +- Lookup item property via `item#to_liquid` before `#data` or `#[]` in filters ([#2493]({{ site.repository }}/issues/2493)) +- Skip initial build of site on serve with flag ([#2477]({{ site.repository }}/issues/2477)) +- Add support for `hl_lines` in `highlight` tag ([#2532]({{ site.repository }}/issues/2532)) +- Spike out `--watch` flag into a separate gem ([#2550]({{ site.repository }}/issues/2550)) + +### Bug Fixes +{: #bug-fixes-v2-1-0} + +- Liquid `sort` filter should sort even if one of the values is `nil` ([#2345]({{ site.repository }}/issues/2345)) +- Remove padding on `pre code` in the site template CSS ([#2383]({{ site.repository }}/issues/2383)) +- Set `log_level` earlier to silence info level configuration output ([#2393]({{ site.repository }}/issues/2393)) +- Only list pages which have `title` in site template ([#2411]({{ site.repository }}/issues/2411)) +- Accept `Numeric` values for dates, not `Number` values ([#2377]({{ site.repository }}/issues/2377)) +- Prevent code from overflowing container in site template ([#2429]({{ site.repository }}/issues/2429)) +- Encode URLs in UTF-8 when escaping and unescaping ([#2420]({{ site.repository }}/issues/2420)) +- No Layouts or Liquid for Asset Files ([#2431]({{ site.repository }}/issues/2431)) +- Allow front matter defaults to set post categories ([#2373]({{ site.repository }}/issues/2373)) +- Fix command in subcommand deprecation warning ([#2457]({{ site.repository }}/issues/2457)) +- Keep all parent directories of files/dirs in `keep_files` ([#2458]({{ site.repository }}/issues/2458)) +- When using RedCarpet and Rouge without Rouge installed, fixed erroneous error which stated that redcarpet was missing, not rouge. ([#2464]({{ site.repository }}/issues/2464)) +- Ignore *all* directories and files that merit it on auto-generation ([#2459]({{ site.repository }}/issues/2459)) +- Before copying file, explicitly remove the old one ([#2535]({{ site.repository }}/issues/2535)) +- Merge file system categories with categories from YAML. ([#2531]({{ site.repository }}/issues/2531)) +- Deep merge front matter defaults ([#2490]({{ site.repository }}/issues/2490)) +- Ensure exclude and include arrays are arrays of strings ([#2542]({{ site.repository }}/issues/2542)) +- Allow collections to have dots in their filenames ([#2552]({{ site.repository }}/issues/2552)) +- Collections shouldn't try to read in directories as files ([#2552]({{ site.repository }}/issues/2552)) +- Be quiet very quickly. ([#2520]({{ site.repository }}/issues/2520)) + +### Development Fixes +{: #development-fixes-v2-1-0} + +- Test Ruby 2.1.2 instead of 2.1.1 ([#2374]({{ site.repository }}/issues/2374)) +- Add test for sorting UTF-8 characters ([#2384]({{ site.repository }}/issues/2384)) +- Use `https` for GitHub links in documentation ([#2470]({{ site.repository }}/issues/2470)) +- Remove coverage reporting with Coveralls ([#2494]({{ site.repository }}/issues/2494)) +- Fix a bit of missing TomDoc to `Jekyll::Commands::Build#build` ([#2554]({{ site.repository }}/issues/2554)) + +### Site Enhancements +{: #site-enhancements-v2-1-0} + +- Set `timezone` to `America/Los_Angeles` ([#2394]({{ site.repository }}/issues/2394)) +- Improve JavaScript in `anchor_links.html` ([#2368]({{ site.repository }}/issues/2368)) +- Remove note on Quickstart page about default markdown converter ([#2387]({{ site.repository }}/issues/2387)) +- Remove broken link in extras.md to a Maruku fork ([#2401]({{ site.repository }}/issues/2401)) +- Update Font Awesome to v4.1.0. ([#2410]({{ site.repository }}/issues/2410)) +- Fix broken link on Installation page to Templates page ([#2421]({{ site.repository }}/issues/2421)) +- Prevent table from extending parent width in permalink style table ([#2424]({{ site.repository }}/issues/2424)) +- Add collections to info about pagination support ([#2389]({{ site.repository }}/issues/2389)) +- Add `jekyll_github_sample` plugin to list of third-party plugins ([#2463]({{ site.repository }}/issues/2463)) +- Clarify documentation around front matter defaults and add details about defaults for collections. ([#2439]({{ site.repository }}/issues/2439)) +- Add Jekyll Project Version Tag to list of third-party plugins ([#2468]({{ site.repository }}/issues/2468)) +- Use `https` for GitHub links across whole site ([#2470]({{ site.repository }}/issues/2470)) +- Add StickerMule + Jekyll post ([#2476]({{ site.repository }}/issues/2476)) +- Add Jekyll Asset Pipeline Reborn to list of third-party plugins ([#2479]({{ site.repository }}/issues/2479)) +- Add link to jekyll-compress-html to list of third-party plugins ([#2514]({{ site.repository }}/issues/2514)) +- Add Piwigo Gallery to list of third-party plugins ([#2526]({{ site.repository }}/issues/2526)) +- Set `show_drafts` to `false` in default configuration listing ([#2536]({{ site.repository }}/issues/2536)) +- Provide an updated link for Windows installation instructions ([#2544]({{ site.repository }}/issues/2544)) +- Remove `url` from configuration docs ([#2547]({{ site.repository }}/issues/2547)) +- Documentation for Continuous Integration for your Jekyll Site ([#2432]({{ site.repository }}/issues/2432)) + + +## 2.0.3 / 2014-05-08 +{: #v2-0-3} + +### Bug Fixes +{: #bug-fixes-v2-0-3} + +- Properly prefix links in site template with URL or baseurl depending upon need. ([#2319]({{ site.repository }}/issues/2319)) +- Update gist tag comments and error message to require username ([#2326]({{ site.repository }}/issues/2326)) +- Fix `permalink` setting in site template ([#2331]({{ site.repository }}/issues/2331)) +- Don't fail if any of the path objects are nil ([#2325]({{ site.repository }}/issues/2325)) +- Instantiate all descendants for converters and generators, not just direct subclasses ([#2334]({{ site.repository }}/issues/2334)) +- Replace all instances of `site.name` with `site.title` in site template ([#2324]({{ site.repository }}/issues/2324)) +- `Jekyll::Filters#time` now accepts UNIX timestamps in string or number form ([#2339]({{ site.repository }}/issues/2339)) +- Use `item_property` for `where` filter so it doesn't break on collections ([#2359]({{ site.repository }}/issues/2359)) +- Rescue errors thrown so `--watch` doesn't fail ([#2364]({{ site.repository }}/issues/2364)) + +### Site Enhancements +{: #site-enhancements-v2-0-3} + +- Add missing "as" to assets docs page ([#2337]({{ site.repository }}/issues/2337)) +- Update docs to reflect new `baseurl` default ([#2341]({{ site.repository }}/issues/2341)) +- Add links to headers who have an ID. ([#2342]({{ site.repository }}/issues/2342)) +- Use symbol instead of HTML number in `upgrading.md` ([#2351]({{ site.repository }}/issues/2351)) +- Fix link to front matter defaults docs ([#2353]({{ site.repository }}/issues/2353)) +- Fix for `History.markdown` in order to fix history page in docs ([#2363]({{ site.repository }}/issues/2363)) + + +## 2.0.2 / 2014-05-07 +{: #v2-0-2} + +### Bug Fixes +{: #bug-fixes-v2-0-2} + +- Correct use of `url` and `baseurl` in the site template. ([#2317]({{ site.repository }}/issues/2317)) +- Default `baseurl` to `""` ([#2317]({{ site.repository }}/issues/2317)) + +### Site Enhancements +{: #site-enhancements-v2-0-2} + +- Correct docs for the `gist` plugin so it always includes the username. ([#2314]({{ site.repository }}/issues/2314)) +- Clarify new (defaults, `where` filter) features in docs ([#2316]({{ site.repository }}/issues/2316)) + + +## 2.0.1 / 2014-05-06 +{: #v2-0-1} + +### Bug Fixes +{: #bug-fixes-v2-0-1} + +- Require `kramdown` gem instead of `maruku` gem + + +## 2.0.0 / 2014-05-06 +{: #v2-0-0} + +### Major Enhancements +{: #major-enhancements-v2-0-0} + +- Add "Collections" feature ([#2199]({{ site.repository }}/issues/2199)) +- Add gem-based plugin whitelist to safe mode ([#1657]({{ site.repository }}/issues/1657)) +- Replace the commander command line parser with a more robust solution for our needs called `mercenary` ([#1706]({{ site.repository }}/issues/1706)) +- Remove support for Ruby 1.8.x ([#1780]({{ site.repository }}/issues/1780)) +- Move to jekyll/jekyll from mojombo/jekyll ([#1817]({{ site.repository }}/issues/1817)) +- Allow custom markdown processors ([#1872]({{ site.repository }}/issues/1872)) +- Provide support for the Rouge syntax highlighter ([#1859]({{ site.repository }}/issues/1859)) +- Provide support for Sass ([#1932]({{ site.repository }}/issues/1932)) +- Provide a 300% improvement when generating sites that use `Post#next` or `Post#previous` ([#1983]({{ site.repository }}/issues/1983)) +- Provide support for CoffeeScript ([#1991]({{ site.repository }}/issues/1991)) +- Replace Maruku with Kramdown as Default Markdown Processor ([#1988]({{ site.repository }}/issues/1988)) +- Expose `site.static_files` to Liquid ([#2075]({{ site.repository }}/issues/2075)) +- Complete redesign of the template site generated by `jekyll new` ([#2050]({{ site.repository }}/issues/2050)) +- Update Listen from 1.x to 2.x ([#2097]({{ site.repository }}/issues/2097)) +- Front matter defaults ([#2205]({{ site.repository }}/issues/2205)) +- Deprecate `relative_permalinks` configuration option (default to `false`) ([#2307]({{ site.repository }}/issues/2307)) +- Exclude files based on prefix as well as `fnmatch?` ([#2303]({{ site.repository }}/issues/2303)) + +### Minor Enhancements +{: #minor-enhancements-v2-0-0} + +- Move the EntryFilter class into the Jekyll module to avoid polluting the global namespace ([#1800]({{ site.repository }}/issues/1800)) +- Add `group_by` Liquid filter create lists of items grouped by a common property's value ([#1788]({{ site.repository }}/issues/1788)) +- Add support for Maruku's `fenced_code_blocks` option ([#1799]({{ site.repository }}/issues/1799)) +- Update Redcarpet dependency to ~> 3.0 ([#1815]({{ site.repository }}/issues/1815)) +- Automatically sort all pages by name ([#1848]({{ site.repository }}/issues/1848)) +- Better error message when time is not parseable ([#1847]({{ site.repository }}/issues/1847)) +- Allow `include` tag variable arguments to use filters ([#1841]({{ site.repository }}/issues/1841)) +- `post_url` tag should raise `ArgumentError` for invalid name ([#1825]({{ site.repository }}/issues/1825)) +- Bump dependency `mercenary` to `~> 0.2.0` ([#1879]({{ site.repository }}/issues/1879)) +- Bump dependency `safe_yaml` to `~> 1.0` ([#1886]({{ site.repository }}/issues/1886)) +- Allow sorting of content by custom properties ([#1849]({{ site.repository }}/issues/1849)) +- Add `--quiet` flag to silence output during build and serve ([#1898]({{ site.repository }}/issues/1898)) +- Add a `where` filter to filter arrays based on a key/value pair ([#1875]({{ site.repository }}/issues/1875)) +- Route 404 errors to a custom 404 page in development ([#1899]({{ site.repository }}/issues/1899)) +- Excludes are now relative to the site source ([#1916]({{ site.repository }}/issues/1916)) +- Bring MIME Types file for `jekyll serve` to complete parity with GH Pages servers ([#1993]({{ site.repository }}/issues/1993)) +- Adding Breakpoint to make new site template more responsive ([#2038]({{ site.repository }}/issues/2038)) +- Default to using the UTF-8 encoding when reading files. ([#2031]({{ site.repository }}/issues/2031)) +- Update Redcarpet dependency to ~> 3.1 ([#2044]({{ site.repository }}/issues/2044)) +- Remove support for Ruby 1.9.2 ([#2045]({{ site.repository }}/issues/2045)) +- Add `.mkdown` as valid Markdown extension ([#2048]({{ site.repository }}/issues/2048)) +- Add `index.xml` to the list of WEBrick directory index files ([#2041]({{ site.repository }}/issues/2041)) +- Make the `layouts` config key relative to CWD or to source ([#2058]({{ site.repository }}/issues/2058)) +- Update Kramdown to `~> 1.3` ([#1894]({{ site.repository }}/issues/1894)) +- Remove unnecessary references to `self` ([#2090]({{ site.repository }}/issues/2090)) +- Update to Mercenary v0.3.x ([#2085]({{ site.repository }}/issues/2085)) +- Ship Sass support as a separate gem ([#2098]({{ site.repository }}/issues/2098)) +- Extract core extensions into a Utils module ([#2112]({{ site.repository }}/issues/2112)) +- Refactor CLI & Commands For Greater Happiness ([#2143]({{ site.repository }}/issues/2143)) +- Provide useful error when Pygments returns `nil` and error out ([#2148]({{ site.repository }}/issues/2148)) +- Add support for unpublished drafts ([#2164]({{ site.repository }}/issues/2164)) +- Add `force_polling` option to the `serve` command ([#2165]({{ site.repository }}/issues/2165)) +- Clean up the `` in the site template ([#2186]({{ site.repository }}/issues/2186)) +- Permit YAML blocks to end with three dots to better conform with the YAML spec ([#2110]({{ site.repository }}/issues/2110)) +- Use `File.exist?` instead of deprecated `File.exists?` ([#2214]({{ site.repository }}/issues/2214)) +- Require newline after start of front matter header ([#2211]({{ site.repository }}/issues/2211)) +- Add the ability for pages to be marked as `published: false` ([#1492]({{ site.repository }}/issues/1492)) +- Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy looking up of variable values in a Liquid context. ([#2253]({{ site.repository }}/issues/2253)) +- Remove literal lang name from class ([#2292]({{ site.repository }}/issues/2292)) +- Return `utf-8` encoding in header for webrick error page response ([#2289]({{ site.repository }}/issues/2289)) +- Make template site easier to customize ([#2268]({{ site.repository }}/issues/2268)) +- Add two-digit year to permalink template option ([#2301]({{ site.repository }}/issues/2301)) +- Add `site.documents` to Liquid payload (list of all docs) ([#2295]({{ site.repository }}/issues/2295)) +- Take into account missing values in the Liquid sort filter ([#2299]({{ site.repository }}/issues/2299)) + +### Bug Fixes +{: #bug-fixes-v2-0-0} + +- Don't allow nil entries when loading posts ([#1796]({{ site.repository }}/issues/1796)) +- Remove the scrollbar that's always displayed in new sites generated from the site template ([#1805]({{ site.repository }}/issues/1805)) +- Add `#path` to required methods in `Jekyll::Convertible` ([#1866]({{ site.repository }}/issues/1866)) +- Default Maruku fenced code blocks to ON for 2.0.0-dev ([#1831]({{ site.repository }}/issues/1831)) +- Change short opts for host and port for `jekyll docs` to be consistent with other subcommands ([#1877]({{ site.repository }}/issues/1877)) +- Fix typos ([#1910]({{ site.repository }}/issues/1910)) +- Lock Maruku at 0.7.0 to prevent bugs caused by Maruku 0.7.1 ([#1958]({{ site.repository }}/issues/1958)) +- Fixes full path leak to source directory when using include tag ([#1951]({{ site.repository }}/issues/1951)) +- Don't generate pages that aren't being published ([#1931]({{ site.repository }}/issues/1931)) +- Use `SafeYAML.load` to avoid conflicts with other projects ([#1982]({{ site.repository }}/issues/1982)) +- Relative posts should never fail to build ([#1976]({{ site.repository }}/issues/1976)) +- Remove executable bits of non executable files ([#2056]({{ site.repository }}/issues/2056)) +- `#path` for a draft is now `_drafts` instead of `_posts` ([#2042]({{ site.repository }}/issues/2042)) +- Patch a couple show-stopping security vulnerabilities ([#1946]({{ site.repository }}/issues/1946)) +- Sanitize paths uniformly, in a Windows-friendly way ([#2065]({{ site.repository }}/issues/2065), [#2109]({{ site.repository }}/issues/2109)) +- Update gem build steps to work correctly on Windows ([#2118]({{ site.repository }}/issues/2118)) +- Remove obsolete `normalize_options` method call from `bin/jekyll` ([#2121]({{ site.repository }}/issues/2121)) +- Remove `+` characters from Pygments lexer names when adding as a CSS class ([#994]({{ site.repository }}/issues/994)) +- Remove some code that caused Ruby interpreter warnings ([#2178]({{ site.repository }}/issues/2178)) +- Only strip the drive name if it begins the string ([#2175]({{ site.repository }}/issues/2175)) +- Remove default post with invalid date from site template ([#2200]({{ site.repository }}/issues/2200)) +- Fix `Post#url` and `Page#url` escape ([#1568]({{ site.repository }}/issues/1568)) +- Strip newlines from the {% raw %}`{% highlight %}`{% endraw %} block content ([#1823]({{ site.repository }}/issues/1823)) +- Load in `rouge` only when it's been requested as the highlighter ([#2189]({{ site.repository }}/issues/2189)) +- Convert input to string before XML escaping (`xml_escape` liquid filter) ([#2244]({{ site.repository }}/issues/2244)) +- Modify configuration key for Collections and reset properly. ([#2238]({{ site.repository }}/issues/2238)) +- Avoid duplicated output using `highlight` tag ([#2264]({{ site.repository }}/issues/2264)) +- Only use Jekyll.logger for output ([#2307]({{ site.repository }}/issues/2307)) +- Close the file descriptor in `has_yaml_header?` ([#2310]({{ site.repository }}/issues/2310)) +- Add `output` to `Document` liquid output hash ([#2309]({{ site.repository }}/issues/2309)) + +### Development Fixes +{: #development-fixes-v2-0-0} + +- Add a link to the site in the README.md file ([#1795]({{ site.repository }}/issues/1795)) +- Add in History and site changes from `v1-stable` branch ([#1836]({{ site.repository }}/issues/1836)) +- Testing additions on the Excerpt class ([#1893]({{ site.repository }}/issues/1893)) +- Fix the `highlight` tag feature ([#1859]({{ site.repository }}/issues/1859)) +- Test Jekyll under Ruby 2.1.0 ([#1900]({{ site.repository }}/issues/1900)) +- Add script/cibuild for fun and profit ([#1912]({{ site.repository }}/issues/1912)) +- Use `Forwardable` for delegation between `Excerpt` and `Post` ([#1927]({{ site.repository }}/issues/1927)) +- Rename `read_things` to `read_content` ([#1928]({{ site.repository }}/issues/1928)) +- Add `script/branding` script for ASCII art lovin' ([#1936]({{ site.repository }}/issues/1936)) +- Update the README to reflect the repo move ([#1943]({{ site.repository }}/issues/1943)) +- Add the project vision to the README ([#1935]({{ site.repository }}/issues/1935)) +- Speed up Travis CI builds by using Rebund ([#1985]({{ site.repository }}/issues/1985)) +- Use Yarp as a Gem proxy for Travis CI ([#1984]({{ site.repository }}/issues/1984)) +- Remove Yarp as a Gem proxy for Travis CI ([#2004]({{ site.repository }}/issues/2004)) +- Move the reading of layouts into its own class ([#2020]({{ site.repository }}/issues/2020)) +- Test Sass import ([#2009]({{ site.repository }}/issues/2009)) +- Switch Maruku and Kramdown in lists of Runtime vs. Development dependencies ([#2049]({{ site.repository }}/issues/2049)) +- Clean up the gemspec for the project ([#2095]({{ site.repository }}/issues/2095)) +- Add Japanese translation of README and CONTRIBUTING docs. ([#2081]({{ site.repository }}/issues/2081)) +- Re-align the tables in Cucumber ([#2108]({{ site.repository }}/issues/2108)) +- Trim trailing spaces and convert tabs to spaces ([#2122]({{ site.repository }}/issues/2122)) +- Fix the failing Travis scenarios due to Cucumber issues ([#2155]({{ site.repository }}/issues/2155)) +- Wrap `bundle install` in `travis_retry` to retry when RubyGems fails ([#2160]({{ site.repository }}/issues/2160)) +- Refactor tags and categories ([#1639]({{ site.repository }}/issues/1639)) +- Extract plugin management into its own class ([#2197]({{ site.repository }}/issues/2197)) +- Add missing tests for `Command` ([#2216]({{ site.repository }}/issues/2216)) +- Update `rr` link in CONTRIBUTING doc ([#2247]({{ site.repository }}/issues/2247)) +- Streamline Cucumber execution of `jekyll` subcommands ([#2258]({{ site.repository }}/issues/2258)) +- Refactor `Commands::Serve`. ([#2269]({{ site.repository }}/issues/2269)) +- Refactor `highlight` tag ([#2154]({{ site.repository }}/issues/2154)) +- Update `Util` hash functions with latest from Rails ([#2273]({{ site.repository }}/issues/2273)) +- Workaround for Travis bug ([#2290]({{ site.repository }}/issues/2290)) + +### Site Enhancements +{: #site-enhancements-v2-0-0} + +- Document Kramdown's GFM parser option ([#1791]({{ site.repository }}/issues/1791)) +- Move CSS to includes & update normalize.css to v2.1.3 ([#1787]({{ site.repository }}/issues/1787)) +- Minify CSS only in production ([#1803]({{ site.repository }}/issues/1803)) +- Fix broken link to installation of Ruby on Mountain Lion blog post on Troubleshooting docs page ([#1797]({{ site.repository }}/issues/1797)) +- Fix issues with 1.4.1 release blog post ([#1804]({{ site.repository }}/issues/1804)) +- Add note about deploying to OpenShift ([#1812]({{ site.repository }}/issues/1812)) +- Collect all Windows-related docs onto one page ([#1818]({{ site.repository }}/issues/1818)) +- Fixed typo in datafiles doc page ([#1854]({{ site.repository }}/issues/1854)) +- Clarify how to access `site` in docs ([#1864]({{ site.repository }}/issues/1864)) +- Add closing `` tag to `context.registers[:site]` note ([#1867]({{ site.repository }}/issues/1867)) +- Fix link to @mojombo's site source ([#1897]({{ site.repository }}/issues/1897)) +- Add `paginate: nil` to default configuration in docs ([#1896]({{ site.repository }}/issues/1896)) +- Add link to our License in the site footer ([#1889]({{ site.repository }}/issues/1889)) +- Add a charset note in "Writing Posts" doc page ([#1902]({{ site.repository }}/issues/1902)) +- Disallow selection of path and prompt in bash examples +- Add jekyll-compass to the plugin list ([#1923]({{ site.repository }}/issues/1923)) +- Add note in Posts docs about stripping `

` tags from excerpt ([#1933]({{ site.repository }}/issues/1933)) +- Add additional info about the new exclude behavior ([#1938]({{ site.repository }}/issues/1938)) +- Linkify 'awesome contributors' to point to the contributors graph on GitHub ([#1940]({{ site.repository }}/issues/1940)) +- Update `docs/sites.md` link to GitHub Training materials ([#1949]({{ site.repository }}/issues/1949)) +- Update `master` with the release info from 1.4.3 ([#1947]({{ site.repository }}/issues/1947)) +- Define docs nav in datafile ([#1953]({{ site.repository }}/issues/1953)) +- Clarify the docs around the naming convention for posts ([#1971]({{ site.repository }}/issues/1971)) +- Add missing `next` and `previous` docs for post layouts and templates ([#1970]({{ site.repository }}/issues/1970)) +- Add note to `Writing posts` page about how to strip html from excerpt ([#1962]({{ site.repository }}/issues/1962)) +- Add `jekyll-humanize` plugin to plugin list ([#1998]({{ site.repository }}/issues/1998)) +- Add `jekyll-font-awesome` plugin to plugin list ([#1999]({{ site.repository }}/issues/1999)) +- Add `sublime-jekyll` to list of Editor plugins ([#2001]({{ site.repository }}/issues/2001)) +- Add `vim-jekyll` to the list of Editor plugins ([#2005]({{ site.repository }}/issues/2005)) +- Fix non-semantic nesting of `p` tags in `news_item` layout ([#2013]({{ site.repository }}/issues/2013)) +- Document destination folder cleaning ([#2016]({{ site.repository }}/issues/2016)) +- Updated instructions for NearlyFreeSpeech.NET installation ([#2015]({{ site.repository }}/issues/2015)) +- Update link to rack-jekyll on "Deployment Methods" page ([#2047]({{ site.repository }}/issues/2047)) +- Fix typo in /docs/configuration ([#2073]({{ site.repository }}/issues/2073)) +- Fix count in docs for `site.static_files` ([#2077]({{ site.repository }}/issues/2077)) +- Update configuration docs to indicate utf-8 is the default for 2.0.0 and ASCII for 1.9.3 ([#2074]({{ site.repository }}/issues/2074)) +- Add info about unreleased feature to the site ([#2061]({{ site.repository }}/issues/2061)) +- Add whitespace to liquid example in GitHub Pages docs ([#2084]({{ site.repository }}/issues/2084)) +- Clarify the way Sass and CoffeeScript files are read in and output ([#2067]({{ site.repository }}/issues/2067)) +- Add lyche gallery tag plugin link to list of plugins ([#2094]({{ site.repository }}/issues/2094)) +- Add Jekyll Pages Directory plugin to list of plugins ([#2096]({{ site.repository }}/issues/2096)) +- Update Configuration docs page with new markdown extension ([#2102]({{ site.repository }}/issues/2102)) +- Add `jekyll-image-set` to the list of third-party plugins ([#2105]({{ site.repository }}/issues/2105)) +- Losslessly compress images ([#2128]({{ site.repository }}/issues/2128)) +- Update normalize.css to 3.0.0 ([#2126]({{ site.repository }}/issues/2126)) +- Update modernizr to v2.7.1 ([#2129]({{ site.repository }}/issues/2129)) +- Add `jekyll-ordinal` to list of third-party plugins ([#2150]({{ site.repository }}/issues/2150)) +- Add `jekyll_figure` to list of third-party plugins ([#2158]({{ site.repository }}/issues/2158)) +- Clarify the documentation for safe mode ([#2163]({{ site.repository }}/issues/2163)) +- Some HTML tidying ([#2130]({{ site.repository }}/issues/2130)) +- Remove modernizr and use html5shiv.js directly for IE less than v9 ([#2131]({{ site.repository }}/issues/2131)) +- Remove unused images ([#2187]({{ site.repository }}/issues/2187)) +- Use `array_to_sentence_string` filter when outputting news item categories ([#2191]({{ site.repository }}/issues/2191)) +- Add link to Help repo in primary navigation bar ([#2177]({{ site.repository }}/issues/2177)) +- Switch to using an ico file for the shortcut icon ([#2193]({{ site.repository }}/issues/2193)) +- Use numbers to specify font weights and only bring in font weights used ([#2185]({{ site.repository }}/issues/2185)) +- Add a link to the list of all tz database time zones ([#1824]({{ site.repository }}/issues/1824)) +- Clean-up and improve documentation `feed.xml` ([#2192]({{ site.repository }}/issues/2192)) +- Remove duplicate entry in list of third-party plugins ([#2206]({{ site.repository }}/issues/2206)) +- Reduce the whitespace in the favicon. ([#2213]({{ site.repository }}/issues/2213)) +- Add `jekyll-page-collections` to list of third-party plugins ([#2215]({{ site.repository }}/issues/2215)) +- Add a cross-reference about `post_url` ([#2243]({{ site.repository }}/issues/2243)) +- Add `jekyll-live-tiles` to list of third-party plugins ([#2250]({{ site.repository }}/issues/2250)) +- Fixed broken link to GitHub training material site source ([#2257]({{ site.repository }}/issues/2257)) +- Update link to help repo, now called `jekyll-help` ([#2277]({{ site.repository }}/issues/2277)) +- Fix capitalization of 'Jekyll' on Deployment Methods page ([#2291]({{ site.repository }}/issues/2291)) +- Include plugins by sonnym in list of third-party plugins ([#2297]({{ site.repository }}/issues/2297)) +- Add deprecated articles keeper filter to list of third-party plugins ([#2300]({{ site.repository }}/issues/2300)) +- Simplify and improve our CSS. ([#2127]({{ site.repository }}/issues/2127)) +- Use black text color for the mobile navbar ([#2306]({{ site.repository }}/issues/2306)) +- Use the built in date filter and `site.time` for the copyright year. ([#2305]({{ site.repository }}/issues/2305)) +- Update html5shiv to v3.7.2 ([#2304]({{ site.repository }}/issues/2304)) +- Add 2.0.0 release post ([#2298]({{ site.repository }}/issues/2298)) +- Add docs for custom markdown processors ([#2298]({{ site.repository }}/issues/2298)) +- Add docs for `where` and `group_by` Liquid filters ([#2298]({{ site.repository }}/issues/2298)) +- Remove notes in docs for unreleased features ([#2309]({{ site.repository }}/issues/2309)) + + +## 1.5.1 / 2014-03-27 +{: #v1-5-1} + +### Bug Fixes +{: #bug-fixes-v1-5-1} + +- Only strip the drive name if it begins the string ([#2176]({{ site.repository }}/issues/2176)) + + +## 1.5.0 / 2014-03-24 +{: #v1-5-0} + +### Minor Enhancements +{: #minor-enhancements-v1-5-0} + +- Loosen `safe_yaml` dependency to `~> 1.0` ([#2167]({{ site.repository }}/issues/2167)) +- Bump `safe_yaml` dependency to `~> 1.0.0` ([#1942]({{ site.repository }}/issues/1942)) + +### Bug Fixes +{: #bug-fixes-v1-5-0} + +- Fix issue where filesystem traversal restriction broke Windows ([#2167]({{ site.repository }}/issues/2167)) +- Lock `maruku` at `0.7.0` ([#2167]({{ site.repository }}/issues/2167)) + +### Development Fixes +{: #development-fixes-v1-5-0} + +- Lock `cucumber` at `1.3.11` ([#2167]({{ site.repository }}/issues/2167)) + + +## 1.4.3 / 2014-01-13 +{: #v1-4-3} + +### Bug Fixes +{: #bug-fixes-v1-4-3} + +- Patch show-stopping security vulnerabilities ([#1944]({{ site.repository }}/issues/1944)) + + +## 1.4.2 / 2013-12-16 +{: #v1-4-2} + +### Bug Fixes +{: #bug-fixes-v1-4-2} + +- Turn on Maruku fenced code blocks by default ([#1830]({{ site.repository }}/issues/1830)) + + +## 1.4.1 / 2013-12-09 +{: #v1-4-1} + +### Bug Fixes +{: #bug-fixes-v1-4-1} + +- Don't allow nil entries when loading posts ([#1796]({{ site.repository }}/issues/1796)) + + +## 1.4.0 / 2013-12-07 +{: #v1-4-0} + +### Major Enhancements +{: #major-enhancements-v1-4-0} + +- Add support for TOML config files ([#1765]({{ site.repository }}/issues/1765)) + +### Minor Enhancements +{: #minor-enhancements-v1-4-0} + +- Sort plugins as a way to establish a load order ([#1682]({{ site.repository }}/issues/1682)) +- Update Maruku to 0.7.0 ([#1775]({{ site.repository }}/issues/1775)) + +### Bug Fixes +{: #bug-fixes-v1-4-0} + +- Add a space between two words in a Pagination warning message ([#1769]({{ site.repository }}/issues/1769)) +- Upgrade `toml` gem to `v0.1.0` to maintain compat with Ruby 1.8.7 ([#1778]({{ site.repository }}/issues/1778)) + +### Development Fixes +{: #development-fixes-v1-4-0} + +- Remove some whitespace in the code ([#1755]({{ site.repository }}/issues/1755)) +- Remove some duplication in the reading of posts and drafts ([#1779]({{ site.repository }}/issues/1779)) + +### Site Enhancements +{: #site-enhancements-v1-4-0} + +- Fixed case of a word in the Jekyll v1.3.0 release post ([#1762]({{ site.repository }}/issues/1762)) +- Fixed the mime type for the favicon ([#1772]({{ site.repository }}/issues/1772)) + + +## 1.3.1 / 2013-11-26 +{: #v1-3-1} + +### Minor Enhancements +{: #minor-enhancements-v1-3-1} + +- Add a `--prefix` option to passthrough for the importers ([#1669]({{ site.repository }}/issues/1669)) +- Push the paginator plugin lower in the plugin priority order so other plugins run before it ([#1759]({{ site.repository }}/issues/1759)) + +### Bug Fixes +{: #bug-fixes-v1-3-1} + +- Fix the include tag when ran in a loop ([#1726]({{ site.repository }}/issues/1726)) +- Fix errors when using `--watch` on 1.8.7 ([#1730]({{ site.repository }}/issues/1730)) +- Specify where the include is called from if an included file is missing ([#1746]({{ site.repository }}/issues/1746)) + +### Development Fixes +{: #development-fixes-v1-3-1} + +- Extract `Site#filter_entries` into its own object ([#1697]({{ site.repository }}/issues/1697)) +- Enable Travis' bundle caching ([#1734]({{ site.repository }}/issues/1734)) +- Remove trailing whitespace in some files ([#1736]({{ site.repository }}/issues/1736)) +- Fix a duplicate test name ([#1754]({{ site.repository }}/issues/1754)) + +### Site Enhancements +{: #site-enhancements-v1-3-1} + +- Update link to example Rakefile to point to specific commit ([#1741]({{ site.repository }}/issues/1741)) +- Fix drafts docs to indicate that draft time is based on file modification time, not `Time.now` ([#1695]({{ site.repository }}/issues/1695)) +- Add `jekyll-monthly-archive-plugin` and `jekyll-category-archive-plugin` to list of third-party plugins ([#1693]({{ site.repository }}/issues/1693)) +- Add `jekyll-asset-path-plugin` to list of third-party plugins ([#1670]({{ site.repository }}/issues/1670)) +- Add `emoji-for-jekyll` to list of third-part plugins ([#1708]({{ site.repository }}/issues/1708)) +- Fix previous section link on plugins page to point to pagination page ([#1707]({{ site.repository }}/issues/1707)) +- Add `org-mode` converter plugin to third-party plugins ([#1711]({{ site.repository }}/issues/1711)) +- Point "Blog migrations" page to http://import.jekyllrb.com ([#1732]({{ site.repository }}/issues/1732)) +- Add docs for `post_url` when posts are in subdirectories ([#1718]({{ site.repository }}/issues/1718)) +- Update the docs to point to `example.com` ([#1448]({{ site.repository }}/issues/1448)) + + +## 1.3.0 / 2013-11-04 +{: #v1-3-0} + +### Major Enhancements +{: #major-enhancements-v1-3-0} + +- Add support for adding data as YAML files under a site's `_data` directory ([#1003]({{ site.repository }}/issues/1003)) +- Allow variables to be used with `include` tags ([#1495]({{ site.repository }}/issues/1495)) +- Allow using gems for plugin management ([#1557]({{ site.repository }}/issues/1557)) + +### Minor Enhancements +{: #minor-enhancements-v1-3-0} + +- Decrease the specificity in the site template CSS ([#1574]({{ site.repository }}/issues/1574)) +- Add `encoding` configuration option ([#1449]({{ site.repository }}/issues/1449)) +- Provide better error handling for Jekyll's custom Liquid tags ([#1514]({{ site.repository }}/issues/1514)) +- If an included file causes a Liquid error, add the path to the include file that caused the error to the error message ([#1596]({{ site.repository }}/issues/1596)) +- If a layout causes a Liquid error, change the error message so that we know it comes from the layout ([#1601]({{ site.repository }}/issues/1601)) +- Update Kramdown dependency to `~> 1.2` ([#1610]({{ site.repository }}/issues/1610)) +- Update `safe_yaml` dependency to `~> 0.9.7` ([#1602]({{ site.repository }}/issues/1602)) +- Allow layouts to be in subfolders like includes ([#1622]({{ site.repository }}/issues/1622)) +- Switch to listen for site watching while serving ([#1589]({{ site.repository }}/issues/1589)) +- Add a `json` liquid filter to be used in sites ([#1651]({{ site.repository }}/issues/1651)) +- Point people to the migration docs when the `jekyll-import` gem is missing ([#1662]({{ site.repository }}/issues/1662)) + +### Bug Fixes +{: #bug-fixes-v1-3-0} + +- Fix up matching against source and destination when the two locations are similar ([#1556]({{ site.repository }}/issues/1556)) +- Fix the missing `pathname` require in certain cases ([#1255]({{ site.repository }}/issues/1255)) +- Use `+` instead of `Array#concat` when building `Post` attribute list ([#1571]({{ site.repository }}/issues/1571)) +- Print server address when launching a server ([#1586]({{ site.repository }}/issues/1586)) +- Downgrade to Maruku `~> 0.6.0` in order to avoid changes in rendering ([#1598]({{ site.repository }}/issues/1598)) +- Fix error with failing include tag when variable was file name ([#1613]({{ site.repository }}/issues/1613)) +- Downcase lexers before passing them to pygments ([#1615]({{ site.repository }}/issues/1615)) +- Capitalize the short verbose switch because it conflicts with the built-in Commander switch ([#1660]({{ site.repository }}/issues/1660)) +- Fix compatibility with 1.8.x ([#1665]({{ site.repository }}/issues/1665)) +- Fix an error with the new file watching code due to library version incompatibilities ([#1687]({{ site.repository }}/issues/1687)) + +### Development Fixes +{: #development-fixes-v1-3-0} + +- Add coverage reporting with Coveralls ([#1539]({{ site.repository }}/issues/1539)) +- Refactor the Liquid `include` tag ([#1490]({{ site.repository }}/issues/1490)) +- Update launchy dependency to `~> 2.3` ([#1608]({{ site.repository }}/issues/1608)) +- Update rr dependency to `~> 1.1` ([#1604]({{ site.repository }}/issues/1604)) +- Update cucumber dependency to `~> 1.3` ([#1607]({{ site.repository }}/issues/1607)) +- Update coveralls dependency to `~> 0.7.0` ([#1606]({{ site.repository }}/issues/1606)) +- Update rake dependency to `~> 10.1` ([#1603]({{ site.repository }}/issues/1603)) +- Clean up `site.rb` comments to be more concise/uniform ([#1616]({{ site.repository }}/issues/1616)) +- Use the master branch for the build badge in the readme ([#1636]({{ site.repository }}/issues/1636)) +- Refactor Site#render ([#1638]({{ site.repository }}/issues/1638)) +- Remove duplication in command line options ([#1637]({{ site.repository }}/issues/1637)) +- Add tests for all the coderay options ([#1543]({{ site.repository }}/issues/1543)) +- Improve some of the Cucumber test code ([#1493]({{ site.repository }}/issues/1493)) +- Improve comparisons of timestamps by ignoring the seconds ([#1582]({{ site.repository }}/issues/1582)) + +### Site Enhancements +{: #site-enhancements-v1-3-0} + +- Fix params for `JekyllImport::WordPress.process` arguments ([#1554]({{ site.repository }}/issues/1554)) +- Add `jekyll-suggested-tweet` to list of third-party plugins ([#1555]({{ site.repository }}/issues/1555)) +- Link to Liquid's docs for tags and filters ([#1553]({{ site.repository }}/issues/1553)) +- Add note about installing Xcode on the Mac in the Installation docs ([#1561]({{ site.repository }}/issues/1561)) +- Simplify/generalize pagination docs ([#1577]({{ site.repository }}/issues/1577)) +- Add documentation for the new data sources feature ([#1503]({{ site.repository }}/issues/1503)) +- Add more information on how to create generators ([#1590]({{ site.repository }}/issues/1590), [#1592]({{ site.repository }}/issues/1592)) +- Improve the instructions for mimicking GitHub Flavored Markdown ([#1614]({{ site.repository }}/issues/1614)) +- Add `jekyll-import` warning note of missing dependencies ([#1626]({{ site.repository }}/issues/1626)) +- Fix grammar in the Usage section ([#1635]({{ site.repository }}/issues/1635)) +- Add documentation for the use of gems as plugins ([#1656]({{ site.repository }}/issues/1656)) +- Document the existence of a few additional plugins ([#1405]({{ site.repository }}/issues/1405)) +- Document that the `date_to_string` always returns a two digit day ([#1663]({{ site.repository }}/issues/1663)) +- Fix navigation in the "Working with Drafts" page ([#1667]({{ site.repository }}/issues/1667)) +- Fix an error with the data documentation ([#1691]({{ site.repository }}/issues/1691)) + + +## 1.2.1 / 2013-09-14 +{: #v1-2-1} + +### Minor Enhancements +{: #minor-enhancements-v1-2-1} + +- Print better messages for detached server. Mute output on detach. ([#1518]({{ site.repository }}/issues/1518)) +- Disable reverse lookup when running `jekyll serve` ([#1363]({{ site.repository }}/issues/1363)) +- Upgrade RedCarpet dependency to `~> 2.3.0` ([#1515]({{ site.repository }}/issues/1515)) +- Upgrade to Liquid `>= 2.5.2, < 2.6` ([#1536]({{ site.repository }}/issues/1536)) + +### Bug Fixes +{: #bug-fixes-v1-2-1} + +- Fix file discrepancy in gemspec ([#1522]({{ site.repository }}/issues/1522)) +- Force rendering of Include tag ([#1525]({{ site.repository }}/issues/1525)) + +### Development Fixes +{: #development-fixes-v1-2-1} + +- Add a rake task to generate a new release post ([#1404]({{ site.repository }}/issues/1404)) +- Mute LSI output in tests ([#1531]({{ site.repository }}/issues/1531)) +- Update contributor documentation ([#1537]({{ site.repository }}/issues/1537)) + +### Site Enhancements +{: #site-enhancements-v1-2-1} + +- Fix a couple of validation errors on the site ([#1511]({{ site.repository }}/issues/1511)) +- Make navigation menus reusable ([#1507]({{ site.repository }}/issues/1507)) +- Fix link to History page from Release v1.2.0 notes post. +- Fix markup in History file for command line options ([#1512]({{ site.repository }}/issues/1512)) +- Expand 1.2 release post title to 1.2.0 ([#1516]({{ site.repository }}/issues/1516)) + + +## 1.2.0 / 2013-09-06 +{: #v1-2-0} + +### Major Enhancements +{: #major-enhancements-v1-2-0} + +- Disable automatically-generated excerpts when `excerpt_separator` is `""`. ([#1386]({{ site.repository }}/issues/1386)) +- Add checking for URL conflicts when running `jekyll doctor` ([#1389]({{ site.repository }}/issues/1389)) + +### Minor Enhancements +{: #minor-enhancements-v1-2-0} + +- Catch and fix invalid `paginate` values ([#1390]({{ site.repository }}/issues/1390)) +- Remove superfluous `div.container` from the default html template for `jekyll new` ([#1315]({{ site.repository }}/issues/1315)) +- Add `-D` short-form switch for the drafts option ([#1394]({{ site.repository }}/issues/1394)) +- Update the links in the site template for Twitter and GitHub ([#1400]({{ site.repository }}/issues/1400)) +- Update dummy email address to example.com domain ([#1408]({{ site.repository }}/issues/1408)) +- Update normalize.css to v2.1.2 and minify; add rake task to update normalize.css with greater ease. ([#1430]({{ site.repository }}/issues/1430)) +- Add the ability to detach the server ran by `jekyll serve` from it's controlling terminal ([#1443]({{ site.repository }}/issues/1443)) +- Improve permalink generation for URLs with special characters ([#944]({{ site.repository }}/issues/944)) +- Expose the current Jekyll version to posts and pages via a new `jekyll.version` variable ([#1481]({{ site.repository }}/issues/1481)) + +### Bug Fixes +{: #bug-fixes-v1-2-0} + +- Markdown extension matching matches only exact matches ([#1382]({{ site.repository }}/issues/1382)) +- Fixed NoMethodError when message passed to `Stevenson#message` is nil ([#1388]({{ site.repository }}/issues/1388)) +- Use binary mode when writing file ([#1364]({{ site.repository }}/issues/1364)) +- Fix 'undefined method `encoding` for "mailto"' errors w/ Ruby 1.8 and Kramdown > 0.14.0 ([#1397]({{ site.repository }}/issues/1397)) +- Do not force the permalink to be a dir if it ends on .html ([#963]({{ site.repository }}/issues/963)) +- When a Liquid Exception is caught, show the full path rel. to site source ([#1415]({{ site.repository }}/issues/1415)) +- Properly read in the config options when serving the docs locally ([#1444]({{ site.repository }}/issues/1444)) +- Fixed `--layouts` option for `build` and `serve` commands ([#1458]({{ site.repository }}/issues/1458)) +- Remove kramdown as a runtime dependency since it's optional ([#1498]({{ site.repository }}/issues/1498)) +- Provide proper error handling for invalid file names in the include tag ([#1494]({{ site.repository }}/issues/1494)) + +### Development Fixes +{: #development-fixes-v1-2-0} + +- Remove redundant argument to Jekyll::Commands::New#scaffold_post_content ([#1356]({{ site.repository }}/issues/1356)) +- Add new dependencies to the README ([#1360]({{ site.repository }}/issues/1360)) +- Fix link to contributing page in README ([#1424]({{ site.repository }}/issues/1424)) +- Update TomDoc in Pager#initialize to match params ([#1441]({{ site.repository }}/issues/1441)) +- Refactor `Site#cleanup` into `Jekyll::Site::Cleaner` class ([#1429]({{ site.repository }}/issues/1429)) +- Several other small minor refactorings ([#1341]({{ site.repository }}/issues/1341)) +- Ignore `_site` in jekyllrb.com deploy ([#1480]({{ site.repository }}/issues/1480)) +- Add Gem version and dependency badge to README ([#1497]({{ site.repository }}/issues/1497)) + +### Site Enhancements +{: #site-enhancements-v1-2-0} + +- Add info about new releases ([#1353]({{ site.repository }}/issues/1353)) +- Update plugin list with jekyll-rss plugin ([#1354]({{ site.repository }}/issues/1354)) +- Update the site list page with Ruby's official site ([#1358]({{ site.repository }}/issues/1358)) +- Add `jekyll-ditaa` to list of third-party plugins ([#1370]({{ site.repository }}/issues/1370)) +- Add `postfiles` to list of third-party plugins ([#1373]({{ site.repository }}/issues/1373)) +- For internal links, use full path including trailing `/` ([#1411]({{ site.repository }}/issues/1411)) +- Use curly apostrophes in the docs ([#1419]({{ site.repository }}/issues/1419)) +- Update the docs for Redcarpet in Jekyll ([#1418]({{ site.repository }}/issues/1418)) +- Add `pluralize` and `reading_time` filters to docs ([#1439]({{ site.repository }}/issues/1439)) +- Fix markup for the Kramdown options ([#1445]({{ site.repository }}/issues/1445)) +- Fix typos in the History file ([#1454]({{ site.repository }}/issues/1454)) +- Add trailing slash to site's post URL ([#1462]({{ site.repository }}/issues/1462)) +- Clarify that `--config` will take multiple files ([#1474]({{ site.repository }}/issues/1474)) +- Fix docs/templates.md private gist example ([#1477]({{ site.repository }}/issues/1477)) +- Use `site.repository` for Jekyll's GitHub URL ([#1463]({{ site.repository }}/issues/1463)) +- Add `jekyll-pageless-redirects` to list of third-party plugins ([#1486]({{ site.repository }}/issues/1486)) +- Clarify that `date_to_xmlschema` returns an ISO 8601 string ([#1488]({{ site.repository }}/issues/1488)) +- Add `jekyll-good-include` to list of third-party plugins ([#1491]({{ site.repository }}/issues/1491)) +- XML escape the blog post title in our feed ([#1501]({{ site.repository }}/issues/1501)) +- Add `jekyll-toc-generator` to list of third-party plugins ([#1506]({{ site.repository }}/issues/1506)) + + +## 1.1.2 / 2013-07-25 +{: #v1-1-2} + +### Bug Fixes +{: #bug-fixes-v1-1-2} + +- Require Liquid 2.5.1 ([#1349]({{ site.repository }}/issues/1349)) + + +## 1.1.1 / 2013-07-24 +{: #v1-1-1} + +### Minor Enhancements +{: #minor-enhancements-v1-1-1} + +- Remove superfluous `table` selector from main.css in `jekyll new` template ([#1328]({{ site.repository }}/issues/1328)) +- Abort with non-zero exit codes ([#1338]({{ site.repository }}/issues/1338)) + +### Bug Fixes +{: #bug-fixes-v1-1-1} + +- Fix up the rendering of excerpts ([#1339]({{ site.repository }}/issues/1339)) + +### Site Enhancements +{: #site-enhancements-v1-1-1} + +- Add Jekyll Image Tag to the plugins list ([#1306]({{ site.repository }}/issues/1306)) +- Remove erroneous statement that `site.pages` are sorted alphabetically. +- Add info about the `_drafts` directory to the directory structure docs ([#1320]({{ site.repository }}/issues/1320)) +- Improve the layout of the plugin listing by organizing it into categories ([#1310]({{ site.repository }}/issues/1310)) +- Add generator-jekyllrb and grunt-jekyll to plugins page ([#1330]({{ site.repository }}/issues/1330)) +- Mention Kramdown as option for markdown parser on Extras page ([#1318]({{ site.repository }}/issues/1318)) +- Update Quick-Start page to include reminder that all requirements must be installed ([#1327]({{ site.repository }}/issues/1327)) +- Change filename in `include` example to an HTML file so as not to indicate that Jekyll will automatically convert them. ([#1303]({{ site.repository }}/issues/1303)) +- Add an RSS feed for commits to Jekyll ([#1343]({{ site.repository }}/issues/1343)) + + +## 1.1.0 / 2013-07-14 +{: #v1-1-0} + +### Major Enhancements +{: #major-enhancements-v1-1-0} + +- Add `docs` subcommand to read Jekyll's docs when offline. ([#1046]({{ site.repository }}/issues/1046)) +- Support passing parameters to templates in `include` tag ([#1204]({{ site.repository }}/issues/1204)) +- Add support for Liquid tags to post excerpts ([#1302]({{ site.repository }}/issues/1302)) + +### Minor Enhancements +{: #minor-enhancements-v1-1-0} + +- Search the hierarchy of pagination path up to site root to determine template page for pagination. ([#1198]({{ site.repository }}/issues/1198)) +- Add the ability to generate a new Jekyll site without a template ([#1171]({{ site.repository }}/issues/1171)) +- Use redcarpet as the default markdown engine in newly generated sites ([#1245]({{ site.repository }}/issues/1245), [#1247]({{ site.repository }}/issues/1247)) +- Add `redcarpet` as a runtime dependency so `jekyll build` works out-of-the-box for new sites. ([#1247]({{ site.repository }}/issues/1247)) +- In the generated site, remove files that will be replaced by a directory ([#1118]({{ site.repository }}/issues/1118)) +- Fail loudly if a user-specified configuration file doesn't exist ([#1098]({{ site.repository }}/issues/1098)) +- Allow for all options for Kramdown HTML Converter ([#1201]({{ site.repository }}/issues/1201)) + +### Bug Fixes +{: #bug-fixes-v1-1-0} + +- Fix pagination in subdirectories. ([#1198]({{ site.repository }}/issues/1198)) +- Fix an issue with directories and permalinks that have a plus sign (+) in them ([#1215]({{ site.repository }}/issues/1215)) +- Provide better error reporting when generating sites ([#1253]({{ site.repository }}/issues/1253)) +- Latest posts first in non-LSI `related_posts` ([#1271]({{ site.repository }}/issues/1271)) + +### Development Fixes +{: #development-fixes-v1-1-0} + +- Merge the theme and layout Cucumber steps into one step ([#1151]({{ site.repository }}/issues/1151)) +- Restrict activesupport dependency to pre-4.0.0 to maintain compatibility with `<= 1.9.2` +- Include/exclude deprecation handling simplification ([#1284]({{ site.repository }}/issues/1284)) +- Convert README to Markdown. ([#1267]({{ site.repository }}/issues/1267)) +- Refactor Jekyll::Site ([#1144]({{ site.repository }}/issues/1144)) + +### Site Enhancements +{: #site-enhancements-v1-1-0} + +- Add "News" section for release notes, along with an RSS feed ([#1093]({{ site.repository }}/issues/1093), [#1285]({{ site.repository }}/issues/1285), [#1286]({{ site.repository }}/issues/1286)) +- Add "History" page. +- Restructured docs sections to include "Meta" section. +- Add message to "Templates" page that specifies that Python must be installed in order to use Pygments. ([#1182]({{ site.repository }}/issues/1182)) +- Update link to the official Maruku repo ([#1175]({{ site.repository }}/issues/1175)) +- Add documentation about `paginate_path` to "Templates" page in docs ([#1129]({{ site.repository }}/issues/1129)) +- Give the quick-start guide its own page ([#1191]({{ site.repository }}/issues/1191)) +- Update ProTip on Installation page in docs to point to all the info about Pygments and the 'highlight' tag. ([#1196]({{ site.repository }}/issues/1196)) +- Run `site/img` through ImageOptim (thanks @qrush!) ([#1208]({{ site.repository }}/issues/1208)) +- Added Jade Converter to `site/docs/plugins` ([#1210]({{ site.repository }}/issues/1210)) +- Fix location of docs pages in Contributing pages ([#1214]({{ site.repository }}/issues/1214)) +- Add ReadInXMinutes plugin to the plugin list ([#1222]({{ site.repository }}/issues/1222)) +- Remove plugins from the plugin list that have equivalents in Jekyll proper ([#1223]({{ site.repository }}/issues/1223)) +- Add jekyll-assets to the plugin list ([#1225]({{ site.repository }}/issues/1225)) +- Add jekyll-pandoc-multiple-formats to the plugin list ([#1229]({{ site.repository }}/issues/1229)) +- Remove dead link to "Using Git to maintain your blog" ([#1227]({{ site.repository }}/issues/1227)) +- Tidy up the third-party plugins listing ([#1228]({{ site.repository }}/issues/1228)) +- Update contributor information ([#1192]({{ site.repository }}/issues/1192)) +- Update URL of article about Blogger migration ([#1242]({{ site.repository }}/issues/1242)) +- Specify that RedCarpet is the default for new Jekyll sites on Quickstart page ([#1247]({{ site.repository }}/issues/1247)) +- Added `site.pages` to Variables page in docs ([#1251]({{ site.repository }}/issues/1251)) +- Add Youku and Tudou Embed link on Plugins page. ([#1250]({{ site.repository }}/issues/1250)) +- Add note that `gist` tag supports private gists. ([#1248]({{ site.repository }}/issues/1248)) +- Add `jekyll-timeago` to list of third-party plugins. ([#1260]({{ site.repository }}/issues/1260)) +- Add `jekyll-swfobject` to list of third-party plugins. ([#1263]({{ site.repository }}/issues/1263)) +- Add `jekyll-picture-tag` to list of third-party plugins. ([#1280]({{ site.repository }}/issues/1280)) +- Update the GitHub Pages documentation regarding relative URLs ([#1291]({{ site.repository }}/issues/1291)) +- Update the S3 deployment documentation ([#1294]({{ site.repository }}/issues/1294)) +- Add suggestion for Xcode CLT install to troubleshooting page in docs ([#1296]({{ site.repository }}/issues/1296)) +- Add 'Working with drafts' page to docs ([#1289]({{ site.repository }}/issues/1289)) +- Add information about time zones to the documentation for a page's date ([#1304]({{ site.repository }}/issues/1304)) + + +## 1.0.3 / 2013-06-07 +{: #v1-0-3} + +### Minor Enhancements +{: #minor-enhancements-v1-0-3} + +- Add support to gist tag for private gists. ([#1189]({{ site.repository }}/issues/1189)) +- Fail loudly when Maruku errors out ([#1190]({{ site.repository }}/issues/1190)) +- Move the building of related posts into their own class ([#1057]({{ site.repository }}/issues/1057)) +- Removed trailing spaces in several places throughout the code ([#1116]({{ site.repository }}/issues/1116)) +- Add a `--force` option to `jekyll new` ([#1115]({{ site.repository }}/issues/1115)) +- Convert IDs in the site template to classes ([#1170]({{ site.repository }}/issues/1170)) + +### Bug Fixes +{: #bug-fixes-v1-0-3} + +- Fix typo in Stevenson constant "ERROR". ([#1166]({{ site.repository }}/issues/1166)) +- Rename Jekyll::Logger to Jekyll::Stevenson to fix inheritance issue ([#1106]({{ site.repository }}/issues/1106)) +- Exit with a non-zero exit code when dealing with a Liquid error ([#1121]({{ site.repository }}/issues/1121)) +- Make the `exclude` and `include` options backwards compatible with versions of Jekyll prior to 1.0 ([#1114]({{ site.repository }}/issues/1114)) +- Fix pagination on Windows ([#1063]({{ site.repository }}/issues/1063)) +- Fix the application of Pygments' Generic Output style to Go code ([#1156]({{ site.repository }}/issues/1156)) + +### Site Enhancements +{: #site-enhancements-v1-0-3} + +- Add a Pro Tip to docs about front matter variables being optional ([#1147]({{ site.repository }}/issues/1147)) +- Add changelog to site as History page in /docs/ ([#1065]({{ site.repository }}/issues/1065)) +- Add note to Upgrading page about new config options in 1.0.x ([#1146]({{ site.repository }}/issues/1146)) +- Documentation for `date_to_rfc822` and `uri_escape` ([#1142]({{ site.repository }}/issues/1142)) +- Documentation highlight boxes shouldn't show scrollbars if not necessary ([#1123]({{ site.repository }}/issues/1123)) +- Add link to jekyll-minibundle in the doc's plugins list ([#1035]({{ site.repository }}/issues/1035)) +- Quick patch for importers documentation +- Fix prefix for WordpressDotCom importer in docs ([#1107]({{ site.repository }}/issues/1107)) +- Add jekyll-contentblocks plugin to docs ([#1068]({{ site.repository }}/issues/1068)) +- Make code bits in notes look more natural, more readable ([#1089]({{ site.repository }}/issues/1089)) +- Fix logic for `relative_permalinks` instructions on Upgrading page ([#1101]({{ site.repository }}/issues/1101)) +- Add docs for post excerpt ([#1072]({{ site.repository }}/issues/1072)) +- Add docs for gist tag ([#1072]({{ site.repository }}/issues/1072)) +- Add docs indicating that Pygments does not need to be installed separately ([#1099]({{ site.repository }}/issues/1099), [#1119]({{ site.repository }}/issues/1119)) +- Update the migrator docs to be current ([#1136]({{ site.repository }}/issues/1136)) +- Add the Jekyll Gallery Plugin to the plugin list ([#1143]({{ site.repository }}/issues/1143)) + +### Development Fixes +{: #development-fixes-v1-0-3} + +- Use Jekyll.logger instead of Jekyll::Stevenson to log things ([#1149]({{ site.repository }}/issues/1149)) +- Fix pesky Cucumber infinite loop ([#1139]({{ site.repository }}/issues/1139)) +- Do not write posts with timezones in Cucumber tests ([#1124]({{ site.repository }}/issues/1124)) +- Use ISO formatted dates in Cucumber features ([#1150]({{ site.repository }}/issues/1150)) + + +## 1.0.2 / 2013-05-12 +{: #v1-0-2} + +### Major Enhancements +{: #major-enhancements-v1-0-2} + +- Add `jekyll doctor` command to check site for any known compatibility problems ([#1081]({{ site.repository }}/issues/1081)) +- Backwards-compatibilize relative permalinks ([#1081]({{ site.repository }}/issues/1081)) + +### Minor Enhancements +{: #minor-enhancements-v1-0-2} + +- Add a `data-lang=""` attribute to Redcarpet code blocks ([#1066]({{ site.repository }}/issues/1066)) +- Deprecate old config `server_port`, match to `port` if `port` isn't set ([#1084]({{ site.repository }}/issues/1084)) +- Update pygments.rb version to 0.5.0 ([#1061]({{ site.repository }}/issues/1061)) +- Update Kramdown version to 1.0.2 ([#1067]({{ site.repository }}/issues/1067)) + +### Bug Fixes +{: #bug-fixes-v1-0-2} + +- Fix issue when categories are numbers ([#1078]({{ site.repository }}/issues/1078)) +- Catching that Redcarpet gem isn't installed ([#1059]({{ site.repository }}/issues/1059)) + +### Site Enhancements +{: #site-enhancements-v1-0-2} + +- Add documentation about `relative_permalinks` ([#1081]({{ site.repository }}/issues/1081)) +- Remove pygments-installation instructions, as pygments.rb is bundled with it ([#1079]({{ site.repository }}/issues/1079)) +- Move pages to be Pages for realz ([#985]({{ site.repository }}/issues/985)) +- Updated links to Liquid documentation ([#1073]({{ site.repository }}/issues/1073)) + + +## 1.0.1 / 2013-05-08 +{: #v1-0-1} + +### Minor Enhancements +{: #minor-enhancements-v1-0-1} + +- Do not force use of `toc_token` when using `generate_tok` in RDiscount ([#1048]({{ site.repository }}/issues/1048)) +- Add newer `language-` class name prefix to code blocks ([#1037]({{ site.repository }}/issues/1037)) +- Commander error message now preferred over process abort with incorrect args ([#1040]({{ site.repository }}/issues/1040)) + +### Bug Fixes +{: #bug-fixes-v1-0-1} + +- Make Redcarpet respect the pygments configuration option ([#1053]({{ site.repository }}/issues/1053)) +- Fix the index build with LSI ([#1045]({{ site.repository }}/issues/1045)) +- Don't print deprecation warning when no arguments are specified. ([#1041]({{ site.repository }}/issues/1041)) +- Add missing `

` to site template used by `new` subcommand, fixed typos in code ([#1032]({{ site.repository }}/issues/1032)) + +### Site Enhancements +{: #site-enhancements-v1-0-1} + +- Changed https to http in the GitHub Pages link ([#1051]({{ site.repository }}/issues/1051)) +- Remove CSS cruft, fix typos, fix HTML errors ([#1028]({{ site.repository }}/issues/1028)) +- Removing manual install of Pip and Distribute ([#1025]({{ site.repository }}/issues/1025)) +- Updated URL for Markdown references plugin ([#1022]({{ site.repository }}/issues/1022)) + +### Development Fixes +{: #development-fixes-v1-0-1} + +- Markdownify history file ([#1027]({{ site.repository }}/issues/1027)) +- Update links on README to point to new jekyllrb.com ([#1018]({{ site.repository }}/issues/1018)) + + +## 1.0.0 / 2013-05-06 +{: #v1-0-0} + +### Major Enhancements +{: #major-enhancements-v1-0-0} + +- Add `jekyll new` subcommand: generate a Jekyll scaffold ([#764]({{ site.repository }}/issues/764)) +- Refactored Jekyll commands into subcommands: build, serve, and migrate. ([#690]({{ site.repository }}/issues/690)) +- Removed importers/migrators from main project, migrated to jekyll-import sub-gem ([#793]({{ site.repository }}/issues/793)) +- Added ability to render drafts in `_drafts` folder via command line ([#833]({{ site.repository }}/issues/833)) +- Add ordinal date permalink style (/:categories/:year/:y_day/:title.html) ([#928]({{ site.repository }}/issues/928)) + +### Minor Enhancements +{: #minor-enhancements-v1-0-0} + +- Site template HTML5-ified ([#964]({{ site.repository }}/issues/964)) +- Use post's directory path when matching for the `post_url` tag ([#998]({{ site.repository }}/issues/998)) +- Loosen dependency on Pygments so it's only required when it's needed ([#1015]({{ site.repository }}/issues/1015)) +- Parse strings into Time objects for date-related Liquid filters ([#1014]({{ site.repository }}/issues/1014)) +- Tell the user if there is no subcommand specified ([#1008]({{ site.repository }}/issues/1008)) +- Freak out if the destination of `jekyll new` exists and is non-empty ([#981]({{ site.repository }}/issues/981)) +- Add `timezone` configuration option for compilation ([#957]({{ site.repository }}/issues/957)) +- Add deprecation messages for pre-1.0 CLI options ([#959]({{ site.repository }}/issues/959)) +- Refactor and colorize logging ([#959]({{ site.repository }}/issues/959)) +- Refactor Markdown parsing ([#955]({{ site.repository }}/issues/955)) +- Added application/vnd.apple.pkpass to mime.types served by WEBrick ([#907]({{ site.repository }}/issues/907)) +- Move template site to default markdown renderer ([#961]({{ site.repository }}/issues/961)) +- Expose new attribute to Liquid via `page`: `page.path` ([#951]({{ site.repository }}/issues/951)) +- Accept multiple config files from command line ([#945]({{ site.repository }}/issues/945)) +- Add page variable to liquid custom tags and blocks ([#413]({{ site.repository }}/issues/413)) +- Add `paginator.previous_page_path` and `paginator.next_page_path` ([#942]({{ site.repository }}/issues/942)) +- Backwards compatibility for 'auto' ([#821]({{ site.repository }}/issues/821), [#934]({{ site.repository }}/issues/934)) +- Added date_to_rfc822 used on RSS feeds ([#892]({{ site.repository }}/issues/892)) +- Upgrade version of pygments.rb to 0.4.2 ([#927]({{ site.repository }}/issues/927)) +- Added short month (e.g. "Sep") to permalink style options for posts ([#890]({{ site.repository }}/issues/890)) +- Expose site.baseurl to Liquid templates ([#869]({{ site.repository }}/issues/869)) +- Adds excerpt attribute to posts which contains first paragraph of content ([#837]({{ site.repository }}/issues/837)) +- Accept custom configuration file via CLI ([#863]({{ site.repository }}/issues/863)) +- Load in GitHub Pages MIME Types on `jekyll serve` ([#847]({{ site.repository }}/issues/847), [#871]({{ site.repository }}/issues/871)) +- Improve debuggability of error message for a malformed highlight tag ([#785]({{ site.repository }}/issues/785)) +- Allow symlinked files in unsafe mode ([#824]({{ site.repository }}/issues/824)) +- Add 'gist' Liquid tag to core ([#822]({{ site.repository }}/issues/822), [#861]({{ site.repository }}/issues/861)) +- New format of Jekyll output ([#795]({{ site.repository }}/issues/795)) +- Reinstate `--limit_posts` and `--future` switches ([#788]({{ site.repository }}/issues/788)) +- Remove ambiguity from command descriptions ([#815]({{ site.repository }}/issues/815)) +- Fix SafeYAML Warnings ([#807]({{ site.repository }}/issues/807)) +- Relaxed Kramdown version to 0.14 ([#808]({{ site.repository }}/issues/808)) +- Aliased `jekyll server` to `jekyll serve`. ([#792]({{ site.repository }}/issues/792)) +- Updated gem versions for Kramdown, Rake, Shoulda, Cucumber, and RedCarpet. ([#744]({{ site.repository }}/issues/744)) +- Refactored Jekyll subcommands into Jekyll::Commands submodule, which now contains them ([#768]({{ site.repository }}/issues/768)) +- Rescue from import errors in Wordpress.com migrator ([#671]({{ site.repository }}/issues/671)) +- Massively accelerate LSI performance ([#664]({{ site.repository }}/issues/664)) +- Truncate post slugs when importing from Tumblr ([#496]({{ site.repository }}/issues/496)) +- Add glob support to include, exclude option ([#743]({{ site.repository }}/issues/743)) +- Layout of Page or Post defaults to 'page' or 'post', respectively ([#580]({{ site.repository }}/issues/580)) REPEALED by ([#977]({{ site.repository }}/issues/977)) +- "Keep files" feature ([#685]({{ site.repository }}/issues/685)) +- Output full path & name for files that don't parse ([#745]({{ site.repository }}/issues/745)) +- Add source and destination directory protection ([#535]({{ site.repository }}/issues/535)) +- Better YAML error message ([#718]({{ site.repository }}/issues/718)) +- Bug Fixes +- Paginate in subdirectories properly ([#1016]({{ site.repository }}/issues/1016)) +- Ensure post and page URLs have a leading slash ([#992]({{ site.repository }}/issues/992)) +- Catch all exceptions, not just StandardError descendents ([#1007]({{ site.repository }}/issues/1007)) +- Bullet-proof `limit_posts` option ([#1004]({{ site.repository }}/issues/1004)) +- Read in YAML as UTF-8 to accept non-ASCII chars ([#836]({{ site.repository }}/issues/836)) +- Fix the CLI option `--plugins` to actually accept dirs and files ([#993]({{ site.repository }}/issues/993)) +- Allow 'excerpt' in front matter to override the extracted excerpt ([#946]({{ site.repository }}/issues/946)) +- Fix cascade problem with site.baseurl, site.port and site.host. ([#935]({{ site.repository }}/issues/935)) +- Filter out directories with valid post names ([#875]({{ site.repository }}/issues/875)) +- Fix symlinked static files not being correctly built in unsafe mode ([#909]({{ site.repository }}/issues/909)) +- Fix integration with directory_watcher 1.4.x ([#916]({{ site.repository }}/issues/916)) +- Accepting strings as arguments to jekyll-import command ([#910]({{ site.repository }}/issues/910)) +- Force usage of older directory_watcher gem as 1.5 is broken ([#883]({{ site.repository }}/issues/883)) +- Ensure all Post categories are downcase ([#842]({{ site.repository }}/issues/842), [#872]({{ site.repository }}/issues/872)) +- Force encoding of the rdiscount TOC to UTF8 to avoid conversion errors ([#555]({{ site.repository }}/issues/555)) +- Patch for multibyte URI problem with `jekyll serve` ([#723]({{ site.repository }}/issues/723)) +- Order plugin execution by priority ([#864]({{ site.repository }}/issues/864)) +- Fixed Page#dir and Page#url for edge cases ([#536]({{ site.repository }}/issues/536)) +- Fix broken `post_url` with posts with a time in their front matter ([#831]({{ site.repository }}/issues/831)) +- Look for plugins under the source directory ([#654]({{ site.repository }}/issues/654)) +- Tumblr Migrator: finds `_posts` dir correctly, fixes truncation of long post names ([#775]({{ site.repository }}/issues/775)) +- Force Categories to be Strings ([#767]({{ site.repository }}/issues/767)) +- Safe YAML plugin to prevent vulnerability ([#777]({{ site.repository }}/issues/777)) +- Add SVG support to Jekyll/WEBrick. ([#407]({{ site.repository }}/issues/407), [#406]({{ site.repository }}/issues/406)) +- Prevent custom destination from causing continuous regen on watch ([#528]({{ site.repository }}/issues/528), [#820]({{ site.repository }}/issues/820), [#862]({{ site.repository }}/issues/862)) + +### Site Enhancements +{: #site-enhancements-v1-0-0} + +- Responsify ([#860]({{ site.repository }}/issues/860)) +- Fix spelling, punctuation and phrasal errors ([#989]({{ site.repository }}/issues/989)) +- Update quickstart instructions with `new` command ([#966]({{ site.repository }}/issues/966)) +- Add docs for page.excerpt ([#956]({{ site.repository }}/issues/956)) +- Add docs for page.path ([#951]({{ site.repository }}/issues/951)) +- Clean up site docs to prepare for 1.0 release ([#918]({{ site.repository }}/issues/918)) +- Bring site into master branch with better preview/deploy ([#709]({{ site.repository }}/issues/709)) +- Redesigned site ([#583]({{ site.repository }}/issues/583)) + +### Development Fixes +{: #development-fixes-v1-0-0} + +- Exclude Cucumber 1.2.4, which causes tests to fail in 1.9.2 ([#938]({{ site.repository }}/issues/938)) +- Added "features:html" rake task for debugging purposes, cleaned up Cucumber profiles ([#832]({{ site.repository }}/issues/832)) +- Explicitly require HTTPS rubygems source in Gemfile ([#826]({{ site.repository }}/issues/826)) +- Changed Ruby version for development to 1.9.3-p374 from p362 ([#801]({{ site.repository }}/issues/801)) +- Including a link to the GitHub Ruby style guide in CONTRIBUTING.md ([#806]({{ site.repository }}/issues/806)) +- Added script/bootstrap ([#776]({{ site.repository }}/issues/776)) +- Running Simplecov under 2 conditions: ENV(COVERAGE)=true and with Ruby version of greater than 1.9 ([#771]({{ site.repository }}/issues/771)) +- Switch to Simplecov for coverage report ([#765]({{ site.repository }}/issues/765)) + + +## 0.12.1 / 2013-02-19 +{: #v0-12-1} + +### Minor Enhancements +{: #minor-enhancements-v0-12-1} + +- Update Kramdown version to 0.14.1 ([#744]({{ site.repository }}/issues/744)) +- Test Enhancements +- Update Rake version to 10.0.3 ([#744]({{ site.repository }}/issues/744)) +- Update Shoulda version to 3.3.2 ([#744]({{ site.repository }}/issues/744)) +- Update Redcarpet version to 2.2.2 ([#744]({{ site.repository }}/issues/744)) + + +## 0.12.0 / 2012-12-22 +{: #v0-12-0} + +### Minor Enhancements +{: #minor-enhancements-v0-12-0} + +- Add ability to explicitly specify included files ([#261]({{ site.repository }}/issues/261)) +- Add `--default-mimetype` option ([#279]({{ site.repository }}/issues/279)) +- Allow setting of RedCloth options ([#284]({{ site.repository }}/issues/284)) +- Add `post_url` Liquid tag for internal post linking ([#369]({{ site.repository }}/issues/369)) +- Allow multiple plugin dirs to be specified ([#438]({{ site.repository }}/issues/438)) +- Inline TOC token support for RDiscount ([#333]({{ site.repository }}/issues/333)) +- Add the option to specify the paginated url format ([#342]({{ site.repository }}/issues/342)) +- Swap out albino for pygments.rb ([#569]({{ site.repository }}/issues/569)) +- Support Redcarpet 2 and fenced code blocks ([#619]({{ site.repository }}/issues/619)) +- Better reporting of Liquid errors ([#624]({{ site.repository }}/issues/624)) +- Bug Fixes +- Allow some special characters in highlight names +- URL escape category names in URL generation ([#360]({{ site.repository }}/issues/360)) +- Fix error with `limit_posts` ([#442]({{ site.repository }}/issues/442)) +- Properly select dotfile during directory scan ([#363]({{ site.repository }}/issues/363), [#431]({{ site.repository }}/issues/431), [#377]({{ site.repository }}/issues/377)) +- Allow setting of Kramdown `smart_quotes` ([#482]({{ site.repository }}/issues/482)) +- Ensure front matter is at start of file ([#562]({{ site.repository }}/issues/562)) + + +## 0.11.2 / 2011-12-27 +{: #v0-11-2} + +- Bug Fixes +- Fix gemspec + + +## 0.11.1 / 2011-12-27 +{: #v0-11-1} + +- Bug Fixes +- Fix extra blank line in highlight blocks ([#409]({{ site.repository }}/issues/409)) +- Update dependencies + + +## 0.11.0 / 2011-07-10 +{: #v0-11-0} + +### Major Enhancements +{: #major-enhancements-v0-11-0} + +- Add command line importer functionality ([#253]({{ site.repository }}/issues/253)) +- Add Redcarpet Markdown support ([#318]({{ site.repository }}/issues/318)) +- Make markdown/textile extensions configurable ([#312]({{ site.repository }}/issues/312)) +- Add `markdownify` filter + +### Minor Enhancements +{: #minor-enhancements-v0-11-0} + +- Switch to Albino gem +- Bundler support +- Use English library to avoid hoops ([#292]({{ site.repository }}/issues/292)) +- Add Posterous importer ([#254]({{ site.repository }}/issues/254)) +- Fixes for Wordpress importer ([#274]({{ site.repository }}/issues/274), [#252]({{ site.repository }}/issues/252), [#271]({{ site.repository }}/issues/271)) +- Better error message for invalid post date ([#291]({{ site.repository }}/issues/291)) +- Print formatted fatal exceptions to stdout on build failure +- Add Tumblr importer ([#323]({{ site.repository }}/issues/323)) +- Add Enki importer ([#320]({{ site.repository }}/issues/320)) +- Bug Fixes +- Secure additional path exploits + + +## 0.10.0 / 2010-12-16 +{: #v0-10-0} + +- Bug Fixes +- Add `--no-server` option. + + +## 0.9.0 / 2010-12-15 +{: #v0-9-0} + +### Minor Enhancements +{: #minor-enhancements-v0-9-0} + +- Use OptionParser's `[no-]` functionality for better boolean parsing. +- Add Drupal migrator ([#245]({{ site.repository }}/issues/245)) +- Complain about YAML and Liquid errors ([#249]({{ site.repository }}/issues/249)) +- Remove orphaned files during regeneration ([#247]({{ site.repository }}/issues/247)) +- Add Marley migrator ([#28]({{ site.repository }}/issues/28)) + + +## 0.8.0 / 2010-11-22 +{: #v0-8-0} + +### Minor Enhancements +{: #minor-enhancements-v0-8-0} + +- Add wordpress.com importer ([#207]({{ site.repository }}/issues/207)) +- Add `--limit-posts` cli option ([#212]({{ site.repository }}/issues/212)) +- Add `uri_escape` filter ([#234]({{ site.repository }}/issues/234)) +- Add `--base-url` cli option ([#235]({{ site.repository }}/issues/235)) +- Improve MT migrator ([#238]({{ site.repository }}/issues/238)) +- Add kramdown support ([#239]({{ site.repository }}/issues/239)) +- Bug Fixes +- Fixed filename basename generation ([#208]({{ site.repository }}/issues/208)) +- Set mode to UTF8 on Sequel connections ([#237]({{ site.repository }}/issues/237)) +- Prevent `_includes` dir from being a symlink + + +## 0.7.0 / 2010-08-24 +{: #v0-7-0} + +### Minor Enhancements +{: #minor-enhancements-v0-7-0} + +- Add support for rdiscount extensions ([#173]({{ site.repository }}/issues/173)) +- Bug Fixes +- Highlight should not be able to render local files +- The site configuration may not always provide a 'time' setting ([#184]({{ site.repository }}/issues/184)) + + +## 0.6.2 / 2010-06-25 +{: #v0-6-2} + +- Bug Fixes +- Fix Rakefile 'release' task (tag pushing was missing origin) +- Ensure that RedCloth is loaded when textilize filter is used ([#183]({{ site.repository }}/issues/183)) +- Expand source, destination, and plugin paths ([#180]({{ site.repository }}/issues/180)) +- Fix `page.url` to include full relative path ([#181]({{ site.repository }}/issues/181)) + + +## 0.6.1 / 2010-06-24 +{: #v0-6-1} + +- Bug Fixes +- Fix Markdown Pygments prefix and suffix ([#178]({{ site.repository }}/issues/178)) + + +## 0.6.0 / 2010-06-23 +{: #v0-6-0} + +### Major Enhancements +{: #major-enhancements-v0-6-0} + +- Proper plugin system ([#19]({{ site.repository }}/issues/19), [#100]({{ site.repository }}/issues/100)) +- Add safe mode so unsafe converters/generators can be added +- Maruku is now the only processor dependency installed by default. Other processors will be lazy-loaded when necessary (and prompt the user to install them when necessary) ([#57]({{ site.repository }}/issues/57)) + +### Minor Enhancements +{: #minor-enhancements-v0-6-0} + +- Inclusion/exclusion of future dated posts ([#59]({{ site.repository }}/issues/59)) +- Generation for a specific time ([#59]({{ site.repository }}/issues/59)) +- Allocate `site.time` on render not per site_payload invocation ([#59]({{ site.repository }}/issues/59)) +- Pages now present in the site payload and can be used through the `site.pages` and `site.html_pages` variables +- Generate phase added to site#process and pagination is now a generator +- Switch to RakeGem for build/test process +- Only regenerate static files when they have changed ([#142]({{ site.repository }}/issues/142)) +- Allow arbitrary options to Pygments ([#31]({{ site.repository }}/issues/31)) +- Allow URL to be set via command line option ([#147]({{ site.repository }}/issues/147)) +- Bug Fixes +- Render highlighted code for non markdown/textile pages ([#116]({{ site.repository }}/issues/116)) +- Fix highlighting on Ruby 1.9 ([#65]({{ site.repository }}/issues/65)) +- Fix extension munging when pretty permalinks are enabled ([#64]({{ site.repository }}/issues/64)) +- Stop sorting categories ([#33]({{ site.repository }}/issues/33)) +- Preserve generated attributes over front matter ([#119]({{ site.repository }}/issues/119)) +- Fix source directory binding using `Dir.pwd` ([#75]({{ site.repository }}/issues/75)) + + +## 0.5.7 / 2010-01-12 +{: #v0-5-7} + +### Minor Enhancements +{: #minor-enhancements-v0-5-7} + +- Allow overriding of post date in the front matter ([#62]({{ site.repository }}/issues/62), [#38]({{ site.repository }}/issues/38)) +- Bug Fixes +- Categories isn't always an array ([#73]({{ site.repository }}/issues/73)) +- Empty tags causes error in read_posts ([#84]({{ site.repository }}/issues/84)) +- Fix pagination to adhere to read/render/write paradigm +- Test Enhancement +- Cucumber features no longer use site.posts.first where a better alternative is available + + +## 0.5.6 / 2010-01-08 +{: #v0-5-6} + +- Bug Fixes +- Require redcloth >= 4.2.1 in tests ([#92]({{ site.repository }}/issues/92)) +- Don't break on triple dashes in front matter ([#93]({{ site.repository }}/issues/93)) + +### Minor Enhancements +{: #minor-enhancements-v0-5-6} + +- Allow .mkd as markdown extension +- Use $stdout/err instead of constants ([#99]({{ site.repository }}/issues/99)) +- Properly wrap code blocks ([#91]({{ site.repository }}/issues/91)) +- Add javascript mime type for webrick ([#98]({{ site.repository }}/issues/98)) + + +## 0.5.5 / 2010-01-08 +{: #v0-5-5} + +- Bug Fixes +- Fix pagination % 0 bug ([#78]({{ site.repository }}/issues/78)) +- Ensure all posts are processed first ([#71]({{ site.repository }}/issues/71)) +- After this point I will no longer be giving credit in the history; that is what the commit log is for. + + +## 0.5.4 / 2009-08-23 +{: #v0-5-4} + +- Bug Fixes +- Do not allow symlinks (security vulnerability) + + +## 0.5.3 / 2009-07-14 +{: #v0-5-3} + +- Bug Fixes +- Solving the permalink bug where non-html files wouldn't work (@jeffrydegrande) + + +## 0.5.2 / 2009-06-24 +{: #v0-5-2} + +- Enhancements +- Added --paginate option to the executable along with a paginator object for the payload (@calavera) +- Upgraded RedCloth to 4.2.1, which makes `` tags work once again. +- Configuration options set in config.yml are now available through the site payload (@vilcans) +- Posts can now have an empty front matter or none at all (@ bahuvrihi) +- Bug Fixes +- Fixing Ruby 1.9 issue that requires `#to_s` on the err object (@Chrononaut) +- Fixes for pagination and ordering posts on the same day (@ujh) +- Made pages respect permalinks style and permalinks in yml front matter (@eugenebolshakov) +- Index.html file should always have index.html permalink (@eugenebolshakov) +- Added trailing slash to pretty permalink style so Apache is happy (@eugenebolshakov) +- Bad markdown processor in config fails sooner and with better message (@ gcnovus) +- Allow CRLFs in front matter (@juretta) +- Added Date#xmlschema for Ruby versions < 1.9 + + +## 0.5.1 / 2009-05-06 +{: #v0-5-1} + +### Major Enhancements +{: #major-enhancements-v0-5-1} + +- Next/previous posts in site payload (@pantulis, @tomo) +- Permalink templating system +- Moved most of the README out to the GitHub wiki +- Exclude option in configuration so specified files won't be brought over with generated site (@duritong) +- Bug Fixes +- Making sure config.yaml references are all gone, using only config.yml +- Fixed syntax highlighting breaking for UTF-8 code (@henrik) +- Worked around RDiscount bug that prevents Markdown from getting parsed after highlight (@henrik) +- CGI escaped post titles (@Chrononaut) + + +## 0.5.0 / 2009-04-07 +{: #v0-5-0} + +### Minor Enhancements +{: #minor-enhancements-v0-5-0} + +- Ability to set post categories via YAML (@qrush) +- Ability to set prevent a post from publishing via YAML (@qrush) +- Add textilize filter (@willcodeforfoo) +- Add 'pretty' permalink style for wordpress-like urls (@dysinger) +- Made it possible to enter categories from YAML as an array (@Chrononaut) +- Ignore Emacs autosave files (@Chrononaut) +- Bug Fixes +- Use block syntax of popen4 to ensure that subprocesses are properly disposed (@jqr) +- Close open4 streams to prevent zombies (@rtomayko) +- Only query required fields from the WP Database (@ariejan) +- Prevent `_posts` from being copied to the destination directory (@bdimcheff) +- Refactors +- Factored the filtering code into a method (@Chrononaut) +- Fix tests and convert to Shoulda (@qrush, @technicalpickles) +- Add Cucumber acceptance test suite (@qrush, @technicalpickles) + + +## 0.4.1 + +### Minor Enhancements +{: #minor-enhancements-v--} + +- Changed date format on wordpress converter (zeropadding) (@dysinger) +- Bug Fixes +- Add Jekyll binary as executable to gemspec (@dysinger) + + +## 0.4.0 / 2009-02-03 +{: #v0-4-0} + +### Major Enhancements +{: #major-enhancements-v0-4-0} + +- Switch to Jeweler for packaging tasks + +### Minor Enhancements +{: #minor-enhancements-v0-4-0} + +- Type importer (@codeslinger) +- `site.topics` accessor (@baz) +- Add `array_to_sentence_string` filter (@mchung) +- Add a converter for textpattern (@PerfectlyNormal) +- Add a working Mephisto / MySQL converter (@ivey) +- Allowing .htaccess files to be copied over into the generated site (@briandoll) +- Add option to not put file date in permalink URL (@mreid) +- Add line number capabilities to highlight blocks (@jcon) +- Bug Fixes +- Fix permalink behavior (@cavalle) +- Fixed an issue with pygments, markdown, and newlines (@zpinter) +- Ampersands need to be escaped (@pufuwozu, @ap) +- Test and fix the site.categories hash (@zzot) +- Fix site payload available to files (@matrix9180) + + +## 0.3.0 / 2008-12-24 +{: #v0-3-0} + +### Major Enhancements +{: #major-enhancements-v0-3-0} + +- Added `--server` option to start a simple WEBrick server on destination directory (@johnreilly and @mchung) + +### Minor Enhancements +{: #minor-enhancements-v0-3-0} + +- Added post categories based on directories containing `_posts` (@mreid) +- Added post topics based on directories underneath `_posts` +- Added new date filter that shows the full month name (@mreid) +- Merge Post's front matter into its to_liquid payload (@remi) +- Restrict includes to regular files underneath `_includes` +- Bug Fixes +- Change YAML delimiter matcher so as to not chew up 2nd level markdown headers (@mreid) +- Fix bug that meant page data (such as the date) was not available in templates (@mreid) +- Properly reject directories in `_layouts` + + +## 0.2.1 / 2008-12-15 +{: #v0-2-1} + +- Major Changes +- Use Maruku (pure Ruby) for Markdown by default (@mreid) +- Allow use of RDiscount with `--rdiscount` flag + +### Minor Enhancements +{: #minor-enhancements-v0-2-1} + +- Don't load directory_watcher unless it's needed (@pjhyett) + + +## 0.2.0 / 2008-12-14 +{: #v0-2-0} + +- Major Changes +- related_posts is now found in `site.related_posts` + + +## 0.1.6 / 2008-12-13 +{: #v0-1-6} + +- Major Features +- Include files in `_includes` with {% raw %}`{% include x.textile %}`{% endraw %} + + +## 0.1.5 / 2008-12-12 +{: #v0-1-5} + +### Major Enhancements +{: #major-enhancements-v0-1-5} + +- Code highlighting with Pygments if `--pygments` is specified +- Disable true LSI by default, enable with `--lsi` + +### Minor Enhancements +{: #minor-enhancements-v0-1-5} + +- Output informative message if RDiscount is not available (@JackDanger) +- Bug Fixes +- Prevent Jekyll from picking up the output directory as a source (@JackDanger) +- Skip `related_posts` when there is only one post (@JackDanger) + + +## 0.1.4 / 2008-12-08 +{: #v0-1-4} + +- Bug Fixes +- DATA does not work properly with rubygems + + +## 0.1.3 / 2008-12-06 +{: #v0-1-3} + +- Major Features +- Markdown support (@vanpelt) +- Mephisto and CSV converters (@vanpelt) +- Code hilighting (@vanpelt) +- Autobuild +- Bug Fixes +- Accept both `\r\n` and `\n` in YAML header (@vanpelt) + + +## 0.1.2 / 2008-11-22 +{: #v0-1-2} + +- Major Features +- Add a real "related posts" implementation using Classifier +- Command Line Changes +- Allow cli to be called with 0, 1, or 2 args intuiting dir paths if they are omitted + + +## 0.1.1 / 2008-11-22 +{: #v0-1-1} + +- Minor Additions +- Posts now support introspectional data e.g. {% raw %}`{{ page.url }}`{% endraw %} + + +## 0.1.0 / 2008-11-05 +{: #v0-1-0} + +- First release +- Converts posts written in Textile +- Converts regular site pages +- Simple copy of binary files + + +## 0.0.0 / 2008-10-19 +{: #v0-0-0} + +- Birthday! diff --git a/docs/_docs/includes.md b/docs/_docs/includes.md new file mode 100644 index 00000000000..8409942ab21 --- /dev/null +++ b/docs/_docs/includes.md @@ -0,0 +1,156 @@ +--- +title: Includes +permalink: /docs/includes/ +--- + +The `include` tag allows you to include the content from another file stored in the `_includes` folder: + +{% raw %} +```liquid +{% include footer.html %} +``` +{% endraw %} + +Jekyll will look for the referenced file (in this case, `footer.html`) in the `_includes` directory at the root of your source directory and insert its contents. + +### Including files relative to another file + +You can choose to include file fragments relative to the current file by using the `include_relative` tag: + +{% raw %} +```liquid +{% include_relative somedir/footer.html %} +``` +{% endraw %} + +You won't need to place your included content within the `_includes` directory. Instead, +the inclusion is specifically relative to the file where the tag is being used. For example, +if `_posts/2014-09-03-my-file.markdown` uses the `include_relative` tag, the included file +must be within the `_posts` directory or one of its subdirectories. + +Note that you cannot use the `../` syntax to specify an include location that refers to a higher-level directory. + +All the other capabilities of the `include` tag are available to the `include_relative` tag, +such as variables. + +### Using variables names for the include file + +The name of the file you want to embed can be specified as a variable instead of an actual file name. For example, suppose you defined a variable in your page's front matter like this: + +```yaml +--- +title: My page +my_variable: footer_company_a.html +--- +``` + +You could then reference that variable in your include: + +{% raw %} +```liquid +{% if page.my_variable %} + {% include {{ page.my_variable }} %} +{% endif %} +``` +{% endraw %} + +In this example, the include would insert the file `footer_company_a.html` from the `_includes/footer_company_a.html` directory. + +### Passing parameters to includes + +You can also pass parameters to an include. For example, suppose you have a file called `note.html` in your `_includes` folder that contains this formatting: + +{% raw %} +```liquid + +``` +{% endraw %} + +The {% raw %}`{{ include.content }}`{% endraw %} is a parameter that gets populated when you call the include and specify a value for that parameter, like this: + +{% raw %} +```liquid +{% include note.html content="This is my sample note." %} +``` +{% endraw %} + +The value of `content` (which is `This is my sample note`) will be inserted into the {% raw %}`{{ include.content }}`{% endraw %} parameter. + +Passing parameters to includes is especially helpful when you want to hide away complex formatting from your Markdown content. + +For example, suppose you have a special image syntax with complex formatting, and you don't want your authors to remember the complex formatting. As a result, you decide to simplify the formatting by using an include with parameters. Here's an example of the special image syntax you might want to populate with an include: + +```html +
+ + Jekyll logo + +
This is the Jekyll logo
+
+``` + +You could templatize this content in your include and make each value available as a parameter, like this: + +{% raw %} +```liquid +
+ + {{ include.alt }} + +
{{ include.caption }}
+
+``` +{% endraw %} + +This include contains 5 parameters: + +* `url` +* `max-width` +* `file` +* `alt` +* `caption` + +Here's an example that passes all the parameters to this include (the include file is named `image.html`): + +{% raw %} +```liquid +{% include image.html url="http://jekyllrb.com" +max-width="200px" file="logo.png" alt="Jekyll logo" +caption="This is the Jekyll logo." %} +``` +{% endraw %} + +The result is the original HTML code shown earlier. + +To safeguard situations where users don't supply a value for the parameter, you can use [Liquid's default filter](https://shopify.github.io/liquid/filters/default/). + +Overall, you can create includes that act as templates for a variety of uses — inserting audio or video clips, alerts, special formatting, and more. Note that you should avoid using too many includes, as this will slow down the build time of your site. For example, don't use includes every time you insert an image. (The above technique shows a use case for special images.) + +### Passing parameter variables to includes + +Suppose the parameter you want to pass to the include is a variable rather than a string. For example, you might be using {% raw %}`{{ site.product_name }}`{% endraw %} to refer to every instance of your product rather than the actual hard-coded name. (In this case, your `_config.yml` file would have a key called `product_name` with a value of your product's name.) + +The string you pass to your include parameter can't contain curly braces. For example, you can't pass a parameter that contains this: {% raw %}`"The latest version of {{ site.product_name }} is now available."`{% endraw %} + +If you want to include this variable in your parameter that you pass to an include, you need to store the entire parameter as a variable before passing it to the include. You can use `capture` tags to create the variable: + +{% raw %} +```liquid +{% capture download_note %} +The latest version of {{ site.product_name }} is now available. +{% endcapture %} +``` +{% endraw %} + +Then pass this captured variable into the parameter for the include. Omit the quotation marks around the parameter content because it's no longer a string (it's a variable): + +{% raw %} +```liquid +{% include note.html content=download_note %} +``` +{% endraw %} diff --git a/docs/_docs/index.md b/docs/_docs/index.md new file mode 100644 index 00000000000..83c3e573b17 --- /dev/null +++ b/docs/_docs/index.md @@ -0,0 +1,55 @@ +--- +title: Quickstart +permalink: /docs/ +redirect_from: + - /docs/home/ + - /docs/quickstart/ + - /docs/extras/ +--- +Jekyll is a static site generator. It takes text written in your +favorite markup language and uses layouts to create a static website. You can +tweak the site's look and feel, URLs, the data displayed on the page, and more. + +## Prerequisites + +Jekyll requires the following: + +* Ruby version **{{ site.data.ruby.min_version }}** or higher +* RubyGems +* GCC and Make + +See [Requirements]({{ '/docs/installation/#requirements' | relative_url }}) for guides and details. + +## Instructions + +1. Install all [prerequisites]({{ '/docs/installation/' | relative_url }}). +2. Install the jekyll and bundler [gems]({{ '/docs/ruby-101/#gems' | relative_url }}). +```sh +gem install jekyll bundler +``` +3. Create a new Jekyll site at `./myblog`. +```sh +jekyll new myblog +``` +4. Change into your new directory. +```sh +cd myblog +``` +5. Build the site and make it available on a local server. +```sh +bundle exec jekyll serve +``` +6. Browse to [http://localhost:4000](http://localhost:4000){:target="_blank"} + +{: .note .warning} +If you are using Ruby version 3.0.0 or higher, step 5 [may fail](https://github.com/github/pages-gem/issues/752). You may fix it by adding `webrick` to your dependencies: `bundle add webrick` + +{: .note .info} +Pass the `--livereload` option to `serve` to automatically refresh the page with each change you make to the source files: `bundle exec jekyll serve --livereload` + + +If you encounter any errors during this process, check that you have installed all the prerequisites in [Requirements]({{ '/docs/installation/#requirements' | relative_url }}). +If you still have issues, see [Troubleshooting]({{ '/docs/troubleshooting/#configuration-problems' | relative_url }}). + +{: .note .info} +Installation varies based on your operating system. See our [guides]({{ '/docs/installation/#guides' | relative_url }}) for OS-specific instructions. diff --git a/docs/_docs/installation.md b/docs/_docs/installation.md new file mode 100644 index 00000000000..fca51c59461 --- /dev/null +++ b/docs/_docs/installation.md @@ -0,0 +1,23 @@ +--- +title: Installation +description: Official guide to install Jekyll on macOS, GNU/Linux or Windows. +permalink: /docs/installation/ +--- + +Jekyll is a [Ruby Gem]({{ '/docs/ruby-101/#gems' | relative_url }}) that can be installed on most systems. + +## Requirements + +* [Ruby](https://www.ruby-lang.org/en/downloads/) version **{{ site.data.ruby.min_version }}** or higher, including all development headers (check your Ruby version using `ruby -v`) +* [RubyGems](https://rubygems.org/pages/download) (check your Gems version using `gem -v`) +* [GCC](https://gcc.gnu.org/install/) and [Make](https://www.gnu.org/software/make/) (check versions using `gcc -v`,`g++ -v`, and `make -v`) + +## Guides + +For detailed install instructions, follow the guide for your operating system. + +* [macOS]({{ '/docs/installation/macos/' | relative_url }}) +* [Ubuntu]({{ '/docs/installation/ubuntu/' | relative_url }}) +* [FreeBSD]({{ '/docs/installation/freebsd/' | relative_url }}) +* [Other Linux]({{ '/docs/installation/other-linux/' | relative_url }}) +* [Windows]({{ '/docs/installation/windows/' | relative_url }}) \ No newline at end of file diff --git a/docs/_docs/installation/freebsd.md b/docs/_docs/installation/freebsd.md new file mode 100644 index 00000000000..37143b86cad --- /dev/null +++ b/docs/_docs/installation/freebsd.md @@ -0,0 +1,50 @@ +--- +title: Jekyll on FreeBSD +permalink: /docs/installation/freebsd/ +--- + +### Install Ruby + +```sh +sudo pkg install ruby +``` + +### Install Ruby Gems + +Find the latest version and install it. (Replace `ruby3x` with whatever the latest version is.) + +```sh +pkg search gems +sudo pkg install ruby3x-gems +``` + +## Set Gems directory and add that to the Bash path + +Avoid installing RubyGems packages (called gems) as the root user. Instead, +set up a gem installation directory for your user account. The following +commands will add environment variables to your `~/.bashrc` file to configure +the gem installation path: + +```sh +echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc +echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc +echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc +source ~/.bashrc +``` + +## Install Jekyll Gems + +```sh +gem install jekyll bundler jekyll-sitemap +``` + +## Verify install + +Both of these commands should return some output showing version number, etc. + +```sh +ruby -v +jekyll -v +``` + +That's it! You're ready to start using Jekyll. diff --git a/docs/_docs/installation/macos.md b/docs/_docs/installation/macos.md new file mode 100644 index 00000000000..86ba74f1b41 --- /dev/null +++ b/docs/_docs/installation/macos.md @@ -0,0 +1,92 @@ +--- +title: Jekyll on macOS +permalink: /docs/installation/macos/ +--- + +## Supported macOS versions + +We match [Homebrew's macOS requirements](https://docs.brew.sh/Installation#macos-requirements), which typically support the last 2 or 3 macOS versions. + +Older macOS versions might work, but we don't officially support them. + +## Install Ruby + +To install Jekyll on macOS, you need a proper Ruby development environment. +While macOS comes preinstalled with Ruby, we don't recommend using that version +to install Jekyll. This external article goes over the various reasons +[why you shouldn't use the system Ruby](https://www.moncefbelyamani.com/why-you-shouldn-t-use-the-system-ruby-to-install-gems-on-a-mac/). + +Instead, you'll need to install a separate and newer version of Ruby using a +version manager such as [asdf], [chruby], [rbenv], or [rvm]. Version managers +allow you to easily install multiple versions of Ruby, and switch between them. + +We recommend `chruby` because it's the simplest and least likely to cause issues. + +The instructions below are an excerpt from this detailed external guide to +[install Ruby on Mac]. They work best if you're setting up development tools +for the first time on your Mac. If you've already tried to install Ruby or +Jekyll on your Mac, or if you run into any issues, read that guide. + +[asdf]: https://asdf-vm.com/ +[chruby]: https://github.com/postmodern/chruby +[rbenv]: https://github.com/rbenv/rbenv +[rvm]: https://rvm.io/ +[install Ruby on Mac]: https://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac/ + +### Step 1: Install Homebrew + +[Homebrew](https://brew.sh/) makes it easy to install development tools on a Mac. + +```sh +/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +``` + +### Step 2: Install chruby and the latest Ruby with ruby-install + +Install `chruby` and `ruby-install` with Homebrew: + +```sh +brew install chruby ruby-install +``` + +Install the latest stable version of Ruby (supported by Jekyll): + +```sh +ruby-install ruby {{ site.data.ruby.current_version }} +``` + +This will take a few minutes, and once it's done, configure your shell to +automatically use `chruby`: + +```sh +echo "source $(brew --prefix)/opt/chruby/share/chruby/chruby.sh" >> ~/.zshrc +echo "source $(brew --prefix)/opt/chruby/share/chruby/auto.sh" >> ~/.zshrc +echo "chruby ruby-{{ site.data.ruby.current_version }}" >> ~/.zshrc # run 'chruby' to see actual version +``` + +If you're using Bash, replace `.zshrc` with `.bash_profile`. If you're not sure, +read this external guide to +[find out which shell you're using](https://www.moncefbelyamani.com/which-shell-am-i-using-how-can-i-switch/). + +Quit and relaunch Terminal, then check that everything is working: + +```sh +ruby -v +``` + +It should show {{ site.data.ruby.current_version_output }} or a newer version. + +Next, read that same external guide for important notes about +[setting and switching between Ruby versions with chruby](https://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac/#how-to-install-different-versions-of-ruby-and-switch-between-them). + +## Install Jekyll + +After installing Ruby with chruby, install the latest Jekyll gem: + +```sh +gem install jekyll +``` + +## Troubleshooting + +See [Troubleshooting]({{ '/docs/troubleshooting/' | relative_url }}) or [ask for help on our forum](https://talk.jekyllrb.com). diff --git a/docs/_docs/installation/other-linux.md b/docs/_docs/installation/other-linux.md new file mode 100644 index 00000000000..95e7156ccc7 --- /dev/null +++ b/docs/_docs/installation/other-linux.md @@ -0,0 +1,60 @@ +--- +title: Jekyll on Linux +permalink: /docs/installation/other-linux/ +--- + +Installation on other Linux distributions works similarly to installing on [Ubuntu](../ubuntu/). + +## Install prerequisites + +### Fedora + +```sh +sudo dnf install ruby ruby-devel openssl-devel redhat-rpm-config gcc-c++ @development-tools +``` +### RHEL8/CentOS8 + +```sh +sudo dnf install ruby ruby-devel +sudo dnf group install "Development Tools" +``` + +### Debian + +```sh +sudo apt-get install ruby-full build-essential +``` + +### Gentoo + +```sh +sudo emerge -av jekyll +``` + +or + +```sh +sudo emerge --ask --verbose jekyll +``` + +### ArchLinux + +```sh +sudo pacman -S ruby base-devel ruby-erb +``` + +### OpenSUSE + +```sh +sudo zypper install -t pattern devel_ruby devel_C_C++ +sudo zypper install ruby-devel +``` + +### Clear Linux + +```sh +sudo swupd bundle-add ruby-basic +``` +## Install Jekyll + +Follow the instructions for [Ubuntu](../ubuntu/). diff --git a/docs/_docs/installation/ubuntu.md b/docs/_docs/installation/ubuntu.md new file mode 100644 index 00000000000..a706a6cde6d --- /dev/null +++ b/docs/_docs/installation/ubuntu.md @@ -0,0 +1,32 @@ +--- +title: Jekyll on Ubuntu +permalink: /docs/installation/ubuntu/ +--- + +## Install dependencies + +Install Ruby and other [prerequisites]({{ '/docs/installation/#requirements' | relative_url }}): + +```sh +sudo apt-get install ruby-full build-essential zlib1g-dev +``` + +Avoid installing RubyGems packages (called gems) as the root user. Instead, +set up a gem installation directory for your user account. The following +commands will add environment variables to your `~/.bashrc` file to configure +the gem installation path: + +```sh +echo '# Install Ruby Gems to ~/gems' >> ~/.bashrc +echo 'export GEM_HOME="$HOME/gems"' >> ~/.bashrc +echo 'export PATH="$HOME/gems/bin:$PATH"' >> ~/.bashrc +source ~/.bashrc +``` + +Finally, install Jekyll and Bundler: + +```sh +gem install jekyll bundler +``` + +That's it! You're ready to start using Jekyll. diff --git a/docs/_docs/installation/windows.md b/docs/_docs/installation/windows.md new file mode 100644 index 00000000000..587982ae521 --- /dev/null +++ b/docs/_docs/installation/windows.md @@ -0,0 +1,117 @@ +--- +title: Jekyll on Windows +permalink: /docs/installation/windows/ +redirect_from: + - /docs/windows/ +--- + +While Windows is not an officially-supported platform, it can be used to run Jekyll with the proper tweaks. + +## Installing Ruby and Jekyll + +### Installation via RubyInstaller + +The easiest way to install Ruby and Jekyll is by using the [RubyInstaller](https://rubyinstaller.org/) for Windows. + +RubyInstaller is a self-contained Windows-based installer that includes the Ruby language, an execution environment, +important documentation, and more. + +We only cover RubyInstaller-2.4 and newer here. Older versions need to +[install the Devkit](https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) manually. + +1. Download and install a **Ruby+Devkit** version from [RubyInstaller Downloads](https://rubyinstaller.org/downloads/). + Use default options for installation. +2. Run the `ridk install` step on the last stage of the installation wizard. This is needed for installing gems with native + extensions. You can find additional information regarding this in the + [RubyInstaller Documentation](https://github.com/oneclick/rubyinstaller2#using-the-installer-on-a-target-system). + From the options choose `MSYS2 and MINGW development toolchain`. +3. Open a new command prompt window from the start menu, so that changes to the `PATH` environment variable becomes effective. + Install Jekyll and Bundler using `gem install jekyll bundler` +4. Check if Jekyll has been installed properly: `jekyll -v` + +{: .note .info} +You may receive an error when checking if Jekyll has not been installed properly. Reboot your system and run `jekyll -v` again. +If the error persists, please open a [RubyInstaller issue](https://github.com/oneclick/rubyinstaller2/issues/new). + +That's it, you're ready to use Jekyll! + +### Installation via Bash on Windows 10 + +If you are using Windows 10 version 1607 or later, another option to run Jekyll is by +[installing](https://msdn.microsoft.com/en-us/commandline/wsl/install_guide) the Windows Subsystem for Linux. + +{: .note .info} +You must have [Windows Subsystem for Linux](https://msdn.microsoft.com/en-us/commandline/wsl/about) enabled. + +Make sure all your packages and repositories are up to date. Open a new Command Prompt or PowerShell window and type `bash`. + +Your terminal should now be a Bash instance. Then, [follow the installation procedure for Ubuntu](https://jekyllrb.com/docs/installation/ubuntu/). + +Once this is done, check your Jekyll version: + +```sh +jekyll -v +``` + +That's it! You're ready to start using Jekyll. + +You can make sure time management is working properly by inspecting your `_posts` folder. You should see a markdown file +with the current date in the filename. + +
+
Non-superuser account issues
+

If the `jekyll new` command prints the error "Your user account isn't allowed to install to the system RubyGems", see + the "Running Jekyll as Non-Superuser" instructions in + Troubleshooting.

+
+ +{: .note .info} +Bash on Ubuntu on Windows is still under development, so you may run into issues. + +## Encoding + +If you use UTF-8 encoding, Jekyll will break if a file starts with characters representing a [BOM](https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8). Therefore, remove this sequence of bytes if it appears at the beginning of your file. + +Additionally, you might need to change the code page of the console window to UTF-8 in case you get a +`Liquid Exception: Incompatible character encoding` error during the site generation process. Run the following: + +```sh +chcp 65001 +``` + +## Time Zone Management + +Since Windows doesn't have a native source of zoneinfo data, the Ruby Interpreter doesn't understand IANA Timezones. +Using them had the `TZ` environment variable default to UTC/GMT 00:00. + +Though Windows users could alternatively define their blog's timezone by setting the key to use the POSIX format of defining +timezones, it wasn't as user-friendly when it came to having the clock altered to changing DST-rules. + +Jekyll now uses a rubygem to internally configure Timezone based on established +[IANA Timezone Database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). + +While 'new' blogs created with Jekyll v3.4 and greater, will have the following added to their `Gemfile` by default, existing +sites *will* have to update their `Gemfile` (and installed gems) to enable development on Windows: + +```ruby +# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem +# and associated library. +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" +end +``` + +## Auto Regeneration + +Jekyll uses the `listen` gem to watch for changes when the `--watch` switch is specified during a build or serve. +While `listen` has built-in support for UNIX systems, it may require an extra gem for compatibility with Windows. + +Add the following to the `Gemfile` for your site if you have issues with auto-regeneration on Windows alone: + +```ruby +gem "wdm", "~> 0.2.0", :install_if => Gem.win_platform? +``` + +You have to use a [Ruby+Devkit](https://rubyinstaller.org/downloads/) version of the RubyInstaller and install +the MSYS2 build tools to successfully install the `wdm` gem. diff --git a/docs/_docs/layouts.md b/docs/_docs/layouts.md new file mode 100644 index 00000000000..1ef7c2a2c42 --- /dev/null +++ b/docs/_docs/layouts.md @@ -0,0 +1,141 @@ +--- +title: Layouts +description: placeholder +permalink: /docs/layouts/ +--- +Layouts are templates that wrap around your content. They allow you to have the +source code for your template in one place so you don't have to repeat things +like your navigation and footer on every page. + +Layouts live in the `_layouts` directory. The convention is to have a base +template called `default.html` and have other layouts [inherit](#inheritance) +from this as needed. + +
+
Layouts Directory
+

+ Jekyll looks for the _layouts directory either at the root of + your site's source or at the root of your theme. +

+

+ While you can configure the directory name in which your layouts can reside by + setting the layouts_dir key in your config file, the directory + itself should be located at the root of your site's source directory. +

+
+ +## Usage + +The first step is to put the template source code in `default.html`. `content` +is a special variable, the value is the rendered content of the post or page +being wrapped. + +{% raw %} +```liquid + + + + + {{ page.title }} + + + + +

{{ page.title }}

+
+ {{ content }} +
+
+ © to me +
+ + +``` +{% endraw %} + +You have full access to the front matter of the origin. In the +example above, `page.title` comes from the page front matter. + +Next you need to specify what layout you're using in your page's front matter. +You can also use +[front matter defaults](/docs/configuration/front-matter-defaults/) to save you +from having to set this on every page. + +```markdown +--- +title: My First Page +layout: default +--- + +This is the content of my page +``` + +The rendered output of this page is: + +```html + + + + + My First Page + + + + +

My First Page

+
+ This is the content of my page +
+
+ © to me +
+ + +``` + +## Inheritance + +Layout inheritance is useful when you want to add something to an existing +layout for a portion of documents on your site. A common example of this is +blog posts, you might want a post to display the date and author but otherwise +be identical to your base layout. + +To achieve this you need to create another layout which specifies your original +layout in front matter. For example this layout will live at +`_layouts/post.html`: + +{% raw %} +```liquid +--- +layout: default +--- +

{{ page.date }} - Written by {{ page.author }}

+ +{{ content }} +``` +{% endraw %} + +Now posts can use this layout while the rest of the pages use the default. + +## Variables + +You can set front matter in layouts, the only difference is when you're +using in Liquid, you need to use the `layout` variable instead of `page`. For +example: + +{% raw %} +```liquid +--- +city: San Francisco +--- +

{{ layout.city }}

+ +{{ content }} +``` +{% endraw %} diff --git a/docs/_docs/liquid.md b/docs/_docs/liquid.md new file mode 100644 index 00000000000..9dead2b8b7c --- /dev/null +++ b/docs/_docs/liquid.md @@ -0,0 +1,19 @@ +--- +title: Liquid +permalink: /docs/liquid/ +redirect_from: "/docs/templates/" +--- + +Jekyll uses the [Liquid](https://shopify.github.io/liquid/) templating language +to process templates. + +Generally in Liquid you output content using two curly braces e.g. +{% raw %}`{{ variable }}`{% endraw %} and perform logic statements by +surrounding them in a curly brace percentage sign e.g. +{% raw %}`{% if statement %}`{% endraw %}. To learn more about Liquid, check +out the [official Liquid Documentation](https://shopify.github.io/liquid/). + +Jekyll provides a number of useful Liquid additions to help you build your site: + +* [Filters]({{ '/docs/liquid/filters/' | relative_url }}) +* [Tags]({{ '/docs/liquid/tags/' | relative_url }}) diff --git a/docs/_docs/liquid/filters.md b/docs/_docs/liquid/filters.md new file mode 100644 index 00000000000..26609b8519f --- /dev/null +++ b/docs/_docs/liquid/filters.md @@ -0,0 +1,154 @@ +--- +title: Liquid Filters +permalink: "/docs/liquid/filters/" +shopify_filter_url: https://shopify.github.io/liquid/filters/ +shopify_filters: +- abs +- append +- at_least +- at_most +- capitalize +- ceil +- compact +- concat +- date +- default +- divided_by +- downcase +- escape +- escape_once +- first +- floor +- join +- last +- lstrip +- map +- minus +- modulo +- newline_to_br +- plus +- prepend +- remove +- remove_first +- replace +- replace_first +- reverse +- round +- rstrip +- size +- slice +- sort +- sort_natural +- split +- strip +- strip_html +- strip_newlines +- times +- truncate +- truncatewords +- uniq +- upcase +- url_decode +- url_encode +--- + +All of the standard Liquid [filters](#standard-liquid-filters) are supported (see below). + +To make common tasks easier, Jekyll even adds a few handy filters of its own, +all of which you can find on this page. You can also create your own filters +using [plugins](/docs/plugins/). + +
+ + + + + + + + + {% for filter in site.data.jekyll_filters %} + + + + + {% endfor %} + +
DescriptionFilter and Output
+

{{ filter.name }}

+

+ {{- filter.description -}} + {%- if filter.version_badge %} + + {{- filter.version_badge -}} + + {% endif -%} +

+
+ {%- for example in filter.examples %} +

{{ example.input }}

+ {% if example.output %}

{{ example.output }}

{% endif %} + {% endfor -%} +
+
+ +### Options for the `slugify` filter + +The `slugify` filter accepts an option, each specifying what to filter. +The default is `default`. They are as follows (with what they filter): + +- `none`: no characters +- `raw`: spaces +- `default`: spaces and non-alphanumeric characters +- `pretty`: spaces and non-alphanumeric characters except for `._~!$&'()+,;=@` +- `ascii`: spaces, non-alphanumeric, and non-ASCII characters +- `latin`: like `default`, except Latin characters are first transliterated (e.g. `àèïòü` to `aeiou`) {%- include docs_version_badge.html version="3.7.0" -%}. + +### Detecting `nil` values with `where` filter {%- include docs_version_badge.html version="4.0" -%} + +You can use the `where` filter to detect documents and pages with properties that are `nil` or `""`. For example, + +{% raw %} +```liquid +// Using `nil` to select posts that either do not have `my_prop` +// defined or `my_prop` has been set to `nil` explicitly. +{% assign filtered_posts = site.posts | where: 'my_prop', nil %} +``` +{% endraw %} + +{% raw %} +```liquid +// Using Liquid's special literal `empty` or `blank` to select +// posts that have `my_prop` set to an empty value. +{% assign filtered_posts = site.posts | where: 'my_prop', empty %} +``` +{% endraw %} + +### Binary operators in `where_exp` filter {%- include docs_version_badge.html version="4.0" -%} + +You can use Liquid binary operators `or` and `and` in the expression passed to the `where_exp` filter to employ multiple +conditionals in the operation. + +For example, to get a list of documents on English horror flicks, one could use the following snippet: + +{% raw %} +```liquid +{{ site.movies | where_exp: "item", "item.genre == 'horror' and item.language == 'English'" }} +``` +{% endraw %} + +Or to get a list of comic-book based movies, one may use the following: + +{% raw %} +```liquid +{{ site.movies | where_exp: "item", "item.sub_genre == 'MCU' or item.sub_genre == 'DCEU'" }} +``` +{% endraw %} + +### Standard Liquid Filters + +For your convenience, here is the list of all [Liquid filters]({{ page.shopify_filter_url }}) with links to examples in the official Liquid documentation. + +{% for filter in page.shopify_filters %} +- [{{ filter }}]({{ filter | prepend: page.shopify_filter_url | append: '/' }}) +{% endfor %} diff --git a/docs/_docs/liquid/tags.md b/docs/_docs/liquid/tags.md new file mode 100644 index 00000000000..7140a030311 --- /dev/null +++ b/docs/_docs/liquid/tags.md @@ -0,0 +1,212 @@ +--- +title: Tags Filters +permalink: "/docs/liquid/tags/" +--- +All of the standard Liquid +[tags](https://shopify.github.io/liquid/tags/control-flow/) are supported. +Jekyll has a few built in tags to help you build your site. You can also create +your own tags using [plugins]({{ '/docs/plugins/' | relative_url }}). + +## Includes + +If you have page snippets that you use repeatedly across your site, an +[include]({{ '/docs/includes/' | relative_url }}) is the perfect way to make this more maintainable. + +## Code snippet highlighting + +Jekyll has built in support for syntax highlighting of over 100 languages +thanks to [Rouge](https://github.com/rouge-ruby/rouge). Rouge is the default highlighter +in Jekyll 3 and above. + +{: .note .warning} +Using Pygments has been deprecated and is not supported in +Jekyll 4; the configuration setting highlighter: pygments +now automatically falls back to using Rouge which is written in Ruby +and 100% compatible with stylesheets for Pygments. + +To render a code block with syntax highlighting, surround your code as follows: + +{% raw %} +```liquid +{% highlight ruby %} +def foo + puts 'foo' +end +{% endhighlight %} +``` +{% endraw %} + +The argument to the `highlight` tag (`ruby` in the example above) is the +language identifier. To find the appropriate identifier to use for the language +you want to highlight, look for the “short name” on the [Rouge +wiki](https://github.com/jayferd/rouge/wiki/List-of-supported-languages-and-lexers). + +
+
Jekyll processes all Liquid filters in code blocks
+

If you are using a language that contains curly braces, you + will likely need to place {% raw %} and + {% endraw %} tags around your code. + Since Jekyll {% include docs_version_badge.html version="4.0" %}, you can add render_with_liquid: false in your front matter to disable Liquid entirely for a particular document.

+
+ +### Line numbers + +There is a second argument to `highlight` called `linenos` that is optional. +Including the `linenos` argument will force the highlighted code to include line +numbers. For instance, the following code block would include line numbers next +to each line: + +{% raw %} +```liquid +{% highlight ruby linenos %} +def foo + puts 'foo' +end +{% endhighlight %} +``` +{% endraw %} + +### Marking specific lines {%- include docs_version_badge.html version="4.4.0" -%} +{: #marking-specific-lines } + +You can mark specific lines in a code snippet by using the optional +argument `mark_lines`. This argument takes a space-separated list of +line numbers which must be wrapped in double quotes. For example, the +following code block will mark lines 1 and 2 but not line 3: + +{% raw %} +```liquid +{% highlight ruby mark_lines="1 2" %} +def foo + puts 'foo' +end +{% endhighlight %} +``` +{% endraw %} + +A default class name of `hll` will be applied to the marked lines. + +### Stylesheets for syntax highlighting + +In order for the highlighting to show up, you’ll need to include a highlighting +stylesheet. For Pygments or Rouge you can use a stylesheet for Pygments, you +can find an example gallery +[here](https://jwarby.github.io/jekyll-pygments-themes/languages/ruby.html) +or from [its repository](https://github.com/jwarby/jekyll-pygments-themes). + +Copy the CSS file (`native.css` for example) into your css directory and import +the syntax highlighter styles into your `main.css`: + +```css +@import "native.css"; +``` + +## Links + +{: .note} +Since Jekyll {% include docs_version_badge.html version="4.0"%}, you don't need to prepend `link` and `post_url` tags with `site.baseurl`. + +### Linking to pages {#link} + +To link to a post, a page, collection item, or file, the `link` tag will generate the correct permalink URL for the path you specify. For example, if you use the `link` tag to link to `mypage.html`, even if you change your permalink style to include the file extension or omit it, the URL formed by the `link` tag will always be valid. + +You must include the file's original extension when using the `link` tag. Here are some examples: + +{% raw %} +```liquid +{% link _collection/name-of-document.md %} +{% link _posts/2016-07-26-name-of-post.md %} +{% link news/index.html %} +{% link /assets/files/doc.pdf %} +``` +{% endraw %} + +You can also use the `link` tag to create a link in Markdown as follows: + +{% raw %} +```liquid +[Link to a document]({% link _collection/name-of-document.md %}) +[Link to a post]({% link _posts/2016-07-26-name-of-post.md %}) +[Link to a page]({% link news/index.html %}) +[Link to a file]({% link /assets/files/doc.pdf %}) +``` +{% endraw %} + +The path to the post, page, or collection is defined as the path relative to the root directory (where your config file is) to the file, not the path from your existing page to the other page. + +For example, suppose you're creating a link in `page_a.md` (stored in `pages/folder1/folder2`) to `page_b.md` (stored in `pages/folder1`). Your path in the link would not be `../page_b.html`. Instead, it would be `/pages/folder1/page_b.md`. + +If you're unsure of the path, add {% raw %}`{{ page.path }}`{% endraw %} to the page and it will display the path. + +One major benefit of using the `link` or `post_url` tag is link validation. If the link doesn't exist, Jekyll won't build your site. This is a good thing, as it will alert you to a broken link so you can fix it (rather than allowing you to build and deploy a site with broken links). + +Note you cannot add filters to `link` tags. For example, you cannot append a string using Liquid filters, such as {% raw %}`{% link mypage.html | append: "#section1" %}`{% endraw %}. To link to sections on a page, you will need to use regular HTML or Markdown linking techniques. + +The name of the file you want to link can be specified as a variable instead of an actual file name. For example, suppose you defined a variable in your page's front matter like this: + +```yaml +--- +title: My page +my_variable: footer_company_a.html +--- +``` + +You could then reference that variable in your link: + +{% raw %} +```liquid +{% link {{ page.my_variable }} %} +``` +{% endraw %} + +In this example, the `link` tag would render a link to the file `footer_company_a.html`. + +### Linking to posts + +If you want to include a link to a post on your site, the `post_url` tag will generate the correct permalink URL for the post you specify. + +{% raw %} +```liquid +{% post_url 2010-07-21-name-of-post %} +``` +{% endraw %} + +If you organize your posts in subdirectories, you need to include subdirectory path to the post: + +{% raw %} +```liquid +{% post_url /subdir/2010-07-21-name-of-post %} +``` +{% endraw %} + +There is no need to include the file extension when using the `post_url` tag. + +You can also use this tag to create a link to a post in Markdown as follows: + +{% raw %} +```liquid +[Name of Link]({% post_url 2010-07-21-name-of-post %}) +``` +{% endraw %} + +Now lets say you have a [datafile]({{ '/docs/datafiles/' | relative_url }}) `_data/cool_posts.yaml` used to keep track +of certain posts that you intend to be listed as say *Cool Posts*: + +```yaml +- title: "An Awesome Post" + slug: "2010-07-21-name-of-post" +- title: "Another Awesome Post" + slug: "2016-07-26-name-of-post" +``` + +You may list such posts using the `post_url` tag as well (from {%- include docs_version_badge.html version="4.5.0" -%}): + +{% raw %} +```liquid +Cool posts: + +{%- for cool_post in site.data.cool_posts %} +- [{{ cool_post.title }}]({% post_url {{ cool_post.slug }} %}) +{%- endfor %} +``` +{% endraw %} diff --git a/docs/_docs/maintaining/affinity-team-captain.md b/docs/_docs/maintaining/affinity-team-captain.md new file mode 100644 index 00000000000..a1d982f9e85 --- /dev/null +++ b/docs/_docs/maintaining/affinity-team-captain.md @@ -0,0 +1,28 @@ +--- +title: Affinity Team Captains +--- + +**This guide is for affinity team captains.** These special people are **team maintainers** of one of our [affinity teams][] and help triage and evaluate the issues and contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +## Affinity teams & their captains + +The Jekyll project uses [affinity teams][] to help break up the work of incoming issues and pull requests from community members. We receive a sizeable number of issues and pull requests each week; the use of affinity teams helps distribute this load across a number of specialized groups instead of pushing it all onto @jekyll/core. + +## Responsibilities of Team Captains + +Each affinity team has a few captains who manage the issues and pull requests for that team. When an issue or PR is opened with a `/cc` for a given affinity team, @jekyllbot automatically assigns a random affinity team captain to the issue to triage it. They have access to add labels, reassign the issue, give LGTM's, and so forth. While they do not merge PR's today, they are still asked to review PR's for parts of the codebase under their purview. + +## How do I become a team captain? + +Just ask! Feel free to open an issue on `jekyll/jekyll` and add `/cc @jekyll/core`. We can add you. :smile: + +Alternatively, you can email or otherwise reach out to [@oe](https://github.com/oe) directly if you prefer the more private route. + +## Ugh, I'm tired and don't have time to be a captain anymore. What now? + +No sweat at all! Email [@oe](https://github.com/oe) and ask to be removed. Alternatively, you should be able to go to your team's page on GitHub.com (go to https://github.com/jekyll, click "Teams", click the link to your team) and change your status to either "member" or leave the team. + +We realize that being a captain is no easy feat so we want to make it a great experience. As always, communicate as much as you can with us about what is working, and what isn't. Thanks for dedicating some time to Jekyll! :sparkles: + +[affinity teams]: https://teams.jekyllrb.com/ diff --git a/docs/_docs/maintaining/avoiding-burnout.md b/docs/_docs/maintaining/avoiding-burnout.md new file mode 100644 index 00000000000..42f4b7d3207 --- /dev/null +++ b/docs/_docs/maintaining/avoiding-burnout.md @@ -0,0 +1,30 @@ +--- +title: "Avoiding Burnout" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +# 1. Use Jekyll + +Maintainers of Jekyll should be using it regularly. This is partly because you won't be a good maintainer unless you can put yourself in the shoes of our users, but also because you may at some point decide to stop using Jekyll, and at that point you should also decide to stop being a maintainer and find other things to work on. + +# 2. No Guilt About Leaving + +All maintainers can stop working on Jekyll at any time without any guilt or explanation (like at a job). We may still ask for your help with questions after you leave but you are under no obligation to answer them. If you create a big mess and then leave you still have no obligations but we may think less of you (or, realistically, probably just revert the problematic work). Also, you should probably take a break from Jekyll at least a few times a year. + +This also means contributors should be consumers. If a maintainer finds they are not using a project in the real-world, they should reconsider their involvement with the project. + +# 3. Prioritise Maintainers Over Users + +It's important to be user-focused but ultimately, as long as you follow #1 above, Jekyll's minimum number of users will be the number of maintainers. However, if Jekyll has no maintainers it will quickly become useless to all users and the project will die. As a result, no user complaint, behaviour or need takes priority over the burnout of maintainers. If users do not like the direction of the project, the easiest way to influence it is to make significant, high-quality code contributions and become a maintainer. + +# 4. Learn To Say No + +Jekyll gets a lot of feature requests, non-reproducible bug reports, usage questions and PRs we won't accept. These should be closed out as soon as we realise that they aren't going to be resolved or merged. This is kinder than deciding this after a long period of review. Our issue tracker should reflect work to be done. + +--- + +Thanks to https://gist.github.com/ryanflorence/124070e7c4b3839d4573 which influenced this document. + +Thanks to [Homebrew's "Avoiding Burnout" document](https://github.com/Homebrew/brew/blob/master/docs/Maintainers-Avoiding-Burnout.md) for providing a perfect base for this document. diff --git a/docs/_docs/maintaining/becoming-a-maintainer.md b/docs/_docs/maintaining/becoming-a-maintainer.md new file mode 100644 index 00000000000..e8a45d29d0e --- /dev/null +++ b/docs/_docs/maintaining/becoming-a-maintainer.md @@ -0,0 +1,38 @@ +--- +title: "Becoming a Maintainer" +--- + +**This guide is for contributors.** These special people have contributed to one or more of Jekyll's repositories, but do not yet have write access to any. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +So you want to become a maintainer of a Jekyll project? We'd love to have you! Here are some things we like to see from community members before we promote them to maintainers. + +## 1. Use Jekyll + +You want to maintain Jekyll? Use it often. Do weird things with it. Do normal things with it. Does it work? Does it have any weaknesses? Is there a gap in the product that you think should be filled? + +## 2. Help Triage Issues + +Watch the repository you're interested in. Join [an Affinity Team](https://teams.jekyllrb.com) and receive mentions regarding a particular interest area of the project. When you receive a notification for an issue that has not been triaged by a maintainer, dive in. Can you reproduce the issue? Can you determine the fix? [More tips on Triaging an Issue in our maintainer guide](../triaging-an-issue/). Every maintainer loves an issue that is resolved before they get to it. :smiley: + +## 3. Write Documentation + +Good documentation means less confusion for our users and fewer issues to triage. Documentation is always in need of fixes and updates as we change the code. Read through the documentation during your normal usage of the product and submit changes as you feel they are necessary. + +## 4. Write Code + +As a maintainer, you will be reviewing pull requests which update code. You should feel comfortable with the Jekyll codebase enough to confidently review any pull request put forward. In order to become more comfortable, write some code of your own and send a pull request. A great place to start is with any issue labeled "bug" in the issue tracker. Write a test which replicates the problem and fails, then work on fixing the code such that the test passes. + +## 5. Review Pull Requests + +Start by reviewing one pull request a week. Leave detailed comments and [follow our guide for reviewing pull requests](../reviewing-a-pull-request/). + +## 6. Ask! + +Open an issue describing your contributions to the project and why you wish to be a maintainer. Issues are nice because you can easily reference where you have demonstrated that you help triage issues, write code & documentation, and review pull requests. You may also email any maintainer privately if you do not feel comfortable asking in the open. + +We would love to expand the team and look forward to many more community members becoming maintainers! + +# Helping Out Elsewhere + +In addition to maintainers of our core and plugin code, the Jekyll team is comprised of moderators for our forums. These helpful community members take a look at the topics posted to [https://talk.jekyllrb.com](https://talk.jekyllrb.com) and ensure they are properly categorized and are acceptable under our Code of Conduct. If you would like to be a moderator, email one of the maintainers with links to where you have answered questions and a request to be added as a moderator. More help is always welcome. diff --git a/docs/_docs/maintaining/index.md b/docs/_docs/maintaining/index.md new file mode 100644 index 00000000000..e7a1b607d50 --- /dev/null +++ b/docs/_docs/maintaining/index.md @@ -0,0 +1,22 @@ +--- +title: Maintaining Jekyll +permalink: /docs/maintaining/ +--- + +**This guide is for Jekyll contributors and maintainers.** These special people contribute to one or more of Jekyll's repositories or help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +Hello! This is where we document various processes for maintaining Jekyll. Being a maintainer for any Jekyll project is a big responsibility, so we put together some helpful documentation for various tasks you might do as a maintainer. + +- [Affinity teams & their captains](affinity-team-captain/) +- [Triaging an issue](triaging-an-issue/) +- [Reviewing a pull request](reviewing-a-pull-request/) +- [Merging a pull request](merging-a-pull-request/) +- [Avoiding burnout](avoiding-burnout/) +- [Special Labels](special-labels/) +- [Releasing a new version](releasing-a-new-version/) +- [Releasing a new version off `*-stable` branches](releasing-off-stable-branches/) + +Interested in becoming a maintainer? Here is some documentation for **contributors**: + +- [Becoming a maintainer](becoming-a-maintainer/) diff --git a/docs/_docs/maintaining/merging-a-pull-request.md b/docs/_docs/maintaining/merging-a-pull-request.md new file mode 100644 index 00000000000..603194cf816 --- /dev/null +++ b/docs/_docs/maintaining/merging-a-pull-request.md @@ -0,0 +1,55 @@ +--- +title: "Merging a Pull Request" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +## Code Review + +All pull requests should be subject to code review. Code review is a [foundational value](https://blog.fullstory.com/what-we-learned-from-google-code-reviews-arent-just-for-catching-bugs/) of good engineering teams. Besides providing validation of correctness, it promotes a sense of community and gives other maintainers understanding of all parts of the code base. In short, code review is crucial to a healthy open source project. + +**Read our guide for [Reviewing a pull request](../reviewing-a-pull-request/) before merging.** Notably, the change must have tests if for code, and at least two maintainers must give it an OK. + +## Merging + +We have [a helpful little bot](https://github.com/jekyllbot) which we use to merge pull requests. We don't use the GitHub.com interface for two reasons: + +1. You can't modify anything on mobile (e.g. titles, labels) +2. We like to provide a consistent paper trail in the `History.markdown` file for each release + +To merge a pull request, leave a comment thanking the contributor, then add the special merge request: + +``` +Thank you very much for your contribution. Folks like you make this project and community strong. :heart: + +@jekyllbot: merge +dev +``` + +The merge request is made up of three things: + +1. `@jekyllbot:` – this is the prefix our bot looks for when processing commands +2. `merge` – the command +3. `+dev` – the category to which the changes belong. + +The categories match the headings in the `History.markdown` file, and they are: + +1. Major Enhancements (`+major`) – major updates or breaking changes to the code which necessitate a major version bump (v3 ~> v4) +2. Minor Enhancements (`+minor`) – minor updates (with the labels `feature` or `enhancement`) which necessitate a minor version bump (v3.1 ~> v3.2) +3. Bug Fixes (`+bug`) – corrections to code which do not change or add functionality, which necessitate a patch version bump (v3.1.0 ~> v3.1.1) +4. Documentation (`+doc`) - changes to the documentation found in `docs/_docs/` +5. Site Enhancements (`+site`) – changes to the source of [https://jekyllrb.com](https://jekyllrb.com) found in `docs/` +6. Development Fixes (`+dev`) – changes which do not affect user-facing functionality or documentation, such as test fixes or bumping internal dependencies +7. Forward Ports (`+port`) — bug fixes applied to a previous version of Jekyll pulled onto `master`, e.g. cherry-picked commits from `3-1-stable` to `master` + +Once @jekyllbot has merged the pull request, you should see three things: + +1. A successful merge +2. Addition of labels for the necessary category if they aren't already applied +3. A commit to the `History.markdown` file which adds a note about the change + +If you forget the category, that's just fine. You can always go back and move the line to the proper category header later. The category is always necessary for `jekyll/jekyll`, but many plugins have too few changes to necessitate changelog categories. + +## Rejoice + +You did it! Thanks for being a maintainer for one of our official Jekyll projects. Your work means the world to our thousands of users who rely on Jekyll daily. :heart: diff --git a/docs/_docs/maintaining/releasing-a-new-version.md b/docs/_docs/maintaining/releasing-a-new-version.md new file mode 100644 index 00000000000..1d8c34713bf --- /dev/null +++ b/docs/_docs/maintaining/releasing-a-new-version.md @@ -0,0 +1,162 @@ +--- +title: "Releasing a new version" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the +contributions of others. You may find what is written here interesting, but it's definitely not for everyone. +{: .note .info} + +The most important thing to understand before making a release is that there's no need to feel nervous. Most things are revertable, and even if +you do publish an incomplete gem version, we can always skip that one. Don't hesitate to contact the other maintainers if you feel unsure or +don't know what to do next. + +### Bump the version + +The only important place you need to manually bump the version is in `lib/jekyll/version.rb`. Adjust that, and everything else should work fine. + +The version will mostly be of the format `"major.minor.patch"`. At times, we may decide to ship pre-releases which will be in the format +`"major.minor.patch.suffix"`. `suffix` is not standardized and may be anything like `pre.alpha1`, `pre.rc2`, or simply `beta3`, etc. + +To determine the correct version, consult the `## HEAD` section of our history document, `History.markdown`, first. + +- If there's a subsection titled `Major Enhancements` + - Increment the `major` component of the version string and reset both `minor` and `patch` components to `0`. + - Add `suffix` if applicable. + - For example, `"3.9.1" => "4.0.0"` or, `"3.9.1 => "4.0.0.alpha1"`. + - Skip to next step in the release process. + +- If there's a subsection titled `Minor Enhancements` + - Increment just the `minor` component and reset the patch component to `0`. + - Add `suffix` if applicable. + - For example, `"4.0.2" => "4.1.0"` or `"4.1.0" => "4.2.0.pre"`. + - Skip to next step in the release process. + +- For anything else, increment just the `patch` component or `suffix` component as applicable. For example, `"4.0.2" => "4.0.3"` or + `"4.1.0.beta3" => "4.1.0.rc"`. + +### Write a release post + +In case this wasn't done already, you can generate a new release post scaffold using the included `rake` command: + +```sh +bundle exec rake site:releases:new[3.8.0] +``` + +where `3.8.0` should be replaced with the new version. + +Then, write the post. Be sure to thank all of the collaborators and maintainers who have contributed since the last release. You can generate +a log of their names using the following command: + +```sh +git shortlog -sn master...v3.7.2 +``` + +where `v3.7.2` is the git tag for the previous release. In case the tag doesn't exist in your repository, run: + +```sh +git pull +``` + +Be sure to open a pull request for your release post once its finished. + +### Update the History document + +Replace the first header of `History.markdown` with a version milestone. This looks like the following: + +```diff +- ## HEAD ++ ## 3.7.1 / 2018-01-25 +``` + +Adjust the version number and the date. The `## HEAD` heading will be regenerated the next time a pull request is merged. + +Rearrange the subsections (as a whole) based on decreasing priorities as illustrated below: + +``` +## 4.2.0 / 2020-12-14 + +### Major Enhancements + +... + +### Minor Enhancements + +... + +### Bug Fixes + +... + +### Security Fixes + +... + +### Optimization Fixes + +... + +### Development Fixes + +... + +### Site Enhancements + +... +``` + +Once you've done this, update the website by running the following command: + +```sh +bundle exec rake site:generate +``` + +This updates the website's changelog, and pushes the versions in various other places. + +It's recommended that you go over the `History.markdown` file manually one more time, in case there are any spelling errors or such. Feel free +to fix those manually, and after you're done generating the website changelog, commit your changes. + +### Push the version + +Before you do this step, make sure the following things are done: + +- A release post has been prepared, and is ideally already live via a prior pull request. +- All of the prior steps are done, especially the change to `lib/jekyll/version.rb` has been staged for commit. +- Commit staged changes to the local `master` branch preferably with commit message `"Release :gem: v[CURRENT_VERSION]"`. + +The only thing left to do now is to run this command: + +```sh +git push upstream master +``` + +where `upstream` references `git@github.com:jekyll/jekyll.git`. + +This will trigger a GitHub Actions workflow that will automatically build the new gem, tag the release commit, push the tag to GitHub and +then finally, push the new gem to RubyGems. Don't worry about creating a GitHub release either, @jekyllbot will take care of that when the +release workflow publishes the new tag. + +And then, if the workflow has completed successfully, you're done! :tada: +Feel free to celebrate! + +If you have access to the [@jekyllrb](https://twitter.com/jekyllrb) Twitter account, you should tweet the release post from there. If not, just +ask another maintainer to do it or to give you access. + +### Build the docs + +We package our documentation as a :gem: Gem for offline use. + +This is done with the [**jekyll-docs**](https://github.com/jekyll/jekyll-docs#building) repository, and more detailed instructions are +provided there. + +## For non-core gems + +If you're not a maintainer for `jekyll/jekyll`, the procedure is much simpler in a lot of cases. Generally, the procedure still looks like +this: + +- Bump the gem version manually, usually in `lib//version.rb` +- Adjust the history file +- Commit changes to default branch preferably with message `"Release :gem: v[CURRENT_VERSION]"` +- Push to remote repository +- Rejoice + +Be sure to ask your project's maintainers if you're unsure! diff --git a/docs/_docs/maintaining/releasing-off-stable-branches.md b/docs/_docs/maintaining/releasing-off-stable-branches.md new file mode 100644 index 00000000000..1fa16fa4971 --- /dev/null +++ b/docs/_docs/maintaining/releasing-off-stable-branches.md @@ -0,0 +1,63 @@ +--- +title: Releasing off older stable branches +--- + +Apart from having releases cut from the default `master` branch, Jekyll Core may occasionally cut releases containing security patches and +critical bug-fixes for older versions under maintenance. Such releases are cut from specially named branches, following the pattern +`[x].[y]-stable` where `[x]` denotes semver-major-version and `[y]`, the semver-minor-version. For example, the branch `3.9-stable` refers to +commits released as part of `jekyll-3.9.x` series. + +Co-ordinating a release off a `*-stable` branch is complicated mainly because the default branch has to inevitably reflect the release as well. + +## Requirements + +- The maintainer has to have **write-access** to both the concerned `*-stable` and `master` branches. +- The maintainer needs to complete the task using their **local CLI program** instead of dispatching via GitHub Web UI. +- The maintainer is abreast with the workflow to [release off `master`]({{ 'docs/maintaining/releasing-a-new-version/' | relative_url }}). The + procedure documented in the following section is an abridged adaptation of the workflow for `master`. +- A release post has been drafted and **is awaiting publish to `master`** via an approved pull request. +- Stable internet connection. + +## Trigger release workflow + +1. Ensure that you've **checked out the concerned `*-stable` branch** and is up-to-date with its counterpart at `jekyll/jekyll` at GitHub. +2. Bump the `VERSION` string in `lib/jekyll/version.rb`. +3. Update the **History document** as documented [here]({{ 'docs/maintaining/releasing-a-new-version/#update-the-history-document' | relative_url }}).
+ (**IMPORTANT: Do not run `rake site:generate` on the stable branch though**). +4. Copy the entire History section pertaining to current release and paste into a new tab / window of your text-editor. We will use this + temporary snippet at a future stage. +5. Commit changes to the version-file and History document with commit message `Release :gem: v[CURRENT_VERSION]`. +6. Push commit to upstream remote `jekyll/jekyll` at GitHub. + +## Publish release post + +1. Ensure the `Release Gem` workflow has completed successfully. +2. Merge release-post pull request to `master`. + +## Update default branch to reflect release off the stable branch + +1. Locally, check out `master` and ensure it is up-to-date with its remote counterpart at `jekyll/jekyll` at GitHub. +2. Update History document using the snippet in the temporary tab / window created earlier. The various sections in the History document are + primarily in reverse chronological order and secondarily scoped to the semver-major-version. For example, a release section for `v3.9.2` + will be listed above the section for `v3.9.1` but under release sections for v4.x. + The snippet stashed earlier has to be injected into the correct location manually. +3. Optionally, update `VERSION` string in `lib/jekyll/version.rb`. (*If existing version is lesser than latest version*). +4. Now **run `rake site:generate`** to update various meta files: + - docs/_config.yml + - docs/_docs/history.md + - docs/latest_version.txt +5. Commit changes to various meta files with commit message `Release :gem: v[CURRENT_VERSION]`. +6. Push commit to upstream remote. + +## Publish GitHub Release + +Unlike releases cut off the `master` branch, our JekyllBot does not automatically create and publish a GitHub Release for tags created from +*non-default* branches. Therefore, the maintainer has to **manually create and publish** the concerned GitHub Release. +1. Choose the newly pushed tag. +2. Title is same as the name of the selected tag. +3. The release snippet stashed previously forms the body. +4. Delete the snippet's title (`## x.y.z / YYYY-MM-DD`) from the release body. +5. Publish. + +Note: The GitHub Release may optionally be *drafted* prior to updating the default branch and then *published* immediately after pushing the +update commit to the default branch to streamline the procedure. diff --git a/docs/_docs/maintaining/reviewing-a-pull-request.md b/docs/_docs/maintaining/reviewing-a-pull-request.md new file mode 100644 index 00000000000..cff0efd3874 --- /dev/null +++ b/docs/_docs/maintaining/reviewing-a-pull-request.md @@ -0,0 +1,46 @@ +--- +title: "Reviewing a Pull Request" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +## Respond Kindly + +Above all else, please review a pull request kindly. Our community can only be strong if we make it a welcoming and inclusive environment. To further promote this, the Jekyll community is governed by a [Code of Conduct](/docs/conduct/) by which all community members must abide. + +Use emoji liberally :heart: :tada: :sparkles: :confetti_ball: and feel free to be emotive!! Contributions keep this project moving forward and we're always happy to receive them, even if the pull request isn't ultimately merged. + +Mike McQuaid's post on the GitHub blog entitled ["Kindly Closing Pull Requests"](https://github.com/blog/2124-kindly-closing-pull-requests) is a great place to start. It describes various scenarios in which it would be acceptable to close a pull request for reasons other than lack of technical integrity or accuracy. Part of being kind is responding to and resolving pull requests quickly. + +## Respond Quickly + +We should be able to review all pull requests within one week. The only time initial review should take longer is if all the maintainers mysteriously took vacation during the same week. Promptness encourages frequent, high-quality contributions from community members and other maintainers. + +If your response requires a response on the part of the author, please add the `pending-feedback` tag. @jekyllbot will automatically remove the tag once the author of the pull request responds. + +## Resolve Quickly + +Similarly, we should aim to resolve pull requests quickly. If a pull request introduces a feature which does not fit into the core purpose or goal of the project, close it promptly with a kind explanation of why it is not acceptable. + +Leave detailed comments wherever possible. Provide the contributor with context around why the change you are requesting is necessary, or why the question you are asking is important to resolve. The more context we can clearly communicate to the contributor, the better able the contributor is to provide high-quality patches. + +You may close a pull request if more than 30 days pass without a response from the author. + +In some cases, review will involve many weeks of back-and-forth. As long as communication continues, this is fine. Ideally, any PR would be capable of resolution within 30 days of it being opened. + +## Look for Tests + +If this is a code change, are there tests for the updated or added behaviour? Shipping a version with bugs is inevitable, but ensuring changes are tested helps keep bugs and regressions to a minimum. + +## CI Must Pass + +It is fine to ask a contributor to investigate failures on Travis and patch them up before you begin your review. It is helpful to leave a message for the contributor indicating that the tests have failed and that no review will occur before the tests pass. If they ask for help, take a look and assist if you can. + +## Rule of Two + +A pull request may be merged once two maintainers have reviewed the pull request and indicated that it is acceptable to them. There is no need to wait for a third unless one of the two reviewers wishes for another set of eyes. + +## Think Security + +We owe it to our users to ensure that using a theme from the community or building someone else's site doesn't come with built-in security vulnerabilities. Things like where files may be read from and written to are important to keep secure. Jekyll is also the basis for hosted services such as [GitHub Pages](https://pages.github.com), which cannot upgrade when security issues are introduced. diff --git a/docs/_docs/maintaining/special-labels.md b/docs/_docs/maintaining/special-labels.md new file mode 100644 index 00000000000..4d89841f6cf --- /dev/null +++ b/docs/_docs/maintaining/special-labels.md @@ -0,0 +1,24 @@ +--- +title: "Special Labels" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +We use a series of "special labels" on GitHub.com to automate handling of some parts of the pull request and issue process. @jekyllbot may automatically apply or remove certain labels based on actions taken by users or maintainers. Below are the labels and how they work: + +## `pending-feedback` + +This label is used to indicate that we need more information from the issue/PR author in order to continue. It may be that you need more info before you can properly triage a bug report, or that you have some unanswered questions about a PR that need to be resolved before moving forward. You can safely ignore any issue with this label, as it is waiting for feedback. + +## `needs-work` & `pending-rebase` + +These labels are used to indicate that the Git state of a pull request must change. Both are removed once a push is registered (a "synchronize" event for the pull request) and the pull request becomes mergable. Add `needs-work` to a PR if, after your review, it requires code changes. Add `pending-rebase` to a PR if the code is fine but the branch is not automatically mergable with the target branch (e.g. `master`). + +## `stale` + +This label is automatically added and removed by @jekyllbot based on activity on an issue or pull request. The rules for this label are laid out in [Triaging an Issue: Staleness and automatic closure](../triaging-an-issue/#staleness-and-automatic-closure). + +## `pinned` + +This label is for @jekyllbot to ignore the age of the issue, which means that the `stale` label won't be automatically added, and the issue won't be closed after a while. This needs to be set manually, and should be set with care. (The `has-pull-request` label does the same thing, but shouldn't be used to _only_ keep an issue open) diff --git a/docs/_docs/maintaining/triaging-an-issue.md b/docs/_docs/maintaining/triaging-an-issue.md new file mode 100644 index 00000000000..b797ff01975 --- /dev/null +++ b/docs/_docs/maintaining/triaging-an-issue.md @@ -0,0 +1,54 @@ +--- +title: "Triaging an Issue" +--- + +**This guide is for maintainers.** These special people have **write access** to one or more of Jekyll's repositories and help merge the contributions of others. You may find what is written here interesting, but it’s definitely not for everyone. +{: .note .info} + +Before evaluating an issue, it is important to identify if it is a feature +request or a bug. For the Jekyll project the following definitions are used +to identify a feature or a bug: + +**Feature** - A feature is defined as a request that adds functionality to +Jekyll outside of its current capabilities. +**Bug** - A bug is defined as an issue that identifies an error that a user +(or users) encounter when using current Jekyll functionalities. + +## Feature? + +If the issue describes a feature request, ask: + +1. Is this a setting? [Settings are a crutch](http://ben.balter.com/2016/03/08/optimizing-for-power-users-and-edge-cases/#settings-are-a-crutch) for doing "the right thing". Settings usually point to a bad default or an edge case that could be solved easily with a plugin. Keep the :christmas_tree: of settings as small as possible so as not to reduce the usability of the product. We like the philosophy "decisions not options." +2. Would at least 80% of users find it useful? If even a quarter of our users won't use it, it's very likely that the request doesn't fit our product's core goal. +3. Is there another way to accomplish the end goal of the request? Most feature requests are due to bad documentation for or understanding of a preexisting feature. See if you can clarify the end goal of the request. What is the user trying to do? Could they accomplish that goal through another feature we already support? +4. Even if 80% of our users will use it, does it fit the core goal of our project? We are writing a tool for making static websites, not a swiss army knife for publishing more generally. + +Feel free to get others' opinions and ask questions of the issue author, but depending upon the answers to the questions above, it may be out of scope for our project. + +If the request is within scope, prioritize it on the product roadmap with the other maintainers. Apply the appropriate tags and ensure the right people have weighed in to define the feature's scope and implementation. If you want to be the _best ever_, submit a PR yourself which adds the feature. + +## Bug? + +### Reproducibility + +If the bug has clear reproduction steps, take a minute to try them. If it helps, write a test in our test suite for the scenario which replicates the problem. Can you reliably replicate the issue? + +If you can't replicate the issue, post your replication steps which didn't work and ask for clarification from the issue author. + +### Supported Platform + +Is the author using a supported platform? We support the latest versions of macOS, Ubuntu, Debian, CentOS, Fedora, and Arch Linux. + +You may close the issue immediately if the author cannot reproduce the issue on a supported platform. For Windows-related problems, leave a comment letting the user know that Windows is not officially supported, but that they may absolutely continue using the issue to communicate with folks from `@jekyll/windows` to further investigate. Additionally, you can point them to Jekyll Talk (https://talk.jekyllrb.com) as a means of getting support from the community. + +If the user is experiencing issues with GitHub Pages or another hosted platform that we cannot reproduce, please direct them to the platform's support channel and close the issue. + +### What they wanted vs. what they got + +An issue without a clear explanation of what the user got and what they were expecting to get is not an issue we can accurately respond to. If the user doesn't provide this information, please ask for clarification and apply the `pending-feedback` label. This information helps us build test cases such that we do not break the behaviour again in the future. The `pending-feedback` label will be removed automatically once the issue author posts a reply. + +Is what they wanted to get something we want to happen? Sometimes a bug report is actually masquerading as a feature request. See the guidance above for handling feature requests. + +### Staleness and automatic closure + +@jekyllbot will automatically mark issues as `stale` if no activity occurs for at least one month. @jekyllbot leaves a comment asking for information about reproducibility in current versions. If no one responds after another month, the issue is automatically closed. This behavior can be suppressed by setting the [`pinned` label](/docs/maintaining/special-labels/#pinned). diff --git a/docs/_docs/markdown-101.md b/docs/_docs/markdown-101.md new file mode 100644 index 00000000000..c1090dbb873 --- /dev/null +++ b/docs/_docs/markdown-101.md @@ -0,0 +1,6 @@ +--- +title: Markdown 101 +permalink: /docs/markdown-101/ +--- + +# TO WRITE diff --git a/site/_docs/migrations.md b/docs/_docs/migrations.md similarity index 63% rename from site/_docs/migrations.md rename to docs/_docs/migrations.md index 0544341ac5d..c3a69caef84 100644 --- a/site/_docs/migrations.md +++ b/docs/_docs/migrations.md @@ -1,9 +1,8 @@ --- -layout: docs -title: Blog migrations +title: Blog Migrations permalink: /docs/migrations/ --- If you’re switching to Jekyll from another blogging system, Jekyll’s importers can help you with the move. To learn more about importing your site to Jekyll, -visit our [`jekyll-import` docs site](http://import.jekyllrb.com/docs/home/). +visit our [`jekyll-import` docs site](https://import.jekyllrb.com/docs/home/). diff --git a/docs/_docs/pages.md b/docs/_docs/pages.md new file mode 100644 index 00000000000..b4f771d939c --- /dev/null +++ b/docs/_docs/pages.md @@ -0,0 +1,40 @@ +--- +title: Pages +permalink: /docs/pages/ +--- + +Pages are the most basic building block for content. They're useful for standalone +content (content which is not date based or is not a group of content such as staff +members or recipes). + +The simplest way of adding a page is to add an HTML file in the root +directory with a suitable filename. You can also write a page in Markdown using +a `.md` extension and front matter which converts to HTML on build. For a site with +a homepage, an about page, and a contact page, here’s what the root directory +and associated URLs might look like: + +``` +. +├── about.md # => http://example.com/about.html +├── index.html # => http://example.com/ +└── contact.html # => http://example.com/contact.html +``` + +If you have a lot of pages, you can organize them into subfolders. The same subfolders that are used to group your pages in your project's source will then exist in the `_site` folder when your site builds. However, when a page has a *different* permalink set in the front matter, the subfolder at `_site` changes accordingly. + +``` +. +├── about.md # => http://example.com/about.html +├── documentation # folder containing pages +│ └── doc1.md # => http://example.com/documentation/doc1.html +├── design # folder containing pages +│ └── draft.md # => http://example.com/design/draft.html +``` + +## Changing the output URL + +You might want to have a particular folder structure for your source files that changes for the built site. With [permalinks](/docs/permalinks/) you have full control of the output URL. + +## Excerpts for pages {%- include docs_version_badge.html version="4.1.1" -%} + +One can *choose* to generate excerpts for their pages by setting `page_excerpts` to `true` in their config file. diff --git a/site/_docs/pagination.md b/docs/_docs/pagination.md similarity index 54% rename from site/_docs/pagination.md rename to docs/_docs/pagination.md index 25482d01a32..11a80d0a2c6 100644 --- a/site/_docs/pagination.md +++ b/docs/_docs/pagination.md @@ -1,5 +1,4 @@ --- -layout: docs title: Pagination permalink: /docs/pagination/ --- @@ -9,13 +8,14 @@ break the main listing of posts up into smaller lists and display them over multiple pages. Jekyll offers a pagination plugin, so you can automatically generate the appropriate files and folders you need for paginated listings. -For Jekyll 3, include the `jekyll-paginate` plugin in your Gemfile and in -your `_config.yml` under `gems`. For Jekyll 2, this is standard. +For Jekyll 3 or higher, include the `jekyll-paginate` plugin in your +Gemfile and in your `_config.yml` under `plugins`. For Jekyll 2, this is +standard.
Pagination only works within HTML files

- Pagination does not work from within Markdown or Textile files from + Pagination does not work from within Markdown files from your Jekyll site. Pagination works when called from within the HTML file, named index.html, which optionally may reside in and produce pagination from within a subdirectory, via the @@ -25,28 +25,28 @@ your `_config.yml` under `gems`. For Jekyll 2, this is standard. ## Enable pagination -To enable pagination for your blog, add a line to the `_config.yml` file that +To enable pagination for posts on your blog, add a line to the `_config.yml` file that specifies how many items should be displayed per page: -{% highlight yaml %} +```yaml paginate: 5 -{% endhighlight %} +``` The number should be the maximum number of Posts you’d like to be displayed per-page in the generated site. You may also specify the destination of the pagination pages: -{% highlight yaml %} +```yaml paginate_path: "/blog/page:num/" -{% endhighlight %} +``` This will read in `blog/index.html`, send it each pagination page in Liquid as `paginator` and write the output to `blog/page:num/`, where `:num` is the -pagination page number, starting with `2`. If a site has 12 posts and specifies -`paginate: 5`, Jekyll will write `blog/index.html` with the first 5 posts, `blog/page2/index.html` with the next 5 posts -and `blog/page3/index.html` with the last 2 posts into the destination -directory. +pagination page number, starting with `2`.
+If a site has 12 posts and specifies `paginate: 5`, Jekyll will write `blog/index.html` +with the first 5 posts, `blog/page2/index.html` with the next 5 posts and +`blog/page3/index.html` with the last 2 posts into the destination directory.

Don't set a permalink
@@ -56,85 +56,29 @@ directory.

+
+
Pagination for categories, tags and collections
+

+ The more recent + jekyll-paginate-v2 plugin supports more features. See the + + pagination examples in the repository. This plugin is not + supported by GitHub Pages. +

+
+ ## Liquid Attributes Available The pagination plugin exposes the `paginator` liquid object with the following attributes: -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AttributeDescription

page

current page number

per_page

number of posts per page

posts

a list of posts for the current page

total_posts

total number of posts in the site

total_pages

number of pagination pages

previous_page

-

- page number of the previous pagination page, - or nil if no previous page exists -

-

previous_page_path

-

- path of previous pagination page, - or nil if no previous page exists -

-

next_page

-

- page number of the next pagination page, - or nil if no subsequent page exists -

-

next_page_path

-

- path of next pagination page, - or nil if no subsequent page exists -

-
-
+{% include docs_variables_table.html scope=site.data.jekyll_variables.paginator %}
Pagination does not support tags or categories

Pagination pages through every post in the posts - variable regardless of variables defined in the YAML Front Matter of - each. It does not currently allow paging over groups of posts linked + variable unless a post has hidden: true in its front matter. + It does not currently allow paging over groups of posts linked by a common tag or category. It cannot include any collection of documents because it is restricted to posts.

@@ -146,8 +90,8 @@ the `paginator` variable that will now be available to you. You’ll probably want to do this in one of the main pages of your site. Here’s one example of a simple way of rendering paginated Posts in a HTML file: -{% highlight html %} {% raw %} +```liquid --- layout: default title: My Blog @@ -167,19 +111,23 @@ title: My Blog +``` {% endraw %} -{% endhighlight %}
Beware the page one edge-case
@@ -193,12 +141,12 @@ title: My Blog The following HTML snippet should handle page one, and render a list of each page with links to all but the current page. -{% highlight html %} {% raw %} +```liquid {% if paginator.total_pages > 1 %} {% endif %} +``` {% endraw %} -{% endhighlight %} diff --git a/docs/_docs/permalinks.md b/docs/_docs/permalinks.md new file mode 100644 index 00000000000..2637ca950f2 --- /dev/null +++ b/docs/_docs/permalinks.md @@ -0,0 +1,170 @@ +--- +title: Permalinks +permalink: /docs/permalinks/ +--- + +Permalinks are the output path for your pages, posts, or collections. They +allow you to structure the directories of your source code different from the +directories in your output. + +## Front Matter + +The simplest way to set a permalink is using front matter. You set the +`permalink` variable in front matter to the output path you'd like. + +For example, you might have a page on your site located at +`/my_pages/about-me.html` and you want the output url to be `/about/`. In +front matter of the page you would set: + +```yaml +--- +permalink: /about/ +--- +``` + +## Global + +Setting a permalink in front matter for every page on your site is no fun. +Luckily, Jekyll lets you set the permalink structure globally in your `_config.yml`. + +To set a global permalink, you use the `permalink` variable in `_config.yml`. +You can use placeholders to your desired output. For example: + +```yaml +permalink: /:categories/:year/:month/:day/:title:output_ext +``` + +Note that pages and collections (excluding `posts` and `drafts`) don't have time +and categories (for pages, the above `:title` is equivalent to `:basename`), these +aspects of the permalink style are ignored for the output. + +For example, a permalink style of +`/:categories/:year/:month/:day/:title:output_ext` for the `posts` collection becomes +`/:title.html` for pages and collections (excluding `posts` and `drafts`). + +### Placeholders + +Here's the full list of placeholders available: + +
+ + + + + + + + + {%- for entry in site.data.permalinks.placeholders %} + + + + + {%- endfor %} + +
VariableDescription

:{{ entry.name }}

+ {%- if entry.intro_ver -%} + {% include docs_version_badge.html version = entry.intro_ver %} + {%- endif -%} +

{{ entry.desc }}

+
+ +### Built-in formats + +For posts, Jekyll also provides the following built-in styles for convenience: + +
+ + + + + + + + + {%- for entry in site.data.permalinks.builtin_formats %} + + + + + {%- endfor %} + +
Permalink StyleURL Template

{{ entry.name }}

+ {%- if entry.intro_ver -%} + {% include docs_version_badge.html version = entry.intro_ver %} + {%- endif -%} +
+

{{ entry.format }} + {%- if entry.note -%}
+ ({{ entry.note }}) + {%- endif -%} +

+
+
+ +Rather than typing `permalink: /:categories/:year/:month/:day/:title/`, you can just type `permalink: pretty`. + +
+
Specifying permalinks through the front matter
+

Built-in permalink styles are not recognized in front matter. As a result, permalink: pretty will not work.

+
+ +### Collections + +For collections (including `posts` and `drafts`), you have the option to override +the global permalink in the collection configuration in `_config.yml`: + +```yaml +collections: + my_collection: + output: true + permalink: /:collection/:name +``` + +Collections have the following placeholders available: + +
+ + + + + + + + + {%- for entry in site.data.permalinks.types.documents -%} + + + + + {%- endfor -%} + +
VariableDescription

:{{ entry.name }}

{{ entry.desc }}

+
+ +### Pages + +For pages, you have to use front matter to override the global permalink, +and if you set a permalink via front matter defaults in `_config.yml`, +it will be ignored. + +Pages have the following placeholders available: + +
+ + + + + + + + + {%- for entry in site.data.permalinks.types.pages -%} + + + + + {%- endfor -%} + +
VariableDescription

:{{ entry.name }}

{{ entry.desc }}

+
diff --git a/docs/_docs/plugins.md b/docs/_docs/plugins.md new file mode 100644 index 00000000000..52a86941676 --- /dev/null +++ b/docs/_docs/plugins.md @@ -0,0 +1,20 @@ +--- +title: Plugins +permalink: /docs/plugins/ +--- + +Jekyll has a plugin system with hooks that allow you to create custom generated +content specific to your site. You can run custom code for your site without +having to modify the Jekyll source itself. + +{: .note .info} +You can add specific plugins to the `whitelist` key in `_config.yml` to allow them to run in safe mode. + +* [Installation]({{ '/docs/plugins/installation/' | relative_url }}) - How to install plugins +* [Your first plugin]({{ '/docs/plugins/your-first-plugin/' | relative_url }}) - How to write plugins +* [Generators]({{ '/docs/plugins/generators/' | relative_url }}) - Create additional content on your site +* [Converters]({{ '/docs/plugins/converters/' | relative_url }}) - Change a markup language into another format +* [Commands]({{ '/docs/plugins/commands/' | relative_url }}) - Extend the `jekyll` executable with subcommands +* [Tags]({{ '/docs/plugins/tags/' | relative_url }}) - Create custom Liquid tags +* [Filters]({{ '/docs/plugins/filters/' | relative_url }}) - Create custom Liquid filters +* [Hooks]({{ '/docs/plugins/hooks/' | relative_url }}) - Fine-grained control to extend the build process diff --git a/docs/_docs/plugins/commands.md b/docs/_docs/plugins/commands.md new file mode 100644 index 00000000000..0666c779a5f --- /dev/null +++ b/docs/_docs/plugins/commands.md @@ -0,0 +1,62 @@ +--- +title: Commands +permalink: /docs/plugins/commands/ +--- +As of version {% include docs_version_badge.html version="2.5.0"%}, Jekyll can be extended with plugins which provide +subcommands for the `jekyll` executable. This is possible by including the +relevant plugins in a `Gemfile` group called `:jekyll_plugins`: + +```ruby +group :jekyll_plugins do + gem "my_fancy_jekyll_plugin" +end +``` + +Each `Command` must be a subclass of the `Jekyll::Command` class and must +contain one class method: `init_with_program`. An example: + +```ruby +class MyNewCommand < Jekyll::Command + class << self + def init_with_program(prog) + prog.command(:new) do |c| + c.syntax "new [options]" + c.description 'Create a new Jekyll site.' + + c.option 'dest', '-d DEST', 'Where the site should go.' + + c.action do |args, options| + Jekyll::Site.new_site_at(options['dest']) + end + end + end + end +end +``` + +Commands should implement this single class method: + +
+ + + + + + + + + + + + + +
MethodDescription
+

init_with_program

+

+ This method accepts one parameter, the + Mercenary::Program + instance, which is the Jekyll program itself. Upon the program, + commands may be created using the above syntax. For more details, + visit the Mercenary repository on GitHub.com. +

+
diff --git a/docs/_docs/plugins/converters.md b/docs/_docs/plugins/converters.md new file mode 100644 index 00000000000..31c99e939fb --- /dev/null +++ b/docs/_docs/plugins/converters.md @@ -0,0 +1,91 @@ +--- +title: Converters +permalink: /docs/plugins/converters/ +--- + +If you have a new markup language you’d like to use with your site, you can +include it by implementing your own converter. Both the Markdown and +[Textile](https://github.com/jekyll/jekyll-textile-converter) markup +languages are implemented using this method. + +
+
Remember your Front Matter
+

+ Jekyll will only convert files that have a YAML header at the top, even for + converters you add using a plugin. +

+
+ +Below is a converter that will take all posts ending in `.upcase` and process +them using the `UpcaseConverter`: + +```ruby +module Jekyll + class UpcaseConverter < Converter + safe true + priority :low + + def matches(ext) + ext =~ /^\.upcase$/i + end + + def output_ext(ext) + ".html" + end + + def convert(content) + content.upcase + end + end +end +``` + +Converters should implement at a minimum 3 methods: + +
+ + + + + + + + + + + + + + + + + + + + + +
MethodDescription
+

matches

+

+ Does the given extension match this converter’s list of acceptable + extensions? Takes one argument: the file’s extension (including the + dot). Must return true if it matches, false + otherwise. +

+

output_ext

+

+ The extension to be given to the output file (including the dot). + Usually this will be ".html". +

+

convert

+

+ Logic to do the content conversion. Takes one argument: the raw content + of the file (without front matter). Must return a String. +

+
+ +In our example, `UpcaseConverter#matches` checks if our filename extension is +`.upcase`, and will render using the converter if it is. It will call +`UpcaseConverter#convert` to process the content. In our simple converter we’re +simply uppercasing the entire content string. Finally, when it saves the page, +it will do so with a `.html` extension. diff --git a/docs/_docs/plugins/filters.md b/docs/_docs/plugins/filters.md new file mode 100644 index 00000000000..a07df697729 --- /dev/null +++ b/docs/_docs/plugins/filters.md @@ -0,0 +1,32 @@ +--- +title: Filters +permalink: /docs/plugins/filters/ +--- + +Filters are modules that export their methods to liquid. +All methods will have to take at least one parameter which represents the input +of the filter. The return value will be the output of the filter. + +```ruby +module Jekyll + module AssetFilter + def asset_url(input) + "http://www.example.com/#{input}?#{Time.now.to_i}" + end + end +end + +Liquid::Template.register_filter(Jekyll::AssetFilter) +``` + +For more details on creating custom Liquid Filters, head to the [Liquid docs](https://github.com/Shopify/liquid/wiki/Liquid-for-Programmers#create-your-own-filters). + +
+
ProTip™: Access the site object using Liquid
+

+ Jekyll lets you access the site object through the + @context.registers feature of Liquid at @context.registers[:site]. For example, you can + access the global configuration file _config.yml using + @context.registers[:site].config. +

+
diff --git a/docs/_docs/plugins/generators.md b/docs/_docs/plugins/generators.md new file mode 100644 index 00000000000..774e33a54dc --- /dev/null +++ b/docs/_docs/plugins/generators.md @@ -0,0 +1,145 @@ +--- +title: Generators +permalink: /docs/plugins/generators/ +--- + +You can create a generator when you need Jekyll to create additional content based on your own rules. + +A generator is a subclass of `Jekyll::Generator` that defines a `generate` method, which receives an instance of +[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). The return value of `generate` is ignored. + +Generators run after Jekyll has made an inventory of the existing content, and before the site is generated. Pages with +front matter are stored as instances of [`Jekyll::Page`]({{ site.repository }}/blob/master/lib/jekyll/page.rb) and are +available via `site.pages`. Static files become instances of +[`Jekyll::StaticFile`]({{ site.repository }}/blob/master/lib/jekyll/static_file.rb) +and are available via `site.static_files`. See [the Variables documentation page](/docs/variables/) and +[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb) for details. + +In the following example, the generator will inject values computed at build time for template variables. The template +named `reading.html` has two undefined variables `ongoing` and `done` that will be defined or assigned a value when +the generator runs: + +```ruby +module Reading + class Generator < Jekyll::Generator + def generate(site) + book_data = site.data['books'] + ongoing = book_data.select { |book| book['status'] == 'ongoing' } + done = book_data.select { |book| book['status'] == 'finished' } + + # get template + reading = site.pages.find { |page| page.name == 'reading.html'} + + # inject data into template + reading.data['ongoing'] = ongoing + reading.data['done'] = done + end + end +end +``` + +The following example is a more complex generator that generates new pages. + +In this example, the aim of the generator is to create a page for each category registered in the `site`. The pages are +created at runtime, so their contents, front matter and other attributes need to be designed by the plugin itself. +* The pages are intended to render a list of all documents under a given category. So the basename of the rendered file +would be better as `index.html`. +* Having the ability to configure the pages via [front matter defaults](/docs/configuration/front-matter-defaults/) +would be awesome! So assigning a particular `type` to these pages would be beneficial. + +```ruby +module SamplePlugin + class CategoryPageGenerator < Jekyll::Generator + safe true + + def generate(site) + site.categories.each do |category, posts| + site.pages << CategoryPage.new(site, category, posts) + end + end + end + + # Subclass of `Jekyll::Page` with custom method definitions. + class CategoryPage < Jekyll::Page + def initialize(site, category, posts) + @site = site # the current site instance. + @base = site.source # path to the source directory. + @dir = category # the directory the page will reside in. + + # All pages have the same filename, so define attributes straight away. + @basename = 'index' # filename without the extension. + @ext = '.html' # the extension. + @name = 'index.html' # basically @basename + @ext. + + # Initialize data hash with a key pointing to all posts under current category. + # This allows accessing the list in a template via `page.linked_docs`. + @data = { + 'linked_docs' => posts + } + + # Look up front matter defaults scoped to type `categories`, if given key + # doesn't exist in the `data` hash. + data.default_proc = proc do |_, key| + site.frontmatter_defaults.find(relative_path, :categories, key) + end + end + + # Placeholders that are used in constructing page URL. + def url_placeholders + { + :path => @dir, + :category => @dir, + :basename => basename, + :output_ext => output_ext, + } + end + end +end +``` + +The generated pages can now be set up to use a particular layout or output at a particular path in the destination +directory all via the config file using front matter defaults. For example: + +```yaml +# _config.yml + +defaults: + - scope: + type: categories # select all category pages + values: + layout: category_page + permalink: categories/:category/ +``` + +## Technical Aspects + +Generators need to implement only one method: + +
+ + + + + + + + + + + + + +
MethodDescription
+

generate

+
+

Generates content as a side-effect.

+
+
+ +If your generator is contained within a single file, it can be named whatever you want but it should have an `.rb` +extension. If your generator is split across multiple files, it should be packaged as a Rubygem to be published at +https://rubygems.org/. In this case, the name of the gem depends on the availability of the name at that site because +no two gems can have the same name. + +By default, Jekyll looks for generators in the `_plugins` directory. However, you can change the default directory by +assigning the desired name to the key `plugins_dir` in the config file. diff --git a/docs/_docs/plugins/hooks.md b/docs/_docs/plugins/hooks.md new file mode 100644 index 00000000000..7841399c083 --- /dev/null +++ b/docs/_docs/plugins/hooks.md @@ -0,0 +1,289 @@ +--- +title: Hooks +permalink: /docs/plugins/hooks/ +--- + +Using hooks, your plugin can exercise fine-grained control over various aspects of the build process. If your plugin defines any hooks, Jekyll +will call them at pre-defined points. + +Hooks are registered to an owner and an event name. To register one, you call `Jekyll::Hooks.register`, and pass the hook owner, event name, +and code to call whenever the hook is triggered. For example, if you want to execute some custom functionality every time Jekyll renders a +page, you could register a hook like this: + +```ruby +Jekyll::Hooks.register :pages, :post_render do |page| + # code to call after Jekyll renders a page +end +``` + +*Note: The `:post_convert` events mentioned hereafter is a feature introduced in v4.2.0.* + +Out of the box, Jekyll has pre-defined hook points for owners `:site`, `:pages`, `:documents` and `:clean`. Additionally, the hook points +defined for `:documents` can be utilized for individual collections only by invoking the collection type instead. i.e. `:posts` for documents +in collection `_posts` and `:movies` for documents in collection `_movies`. In all cases, Jekyll calls your hooks with the owner object as the +first callback parameter. + +Every registered hook owner supports the following events — `:post_init`, `:pre_render`, `:post_convert`, `:post_render`, `:post_write` +— however, the `:site` owner is set up to *respond* to *special event names*. Refer to the subsequent section for details. + +All `:pre_render` hooks and the `:site, :post_render` hook will also provide a `payload` hash as a second parameter. While in the case of +`:pre_render` events, the payload gives you full control over the variables that are available during rendering, with the `:site, :post_render` +event, the payload contains final values after rendering all the site (useful for sitemaps, feeds, etc). + +## Built-in Hook Owners and Events +The complete list of available hooks: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OwnerEventTriggered at
+

:site

+

Encompasses the entire site

+
+

:after_init

+
+

Just after the site initializes. Good for modifying the configuration of the site. Triggered once per build / serve session

+
+

:after_reset

+
+

Just after the site resets during regeneration

+
+

:post_read

+
+

After all source files have been read and loaded from disk

+
+

:pre_render

+
+

Just before rendering the whole site

+
+

:post_render

+
+

After rendering the whole site, but before writing any files

+
+

:post_write

+
+

After writing all of the rendered files to disk

+
+

:pages

+

Allows fine-grained control over all pages in the site

+
+

:post_init

+
+

Whenever a page is initialized

+
+

:pre_render

+
+

Just before rendering a page

+
+

:post_convert

+
+

After converting the page content, but before rendering the page layout

+
+

:post_render

+
+

After rendering a page, but before writing it to disk

+
+

:post_write

+
+

After writing a page to disk

+
+

:documents

+

Allows fine-grained control over all documents in the site including posts and documents in user-defined collections

+
+

:post_init

+
+

Whenever any document is initialized

+
+

:pre_render

+
+

Just before rendering a document

+
+

:post_convert

+
+

+ After converting the document content, but before rendering the document + layout +

+
+

:post_render

+
+

After rendering a document, but before writing it to disk

+
+

:post_write

+
+

After writing a document to disk

+
+

:posts

+

Allows fine-grained control over all posts in the site without affecting documents in user-defined collections

+
+

:post_init

+
+

Whenever a post is initialized

+
+

:pre_render

+
+

Just before rendering a post

+
+

:post_convert

+
+

After converting the post content, but before rendering the post layout

+
+

:post_render

+
+

After rendering a post, but before writing it to disk

+
+

:post_write

+
+

After writing a post to disk

+
+

:clean

+

Fine-grained control on the list of obsolete files determined to be deleted during the site's cleanup phase.

+
+

:on_obsolete

+
+

During the cleanup of a site's destination before it is built

+
+
+ +## Hooks for custom Jekyll objects + +You can also register and trigger hooks for Jekyll objects introduced by your plugin. All it takes is placing `trigger` calls under a suitable +`owner` name, at positions desired within your custom class and registering the `owner` by your plugin. + +To illustrate, consider the following plugin that implements custom functionality for every custom `Excerpt` object initialized: + +```ruby +module Foobar + class HookedExcerpt < Jekyll::Excerpt + def initialize(doc) + super + trigger_hooks(:post_init) + end + + def output + @output ||= trigger_hooks(:post_render, renderer.run) + end + + def renderer + @renderer ||= Jekyll::Renderer.new( + doc.site, self, site.site_payload + ) + end + + def trigger_hooks(hook_name, *args) + Jekyll::Hooks.trigger :excerpts, hook_name, self, *args + end + end +end + +Jekyll::Hooks.register :excerpts, :post_init do |excerpt| + Jekyll.logger.debug "Initialized:", + "Hooked Excerpt for #{excerpt.doc.inspect}" +end + +Jekyll::Hooks.register :excerpts, :post_render do |excerpt, output| + return output unless excerpt.doc.type == :posts + Foobar.transform(output) +end +``` diff --git a/docs/_docs/plugins/installation.md b/docs/_docs/plugins/installation.md new file mode 100644 index 00000000000..f3f16c94440 --- /dev/null +++ b/docs/_docs/plugins/installation.md @@ -0,0 +1,127 @@ +--- +title: Plugins +permalink: /docs/plugins/installation/ +--- + +Jekyll has built-in support for using plugins to extend the core functionality. + +Primarily, any file with extension `.rb` placed within a `_plugins` directory at the root of the site's `source`, will be automatically loaded +during a build session. + +This behavior can be configured as follows: + +- The `_plugins` directory may be changed either directly via the command-line or via the configuration file(s). +- Plugins in the `_plugins` directory (or its equivalent(s)) will not be loaded when Jekyll is running in `safe` mode. +- This route cannot be used to extend the Jekyll CLI. + +To work with plugins packaged as gems, one has to list the desired gems in the configuration file under a top-level key named `plugins`. +Additionally, if you're building in `safe` mode, the gem needs to be listed under a top-level key named `whitelist`. For example: + +```yaml +plugins: + - jekyll-gist + - jekyll-coffeescript + - jekyll-seo-tag + - some-other-jekyll-plugin + +# Enable safe mode +safe: true + +# Whitelist plugins under safe mode. +# Note that `some-other-jekyll-plugin` is not listed here. Therefore, +# it will not be loaded under safe mode. +whitelist: + - jekyll-gist + - jekyll-coffeescript + - jekyll-seo-tag +``` + +In the absence of a Gemfile, one must manually ensure that listed plugins have been installed prior to invoking Jekyll. For example, the +latest versions of gems in the above list may be installed to a system-wide location by running: + +```sh +gem install jekyll-gist jekyll-coffeescript jekyll-remote-theme some-other-jekyll-plugin +``` + +## Using a Gemfile + +The maintenance of various gem dependencies may be greatly simplified by using a Gemfile (usually at the root of the site's source) in +conjunction with a Rubygem named `bundler`. The Gemfile however **should** list all the primary dependencies of your site, including Jekyll +itself, not just gem-based plugins of the site because Bundler narrows the scope of installed gems to just *runtime dependencies* resolved by +evaluating the Gemfile. For example: + +```ruby +source "https://rubygems.org" + +# Use the latest version. +gem "jekyll" + +# The theme of current site, locked to a certain version. +gem "minima", "2.4.1" + +# Plugins of this site loaded during a build with proper +# site configuration. +gem "jekyll-gist" +gem "jekyll-coffeescript" +gem "jekyll-seo-tag", "~> 1.5" +gem "some-other-jekyll-plugin" + +# A dependency of a custom-plugin inside `_plugins` directory. +gem "nokogiri", "~> 1.11" +``` + +The gems listed in the Gemfile can be collectively installed by simply running `bundle install`. + +### The `:jekyll_plugins` Gemfile group +{: #the-jekyll_plugins-group} + +Jekyll gives a special treatment to gems listed as part of the `:jekyll_plugins` group in a Gemfile. Any gem under this group is loaded at +the very beginning of any Jekyll process, irrespective of the `--safe` CLI flag or entries in the configuration file(s). + +While this route allows one to enhance Jekyll's CLI with additional subcommands and options, or avoid having to list gems in the configuration +file, the downside is the necessity to be mindful of what gems are included in the group. For example: + +```ruby +source "https://rubygems.org" + +# Use the latest version. +gem "jekyll" + +# The theme of current site, locked to a certain version. +gem "minima", "2.4.1" + +# Plugins of this site loaded only if configured correctly. +gem "jekyll-gist" +gem "jekyll-coffeescript" + +# Gems loaded irrespective of site configuration. +group :jekyll_plugins do + gem "jekyll-cli-plus" + gem "jekyll-seo-tag", "~> 1.5" + gem "some-other-jekyll-plugin" +end +``` + +
+
Plugins on GitHub Pages
+

+ GitHub Pages is powered by Jekyll. All GitHub Pages sites are generated using the + --safe option to disable plugins (with the exception of some + whitelisted plugins) for security reasons. Unfortunately, this means your plugins won't + work if you’re deploying via GitHub Pages.

+ You can still use GitHub Pages to publish your site, but you'll need to either build the site locally and push the generated files to + your GitHub repository or use + GitHub Actions to host source + files on GitHub yet build and deploy with full control on GitHub Pages. +

+
+ +
+
+ _plugins, _config.yml and Gemfile can be used simultaneously +
+

+ You may use any of the aforementioned plugin routes simultaneously in the same site if you so choose. + Use of one does not restrict the use of the others. +

+
diff --git a/docs/_docs/plugins/tags.md b/docs/_docs/plugins/tags.md new file mode 100644 index 00000000000..3695a94c712 --- /dev/null +++ b/docs/_docs/plugins/tags.md @@ -0,0 +1,114 @@ +--- +title: Tags +permalink: /docs/plugins/tags/ +--- + +If you’d like to include custom liquid tags in your site, you can do so by +hooking into the tagging system. Built-in examples added by Jekyll include the +`highlight` and `include` tags. Below is an example of a custom liquid tag that +will output the time the page was rendered: + +```ruby +module Jekyll + class RenderTimeTag < Liquid::Tag + + def initialize(tag_name, text, tokens) + super + @text = text + end + + def render(context) + "#{@text} #{Time.now}" + end + end +end + +Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag) +``` + +At a minimum, liquid tags must implement: + +
+ + + + + + + + + + + + + +
MethodDescription
+

render

+
+

Outputs the content of the tag.

+
+
+ +You must also register the custom tag with the Liquid template engine as +follows: + +```ruby +Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag) +``` + +In the example above, we can place the following tag anywhere in one of our +pages: + +{% raw %} +```liquid +

{% render_time page rendered at: %}

+``` +{% endraw %} + +And we would get something like this on the page: + +```html +

page rendered at: Tue June 22 23:38:47 –0500 2010

+``` + +## Tag Blocks + +The `render_time` tag seen above can also be rewritten as a tag block by +inheriting the `Liquid::Block` class. Look at the example below: + +```ruby +module Jekyll + class RenderTimeTagBlock < Liquid::Block + + def render(context) + text = super + "

#{text} #{Time.now}

" + end + + end +end + +Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTagBlock) +``` + +We can now use the tag block anywhere: + +{% raw %} +```liquid +{% render_time %} +page rendered at: +{% endrender_time %} +``` +{% endraw %} + +And we would still get the same output as above on the page: + +```html +

page rendered at: Tue June 22 23:38:47 –0500 2010

+``` + +{: .note .info} +In the above example, the tag block and the tag are both registered with +the name render_time, but to register a tag and a tag block using +the same name in the same project is not recommended as this may lead to +conflicts. diff --git a/docs/_docs/plugins/your-first-plugin.md b/docs/_docs/plugins/your-first-plugin.md new file mode 100644 index 00000000000..e20bdda5494 --- /dev/null +++ b/docs/_docs/plugins/your-first-plugin.md @@ -0,0 +1,142 @@ +--- +title: Your first plugin +permalink: /docs/plugins/your-first-plugin/ +--- + +Plugins allow you to extend Jekyll's behavior to fit your needs. There are six +types of plugins in Jekyll. + +## Generators + +[Generators](/docs/plugins/generators/) create content on your site. +For example: + +* [jekyll-feed](https://github.com/jekyll/jekyll-feed) creates an Atom feed of +blog posts. +* [jekyll-archives](https://github.com/jekyll/jekyll-archives) creates archive +pages for blog categories and tags. +* [jekyll-sitemap](https://github.com/jekyll/jekyll-sitemap) creates a sitemap. + +## Converters + +[Converters](/docs/plugins/converters/) change a markup language into another +format. For example: + +* [jekyll-textile-converter](https://github.com/jekyll/jekyll-textile-converter) +converts textile to HTML. +* [jekyll-coffeescript](https://github.com/jekyll/jekyll-coffeescript) converts +Coffeescript to JavaScript. +* [jekyll-opal](https://github.com/jekyll/jekyll-opal) converts Ruby to +JavaScript. + +## Commands + +[Commands](/docs/plugins/commands/) extend the `jekyll` executable with +subcommands. For example: + +* [jekyll-compose](https://github.com/jekyll/jekyll-compose) adds subcommands +for creating a post, page or draft. + +## Tags + +[Tags](/docs/plugins/tags/) create custom Liquid tags. For example: + +* [jekyll-youtube](https://github.com/dommmel/jekyll-youtube) embeds a YouTube +video. +* [jekyll-asset-path-plugin](https://github.com/samrayner/jekyll-asset-path-plugin) +outputs a relative URL for assets. +* [jekyll-swfobject](https://github.com/sectore/jekyll-swfobject) embeds a SWF +object. + +## Filters + +[Filters](/docs/plugins/filters/) create custom Liquid filters. For example: + +* [jekyll-time-ago](https://github.com/markets/jekyll-timeago) - The distance +between two dates in words. +* [jekyll-toc](https://github.com/toshimaru/jekyll-toc) - Generates a table of +content. +* [jekyll-email-protect](https://github.com/vwochnik/jekyll-email-protect) - +Obfuscates emails to protect them from spam bots. + +## Hooks + +[Hooks](/docs/plugins/hooks/) give fine-grained control to extend the build +process. For example: + +* [jemoji](https://github.com/jekyll/jemoji) Display emojis :+1: +* [jekyll-mentions](https://github.com/jekyll/jekyll-mentions) turns mentions @jekyll into links +* [jekyll-spaceship](https://github.com/jeffreytse/jekyll-spaceship) - advanced example. Provides +powerful supports for table, mathjax, plantuml, video, etc. + +## Flags + +There are two flags to be aware of when writing a plugin: + +
+ + + + + + + + + + + + + + + + + +
FlagDescription
+

safe

+
+

+ A boolean flag that informs Jekyll whether this plugin may be safely + executed in an environment where arbitrary code execution is not + allowed. This is used by GitHub Pages to determine which core plugins + may be used, and which are unsafe to run. If your plugin does not + allow for arbitrary code execution, set this to true. + GitHub Pages still won’t load your plugin, but if you submit it for + inclusion in core, it’s best for this to be correct! +

+
+

priority

+
+

+ This flag determines what order the plugin is loaded in. Valid values + are: :lowest, :low, :normal, + :high, and :highest. Highest priority + matches are applied first, lowest priority are applied last. +

+
+
+ +To use one of the example plugins above as an illustration, here is how you’d +specify these two flags: + +```ruby +module Jekyll + class UpcaseConverter < Converter + safe true + priority :low + ... + end +end +``` + +## Best Practices + +The guides help you with the specifics of creating plugins. We also have some +recommended best practices to help structure your plugin. + +We recommend using a [gem](/docs/ruby-101/#gems) for your plugin. This will +help you manage dependencies, keep separation from your site source code and +allow you to share functionality across multiple projects. For tips on creating +a gem take a look at the +[Ruby gems guide](https://guides.rubygems.org/make-your-own-gem/) or look +through the source code of an existing plugin such as +[jekyll-feed](https://github.com/jekyll/jekyll-feed). diff --git a/docs/_docs/posts.md b/docs/_docs/posts.md new file mode 100644 index 00000000000..7167f672e3d --- /dev/null +++ b/docs/_docs/posts.md @@ -0,0 +1,240 @@ +--- +title: Posts +permalink: /docs/posts/ +redirect_from: + - /docs/drafts/ +--- + +Blogging is baked into Jekyll. You write blog posts as text files and Jekyll +provides everything you need to turn it into a blog. + +## The Posts Folder + +The `_posts` folder is where your blog posts live. You typically write posts +in [Markdown](https://daringfireball.net/projects/markdown/), HTML is +also supported. + +## Creating Posts + +To create a post, add a file to your `_posts` directory with the following +format: + +``` +YEAR-MONTH-DAY-title.MARKUP +``` + +Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit +numbers, and `MARKUP` is the file extension representing the format used in the +file. For example, the following are examples of valid post filenames: + +``` +2011-12-31-new-years-eve-is-awesome.md +2012-09-12-how-to-write-a-blog.md +``` + +All blog post files must begin with [front matter](/docs/front-matter/) which is +typically used to set a [layout](/docs/layouts/) or other meta data. For a simple +example this can just be empty: + +```markdown +--- +layout: post +title: "Welcome to Jekyll!" +--- + +# Welcome + +**Hello world**, this is my first Jekyll blog post. + +I hope you like it! +``` + +
+
ProTip™: Link to other posts
+

+ Use the post_url + tag to link to other posts without having to worry about the URLs + breaking when the site permalink style changes. +

+
+ +
+
Be aware of character sets
+

+ Content processors can modify certain characters to make them look nicer. + For example, the smart extension in Redcarpet converts standard, + ASCII quotation characters to curly, Unicode ones. In order for the browser + to display those characters properly, define the charset meta value by + including <meta charset="utf-8"> in the + <head> of your layout. +

+
+ +## Including images and resources + +At some point, you'll want to include images, downloads, or other +digital assets along with your text content. One common solution is to create +a folder in the root of the project directory called something like `assets`, +into which any images, files or other resources are placed. Then, from within +any post, they can be linked to using the site’s root as the path for the asset +to include. The best way to do this depends on the way your site’s (sub)domain +and path are configured, but here are some simple examples in Markdown: + +Including an image asset in a post: + +```markdown +... which is shown in the screenshot below: +![My helpful screenshot](/assets/screenshot.jpg) +``` + +Linking to a PDF for readers to download: + +```markdown +... you can [get the PDF](/assets/mydoc.pdf) directly. +``` + +## Displaying an index of posts + +Creating an index of posts on another page should be easy thanks to +[Liquid](https://shopify.github.io/liquid/) and its tags. Here’s a +simple example of how to create a list of links to your blog posts: + +{% raw %} +```liquid + +``` +{% endraw %} + +You have full control over how (and where) you display your posts, +and how you structure your site. You should read more about [how templates +work](/docs/templates/) with Jekyll if you want to know more. + +Note that the `post` variable only exists inside the `for` loop above. If +you wish to access the currently-rendering page/posts's variables (the +variables of the post/page that has the `for` loop in it), use the `page` +variable instead. + +## Tags and Categories + +Jekyll has first class support for *tags* and *categories* in blog posts. + +### Tags + +Tags for a post are defined in the post's front matter using either the key +`tag` for a single entry or `tags` for multiple entries.
Since Jekyll +expects multiple items mapped to the key `tags`, it will automatically *split* +a string entry if it contains whitespace. For example, while front matter +`tag: classic hollywood` will be processed into a singular entity +`"classic hollywood"`, front matter `tags: classic hollywood` will be processed +into an array of entries `["classic", "hollywood"]`. + +Irrespective of the front matter key chosen, Jekyll stores the metadata mapped +to the plural key which is exposed to Liquid templates. + +All tags registered in the current site are exposed to Liquid templates via +`site.tags`. Iterating over `site.tags` on a page will yield another array with +two items, where the first item is the name of the tag and the second item being +*an array of posts* with that tag. + +{% raw %} +```liquid +{% for tag in site.tags %} +

{{ tag[0] }}

+ +{% endfor %} +``` +{% endraw %} + + +### Categories + +Categories of a post work similar to the tags above: + * They can be defined via the front matter using keys `category` or + `categories` (that follow the same logic as for tags) + * All categories registered in the site are exposed to Liquid templates via + `site.categories` which can be iterated over (similar to the loop for tags + above.) + +*The similarity between categories and tags however, ends there.* + +Unlike tags, categories for posts can also be defined by a post's file path. +Any directory above `_posts` will be read-in as a category. For example, +if a post is at path `movies/horror/_posts/2019-05-21-bride-of-chucky.markdown`, +then `movies` and `horror` are automatically registered as categories for that +post. + +When the post also has front matter defining categories, they just get added to +the existing list if not present already. + +The hallmark difference between categories and tags is that categories of a post +may be incorporated into [the generated URL](/docs/permalinks/#global) for the +post, while tags cannot be. + +Therefore, depending on whether front matter has `category: classic hollywood`, +or `categories: classic hollywood`, the example post above would have the URL as +either +`movies/horror/classic%20hollywood/2019/05/21/bride-of-chucky.html` or +`movies/horror/classic/hollywood/2019/05/21/bride-of-chucky.html` respectively. + + +## Post excerpts + +You can access a snippet of a posts's content by using `excerpt` variable on a +post. By default this is the first paragraph of content in the post, however it +can be customized by setting a `excerpt_separator` variable in front matter or +`_config.yml`. + +```markdown +--- +excerpt_separator: +--- + +Excerpt with multiple paragraphs + +Here's another paragraph in the excerpt. + +Out-of-excerpt +``` + +Here's an example of outputting a list of blog posts with an excerpt: + +{% raw %} +```liquid +
    + {% for post in site.posts %} +
  • + {{ post.title }} + {{ post.excerpt }} +
  • + {% endfor %} +
+``` +{% endraw %} + +## Drafts + +Drafts are posts without a date in the filename. They're posts you're still +working on and don't want to publish yet. To get up and running with drafts, +create a `_drafts` folder in your site's root and create your first draft: + +``` +. +├── _drafts +│ └── a-draft-post.md +... +``` + +To preview your site with drafts, run `jekyll serve` or `jekyll build` +with the `--drafts` switch. Each will be assigned the value modification time +of the draft file for its date, and thus you will see currently edited drafts +as the latest posts. diff --git a/docs/_docs/rendering-process.md b/docs/_docs/rendering-process.md new file mode 100644 index 00000000000..6657bc5273c --- /dev/null +++ b/docs/_docs/rendering-process.md @@ -0,0 +1,28 @@ +--- +--- + +For any Jekyll site, a *build session* consists of discrete phases in the following order --- *setting up plugins, +reading source files, running generators, rendering templates*, and finally *writing files to disk*. + +While the phases above are self-explanatory, the one phase that warrants dissection is *the rendering phase*. + +The rendering phase is further divisible into three optional stages. Every file rendered, passes through one or more of +these stages as determined by the file's content string, front matter and extension. The stages are akin to an assembly +line, with the *output* from a stage being the *input* for the succeeding stage: +- **Interpreting Liquid expressions in the file**
+ This stage evaluates Liquid expressions in the current file. By default, the interpretation is *shallow* --- in that + any Liquid expression in resulting output is not further interpreted. Moreover, any Liquid expression in the file's + front matter is left untouched. +- **Unleashing the converters**
+ This stage invokes the converter mapped to the current file's extension and converts the input string. This is when + Markdown gets converted into HTML and Sass / Scss into CSS or CoffeeScript into JavaScript, etc, etc. Since this stage + is determined by the file's extension, Markdown or Sass inside a `.html` file will remain untouched. +- **Populating the layouts**
+ By this stage, *the source file* is considered rendered and it will not be revisited. However, based on the file's + extension and consequently based on the front matter, it is determined whether to take the *output* string from + the preceding stage and place into layouts or not. Whereas output from Sass files or CoffeeScript files are *never* + placed into a layout, regular text output can go either ways based on whether a layout has been assigned via the front + matter.

+ Placement into layouts work similar to how Russian dolls encase the smaller ones within itself or how an oyster + generates a pearl --- the converted output from the preceding stage forms the core and layout(s) are successively + *rendered* separately onto the core. diff --git a/docs/_docs/ruby-101.md b/docs/_docs/ruby-101.md new file mode 100644 index 00000000000..264f8087719 --- /dev/null +++ b/docs/_docs/ruby-101.md @@ -0,0 +1,56 @@ +--- +title: Ruby 101 +permalink: /docs/ruby-101/ +--- + +Jekyll is written in Ruby. If you're new to Ruby, this page helps you learn some of the terminology. + +## Gems + +Gems are code you can include in Ruby projects. Gems package specific functionality. You can share gems across multiple projects or with other people. +Gems can perform actions like: + +* Converting a Ruby object to JSON +* Pagination +* Interacting with APIs such as GitHub + +Jekyll is a gem. Many Jekyll [plugins]({{ '/docs/plugins/' | relative_url }}) are also gems, including +[jekyll-feed](https://github.com/jekyll/jekyll-feed), +[jekyll-seo-tag](https://github.com/jekyll/jekyll-seo-tag) and +[jekyll-archives](https://github.com/jekyll/jekyll-archives). + +## Gemfile + +A `Gemfile` is a list of gems used by your site. Every Jekyll site has a Gemfile in the main folder. + +For a simple Jekyll site it might look something like this: + +```ruby +source "https://rubygems.org" + +gem "jekyll" + +group :jekyll_plugins do + gem "jekyll-feed" + gem "jekyll-seo-tag" +end +``` + +## Bundler + +[Bundler](https://rubygems.org/gems/bundler) is a gem that installs all gems in your `Gemfile`. + +While you don't have to use `Gemfile` and `bundler`, it is highly recommended as it ensures you're running the same version of Jekyll and its plugins across different environments. + +Install Bundler using `gem install bundler`. You only need to install it once, not every time you create a new Jekyll project. + +To install gems in your Gemfile using Bundler, run the following in the directory that has the Gemfile: + +``` +bundle install +bundle exec jekyll serve +``` + +To bypass Bundler if you aren't using a Gemfile, run `jekyll serve`. + +See [Using Jekyll with Bundler](/tutorials/using-jekyll-with-bundler/) for more information about Bundler in Jekyll and for instructions to get up and running quickly. diff --git a/docs/_docs/security.md b/docs/_docs/security.md new file mode 100644 index 00000000000..631a163f9e3 --- /dev/null +++ b/docs/_docs/security.md @@ -0,0 +1,36 @@ +--- +title: Security Policy +permalink: "/docs/security/" +note: This file is autogenerated. Edit /.github/SECURITY.markdown instead. +--- + +## Supported Versions + +Security updates are applied to the latest MINOR version of Jekyll, and the version used by GitHub Pages, v3.9.x. + +| Version | Supported | +| ------- | ------------------ | +| 4.2.x | :white_check_mark: | +| 3.9.x | :white_check_mark: | +| < 3.9.x | :x: | + +## Reporting a Vulnerability + +Please report vulnerabilities by sending an email to security@jekyllrb.com with the following information: + +1. A description of the vulnerability +2. Reproduction steps and/or a sample site (share a private repo to the [Jekyll Security Team](docs/pages/team.md)) +3. Your contact information + +The Jekyll security team will respond to your submission and notify you whether it has been confirmed by the team. +Your confidentiality is kindly requested as we work on a fix. We will provide our patch to you to test and verify that the vulnerability has +been closed. + +If you have created a patch and would like to submit that to us as well, we will happily consider it though we cannot guarantee that we will +use it. If we use your patch, we will attribute authorship to you either as the commit author, or as a co-author. + +Once a fix is verified, we will release PATCH versions of the supported MINOR versions and assign a CVE to the vulnerability. You will receive +credit in our release post. + +Once the patched version has been released, we will no longer request you to maintain confidentiality and you may choose to share details on +how you found the vulnerability with the community. diff --git a/docs/_docs/static_files.md b/docs/_docs/static_files.md new file mode 100644 index 00000000000..037b2e8f7c3 --- /dev/null +++ b/docs/_docs/static_files.md @@ -0,0 +1,96 @@ +--- +title: Static Files +permalink: /docs/static-files/ +--- +A static file is a file that does not contain any front matter. These +include images, PDFs, and other un-rendered content. + +They're accessible in Liquid via `site.static_files` and contain the +following metadata: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableDescription

file.path

+ + The relative path to the file, e.g. /assets/img/image.jpg + +

file.modified_time

+ + The `Time` the file was last modified, e.g. 2016-04-01 16:35:26 +0200 + +

file.name

+ + The string name of the file e.g. image.jpg for image.jpg + +

file.basename

+ + The string basename of the file e.g. image for image.jpg + +

file.extname

+ + The extension name for the file, e.g. + .jpg for image.jpg + +

+
+ +Note that in the above table, `file` can be anything. It's an arbitrarily set variable used in your own logic (such as in a for loop). It isn't a global site or page variable. + +## Add front matter to static files + +Although you can't directly add front matter values to static files, you can set front matter values through the [defaults property](/docs/configuration/front-matter-defaults/) in your configuration file. When Jekyll builds the site, it will use the front matter values you set. + +Here's an example: + +In your `_config.yml` file, add the following values to the `defaults` property: + +```yaml +defaults: + - scope: + path: "assets/img" + values: + image: true +``` + +This assumes that your Jekyll site has a folder path of `assets/img` where you have images (static files) stored. When Jekyll builds the site, it will treat each image as if it had the front matter value of `image: true`. + +Suppose you want to list all your image assets as contained in `assets/img`. You could use this for loop to look in the `static_files` object and get all static files that have this front matter property: + +{% raw %} +```liquid +{% assign image_files = site.static_files | where: "image", true %} +{% for myimage in image_files %} + {{ myimage.path }} +{% endfor %} +``` +{% endraw %} + +When you build your site, the output will list the path to each file that meets this front matter condition. diff --git a/docs/_docs/step-by-step/01-setup.md b/docs/_docs/step-by-step/01-setup.md new file mode 100644 index 00000000000..c662d7d0771 --- /dev/null +++ b/docs/_docs/step-by-step/01-setup.md @@ -0,0 +1,103 @@ +--- +layout: step +title: Setup +menu_name: Step by Step Tutorial +position: 1 +redirect_from: +- /docs/step-by-step/ +--- +Welcome to Jekyll's step-by-step tutorial. This tutorial takes +you from having some front-end web development experience to building your +first Jekyll site from scratch without relying on the default gem-based theme. + +## Installation + +Jekyll is a Ruby gem. First, install Ruby on your machine. +Go to [Installation]({{ '/docs/installation/' | relative_url }}) and follow the +instructions for your operating system. + +With Ruby installed, install Jekyll from the terminal: + +```sh +gem install jekyll bundler +``` + +Create a new `Gemfile` to list your project's dependencies: + +```sh +bundle init +``` + +Edit the `Gemfile` in a text editor and add jekyll as a dependency: + +```ruby +gem "jekyll" +``` + +Run `bundle` to install jekyll for your project. + +You can now prefix all jekyll commands listed in this tutorial with `bundle exec` +to make sure you use the jekyll version defined in your `Gemfile`. + +## Create a site + +It's time to create a site! Create a new directory for your site and name +it whatever you want. Through the rest of this tutorial we'll refer to this +directory as **root**. + +You can also initialize a Git repository here. + +One of the great things about Jekyll is there's no database. All content and +site structure are files that a Git repository can version. Using a repository +is optional but is recommended. You can learn more +about using Git by reading the +[Git Handbook](https://guides.github.com/introduction/git-handbook/). + +Let's add your first file. Create `index.html` in **root** with the following +content: + +```html + + + + + Home + + +

Hello World!

+ + +``` + +## Build + +Since Jekyll is a static site generator, it has to build the site +before we can view it. Run either of the following commands to build your site: + +* `jekyll build` - Builds the site and outputs a static site to a directory +called `_site`. +* `jekyll serve` - Does `jekyll build` and runs it on a local web server at `http://localhost:4000`, rebuilding the site any time you make a change. + +{: .note .info} +When you're developing a site, use `jekyll serve`. To force the browser to refresh with every change, use `jekyll serve --livereload`. +If there's a conflict or you'd like Jekyll to serve your development site at a different URL, use the `--host` and `--port` arguments, +as described in the [serve command options]({{ '/docs/configuration/options/#serve-command-options' | relative_url }}). + +{: .note .warning} +The version of the site that `jekyll serve` builds in `_site` is not suited for deployment. Links and asset URLs in sites created +with `jekyll serve` will use `https://localhost:4000` or the value set with command-line configuration, instead of the values set +in [your site's configuration file]({{ '/docs/configuration/' | relative_url }}). To learn about how to build your site when it's +ready for deployment, read the [Deployment]({{ '/docs/step-by-step/10-deployment/' | relative_url }}) section of this tutorial. + + +Run `jekyll serve` and go to +http://localhost:4000 in +your browser. You should see "Hello World!". + +At this point, you might be thinking, "So what?". The only thing that happened was that Jekyll copied an +HTML file from one place to another. + +Patience, young grasshopper, there's +still much to learn! + +Next. you'll learn about Liquid and templating. diff --git a/docs/_docs/step-by-step/02-liquid.md b/docs/_docs/step-by-step/02-liquid.md new file mode 100644 index 00000000000..012a8c63f09 --- /dev/null +++ b/docs/_docs/step-by-step/02-liquid.md @@ -0,0 +1,101 @@ +--- +layout: step +title: Liquid +position: 2 +--- +Liquid is where Jekyll starts to get more interesting. It is a templating +language which has three main components: + * [objects](#objects) + * [tags](#tags) + * [filters](#filters) + +## Objects + +Objects tell Liquid to output predefined [variables](../../variables/) as content on a page. Use double curly braces for objects: {% raw %}`{{`{% endraw %} and {% raw %}`}}`{% endraw %}. + +For example, {% raw %}`{{ page.title }}`{% endraw %} displays the `page.title` variable. + +## Tags + +Tags define the logic and control flow for templates. Use curly +braces and percent signs for tags: {% raw %}`{%`{% endraw %} and +{% raw %}`%}`{% endraw %}. + +For example: + +{% raw %} +```liquid +{% if page.show_sidebar %} + +{% endif %} +``` +{% endraw %} + +This displays the sidebar if the value of the `show_sidebar` page variable is true. + +Learn more about the tags available in Jekyll [here](/docs/liquid/tags/). + +## Filters + +Filters change the output of a Liquid object. They are used within an output +and are separated by a `|`. + +For example: + +{% raw %} +```liquid +{{ "hi" | capitalize }} +``` +{% endraw %} + +This displays `Hi` instead of `hi`. + +[Learn more about the filters](/docs/liquid/filters/) available. + +## Use Liquid + +Now, use Liquid to make your `Hello World!` text from [Setup](../01-setup/) lowercase: + +{% raw %} +```liquid +... +

{{ "Hello World!" | downcase }}

+... +``` +{% endraw %} + +To make Jekyll process your changes, add [front matter](../03-front-matter/) to the top of the page: + +```yaml +--- +# front matter tells Jekyll to process Liquid +--- +``` + +Your HTML document should look like this: + +{% raw %} +```html +--- +--- + + + + + + Home + + +

{{ "Hello World!" | downcase }}

+ + +``` +{% endraw %} + +When you reload your browser, you should see `hello world!`. + +Much of Jekyll's power comes from combining Liquid with other features. Add frontmatter to pages to make Jekyll process the Liquid on those pages. + +Next, you'll learn more about frontmatter. diff --git a/docs/_docs/step-by-step/03-front-matter.md b/docs/_docs/step-by-step/03-front-matter.md new file mode 100644 index 00000000000..17bb145118a --- /dev/null +++ b/docs/_docs/step-by-step/03-front-matter.md @@ -0,0 +1,58 @@ +--- +layout: step +title: Front Matter +position: 3 +--- +Front matter is a snippet of [YAML](http://yaml.org/) placed between two +triple-dashed lines at the start of a file. + +You can use front matter to set variables for the page: + +```yaml +--- +my_number: 5 +--- +``` + +You can call front matter variables in Liquid using the `page` variable. For +example, to output the value of the `my_number` variable above: + +{% raw %} +```liquid +{{ page.my_number }} +``` +{% endraw %} + +## Use front matter + +Change the `` on your site to use front matter: + +{% raw %} +```liquid +--- +title: Home +--- +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title>{{ page.title }} + + +

{{ "Hello World!" | downcase }}

+ + +``` +{% endraw %} + +{: .note .info } +You _must_ include front matter on the page for Jekyll to process any Liquid tags on it. + +To make Jekyll process a page without defining variables in the front matter, use: + +```yaml +--- +--- +``` + +Next, you'll learn more about layouts and why your pages use more source code than plain HTML. \ No newline at end of file diff --git a/docs/_docs/step-by-step/04-layouts.md b/docs/_docs/step-by-step/04-layouts.md new file mode 100644 index 00000000000..ae2dd162dff --- /dev/null +++ b/docs/_docs/step-by-step/04-layouts.md @@ -0,0 +1,89 @@ +--- +layout: step +title: Layouts +position: 4 +--- +Jekyll supports [Markdown](https://daringfireball.net/projects/markdown/syntax) +in addition to HTML when building pages. Markdown is a great choice for pages with a simple +content structure (just paragraphs, headings and images), as it's less verbose +than raw HTML. + +Create a new Markdown file named `about.md` in your site's root folder. + +You could copy the contents of `index` and modify it for the About page. However, +this creates duplicate code that has to be customized for each new page you add +to your site. + +For example, adding a new stylesheet to your site would involve adding the link +to the stylesheet to the `` of each page. For sites with many pages, this +is a waste of time. + +## Creating a layout + +Layouts are templates that can be used by any page in your site and wrap around page content. +They are stored in a directory called `_layouts`. + +Create the `_layouts` directory in your site's root folder and create a new `default.html` file with the following content: + +{% raw %} +```liquid + + + + + {{ page.title }} + + + {{ content }} + + +``` +{% endraw %} + +This HTML is almost identical to `index.html` except there's +no front matter and the content of the page is replaced by a `content` +variable. + +`content` is a special variable that returns the rendered +content of the page on which it's called. + +## Use layouts + +To make `index.html` use your new layout, set the `layout` variable in the front +matter. The file should look like this: + +{% raw %} +```liquid +--- +layout: default +title: Home +--- +

{{ "Hello World!" | downcase }}

+``` +{% endraw %} + +When you reload the site, the output remains the same. + +Since the layout wraps around the content on the page, you can call front matter like `page` +in the layout file. When you apply the layout to a page, it uses the front matter on that page. + +## Build the About page + +Add the following to `about.md` to use your new layout in the About page: + +```markdown +--- +layout: default +title: About +--- +# About page + +This page tells you a little bit about me. +``` + +Open http://localhost:4000/about.html +in your browser and view your new page. + +Congratulations, you now have a two page website! + +Next, you'll learn about navigating from page to page in your site. \ No newline at end of file diff --git a/docs/_docs/step-by-step/05-includes.md b/docs/_docs/step-by-step/05-includes.md new file mode 100644 index 00000000000..b0b8ca9eb9c --- /dev/null +++ b/docs/_docs/step-by-step/05-includes.md @@ -0,0 +1,83 @@ +--- +layout: step +title: Includes +position: 5 +--- +The site is coming together; however, there's no way to navigate between +pages. Let's fix that. + +Navigation should be on every page so adding it to your layout is the correct +place to do this. Instead of adding it directly to the layout, let's use this +as an opportunity to learn about includes. + +## Include tag + +The `include` tag allows you to include content from another file stored +in an `_includes` folder. Includes are useful for having a single source for +source code that repeats around the site or for improving the readability. + +Navigation source code can get complex, so sometimes it's nice to move it into an +include. + +## Include usage + +Create a file for the navigation at `_includes/navigation.html` with the +following content: + +``` + +``` + +Try using the include tag to add the navigation to `_layouts/default.html`: + +{% raw %} +```liquid + + + + + {{ page.title }} + + + {% include navigation.html %} + {{ content }} + + +``` +{% endraw %} + +Open http://localhost:4000 +in your browser and try switching between the pages. + +## Current page highlighting + +Let's take this a step further and highlight the current page in the navigation. + +`_includes/navigation.html` needs to know the URL of the page it's inserted into +so it can add styling. Jekyll has useful [variables](/docs/variables/) available, +one of which is `page.url`. + +Using `page.url` you can check if each link is the current page and color it red +if true: + +{% raw %} +```liquid + +``` +{% endraw %} + +Take a look at http://localhost:4000 +and see your red link for the current page. + +There's still a lot of repetition here if you wanted to add a new item to the +navigation or change the highlight color. In the next step we'll address this. diff --git a/docs/_docs/step-by-step/06-data-files.md b/docs/_docs/step-by-step/06-data-files.md new file mode 100644 index 00000000000..d87a40c99b3 --- /dev/null +++ b/docs/_docs/step-by-step/06-data-files.md @@ -0,0 +1,48 @@ +--- +layout: step +title: Data Files +position: 6 +--- +Jekyll supports loading data from YAML, JSON, and CSV files located in a `_data` +directory. Data files are a great way to separate content from source code to +make the site easier to maintain. + +In this step you'll store the contents of the navigation in a data file +and then iterate over it in the navigation include. + +## Data file usage + +[YAML](http://yaml.org/) is a format that's common in the Ruby ecosystem. You'll +use it to store an array of navigation items each with a name and link. + +Create a data file for the navigation at `_data/navigation.yml` with the +following: + +```yaml +- name: Home + link: / +- name: About + link: /about.html +``` + +Jekyll makes this data file available to you at `site.data.navigation`. Instead +of outputting each link in `_includes/navigation.html`, now you can iterate over +the data file instead: + +{% raw %} +```liquid + +``` +{% endraw %} + +The output will be exactly the same. The difference is you’ve made it easier to +add new navigation items and change the HTML structure. + +What good is a site without CSS, JS and images? Let’s look at how to handle +assets in Jekyll. diff --git a/docs/_docs/step-by-step/07-assets.md b/docs/_docs/step-by-step/07-assets.md new file mode 100644 index 00000000000..2d1d83f25ed --- /dev/null +++ b/docs/_docs/step-by-step/07-assets.md @@ -0,0 +1,92 @@ +--- +layout: step +title: Assets +position: 7 +--- +Using CSS, JS, images and other assets is straightforward with Jekyll. Place +them in your site folder and they’ll copy across to the built site. + +Jekyll sites often use this structure to keep assets organized: + +``` +. +├── assets +│ ├── css +│ ├── images +│ └── js +... +``` +So, from your assets folder, create folders called css, images and js. +Additionally, directly under the root create another folder called `_sass`, which you will need shortly. + +## Sass + +Inlining the styles used in `_includes/navigation.html`(adding or configuring within the same file) is not a best practice. +Instead, let's style the current page by defining our first class in a new css file instead. + +To do this, refer to the class (that you will configure in the next parts of this step) from within the `navigation.html` file by removing the code you added earlier (to color the current link red) and inserting the following code: + +{% raw %} +```liquid + +``` +{% endraw %} + +You could use a standard CSS file for styling, we're going to take it a step +further by using [Sass](https://sass-lang.com/). Sass is a fantastic extension +to CSS baked right into Jekyll. + +First create a Sass file at `assets/css/styles.scss` with the following content: + +```sass +--- +--- +@import "main"; +``` + +The empty front matter at the top tells Jekyll it needs to process the file. The +`@import "main"` tells Sass to look for a file called `main.scss` in the sass +directory (`_sass/` by default) you already created at the root of your working directory earlier. + +At this stage you'll just have a main css file. For larger projects, this is a +great way to keep your CSS organized. + +Create the current class mentioned above in order to color the current link green. Create a Sass file at `_sass/main.scss` with the following content: + +```sass +.current { + color: green; +} +``` + +You'll need to reference the stylesheet in your layout. + +Open `_layouts/default.html` and add the stylesheet to the ``: + +{% raw %} +```liquid + + + + + {{ page.title }} + + + + {% include navigation.html %} + {{ content }} + + +``` +{% endraw %} + +The `styles.css` referenced here is generated by Jekyll from the `styles.scss` you created earlier in `assets/css/`. + +Load up http://localhost:4000 +and check that the active link in the navigation is green. + +Next we're looking at one of Jekyll's most popular features, blogging. diff --git a/docs/_docs/step-by-step/08-blogging.md b/docs/_docs/step-by-step/08-blogging.md new file mode 100644 index 00000000000..09f35a085e0 --- /dev/null +++ b/docs/_docs/step-by-step/08-blogging.md @@ -0,0 +1,146 @@ +--- +layout: step +title: Blogging +position: 8 +--- +You might be wondering how you can have a blog without a database. In true +Jekyll style, blogging is powered by text files only. + +## Posts + +Blog posts live in a folder called `_posts`. The filename for posts have a +special format: the publish date, then a title, followed by an extension. + +Create your first post at `_posts/2018-08-20-bananas.md` with the +following content: + +```markdown +--- +layout: post +author: jill +--- + +A banana is an edible fruit – botanically a berry – produced by several +kinds of large herbaceous flowering plants in the genus Musa. + +In some countries, bananas used for cooking may be called "plantains", +distinguishing them from dessert bananas. The fruit is variable in size, +color, and firmness, but is usually elongated and curved, with soft +flesh rich in starch covered with a rind, which may be green, yellow, +red, purple, or brown when ripe. +``` + +This is like the `about.md` you created before except it has an author and +a different layout. `author` is a custom variable, it's not required and could +have been named something like `creator`. + +## Layout + +The `post` layout doesn't exist so you'll need to create it at +`_layouts/post.html` with the following content: + +{% raw %} +```liquid +--- +layout: default +--- +

{{ page.title }}

+

{{ page.date | date_to_string }} - {{ page.author }}

+ +{{ content }} +``` +{% endraw %} + +This is an example of layout inheritance. The post layout outputs the title, +date, author and content body which is wrapped by the default layout. + +Also note the `date_to_string` filter, this formats a date into a nicer format. + +## List posts + +There's currently no way to navigate to the blog post. Typically a blog has a +page which lists all the posts, let's do that next. + +Jekyll makes posts available at `site.posts`. + +Create `blog.html` in your root (`/blog.html`) with the following content: + +{% raw %} +```liquid +--- +layout: default +title: Blog +--- +

Latest Posts

+ +
    + {% for post in site.posts %} +
  • +

    {{ post.title }}

    + {{ post.excerpt }} +
  • + {% endfor %} +
+``` +{% endraw %} + +There's a few things to note with this code: + +* `post.url` is automatically set by Jekyll to the output path of the post +* `post.title` is pulled from the post filename and can be overridden by +setting `title` in front matter +* `post.excerpt` is the first paragraph of content by default + +You also need a way to navigate to this page through the main navigation. Open +`_data/navigation.yml` and add an entry for the blog page: + +```yaml +- name: Home + link: / +- name: About + link: /about.html +- name: Blog + link: /blog.html +``` + +## More posts + +A blog isn't very exciting with a single post. Add a few more: + +`_posts/2018-08-21-apples.md`: + +```markdown +--- +layout: post +author: jill +--- +An apple is a sweet, edible fruit produced by an apple tree. + +Apple trees are cultivated worldwide, and are the most widely grown +species in the genus Malus. The tree originated in Central Asia, where +its wild ancestor, Malus sieversii, is still found today. Apples have +been grown for thousands of years in Asia and Europe, and were brought +to North America by European colonists. +``` + +`_posts/2018-08-22-kiwifruit.md`: + +```markdown +--- +layout: post +author: ted +--- +Kiwifruit (often abbreviated as kiwi), or Chinese gooseberry is the +edible berry of several species of woody vines in the genus Actinidia. + +The most common cultivar group of kiwifruit is oval, about the size of +a large hen's egg (5–8 cm (2.0–3.1 in) in length and 4.5–5.5 cm +(1.8–2.2 in) in diameter). It has a fibrous, dull greenish-brown skin +and bright green or golden flesh with rows of tiny, black, edible +seeds. The fruit has a soft texture, with a sweet and unique flavor. +``` + +Open http://localhost:4000 +and have a look through your blog posts. + +Next we'll focus on creating a page for each post author. diff --git a/docs/_docs/step-by-step/09-collections.md b/docs/_docs/step-by-step/09-collections.md new file mode 100644 index 00000000000..194f1af9624 --- /dev/null +++ b/docs/_docs/step-by-step/09-collections.md @@ -0,0 +1,256 @@ +--- +layout: step +title: Collections +position: 9 +--- +Let's look at fleshing out authors so each author has their own page with a +blurb and the posts they've published. + +To do this you'll use collections. Collections are similar to posts except the +content doesn't have to be grouped by date. + +## Configuration + +To set up a collection you need to tell Jekyll about it. Jekyll configuration +happens in a file called `_config.yml` (by default). + +Create `_config.yml` in the root with the following: + +```yaml +collections: + authors: +``` + +To (re)load the configuration, restart the jekyll server. Press `Ctrl`+`C` in your terminal to stop the server, and then `jekyll serve` to restart it. + +## Add authors + +Documents (the items in a collection) live in a folder in the root of the site +named `_*collection_name*`. In this case, `_authors`. + +Create a document for each author: + +`_authors/jill.md`: + +```markdown +--- +short_name: jill +name: Jill Smith +position: Chief Editor +--- +Jill is an avid fruit grower based in the south of France. +``` + +`_authors/ted.md`: + +```markdown +--- +short_name: ted +name: Ted Doe +position: Writer +--- +Ted has been eating fruit since he was baby. +``` + +## Staff page + +Let's add a page which lists all the authors on the site. Jekyll makes the +collection available at `site.authors`. + +Create `staff.html` in the root directory and iterate over `site.authors` to output all the staff: + +{% raw %} +```liquid +--- +layout: default +title: Staff +--- +

Staff

+ +
    + {% for author in site.authors %} +
  • +

    {{ author.name }}

    +

    {{ author.position }}

    +

    {{ author.content | markdownify }}

    +
  • + {% endfor %} +
+``` +{% endraw %} + +Since the content is markdown, you need to run it through the +`markdownify` filter. This happens automatically when outputting using +{% raw %}`{{ content }}`{% endraw %} in a layout. + +You also need a way to navigate to this page through the main navigation. Open +`_data/navigation.yml` and add an entry for the staff page: + +```yaml +- name: Home + link: / +- name: About + link: /about.html +- name: Blog + link: /blog.html +- name: Staff + link: /staff.html +``` + +## Output a page + +By default, collections do not output a page for documents. In this case we +want each author to have their own page so let's tweak the collection +configuration. + +Open `_config.yml` and add `output: true` to the author collection +configuration: + +```yaml +collections: + authors: + output: true +``` + +Restart the jekyll server once more for the configuration changes to take effect. + +You can link to the output page using `author.url`. + +Add the link to the `staff.html` page: + +{% raw %} +```liquid +--- +layout: default +title: Staff +--- +

Staff

+ +
    + {% for author in site.authors %} +
  • +

    {{ author.name }}

    +

    {{ author.position }}

    +

    {{ author.content | markdownify }}

    +
  • + {% endfor %} +
+``` +{% endraw %} + +Just like posts you'll need to create a layout for authors. + +Create `_layouts/author.html` with the following content: + +{% raw %} +```liquid +--- +layout: default +--- +

{{ page.name }}

+

{{ page.position }}

+ +{{ content }} +``` +{% endraw %} + +## Front matter defaults + +Now you need to configure the author documents to use the `author` layout. You +could do this in the front matter like we have previously but that's getting +repetitive. + +What you really want is all posts to automatically have the post +layout, authors to have author and everything else to use the default. + +You can achieve this by using [front matter defaults](/docs/configuration/front-matter-defaults/) +in `_config.yml`. You set a scope of what the default applies to, then the +default front matter you'd like. + +Add defaults for layouts to your `_config.yml`, + +```yaml +collections: + authors: + output: true + +defaults: + - scope: + path: "" + type: "authors" + values: + layout: "author" + - scope: + path: "" + type: "posts" + values: + layout: "post" + - scope: + path: "" + values: + layout: "default" +``` + +Now you can remove layout from the front matter of all pages and posts. Note +that any time you update `_config.yml` you'll need to restart Jekyll for the +changes to take effect. + +## List author's posts + +Let's list the posts an author has published on their page. To do +this you need to match the author `short_name` to the post `author`. You +use this to filter the posts by author. + +Iterate over this filtered list in `_layouts/author.html` to output the +author's posts: + +{% raw %} +```liquid +--- +layout: default +--- +

{{ page.name }}

+

{{ page.position }}

+ +{{ content }} + +

Posts

+
    + {% assign filtered_posts = site.posts | where: 'author', page.short_name %} + {% for post in filtered_posts %} +
  • {{ post.title }}
  • + {% endfor %} +
+``` +{% endraw %} + +## Link to authors page + +The posts have a reference to the author so let's link it to the author's page. +You can do this using a similar filtering technique in `_layouts/post.html`: + +{% raw %} +```liquid +--- +layout: default +--- +

{{ page.title }}

+ +

+ {{ page.date | date_to_string }} + {% assign author = site.authors | where: 'short_name', page.author | first %} + {% if author %} + - {{ author.name }} + {% endif %} +

+ +{{ content }} +``` +{% endraw %} + +Open up http://localhost:4000 and +have a look at the staff page and the author links on posts to check everything +is linked together correctly. + +In the next and final step of this tutorial, we'll add polish to the site and +get it ready for a production deployment. diff --git a/docs/_docs/step-by-step/10-deployment.md b/docs/_docs/step-by-step/10-deployment.md new file mode 100644 index 00000000000..1514c896d62 --- /dev/null +++ b/docs/_docs/step-by-step/10-deployment.md @@ -0,0 +1,177 @@ +--- +layout: step +title: Deployment +position: 10 +--- +In this final step we'll get the site ready for production. + +## Gemfile + +It's good practice to have a [Gemfile](/docs/ruby-101/#gemfile) for your site. +This ensures the version of Jekyll and other gems remains consistent across +different environments. + +If you completed step one in this tutorial, you have already created a Gemfile. If you skipped step one, create a `Gemfile` in the root. +The file should be called 'Gemfile' and should *not* have any extension. +You can create a Gemfile with Bundler and then add the `jekyll` gem: + +```sh +bundle init +bundle add jekyll +``` + +Your `Gemfile` should look something like: + +```ruby +# frozen_string_literal: true +source "https://rubygems.org" + +gem "jekyll" +``` + +Bundler installs the gems and creates a `Gemfile.lock` which locks the current +gem versions for a future `bundle install`. If you ever want to update your gem +versions you can run `bundle update`. + +When using a `Gemfile`, you'll run commands like `jekyll serve` with +`bundle exec` prefixed. So the full command is: + +```sh +bundle exec jekyll serve +``` + +This restricts your Ruby environment to only use gems set in your `Gemfile`. + +Note: if publishing your site with GitHub Pages, you can match production +version of Jekyll by using the `github-pages` gem instead of `jekyll` +in your `Gemfile`. In this scenario you may also want to exclude `Gemfile.lock` +from your repository because GitHub Pages ignores that file. + +## Plugins + +Jekyll plugins allow you to create custom generated content specific to your +site. There are many [plugins](/docs/plugins/) available or you can even +write your own. + +There are three official plugins which are useful on almost any Jekyll site: + +* [jekyll-sitemap](https://github.com/jekyll/jekyll-sitemap) - Creates a sitemap +file to help search engines index content +* [jekyll-feed](https://github.com/jekyll/jekyll-feed) - Creates an RSS feed for +your posts +* [jekyll-seo-tag](https://github.com/jekyll/jekyll-seo-tag) - Adds meta tags to help +with SEO + +To use these first you need to add them to your `Gemfile`. If you put them +in a `jekyll_plugins` group they'll automatically be required into Jekyll: + +```ruby +source 'https://rubygems.org' + +gem "jekyll" + +group :jekyll_plugins do + gem "jekyll-sitemap" + gem "jekyll-feed" + gem "jekyll-seo-tag" +end +``` + +Then add these lines to your `_config.yml`: + +```yaml +plugins: + - jekyll-feed + - jekyll-sitemap + - jekyll-seo-tag +``` + +Now install them by running a `bundle update`. + +`jekyll-sitemap` doesn't need any setup, it will create your sitemap on build. + +For `jekyll-feed` and `jekyll-seo-tag` you need to add tags to +`_layouts/default.html`: + +{% raw %} +```liquid + + + + + {{ page.title }} + + {% feed_meta %} + {% seo %} + + + {% include navigation.html %} + {{ content }} + + +``` +{% endraw %} + +Restart your Jekyll server and check these tags are added to the ``. + +## Environments + +Sometimes you might want to output something in production but not +in development. Analytics scripts are the most common example of this. + +To do this you can use [environments](/docs/configuration/environments/). You +can set the environment by using the `JEKYLL_ENV` environment variable when +running a command. For example: + +```sh +JEKYLL_ENV=production bundle exec jekyll build +``` + +By default `JEKYLL_ENV` is development. The `JEKYLL_ENV` is available to you +in liquid using `jekyll.environment`. So to only output the analytics script +on production you would do the following: + +{% raw %} +```liquid +{% if jekyll.environment == "production" %} + +{% endif %} +``` +{% endraw %} + +## Deployment + +The final step is to get the site onto a production server. The most basic way +to do this is to run a production build: + +```sh +JEKYLL_ENV=production bundle exec jekyll build +``` + +And then copy the contents of `_site` to your server. + +
+
Destination folders are cleaned on site builds
+

+ The contents of _site are automatically cleaned, by default, when + the site is built. Files or folders that are not created by your site's build + process will be removed. +

+

+ Some files could be retained by specifying them within the keep_files + configuration directive. Other files could be retained by keeping them in your + assets directory. +

+
+ +A better way is to automate this process using a [CI](/docs/deployment/automated/) +or [3rd party](/docs/deployment/third-party/). + +## Wrap up + +That brings us to the end of this step-by-step tutorial and the beginning of +your Jekyll journey! + +* Come say hi to the [community forums](https://talk.jekyllrb.com) +* Help us make Jekyll better by [contributing](/docs/contributing/) +* Keep building Jekyll sites! diff --git a/docs/_docs/structure.md b/docs/_docs/structure.md new file mode 100644 index 00000000000..bdec1fdbef3 --- /dev/null +++ b/docs/_docs/structure.md @@ -0,0 +1,239 @@ +--- +title: Directory Structure +permalink: /docs/structure/ +--- +A basic Jekyll site usually looks something like this: + +``` +. +├── _config.yml +├── _data +│ └── members.yml +├── _drafts +│ ├── begin-with-the-crazy-ideas.md +│ └── on-simplicity-in-technology.md +├── _includes +│ ├── footer.html +│ └── header.html +├── _layouts +│ ├── default.html +│ └── post.html +├── _posts +│ ├── 2007-10-29-why-every-programmer-should-play-nethack.md +│ └── 2009-04-26-barcamp-boston-4-roundup.md +├── _sass +│ ├── _base.scss +│ └── _layout.scss +├── _site +├── .jekyll-cache +│ └── Jekyll +│ └── Cache +│ └── [...] +├── .jekyll-metadata +└── index.html # can also be an 'index.md' with valid front matter +``` + +
+
Directory structure of Jekyll sites using gem-based themes
+

+ Since version {% include docs_version_badge.html version="3.2"%}, a new Jekyll project bootstrapped with jekyll new uses gem-based themes to define the look of the site. This results in a lighter default directory structure: _layouts, _includes and _sass are stored in the theme-gem, by default. +

+
+

+ minima is the current default theme, and bundle info minima will show you where minima theme's files are stored on your computer. +

+
+ +An overview of what each of these does: + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
File / DirectoryDescription
+

_config.yml

+
+

+ Stores configuration data. Many of + these options can be specified from the command line executable but + it’s easier to specify them here so you don’t have to remember them. +

+
+

_drafts

+
+

+ Drafts are unpublished posts. The format of these files is without a + date: title.MARKUP. Learn how to + work with drafts. +

+
+

_includes

+
+

+ These are the partials that can be mixed and matched by your layouts + and posts to facilitate reuse. The liquid tag + {% raw %}{% include file.ext %}{% endraw %} + can be used to include the partial in + _includes/file.ext. +

+
+

_layouts

+
+

+ These are the templates that wrap posts. Layouts are chosen on a + post-by-post basis in the + front matter, + which is described in the next section. The liquid tag + {% raw %}{{ content }}{% endraw %} + is used to inject content into the web page. +

+
+

_posts

+
+

+ Your dynamic content, so to speak. The naming convention of these + files is important, and must follow the format: + YEAR-MONTH-DAY-title.MARKUP. + The permalinks can be customized for + each post, but the date and markup language are determined solely by + the file name. +

+
+

_data

+
+

+ Well-formatted site data should be placed here. The Jekyll engine + will autoload all data files (using either the .yml, + .yaml, .json, .csv or + .tsv formats and extensions) in this directory, + and they will be accessible via `site.data`. If there's a file + members.yml under the directory, then you can access + contents of the file through site.data.members. +

+
+

_sass

+
+

+ These are sass partials that can be imported into your main.scss + which will then be processed into a single stylesheet + main.css that defines the styles to be used by your site. + Learn how to work with assets. +

+
+

_site

+
+

+ This is where the generated site will be placed (by default) once + Jekyll is done transforming it. It’s probably a good idea to add this + to your .gitignore file. +

+
+

.jekyll-cache

+
+

+ Keeps a copy of the generated pages and markup (e.g.: markdown) for + faster serving. Created when using e.g.: jekyll serve. + Can be disabled with + an option and/or flag. + This directory will not be included in the generated site. It’s + probably a good idea to add this to your .gitignore + file. +

+
+

.jekyll-metadata

+
+

+ This helps Jekyll keep track of which files have not been modified + since the site was last built, and which files will need to be + regenerated on the next build. Only created when using + + incremental regeneration (e.g.: with jekyll serve -I). + This file will not be included in the generated site. It’s probably + a good idea to add this to your .gitignore file. +

+
+

index.html or index.md and other HTML, + Markdown files

+
+

+ Provided that the file has a front + matter section, it will be transformed by Jekyll. The same will + happen for any .html, .markdown, + .md, or .textile file in your site’s root + directory or directories not listed above. +

+
+

Other Files/Folders

+
+

+ Except for the special cases listed above, every other directory and + file—such as css and images folders, + favicon.ico files, and so forth—will be copied verbatim + to the generated site. There are plenty of sites + already using Jekyll if you’re curious to see how they’re laid + out. +

+
+
+ +Every file or directory beginning with the following characters: `.`, `_ `, `#` or `~` in the `source` directory will not be included in the `destination` folder. Such paths will have to be explicitly specified via the config file in the `include` directive to make sure they're copied over: + +```yaml +include: + - _pages + - .htaccess + ``` diff --git a/docs/_docs/support.md b/docs/_docs/support.md new file mode 100644 index 00000000000..d22331879e1 --- /dev/null +++ b/docs/_docs/support.md @@ -0,0 +1,24 @@ +--- +title: Support +permalink: "/docs/support/" +note: This file is autogenerated. Edit /.github/SUPPORT.markdown instead. +--- + +## Getting Help + +**Jekyll's issue tracker is not a support forum.** + +If you're looking for support for Jekyll, there are a lot of options: + +* Read [Jekyll Documentation](https://jekyllrb.com/docs/home/) +* If you have a question about using Jekyll, start a discussion on [Jekyll Forum](https://talk.jekyllrb.com/) or [StackOverflow](https://stackoverflow.com/questions/tagged/jekyll) +* Chat with Jekyllers — Join [our Gitter channel](https://gitter.im/jekyll/jekyll) or [our IRC channel on Freenode](irc:irc.freenode.net/jekyll) + +There are a bunch of helpful community members on these services that should be willing to point you in the right direction. + +## Report a bug + +* If you think you've found a bug within a Jekyll plugin, open an issue in that plugin's repository — First [look for the plugin on rubygems](https://rubygems.org/) then click on the `Homepage` link to access the plugin repository. +* If you think you've found a bug within Jekyll itself, [open an issue](https://github.com/jekyll/jekyll/issues/new). + +Happy Jekyllin'! diff --git a/docs/_docs/themes.md b/docs/_docs/themes.md new file mode 100644 index 00000000000..13be0651403 --- /dev/null +++ b/docs/_docs/themes.md @@ -0,0 +1,398 @@ +--- +title: Themes +permalink: /docs/themes/ +--- + +Jekyll has an extensive theme system that allows you to leverage community-maintained templates and styles to customize your site's presentation. Jekyll themes specify plugins and package up assets, layouts, includes, and stylesheets in a way that can be overridden by your site's content. + +## Pick up a theme + +You can find and preview themes on different galleries: + +- [GitHub.com #jekyll-theme repos](https://github.com/topics/jekyll-theme) +- [jamstackthemes.dev](https://jamstackthemes.dev/ssg/jekyll/) +- [jekyllthemes.org](http://jekyllthemes.org/) +- [jekyllthemes.io](https://jekyllthemes.io/) +- [jekyll-themes.com](https://jekyll-themes.com/) +- [jekyllup.com](https://jekyllup.com/) + +See also: [resources](/resources/). + +## Understanding gem-based themes + +When you [create a new Jekyll site](/docs/) (by running the `jekyll new ` command), Jekyll installs a site that uses a gem-based theme called [Minima](https://github.com/jekyll/minima). + +With gem-based themes, some of the site's directories (such as the `assets`, `_data`, `_layouts`, `_includes`, and `_sass` directories) are stored in the theme's gem, hidden from your immediate view. Yet all of the necessary directories will be read and processed during Jekyll's build process. + +In the case of Minima, you see only the following files in your Jekyll site directory: + +``` +. +├── Gemfile +├── Gemfile.lock +├── _config.yml +├── _posts +│ └── 2016-12-04-welcome-to-jekyll.markdown +├── about.markdown +└── index.markdown +``` + +The `Gemfile` and `Gemfile.lock` files are used by Bundler to keep track of the required gems and gem versions you need to build your Jekyll site. + +Gem-based themes make it easier for theme developers to make updates available to anyone who has the theme gem. When there's an update, theme developers push the update to RubyGems. + +If you have the theme gem, you can (if you desire) run `bundle update` to update all gems in your project. Or you can run `bundle update `, replacing `` with the theme name, such as `minima`, to just update the theme gem. Any new files or updates the theme developer has made (such as to stylesheets or includes) will be pulled into your project automatically. + +The goal of gem-based themes is to allow you to get all the benefits of a robust, continually updated theme without having all the theme's files getting in your way and over-complicating what might be your primary focus: creating content. + +## Overriding theme defaults + +Jekyll themes set default data, layouts, includes, and stylesheets. However, you can override any of the theme defaults with your own site content. + +To replace layouts or includes in your theme, make a copy in your `_layouts` or `_includes` directory of the specific file you wish to modify, or create the file from scratch giving it the same name as the file you wish to override. + +For example, if your selected theme has a `page` layout, you can override the theme's layout by creating your own `page` layout in the `_layouts` directory (that is, `_layouts/page.html`). + +To locate a theme's files on your computer: + +1. Run `bundle info --path` followed by the name of the theme's gem, e.g., `bundle info --path minima` for Jekyll's default theme. + + This returns the location of the gem-based theme files. For example, the Minima theme's files might be located in `/usr/local/lib/ruby/gems/2.6.0/gems/minima-2.5.1` on macOS. + +2. Open the theme's directory in Finder or Explorer: + + ```sh + # On MacOS + open $(bundle info --path minima) + + # On Windows + # First get the gem's installation path: + # + # bundle info --path minima + # => C:/Ruby26-x64/lib/ruby/gems/{{ site.data.ruby.current_version }}/gems/minima-2.5.1 + # + # then invoke explorer with above path, substituting `/` with `\` + explorer C:\Ruby26-x64\lib\ruby\gems\{{ site.data.ruby.current_version}}\gems\minima-2.5.1 + + # On Linux + xdg-open $(bundle info --path minima) + ``` + + A Finder or Explorer window opens showing the theme's files and directories. The Minima theme gem contains these files: + + ``` + . + ├── LICENSE.txt + ├── README.md + ├── _includes + │   ├── disqus_comments.html + │   ├── footer.html + │   ├── google-analytics.html + │   ├── head.html + │   ├── header.html + │   ├── icon-github.html + │   ├── icon-github.svg + │   ├── icon-twitter.html + │   └── icon-twitter.svg + ├── _layouts + │   ├── default.html + │   ├── home.html + │   ├── page.html + │   └── post.html + ├── _sass + │   ├── minima + │   │   ├── _base.scss + │   │   ├── _layout.scss + │   │   └── _syntax-highlighting.scss + │   └── minima.scss + └── assets + └── main.scss + ``` + +With a clear understanding of the theme's files, you can now override any theme file by creating a similarly named file in your Jekyll site directory. + +Let's say, for a second example, you want to override Minima's footer. In your Jekyll site, create an `_includes` folder and add a file in it called `footer.html`. Jekyll will now use your site's `footer.html` file instead of the `footer.html` file from the Minima theme gem. + +To modify any stylesheet you must take the extra step of also copying the main sass file (`_sass/minima.scss` in the Minima theme) into the `_sass` directory in your site's source. + +Jekyll will look first to your site's content before looking to the theme's defaults for any requested file in the following folders: + +- `/assets` +- `/_data` +- `/_layouts` +- `/_includes` +- `/_sass` + +Note that making copies of theme files will prevent you from receiving any theme updates on those files. An alternative, to continue getting theme updates on all stylesheets, is to use higher specificity CSS selectors in your own additional, originally named CSS files. + +{: .note .info} +Refer to your selected theme's documentation and source repository for more information on which files you can override. + +### Themes with `_data` directory {%- include docs_version_badge.html version="4.3.0" -%} +{: #themes-with-data-directory } + +Starting with version 4.3.0, Jekyll also takes into account the `_data` directory of themes. This allows data to be distributed across themes. + +A typical example is text used within design elements. + +Imagine a theme provides the include file `testimonials.html`. This design element creates a new section on the page, and puts a h3 heading over the list of testimonials. + +A theme developer will probably formulate the heading in English and put it directly into the HTML source code. + +Consumers of the theme can copy the included file into their project and replace the heading there. + +With the consideration of the `_data` directory there is another solution for this standard task. + +Instead of entering the text directly into the design template, the designer adds a reference to a text catalog (e.g. `site.data.i18n.testimonials.header`) and create a file `_data/i18n/testimonials.yml` in the data directory of the theme. + +In this file the header is put under the key `header` and Jekyll takes care of the rest. + +For theme developers, this, at first sight, is of course a bigger effort than before. + +However, for the consumers of the theme, the customization is greatly simplified. + +Imagine the theme is used by a customer from Germany. In order for her to get the translated header for the testimonials design element in, she just has to create a data file in her project directory with the key `site.data.i18n.testimonials.header`, put the German translation or a header of her choice on top of it and the design element is already customized. + +She no longer has to copy the included file into her project directory, customize it there and, what weighs heaviest, waiver all updates of the theme, simply because the theme developer offered her the possibility to make changes to text modules centrally via text files. + +{: .note .warning} +Data files provide a high degree of flexibility. The place where theme developers put text modules may differ from that of the consumer of the theme which can cause unforeseen troubles! + +Related to above example the overriding key `site.data.i18n.testimonials.header` from the theme's `_data/i18n/testimonials.yml` file on the consumer site can be located in three different locations: + +- `_data/i18n.yml` with key `testimonials.header` +- `_data/i18n/testimonials.yml` with key `header` (which mirrors the layout of the given example) +- `_data/i18n/testimonials/header.yml` without any key, the headline can go straight into the file + +Theme developers should have this ambiguity in mind, when supporting consumers that feel lost in setting their text modules for the design elements the theme provides. + +{: .note .info} +When using the data feature ask yourself, is the key that you introduce something that changes the behaviour of the theme when present or not, or is it just data that's displayed anyway. If it's changing the behaviour of the theme it should go into `site.config` otherwise it's fine to be provided via `site.data`. + +Bundling data that modifies the behavior of a theme is considered an **anti-pattern** whose use is strongly discouraged. It is solely up to the author of the theme to ensure that every provided data can be easily overridden by the consumer of the theme if they desire to. + +## Converting gem-based themes to regular themes + +Suppose you want to get rid of the gem-based theme and convert it to a regular theme, where all files are present in your Jekyll site directory, with nothing stored in the theme gem. + +To do this, copy the files from the theme gem's directory into your Jekyll site directory. (For example, copy them to `/myblog` if you created your Jekyll site at `/myblog`. See the previous section for details.) + +Then you must tell Jekyll about the plugins that were referenced by the theme. You can find these plugins in the theme's gemspec file as runtime dependencies. If you were converting the Minima theme, for example, you might see: + +```ruby +spec.add_runtime_dependency "jekyll-feed", "~> 0.12" +spec.add_runtime_dependency "jekyll-seo-tag", "~> 2.6" +``` + +You should include these references in the `Gemfile` in one of two ways. + +You could list them individually in both `Gemfile` and `_config.yml`. + +```ruby +# ./Gemfile + +gem "jekyll-feed", "~> 0.12" +gem "jekyll-seo-tag", "~> 2.6" +``` + +```yaml +# ./_config.yml + +plugins: + - jekyll-feed + - jekyll-seo-tag +``` + +Or you could list them explicitly as Jekyll plugins in your Gemfile, and not update `_config.yml`, like this: + +```ruby +# ./Gemfile + +group :jekyll_plugins do + gem "jekyll-feed", "~> 0.12" + gem "jekyll-seo-tag", "~> 2.6" +end +``` + +Either way, don't forget to `bundle update`. + +If you're publishing on GitHub Pages you should update only your `_config.yml` as GitHub Pages doesn't load plugins via Bundler. + +Finally, remove references to the theme gem in `Gemfile` and configuration. For example, to remove `minima`: + +- Open `Gemfile` and remove `gem "minima", "~> 2.5"`. +- Open `_config.yml` and remove `theme: minima`. + +Now `bundle update` will no longer get updates for the theme gem. + +## Installing a gem-based theme {#installing-a-theme} + +The `jekyll new ` command isn't the only way to create a new Jekyll site with a gem-based theme. You can also find gem-based themes online and incorporate them into your Jekyll project. + +For example, search for [jekyll theme on RubyGems](https://rubygems.org/search?utf8=%E2%9C%93&query=jekyll-theme) to find other gem-based themes. (Note that not all themes are using `jekyll-theme` as a convention in the theme name.) + +To install a gem-based theme: + +1. Add the theme gem to your site's `Gemfile`: + + ```ruby + # ./Gemfile + + # This is an example, declare the theme gem you want to use here + gem "jekyll-theme-minimal" + ``` + + Or if you've started with the `jekyll new` command, replace `gem "minima", "~> 2.0"` with the gem you want, e.g: + + ```diff + # ./Gemfile + + - gem "minima", "~> 2.5" + + gem "jekyll-theme-minimal" + ``` + +2. Install the theme: + + ```sh + bundle install + ``` + +3. Add the following to your site's `_config.yml` to activate the theme: + + ```yaml + theme: jekyll-theme-minimal + ``` + +4. Build your site: + + ```sh + bundle exec jekyll serve + ``` + +{: .note .info} +You can have multiple themes listed in your site's `Gemfile`, but only one theme can be selected in your site's `_config.yml`. + +If you're publishing your Jekyll site on [GitHub Pages](https://pages.github.com/), note that GitHub Pages supports only [some gem-based themes](https://pages.github.com/themes/). GitHub Pages also supports [using any theme hosted on GitHub](https://help.github.com/articles/adding-a-jekyll-theme-to-your-github-pages-site/#adding-a-jekyll-theme-in-your-sites-_configyml-file) using the `remote_theme` configuration as if it were a gem-based theme. + +## Creating a gem-based theme + +If you're a Jekyll theme developer (rather than a consumer of themes), you can package up your theme in RubyGems and allow users to install it through Bundler. + +If you're unfamiliar with creating Ruby gems, don't worry. Jekyll will help you scaffold a new theme with the `new-theme` command. Run `jekyll new-theme` with the theme name as an argument. + +Here is an example: + +```sh +jekyll new-theme jekyll-theme-awesome + create /path/to/jekyll-theme-awesome/_layouts + create /path/to/jekyll-theme-awesome/_includes + create /path/to/jekyll-theme-awesome/_sass + create /path/to/jekyll-theme-awesome/_layouts/page.html + create /path/to/jekyll-theme-awesome/_layouts/post.html + create /path/to/jekyll-theme-awesome/_layouts/default.html + create /path/to/jekyll-theme-awesome/Gemfile + create /path/to/jekyll-theme-awesome/jekyll-theme-awesome.gemspec + create /path/to/jekyll-theme-awesome/README.md + create /path/to/jekyll-theme-awesome/LICENSE.txt + initialize /path/to/jekyll-theme-awesome/.git + create /path/to/jekyll-theme-awesome/.gitignore +Your new Jekyll theme, jekyll-theme-awesome, is ready for you in /path/to/jekyll-theme-awesome! +For help getting started, read /path/to/jekyll-theme-awesome/README.md. +``` + +Add your template files in the corresponding folders. Then complete the `.gemspec` and the README files according to your needs. + +### Layouts and includes + +Theme layouts and includes work just like they work in any Jekyll site. Place layouts in your theme's `/_layouts` folder, and place includes in your themes `/_includes` folder. + +For example, if your theme has a `/_layouts/page.html` file, and a page has `layout: page` in its front matter, Jekyll will first look to the site's `_layouts` folder for the `page` layout, and if none exists, will use your theme's `page` layout. + +### Assets + +Any file in `/assets` will be copied over to the user's site upon build unless they have a file with the same relative path. You can ship any kind of asset here: SCSS, an image, a webfont, etc. These files behave like pages and static files in Jekyll: + +- If the file has [front matter](/docs/front-matter/) at the top, it will be rendered. +- If the file does not have front matter, it will simply be copied over into the resulting site. + +This allows theme creators to ship a default `/assets/styles.scss` file which their layouts can depend on as `/assets/styles.css`. + +All files in `/assets` will be output into the compiled site in the `/assets` folder just as you'd expect from using Jekyll on your sites. + +### Stylesheets + +Your theme's stylesheets should be placed in your theme's `_sass` folder, again, just as you would when authoring a Jekyll site. + +``` +_sass +└── jekyll-theme-awesome.scss +``` + +Your theme's styles can be included in the user's stylesheet using the `@import` directive. + +{% raw %} +```css +@import "{{ site.theme }}"; +``` +{% endraw %} + +### Theme-gem dependencies {%- include docs_version_badge.html version="3.5.0" -%} + +Jekyll will automatically require all whitelisted `runtime_dependencies` of your theme-gem even if they're not explicitly included under the `plugins` array in the site's config file. (Note: whitelisting is only required when building or serving with the `--safe` option.) + +With this, the end-user need not keep track of the plugins required to be included in their config file for their theme-gem to work as intended. + +### Pre-configuring Theme-gems {%- include docs_version_badge.html version="4.0" -%} + +Jekyll will read-in a `_config.yml` at the root of the theme-gem and merge its data into the site's existing configuration data. + +But unlike other entities loaded from within the theme, loading the config file comes with a few restrictions, as summarized below: + * Jekyll's default settings cannot be overridden by a theme-config. That *ball is still in the user's court.* + * The theme-config-file cannot be a symlink, irrespective of `safe mode` and whether the file pointed to by the symlink is a legitimate file within the theme-gem. + * The theme-config should be a set of key-value pairs. An empty config file, a config file that simply *lists items* under a key, or a config file with just a simple string of text will simply be ignored silently. Users will not get a warning or any log output regarding this discrepancy. + * Any settings defined by the theme-config can be overridden by the user. + +While this feature is to enable easier adoption of a theme, the restrictions ensure that a theme-config cannot affect the build in a concerning manner. Any plugins required by the theme will have to be listed manually by the user or provided by the theme's `gemspec` file. + +This feature will let the theme-gem to work with *theme-specific config variables* out-of-the-box. + +### Documenting your theme + +Your theme should include a `/README.md` file, which explains how site authors can install and use your theme. What layouts are included? What includes? Do they need to add anything special to their site's configuration file? + +### Adding a screenshot + +Themes are visual. Show users what your theme looks like by including a screenshot as `/screenshot.png` within your theme's repository where it can be retrieved programmatically. You can also include this screenshot within your theme's documentation. + +### Previewing your theme + +To preview your theme as you're authoring it, it may be helpful to add dummy content in, for example, `/index.html` and `/page.html` files. This will allow you to use the `jekyll build` and `jekyll serve` commands to preview your theme, just as you'd preview a Jekyll site. + +{: .note .info} +If you do preview your theme locally, be sure to add `/_site` to your theme's `.gitignore` file to prevent the compiled site from also being included when you distribute your theme. + +### Publishing your theme + +Themes are published via [RubyGems.org](https://rubygems.org). You will need a RubyGems account, which you can [create for free](https://rubygems.org/sign_up). + +1. First, you need to have it in a git repository: + + ```sh + git init # Only the first time + git add -A + git commit -m "Init commit" + ``` + +2. Next, package your theme, by running the following command, replacing `jekyll-theme-awesome` with the name of your theme: + + ```sh + gem build jekyll-theme-awesome.gemspec + ``` + +3. Finally, push your packaged theme up to the RubyGems service, by running the following command, again replacing `jekyll-theme-awesome` with the name of your theme: + + ```sh + gem push jekyll-theme-awesome-*.gem + ``` + +4. To release a new version of your theme, update the version number in the gemspec file, ( `jekyll-theme-awesome.gemspec` in this example ), and then repeat Steps 1 - 3 above. We recommend that you follow [Semantic Versioning](https://semver.org) while bumping your theme-version. diff --git a/docs/_docs/troubleshooting.md b/docs/_docs/troubleshooting.md new file mode 100644 index 00000000000..e6cfc35d047 --- /dev/null +++ b/docs/_docs/troubleshooting.md @@ -0,0 +1,323 @@ +--- +title: Troubleshooting +permalink: /docs/troubleshooting/ +--- + +If you ever run into problems installing or using Jekyll, here are a few tips +that might be of help. If the problem you’re experiencing isn’t covered below, +**please [check out our other help resources](/help/)** as well. + +- [Installation Problems](#installation-problems) +- [Problems running Jekyll](#problems-running-jekyll) +- [Base-URL Problems](#base-url-problems) +- [Configuration problems](#configuration-problems) +- [Markup Problems](#markup-problems) +- [Production Problems](#production-problems) + +## Installation Problems + +If you encounter errors during gem installation, you may need to install +the header files for compiling extension modules for Ruby 2.x This +can be done on Ubuntu or Debian by running: + +```sh +sudo apt-get install ruby2.6-dev +``` + +On Red Hat, CentOS, and Fedora systems you can do this by running: + +```sh +sudo yum install ruby-devel +``` + +On Arch Linux you need to run: + +```sh +sudo pacman -S ruby-ffi +``` + +On Ubuntu if you get stuck after `bundle exec jekyll serve` and see error +messages like `Could not locate Gemfile` or `.bundle/ directory`, it's likely +because all requirements have not been fully met. Recent stock Ubuntu +distributions require the installation of both the `ruby` and `ruby-all-dev` +packages: + +```sh +sudo apt-get install ruby ruby-all-dev +``` + +On [NearlyFreeSpeech](https://www.nearlyfreespeech.net/) you need to run the +following commands before installing Jekyll: + +```sh +export GEM_HOME=/home/private/gems +export GEM_PATH=/home/private/gems:/usr/local/lib/ruby/gems/1.8/ +export PATH=$PATH:/home/private/gems/bin +export RB_USER_INSTALL='true' +``` + +To install RubyGems on Gentoo: + +```sh +sudo emerge -av dev-ruby/rubygems +``` + +On Windows, you may need to install [RubyInstaller +DevKit](https://wiki.github.com/oneclick/rubyinstaller/development-kit). + +On Android (with Termux) you can install all requirements by running: + +```sh +apt update && apt install libffi-dev clang ruby-dev make +``` + +On macOS, you may need to update RubyGems (using `sudo` only if necessary): + +```sh +gem update --system +``` + +If you still have issues, you can download and install new Command Line +Tools (such as `gcc`) using the following command: + +```sh +xcode-select --install +``` + +which may allow you to install native gems using this command (again, using +`sudo` only if necessary): + +```sh +gem install jekyll +``` + +Note that upgrading macOS does not automatically upgrade Xcode itself +(that can be done separately via the App Store), and having an out-of-date +Xcode.app can interfere with the command line tools downloaded above. If +you run into this issue, upgrade Xcode and install the upgraded Command +Line Tools. + +### Running Jekyll as Non-Superuser (no sudo!) +{: #no-sudo} + +On most flavors of Linux, macOS, and Bash on Ubuntu on Windows, it is +possible to run Jekyll as a non-superuser and without having to install +gems to system-wide locations by adding the following lines to the end +of your `.bashrc` file: + +```bash +# Ruby exports + +export GEM_HOME=$HOME/gems +export PATH=$HOME/gems/bin:$PATH +``` + +This tells `gem` to place its gems within the user's home folder, +not in a system-wide location, and adds the local `jekyll` command to the +user's `PATH` ahead of any system-wide paths. + +This is also useful for many shared webhosting services, where user accounts +have only limited privileges. Adding these exports to `.bashrc` before running +`gem install jekyll bundler` allows a complete non-`sudo` install of Jekyll. + +To activate the new exports, either close and restart Bash, logout and +log back into your shell account, or run `. .bashrc` in the +currently-running shell. + +If you see the following error when running the `jekyll new` command, +you can solve it by using the above-described procedure: + +```sh +jekyll new test + +Running bundle install in /home/user/test... + +Your user account is not allowed to install to the system RubyGems. +You can cancel this installation and run: + + bundle install --path vendor/bundle + +to install the gems into ./vendor/bundle/, or you can enter your password +and install the bundled gems to RubyGems using sudo. + +Password: +``` + +Once this is done, the `jekyll new` command should work properly for +your user account. + +### Jekyll & macOS + +With the introduction of System Integrity Protection in v10.11, several directories +that were previously writable are now considered system locations and are no +longer available. Given these changes, there are a couple of simple ways to get +up and running. One option is to change the location where the gem will be +installed (again, using `sudo` only if necessary): + +```sh +gem install -n /usr/local/bin jekyll +``` + +Alternatively, Homebrew can be installed and used to set up Ruby. This can be +done as follows: + +```sh +ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +``` + +Once Homebrew is installed, the second step is to run: + +```sh +brew install ruby +``` + +Advanced users (with more complex needs) may find it helpful to choose one of a +number of Ruby version managers ([RVM][], [rbenv][], [chruby][], [etc][].) in +which to install Jekyll. + +[RVM]: https://rvm.io +[rbenv]: http://rbenv.org +[chruby]: https://github.com/postmodern/chruby +[etc]: https://github.com/rvm/rvm/blob/master/docs/alt.md + +If you elect to use one of the above methods to install Ruby, it might be +necessary to modify your `$PATH` variable using the following command: + +```sh +export PATH=/usr/local/bin:$PATH +``` + +GUI apps can modify the `$PATH` as follows: + +```sh +launchctl setenv PATH "/usr/local/bin:$PATH" +``` + +Either of these approaches are useful because `/usr/local` is considered a +"safe" location on systems which have SIP enabled, they avoid potential +conflicts with the version of Ruby included by Apple, and it keeps Jekyll and +its dependencies in a sandboxed environment. This also has the added +benefit of not requiring `sudo` when you want to add or remove a gem. + +### Could not find a JavaScript runtime. (ExecJS::RuntimeUnavailable) + +This error can occur during the installation of `jekyll-coffeescript` when +you don't have a proper JavaScript runtime. To solve this, either install +`execjs` and `therubyracer` gems, or install `nodejs`. Check out +[issue #2327](https://github.com/jekyll/jekyll/issues/2327) for more info. + +## Problems running Jekyll + +### macOS + +Jekyll is compatible with macOS with ARM64 architecture. +However, `bundle exec jekyll serve` may [fail with older version `ffi`](https://github.com/ffi/ffi/issues/870). + +You may need to run `bundle update` or update `ffi` to at least `1.14.2` manually. + +### Debian or Ubuntu + +On Debian or Ubuntu, you may need to add `/var/lib/gems/1.8/bin/` to your path +in order to have the `jekyll` executable be available in your Terminal. + +## Base-URL Problems + +If you are using base-url option like: + +```sh +jekyll serve --baseurl '/blog' +``` + +… then make sure that you access the site at: + +``` +http://localhost:4000/blog/index.html +``` + +It won’t work to just access: + +``` +http://localhost:4000/blog +``` + +## Configuration problems + +The order of precedence for conflicting [configuration settings](/docs/configuration/) +is as follows: + +1. Command-line flags +2. Configuration file settings +3. Defaults + +That is: defaults are overridden by options specified in `_config.yml`, +and flags specified at the command-line will override all other settings +specified elsewhere. + +**Note: From v3.3.0 onward, Jekyll does not process `node_modules` and certain subdirectories within `vendor`, by default. But, by having an `exclude:` array defined explicitly in the config file overrides this default setting, which results in some users to encounter an error in building the site, with the following error message:** + +``` + ERROR: YOUR SITE COULD NOT BE BUILT: + ------------------------------------ + Invalid date '<%= Time.now.strftime('%Y-%m-%d %H:%M:%S %z') %>': + Document 'vendor/bundle/gems/jekyll-3.4.3/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb' + does not have a valid date in front matter. +``` + +Adding `vendor/bundle` to the `exclude:` list will solve this problem but will lead to having other sub-directories under `/vendor/` (and also `/node_modules/`, if present) be processed to the destination folder `_site`. + +The proper solution is to incorporate the default setting for `exclude:` rather than override it completely: + +For versions up to `v3.4.3`, the `exclude:` setting must look like following: + +```yaml +exclude: + - Gemfile + - Gemfile.lock + - node_modules + - vendor/bundle/ + - vendor/cache/ + - vendor/gems/ + - vendor/ruby/ + - any_additional_item # any user-specific listing goes at the end +``` + +From `v3.5` onward, `Gemfile` and `Gemfile.lock` are also excluded by default. So, in most cases there is no need to define another `exclude:` array in the config file. So an existing definition can either be modified as above, or removed completely, or commented out to enable easy edits in future. + +## Markup Problems + +The various markup engines that Jekyll uses may have some issues. This +page will document them to help others who may run into the same +problems. + +### Liquid + +Liquid version 2.0 seems to break the use of `{{ "{{" }}` in templates. +Unlike previous versions, using `{{ "{{" }}` in 2.0 triggers the following error: + +``` +'{{ "{{" }}' was not properly terminated with regexp: /\}\}/ (Liquid::SyntaxError) +``` + +### Excerpts + +Since v1.0.0, Jekyll has had automatically-generated post excerpts. Since +v1.1.0, Jekyll also passes these excerpts through Liquid, which can cause +strange errors where references don't exist or a tag hasn't been closed. If you +run into these errors, try setting `excerpt_separator: ""` in your +`_config.yml`, or set it to some nonsense string. + +## Production Problems + +If you run into an issue that a static file can't be found in your +production environment during build since v3.2.0 you should set your +[environment to `production`](/docs/configuration/environments/). +The issue is caused by trying to copy a non-existing symlink. + +
+
Please report issues you encounter!
+

+ If you come across a bug, please create an issue + on GitHub describing the problem and any workarounds you find so we can + document it here for others. +

+
diff --git a/docs/_docs/upgrading.md b/docs/_docs/upgrading.md new file mode 100644 index 00000000000..37138000069 --- /dev/null +++ b/docs/_docs/upgrading.md @@ -0,0 +1,30 @@ +--- +layout: docs +title: Upgrading +permalink: /docs/upgrading/ +--- + +Upgrading from an older version of Jekyll? Upgrading to a new major version of +Jekyll (e.g. from v2.x to v3.x) may cause some headaches. Take the following +guides to aid your upgrade: + +- [From 0.x to 1.x and 2.x](/docs/upgrading/0-to-2/) +- [From 2.x to 3.x](/docs/upgrading/2-to-3/) +- [From 3.x to 4.x](/docs/upgrading/3-to-4/) + +## Minor updates + +
+
Stay Up to Date
+

We recommend you update Jekyll as often as possible to benefit from + the latest bug fixes. +

+
+ +If you followed our setup recommendations and installed [Bundler](http://bundler.io/), run `bundle update jekyll` or simply `bundle update` and all your gems will +update to the latest versions. + +If you don't have Bundler installed, run `gem update jekyll`. + +The procedure is similar [if you use the `github-pages` +gem](https://help.github.com/articles/setting-up-your-github-pages-site-locally-with-jekyll/#keeping-your-site-up-to-date-with-the-github-pages-gem). diff --git a/site/_docs/upgrading/0-to-2.md b/docs/_docs/upgrading/0-to-2.md similarity index 92% rename from site/_docs/upgrading/0-to-2.md rename to docs/_docs/upgrading/0-to-2.md index 84ec90e71b7..5ea821900fa 100644 --- a/site/_docs/upgrading/0-to-2.md +++ b/docs/_docs/upgrading/0-to-2.md @@ -1,5 +1,4 @@ --- -layout: docs title: Upgrading from 0.x to 2.x permalink: /docs/upgrading/0-to-2/ --- @@ -9,9 +8,9 @@ and 2.0 that you'll want to know about. Before we dive in, go ahead and fetch the latest version of Jekyll: -{% highlight bash %} -$ gem update jekyll -{% endhighlight %} +```sh +gem update jekyll +```
Diving in
@@ -54,9 +53,9 @@ relative permalinks. Relative permalink backwards-compatibility was removed in v ### Draft Posts Jekyll now lets you write draft posts, and allows you to easily preview how -they will look prior to publishing. To start a draft, simply create a folder +they will look prior to publishing. To start a draft, create a folder called `_drafts` in your site's source directory (e.g., alongside `_posts`), -and add a new markdown file to it. To preview your new post, simply run the +and add a new markdown file to it. To preview your new post, run the `jekyll serve` command with the `--drafts` flag.
@@ -73,7 +72,7 @@ and add a new markdown file to it. To preview your new post, simply run the Rather than passing individual flags via the command line, you can now pass an entire custom Jekyll config file. This helps to distinguish between environments, or lets you programmatically override user-specified -defaults. Simply add the `--config` flag to the `jekyll` command, followed +defaults. Add the `--config` flag to the `jekyll` command, followed by the path to one or more config files (comma-delimited, no spaces). #### As a result, the following command line flags are now deprecated: @@ -120,14 +119,13 @@ Often, you'll want the ability to run a Jekyll site in multiple places, such as previewing locally before pushing to GitHub Pages. Jekyll 1.0 makes that easier with the new `--baseurl` flag. To take advantage of this feature, first add the production `baseurl` to your site's `_config.yml` -file. Then, throughout the site, simply prefix relative URLs -with `{% raw %}{{ site.baseurl }}{% endraw %}`. +file. Then, throughout the site, prefix relative URLs +with {% raw %}`{{ site.baseurl }}`{% endraw %}. When you're ready to preview your site locally, pass along the `--baseurl` flag with your local baseurl (most likely `/`) to `jekyll serve` and Jekyll will swap in whatever you've passed along, ensuring all your links work as you'd expect in both environments. -
All page and post URLs contain leading slashes

If you use the method described above, please remember diff --git a/docs/_docs/upgrading/2-to-3.md b/docs/_docs/upgrading/2-to-3.md new file mode 100644 index 00000000000..2426a5762f2 --- /dev/null +++ b/docs/_docs/upgrading/2-to-3.md @@ -0,0 +1,142 @@ +--- +title: Upgrading from 2.x to 3.x +permalink: /docs/upgrading/2-to-3/ +--- + +Upgrading from an older version of Jekyll? A few things have changed in Jekyll 3 +that you'll want to know about. + +Before we dive in, go ahead and fetch the latest version of Jekyll: + +```sh +gem update jekyll +``` + +{: .note .warning} +Since version {% include docs_version_badge.html version="3.2"%}, Jekyll requires Ruby version >= 2.1. + +

+
Diving in
+

Want to get a new Jekyll site up and running quickly? Simply + run jekyll new SITENAME to create a new folder with a bare bones + Jekyll site.

+
+ +### site.collections has changed + +In 2.x, your iterations over `site.collections` yielded an array with the collection +label and the collection object as the first and second items, respectively. In 3.x, +this complication has been removed and iterations now yield simply the collection object. +A simple conversion must be made in your templates: + +- `collection[0]` becomes `collection.label` +- `collection[1]` becomes `collection` + +When iterating over `site.collections`, ensure the above conversions are made. + +For `site.collections.myCollection` in Jekyll 2, you now do: + +{% raw %} +```liquid +{% assign myCollection = site.collections | where: "label", "myCollection" | first %} +``` +{% endraw %} + +This is a bit cumbersome at first, but is easier than a big `for` loop. + +### Textile support + +We dropped native support for Textile, from now on you have to install our [jekyll-textile-converter](https://github.com/jekyll/jekyll-textile-converter) plugin to work with Textile files. + +### Dropped dependencies + +We dropped a number of dependencies the Core Team felt were optional. As such, in 3.0, they must be explicitly installed and included if you use any of the features. They are: + +- jekyll-paginate – Jekyll's pagination solution from days past +- jekyll-coffeescript – processing of CoffeeScript +- jekyll-gist – the `gist` Liquid tag +- pygments.rb – the Pygments highlighter +- redcarpet – the Markdown processor +- toml – an alternative to YAML for configuration files +- classifier-reborn – for `site.related_posts` + +### Future posts + +A seeming feature regression in 2.x, the `--future` flag was automatically _enabled_. +The future flag allows post authors to give the post a date in the future and to have +it excluded from the build until the system time is equal or after the post time. +In Jekyll 3, this has been corrected. **Now, `--future` is disabled by default.** +This means you will need to include `--future` if you want your future-dated posts to +generate when running `jekyll build` or `jekyll serve`. + +
+
Future Posts on GitHub Pages
+

+ An exception to the above rule are GitHub Pages sites, where the --future flag remains enabled + by default to maintain historical consistency for those sites. +

+
+ +### Layout metadata + +Introducing: `layout`. In Jekyll 2 and below, any metadata in the layout was merged onto +the `page` variable in Liquid. This caused a lot of confusion in the way the data was +merged and some unexpected behaviour. In Jekyll 3, all layout data is accessible via `layout` +in Liquid. For example, if your layout has `class: my-layout` in its front matter, +then the layout can access that via {% raw %}`{{ layout.class }}`{% endraw %}. + +### Syntax highlighter changed + +For the first time, the default syntax highlighter has changed for the +`highlight` tag and for backtick code blocks. Instead of [Pygments.rb](https://github.com/tmm1/pygments.rb), +it's now [Rouge](https://github.com/rouge-ruby/rouge). If you were using the `highlight` tag with certain +options, such as `hl_lines`, they may not be available when using Rouge. To +go back to using Pygments, set `highlighter: pygments` in your +`_config.yml` file and run `gem install pygments.rb` or add +`gem "pygments.rb"` to your project's `Gemfile`. + +### Relative Permalink support removed + +In Jekyll 3 and above, relative permalinks have been deprecated. If you +created your site using Jekyll 2 and below, you may receive the following +error when trying to **serve** or **build**: + +``` +Since v3.0, permalinks for pages in subfolders must be relative to the site +source directory, not the parent directory. Check +https://jekyllrb.com/docs/upgrading/ for more info. +``` + +This can be fixed by removing the following line from your `_config.yml` file: + +```yaml +relative_permalinks: true +``` + +### Permalinks no longer automatically add a trailing slash + +In Jekyll 2, any URL constructed from the `permalink:` field had a trailing slash (`/`) added to it automatically. Jekyll 3 no longer adds a trailing slash automatically to `permalink:` URLs. This can potentially result in old links to pages returning a 404 error. For example, suppose a page previously contained the YAML `permalink: /:year-:month-:day-:title` that resulted in the URL `example.com/2016-02-01-test/` (notice the trailing slash), Jekyll internally generates a folder named `2016-02-01-test`. In Jekyll 3, the same `permalink:` generate the file `2016-02-01-test.html` and the URL for the same page will be `example.com/2016-02-01-test`, and consequently any links to the old URL will result in a 404 error. In order to maintain the same URLs and avoid this problem, a trailing slash should be added to the `permalink:` field, for example `permalink: /:year-:month-:day-:title/`. + +### All my posts are gone! Where'd they go! + +Try adding `future: true` to your `_config.yml` file. Are they showing up now? If they are, then you were ensnared by an issue with the way Ruby parses times. Each of your posts is being read in a different timezone than you might expect and, when compared to the computer's current time, is "in the future." The fix for this is to add [a timezone offset](https://en.wikipedia.org/wiki/List_of_UTC_time_offsets) to each post (and make sure you remove `future: true` from your `_config.yml` file). If you're writing from California, for example, you would change this: + +```yaml +--- +date: 2016-02-06 19:32:10 +--- +``` + +to this (note the offset): + +```yaml +--- +date: 2016-02-06 19:32:10 -0800 +--- +``` + +### My categories have stopped working! + +If you organized your categories as `/_posts/code/2008-12-24-closures.md`, you will need to restructure your directories to put the categories _above_ the `_posts` directories, as follows: `/code/_posts/2008-12-24-closures.md`. + +_Did we miss something? Please click "Improve this page" above and add a section. Thanks!_ diff --git a/docs/_docs/upgrading/3-to-4.md b/docs/_docs/upgrading/3-to-4.md new file mode 100644 index 00000000000..3d03968fd40 --- /dev/null +++ b/docs/_docs/upgrading/3-to-4.md @@ -0,0 +1,175 @@ +--- +title: Upgrading from 3.x to 4.x +permalink: /docs/upgrading/3-to-4/ +--- + +A few things have changed in Jekyll 4. + +Before we dive in, you need to have at least Ruby {{ site.data.ruby.min_version }} +installed. + +Run the following in your terminal to check + +```sh +ruby -v +{{ site.data.ruby.current_version_output }} +``` + +If you're using a supported Ruby version >= {{ site.data.ruby.min_version }}, go ahead +and fetch the latest version of Jekyll: + +```sh +gem update jekyll +``` + +
+
post_url Tag and Baseurl
+

 

+

+ The post_url tag now incorporates the relative_url filter within itself + and therefore automatically prepends your site's baseurl to the post's url + value. +

+

+ Please ensure that you change all instances of the post_url usage as following: +

+ +{% highlight diff %} +{% raw %} +- {{ site.baseurl }}/{% post_url 2018-03-20-hello-world.markdown %} ++ {% post_url 2018-03-20-hello-world.markdown %} +{% endraw %} +{% endhighlight %} +
+ +## Template rendering + +We've slightly altered the way Jekyll parses and renders your various templates +to improve the overall build times. Jekyll now parses a template once, caches it +internally and then renders the parsed template multiple times as required by +your pages and documents. + +The downside to this is that some of the community-authored plugins may not work +as they previously used to. + +## Static files in unrendered collections + +Collections other than `posts` can contain static assets along with Markdown files. +But if the collection has not been configured with metadata `output: true`, then +neither its *documents* nor its *static assets* will be output to the destination +directory. + +## For plugin authors + +* If your plugin depends on the following code: `site.liquid_renderer.file(path).parse(content)`, +note that the return value (`template`, an instance of *`Liquid::Template`*), from that line will +always be the **same object** for a given `path`.
+The *`template`* instance is then rendered as previously, with respect to the `payload` passed to it. +You'll therefore have to ensure that *`payload`* is not memoized or cached in your plugin instance. + +* If its a requirement that `template` you get from the above step *be different* at all times, +you can invoke *`Liquid::Template`* directly: + + ```diff + - template = site.liquid_renderer.file(path).parse(content) + + template = Liquid::Template.parse(content) + ``` + +## Exclusion changes + +We've enhanced our default exclusion array. +It now looks like the following: + +```yaml +# default excludes +exclude: +- .sass-cache/ +- .jekyll-cache/ +- gemfiles/ +- Gemfile +- Gemfile.lock +- node_modules/ +- vendor/bundle/ +- vendor/cache/ +- vendor/gems/ +- vendor/ruby/ +``` + +What's new is that this array **does not get overridden by the `exclude` array +in the user's config file anymore**. The user's exclude entries simply get +**added** to the above default array (if the entry isn't already excluded). + +To forcibly "process" directories or files that have been excluded, list them +in the `include` array instead: + +```yaml +# overrides your excluded items configuration and the default include array ([".htaccess"]) +include: + - .htaccess + - node_modules/uglifier/index.js +``` + +The above configuration directs Jekyll to handle only +`node_modules/uglifier/index.js` while ignoring every other file in the +`node_modules` directory since that directory is "excluded" by default. + +Note that the default `include` array still gets overridden by the `include` +array in your config file. So, be sure to add `.htaccess` to the list if you +need that file to be present in the generated site. + +## Kramdown v2 + +Jekyll has dropped support for `kramdown-1.x` entirely. + +From [`v2.0` onwards](https://kramdown.gettalong.org/news.html#kramdown-200-released) +kramdown requires specific extensions to be additionally installed to use +certain desired features outside of kramdown's core functionality. + +Out of all the extensions listed in the report linked above, gem +`kramdown-parser-gfm` is automatically installed along with Jekyll 4.0. The +remaining extensions will have to be manually installed by the user depending on +desired functionality, by listing the extension's gem-name in their `Gemfile`. + +Notes: + * `kramdown-converter-pdf` will be ignored by Jekyll Core. To have Jekyll convert Markdown to PDF + you'll have to depend on a plugin that subclasses `Jekyll::Converter` with the + [required methods]({% link _docs/plugins/converters.md %}). + + For example: + + ```ruby + module Jekyll + External.require_with_graceful_fail "kramdown-converter-pdf" + + class Markdown2PDF < Converter + safe true + priority :low + + def matches(ext) + # match only files that have an extension exactly ".markdown" + ext =~ /^\.markdown$/ + end + + def convert(content) + Kramdown::Document.new(content).to_pdf + end + + def output_ext + ".pdf" + end + end + end + ``` + + * Vendors that provide a versioned Jekyll Environment Image (e.g. Docker Image, GitHub Pages, etc) + will have to manually whitelist kramdown's extension gems in their distributions for Jekyll 4.0. + +## Deprecated Configuration Options + +Jekyll 4.0 has dropped support for all legacy configuration options that were deprecated over multiple +releases in the previous series. + +To that end, we shall no longer output a deprecation warning when we encounter a legacy config key nor +shall we gracefully assign their values to the newer counterparts. Depending on the key, it shall either +be ignored or raise an `InvalidConfigurationError` error if the key is still valid but the associated +value is not of the valid type. diff --git a/docs/_docs/usage.md b/docs/_docs/usage.md new file mode 100644 index 00000000000..42cd6f20181 --- /dev/null +++ b/docs/_docs/usage.md @@ -0,0 +1,33 @@ +--- +title: Command Line Usage +permalink: /docs/usage/ +--- + +The Jekyll gem makes a `jekyll` executable available to you in your terminal. + +The `jekyll` program has several commands but the structure is always: + +``` +jekyll command [argument] [option] [argument_to_option] + +Examples: + jekyll new site/ --blank + jekyll serve --config _alternative_config.yml +``` + +Typically you'll use `jekyll serve` while developing locally and `jekyll build` when you need to generate the site for production. + +For a full list of options and their argument, see [Build Command Options](/docs/configuration/options/#build-command-options). + +Here are some of the most common commands: + +* `jekyll new PATH` - Creates a new Jekyll site with default gem-based theme at specified path. The directories will be created as necessary. +* `jekyll new PATH --blank` - Creates a new blank Jekyll site scaffold at specified path. +* `jekyll build` or `jekyll b` - Performs a one off build your site to `./_site` (by default). +* `jekyll serve` or `jekyll s` - Builds your site any time a source file changes and serves it locally. +* `jekyll clean` - Removes all generated files: destination folder, metadata file, Sass and Jekyll caches. +* `jekyll help` - Shows help, optionally for a given subcommand, e.g. `jekyll help build`. +* `jekyll new-theme` - Creates a new Jekyll theme scaffold. +* `jekyll doctor` - Outputs any deprecation or configuration issues. + +To change Jekyll's default build behavior have a look through the [configuration options](/docs/configuration/). diff --git a/docs/_docs/variables.md b/docs/_docs/variables.md new file mode 100644 index 00000000000..aafb63f92ed --- /dev/null +++ b/docs/_docs/variables.md @@ -0,0 +1,56 @@ +--- +title: Variables +permalink: /docs/variables/ +--- + +Jekyll traverses your site looking for files to process. Any files with +[front matter](/docs/front-matter/) are subject to processing. For each of these +files, Jekyll makes a variety of data available via [Liquid](/docs/liquid/). +The following is a reference of the available data. + +## Global Variables + +{% include docs_variables_table.html scope=site.data.jekyll_variables.global %} + +## Site Variables + +{% include docs_variables_table.html scope=site.data.jekyll_variables.site %} + +## Page Variables + +{% include docs_variables_table.html scope=site.data.jekyll_variables.page %} + +
+
ProTip™: Use Custom Front Matter
+

+ Any custom front matter that you specify will be available under + page. For example, if you specify custom_css: true + in a page’s front matter, that value will be available as page.custom_css. +

+

+ If you specify front matter in a layout, access that via layout. + For example, if you specify class: full_page in a layout’s front matter, + that value will be available as layout.class in the layout and its parents. +

+
+ +## Jekyll Variables + +{% include docs_variables_table.html scope=site.data.jekyll_variables.jekyll %} + +## Theme Variables {%- include docs_version_badge.html version="4.3.0" -%} +{: #theme-variables } + +{% include docs_variables_table.html scope=site.data.jekyll_variables.theme %} + +## Paginator + +{% include docs_variables_table.html scope=site.data.jekyll_variables.paginator %} + +
+
Paginator variable availability
+

+ These are only available in index files, however they can be located in a subdirectory, + such as /blog/index.html. +

+
diff --git a/docs/_includes/analytics.html b/docs/_includes/analytics.html new file mode 100644 index 00000000000..5d0e9c4bf8e --- /dev/null +++ b/docs/_includes/analytics.html @@ -0,0 +1,12 @@ +{% if site.google_analytics_id -%} + + +{% endif -%} diff --git a/docs/_includes/anchor_links.html b/docs/_includes/anchor_links.html new file mode 100644 index 00000000000..918ac9035cc --- /dev/null +++ b/docs/_includes/anchor_links.html @@ -0,0 +1,33 @@ + diff --git a/docs/_includes/docs_contents.html b/docs/_includes/docs_contents.html new file mode 100644 index 00000000000..04cb94f0a0a --- /dev/null +++ b/docs/_includes/docs_contents.html @@ -0,0 +1,18 @@ +
+ +
diff --git a/docs/_includes/docs_contents_mobile.html b/docs/_includes/docs_contents_mobile.html new file mode 100644 index 00000000000..a639c53b2d0 --- /dev/null +++ b/docs/_includes/docs_contents_mobile.html @@ -0,0 +1,15 @@ +
+ +
diff --git a/docs/_includes/docs_variables_table.html b/docs/_includes/docs_variables_table.html new file mode 100644 index 00000000000..feafa7106c3 --- /dev/null +++ b/docs/_includes/docs_variables_table.html @@ -0,0 +1,18 @@ +
+ + + + + + + + + {% for var in include.scope -%} + + + + + {% endfor -%} + +
VariableDescription

{{ var.name }}

{{- var.description -}}

+
diff --git a/docs/_includes/docs_version_badge.html b/docs/_includes/docs_version_badge.html new file mode 100644 index 00000000000..3c358109ffe --- /dev/null +++ b/docs/_includes/docs_version_badge.html @@ -0,0 +1 @@ +{{ include.version }} diff --git a/docs/_includes/footer.html b/docs/_includes/footer.html new file mode 100644 index 00000000000..96032159492 --- /dev/null +++ b/docs/_includes/footer.html @@ -0,0 +1,19 @@ +
+
+
+

Jekyll is lovingly maintained by the core team of volunteers.

+

The contents of this website are
© {{ site.time | date: '%Y' }} under the terms of the MIT License.

+
+ +
+
diff --git a/docs/_includes/header.html b/docs/_includes/header.html new file mode 100644 index 00000000000..b03a850dc6a --- /dev/null +++ b/docs/_includes/header.html @@ -0,0 +1,27 @@ +
+
+ + + + +
+ +
diff --git a/docs/_includes/improve_doc_link.html b/docs/_includes/improve_doc_link.html new file mode 100644 index 00000000000..db7f707d2ca --- /dev/null +++ b/docs/_includes/improve_doc_link.html @@ -0,0 +1,5 @@ + diff --git a/docs/_includes/mobile-nav-items.html b/docs/_includes/mobile-nav-items.html new file mode 100644 index 00000000000..ca337ba378d --- /dev/null +++ b/docs/_includes/mobile-nav-items.html @@ -0,0 +1,14 @@ +
    + {% for p in site.data.primary_nav -%} + {% if p.show_on_mobile -%} +
  • {{ p.title }}
  • + {% endif -%} + {% endfor -%} +
  • GitHub
  • +
\ No newline at end of file diff --git a/docs/_includes/news_contents.html b/docs/_includes/news_contents.html new file mode 100644 index 00000000000..e8f7ed17f2a --- /dev/null +++ b/docs/_includes/news_contents.html @@ -0,0 +1,33 @@ +
+ +
diff --git a/docs/_includes/news_contents_mobile.html b/docs/_includes/news_contents_mobile.html new file mode 100644 index 00000000000..6f6a98e4734 --- /dev/null +++ b/docs/_includes/news_contents_mobile.html @@ -0,0 +1,11 @@ +
+ +
\ No newline at end of file diff --git a/docs/_includes/news_item.html b/docs/_includes/news_item.html new file mode 100644 index 00000000000..6529a5f7a6a --- /dev/null +++ b/docs/_includes/news_item.html @@ -0,0 +1,25 @@ + diff --git a/docs/_includes/news_item_archive.html b/docs/_includes/news_item_archive.html new file mode 100644 index 00000000000..c5e865455ff --- /dev/null +++ b/docs/_includes/news_item_archive.html @@ -0,0 +1,26 @@ + diff --git a/docs/_includes/primary-nav-items.html b/docs/_includes/primary-nav-items.html new file mode 100644 index 00000000000..06354780d8a --- /dev/null +++ b/docs/_includes/primary-nav-items.html @@ -0,0 +1,11 @@ +
    + {% for p in site.data.primary_nav -%} +
  • {{ p.title }}
  • + {% endfor -%} +
diff --git a/docs/_includes/search/input.html b/docs/_includes/search/input.html new file mode 100644 index 00000000000..65015ee406c --- /dev/null +++ b/docs/_includes/search/input.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/_includes/search/script.html b/docs/_includes/search/script.html new file mode 100644 index 00000000000..dca756d7709 --- /dev/null +++ b/docs/_includes/search/script.html @@ -0,0 +1,9 @@ + + diff --git a/docs/_includes/section_nav_tutorials.html b/docs/_includes/section_nav_tutorials.html new file mode 100644 index 00000000000..7a684b644b7 --- /dev/null +++ b/docs/_includes/section_nav_tutorials.html @@ -0,0 +1,39 @@ +{%- comment -%} +Map grabs the tutorials sections, giving us an array of arrays. Join, flattens all +the items to a comma delimited string. Split turns it into an array again. +{%- endcomment -%} +{%- assign tutorials = site.data.tutorials | map: 'tutorials' | join: ',' | split: ',' -%} + +{%- comment -%} +Because this is built for every page, lets find where we are in the ordered +document list by comparing url strings. Then if there's something previous or +next, lets build a link to it. +{%- endcomment -%} + +{% for tutorial in tutorials -%} + {% assign tutorial_url = tutorial | prepend:"/tutorials/" | append:"/" -%} + {% if tutorial_url == page.url -%} +
+
+ {% if forloop.first -%} + Back + {% else -%} + {% assign previous = forloop.index0 | minus: 1 -%} + {% assign previous_page = tutorials[previous] | prepend:"/tutorials/" | append:"/" -%} + + {% endif -%} +
+
+ {% if forloop.last -%} + Next + {% else -%} + {% assign next = forloop.index0 | plus: 1 -%} + {% assign next_page = tutorials[next] | prepend:"/tutorials/" | append:"/" -%} + + {% endif -%} +
+
+
+ {% break -%} + {% endif -%} +{% endfor -%} diff --git a/docs/_includes/step-index.html b/docs/_includes/step-index.html new file mode 100644 index 00000000000..798fb7c5531 --- /dev/null +++ b/docs/_includes/step-index.html @@ -0,0 +1,34 @@ +{% assign docs = site.docs | where_exp: "doc", "doc.url contains '/step-by-step/'" -%} + +{% for doc in docs -%} + {% if doc.url == page.url -%} +
+
+ {% if forloop.first -%} + Back + {% else -%} + {% assign previous = forloop.index0 | minus: 1 -%} + + {% endif -%} +
+
+ {% if forloop.last -%} + Next + {% else -%} + {% assign next = forloop.index0 | plus: 1 -%} + + {% endif -%} +
+
+
+ {% break -%} + {% endif -%} +{% endfor -%} + +
    + {% for step in docs -%} +
  1. + {{- step.title -}} +
  2. + {% endfor -%} +
diff --git a/docs/_includes/top.html b/docs/_includes/top.html new file mode 100644 index 00000000000..0868d0cf43d --- /dev/null +++ b/docs/_includes/top.html @@ -0,0 +1,19 @@ + + + + + + {% feed_meta %} + + + + + + + + {% seo %} + + diff --git a/docs/_includes/tutorials_contents.html b/docs/_includes/tutorials_contents.html new file mode 100644 index 00000000000..76684ac90fd --- /dev/null +++ b/docs/_includes/tutorials_contents.html @@ -0,0 +1,16 @@ +
+ +
diff --git a/docs/_includes/tutorials_contents_mobile.html b/docs/_includes/tutorials_contents_mobile.html new file mode 100644 index 00000000000..4a8a9478382 --- /dev/null +++ b/docs/_includes/tutorials_contents_mobile.html @@ -0,0 +1,14 @@ +
+ +
\ No newline at end of file diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html new file mode 100644 index 00000000000..fb30f981d0a --- /dev/null +++ b/docs/_layouts/default.html @@ -0,0 +1,24 @@ +{%- include top.html -%} + + + {%- include header.html -%} + + {{- content -}} + + {%- include footer.html -%} + {%- include anchor_links.html -%} + {%- include analytics.html -%} + {%- include search/script.html -%} + + + + diff --git a/docs/_layouts/docs.html b/docs/_layouts/docs.html new file mode 100644 index 00000000000..ad52bcc4ac7 --- /dev/null +++ b/docs/_layouts/docs.html @@ -0,0 +1,18 @@ +--- +layout: default +--- + +
+
+ {% include docs_contents_mobile.html -%} +
+
+ {% include improve_doc_link.html %} +

{{ page.title }}

+ {{ content }} +
+
+ {% include docs_contents.html -%} +
+
+
diff --git a/docs/_layouts/error.html b/docs/_layouts/error.html new file mode 100644 index 00000000000..f5bc5c9b31d --- /dev/null +++ b/docs/_layouts/error.html @@ -0,0 +1,23 @@ +{% include top.html %} + + +
+
+ +
+
+ + {{ content }} + + {% include anchor_links.html %} + {% include analytics.html %} + + + diff --git a/docs/_layouts/news.html b/docs/_layouts/news.html new file mode 100644 index 00000000000..7b776bc7446 --- /dev/null +++ b/docs/_layouts/news.html @@ -0,0 +1,14 @@ +--- +layout: default +--- + +
+
+ {% include news_contents_mobile.html -%} +
+ {{- content -}} +
+ {% include news_contents.html -%} +
+
+
diff --git a/docs/_layouts/news_item.html b/docs/_layouts/news_item.html new file mode 100644 index 00000000000..7be7bf76bc9 --- /dev/null +++ b/docs/_layouts/news_item.html @@ -0,0 +1,31 @@ +--- +layout: news +--- + + diff --git a/site/_layouts/page.html b/docs/_layouts/page.html similarity index 68% rename from site/_layouts/page.html rename to docs/_layouts/page.html index bae31bb365c..6e7541f55d5 100644 --- a/site/_layouts/page.html +++ b/docs/_layouts/page.html @@ -4,15 +4,15 @@
-
+ {%- if page.permalink contains "resources" %} + {% include improve_doc_link.html %} + {% endif -%}

{{ page.title }}

{{ content }}
-
-
diff --git a/docs/_layouts/step.html b/docs/_layouts/step.html new file mode 100644 index 00000000000..a9f551a7e6d --- /dev/null +++ b/docs/_layouts/step.html @@ -0,0 +1,19 @@ +--- +layout: default +--- +
+
+ {% include docs_contents_mobile.html -%} +
+
+ {% include improve_doc_link.html %} +

Step by Step Tutorial

+

{{ page.position }}. {{ page.title }}

+ {{ content }} + {% include step-index.html -%} +
+
+ {% include docs_contents.html -%} +
+
+
diff --git a/docs/_layouts/tutorials.html b/docs/_layouts/tutorials.html new file mode 100644 index 00000000000..b73fd326335 --- /dev/null +++ b/docs/_layouts/tutorials.html @@ -0,0 +1,40 @@ +--- +layout: default +--- + +
+
+ {%- include tutorials_contents_mobile.html -%} +
+
+
+ {% include improve_doc_link.html %} +

{{ page.title }}

+ {% assign author = page.author %} + {% if author %} +
+ + {{ page.date | date_to_long_string }} + + + {% avatar user=author size=24 %} + {{ author }} + +
+ {% endif %} +
+ {{- content -}} + {% if page.plugin_disclaimer %} +
+ Disclaimer: The Jekyll Core Team does not endorse the Ruby code in this tutorial and is + not liable to resolve any bugs therein or issues arising otherwise from the use of the + provided example(s) in production builds. +
+ {% endif %} + {%- include section_nav_tutorials.html -%} +
+
+ {%- include tutorials_contents.html -%} +
+
+
diff --git a/site/_posts/2013-05-06-jekyll-1-0-0-released.markdown b/docs/_posts/2013-05-06-jekyll-1-0-0-released.markdown similarity index 86% rename from site/_posts/2013-05-06-jekyll-1-0-0-released.markdown rename to docs/_posts/2013-05-06-jekyll-1-0-0-released.markdown index 4b8e3be1917..0b03b43e407 100644 --- a/site/_posts/2013-05-06-jekyll-1-0-0-released.markdown +++ b/docs/_posts/2013-05-06-jekyll-1-0-0-released.markdown @@ -1,16 +1,15 @@ --- -layout: news_item title: "Jekyll 1.0.0 Released" date: "2013-05-06 02:12:52 +0200" author: parkr version: 1.0.0 -categories: [release] +category: release --- Hey! After many months of hard work by Jekyll's contributors, we're excited to announce the first major release of the project in a long while. v1.0.0 is finally here! While the list of improvements and bug fixes is [quite lengthy][history], -here are the highlights (thanks to [@benbalter](http://twitter.com/BenBalter) for the +here are the highlights (thanks to [@benbalter](https://twitter.com/BenBalter) for the examples and for compiling this list): - Support for the Gist tag for easily embedding Gists ([example](https://gist.github.com/benbalter/5555251)) diff --git a/site/_posts/2013-05-08-jekyll-1-0-1-released.markdown b/docs/_posts/2013-05-08-jekyll-1-0-1-released.markdown similarity index 96% rename from site/_posts/2013-05-08-jekyll-1-0-1-released.markdown rename to docs/_posts/2013-05-08-jekyll-1-0-1-released.markdown index 90edcc26a43..a1f1c7e85c9 100644 --- a/site/_posts/2013-05-08-jekyll-1-0-1-released.markdown +++ b/docs/_posts/2013-05-08-jekyll-1-0-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.0.1 Released" date: "2013-05-08 23:46:11 +0200" author: parkr version: 1.0.1 -categories: [release] +category: release --- Hot on the trails of v1.0, v1.0.1 is out! Here are the highlights: diff --git a/site/_posts/2013-05-12-jekyll-1-0-2-released.markdown b/docs/_posts/2013-05-12-jekyll-1-0-2-released.markdown similarity index 87% rename from site/_posts/2013-05-12-jekyll-1-0-2-released.markdown rename to docs/_posts/2013-05-12-jekyll-1-0-2-released.markdown index 2a2b97e6afc..10dfa0ff841 100644 --- a/site/_posts/2013-05-12-jekyll-1-0-2-released.markdown +++ b/docs/_posts/2013-05-12-jekyll-1-0-2-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.0.2 Released" date: "2013-05-12 14:45:00 +0200" author: parkr version: 1.0.2 -categories: [release] +category: release --- v1.0.2 has some key bugfixes that optionally restore some behaviour from pre-1.0 @@ -13,7 +12,7 @@ releases, and fix some other annoying bugs: * Backwards-compatibilize relative permalinks ([#1081][]) * Add `jekyll doctor` command to check site for any known compatibility problems ([#1081][]) * Deprecate old config `server_port`, match to `port` if `port` isn't set ([#1084][]) -* Update pygments.rb and kramdon versions to 0.5.0 and 1.0.2, respectively ([#1061][], [#1067][]) +* Update pygments.rb and kramdown versions to 0.5.0 and 1.0.2, respectively ([#1061][], [#1067][]) * Fix issue when post categories are numbers ([#1078][]) * Add a `data-lang=""` attribute to Redcarpet code blocks ([#1066][]) * Catching that Redcarpet gem isn't installed ([#1059][]) diff --git a/site/_posts/2013-06-07-jekyll-1-0-3-released.markdown b/docs/_posts/2013-06-07-jekyll-1-0-3-released.markdown similarity index 95% rename from site/_posts/2013-06-07-jekyll-1-0-3-released.markdown rename to docs/_posts/2013-06-07-jekyll-1-0-3-released.markdown index 566ae6688cf..c81f1ced145 100644 --- a/site/_posts/2013-06-07-jekyll-1-0-3-released.markdown +++ b/docs/_posts/2013-06-07-jekyll-1-0-3-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.0.3 Released" date: "2013-06-07 21:02:13 +0200" author: parkr version: 1.0.3 -categories: [release] +category: release --- v1.0.3 contains some key enhancements and bug fixes: diff --git a/site/_posts/2013-07-14-jekyll-1-1-0-released.markdown b/docs/_posts/2013-07-14-jekyll-1-1-0-released.markdown similarity index 96% rename from site/_posts/2013-07-14-jekyll-1-1-0-released.markdown rename to docs/_posts/2013-07-14-jekyll-1-1-0-released.markdown index 12b3d92130a..8d8361a547c 100644 --- a/site/_posts/2013-07-14-jekyll-1-1-0-released.markdown +++ b/docs/_posts/2013-07-14-jekyll-1-1-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.1.0 Released" date: "2013-07-14 19:38:02 +0200" author: parkr version: 1.1.0 -categories: [release] +category: release --- After a month of hard work, the Jekyll core team is excited to announce the release of diff --git a/docs/_posts/2013-07-24-jekyll-1-1-1-released.markdown b/docs/_posts/2013-07-24-jekyll-1-1-1-released.markdown new file mode 100644 index 00000000000..7256e08ec4f --- /dev/null +++ b/docs/_posts/2013-07-24-jekyll-1-1-1-released.markdown @@ -0,0 +1,23 @@ +--- +title: "Jekyll 1.1.1 Released" +date: "2013-07-24 22:24:14 +0200" +author: parkr +version: 1.1.1 +category: release +--- + +Coming just 10 days after the release of v1.1.0, v1.1.1 is out with a patch for +the nasty excerpt inception bug ([#1339]({{ site.repository }}/issues/1339)) and +non-zero exit codes for invalid commands ([#1338]({{ site.repository +}}/issues/1338)). + +To all those affected by the [strange excerpt bug in v1.1.0]({{ site.repository +}}/issues/1321), I'm sorry. I think we have it all patched up and it should be +deployed to [GitHub Pages](https://pages.github.com/) in the next couple weeks. +Thank you for your patience! + +If you're checking out v1.1.x for the first time, definitely check out [what +shipped with v1.1.0!]({{ site.repository }}/releases/tag/v1.1.0) + +See the [GitHub Release]({{ site.repository }}/releases/tag/v1.1.1) page for +more a more detailed changelog for this release. diff --git a/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown b/docs/_posts/2013-07-25-jekyll-1-0-4-released.markdown similarity index 95% rename from site/_posts/2013-07-25-jekyll-1-0-4-released.markdown rename to docs/_posts/2013-07-25-jekyll-1-0-4-released.markdown index 635d0e6cd09..7823468a33b 100644 --- a/site/_posts/2013-07-25-jekyll-1-0-4-released.markdown +++ b/docs/_posts/2013-07-25-jekyll-1-0-4-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.0.4 Released" date: "2013-07-25 09:08:38 +0200" author: mattr- version: 1.0.4 -categories: [release] +category: release --- Version 1.0.4 fixes a minor, but nonetheless important security vulnerability affecting several third-party Jekyll plugins. If your Jekyll site does not use plugins, you may, but are not required to upgrade at this time. diff --git a/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown b/docs/_posts/2013-07-25-jekyll-1-1-2-released.markdown similarity index 95% rename from site/_posts/2013-07-25-jekyll-1-1-2-released.markdown rename to docs/_posts/2013-07-25-jekyll-1-1-2-released.markdown index ed16ca717c4..26c034537fe 100644 --- a/site/_posts/2013-07-25-jekyll-1-1-2-released.markdown +++ b/docs/_posts/2013-07-25-jekyll-1-1-2-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.1.2 Released" date: "2013-07-25 09:08:38 +0200" author: parkr version: 1.1.2 -categories: [release] +category: release --- Version 1.1.2 fixes a minor, but nonetheless important security vulnerability affecting several third-party Jekyll plugins. If your Jekyll site does not use plugins, you may, but are not required to upgrade at this time. diff --git a/site/_posts/2013-09-06-jekyll-1-2-0-released.markdown b/docs/_posts/2013-09-06-jekyll-1-2-0-released.markdown similarity index 96% rename from site/_posts/2013-09-06-jekyll-1-2-0-released.markdown rename to docs/_posts/2013-09-06-jekyll-1-2-0-released.markdown index ae5448c21a3..a227b4e18fd 100644 --- a/site/_posts/2013-09-06-jekyll-1-2-0-released.markdown +++ b/docs/_posts/2013-09-06-jekyll-1-2-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll 1.2.0 Released" date: "2013-09-06 22:02:41 -0400" author: parkr version: 1.2.0 -categories: [release] +category: release --- After nearly a month and a half of hard work, the Jekyll team is happy to diff --git a/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown b/docs/_posts/2013-09-14-jekyll-1-2-1-released.markdown similarity index 94% rename from site/_posts/2013-09-14-jekyll-1-2-1-released.markdown rename to docs/_posts/2013-09-14-jekyll-1-2-1-released.markdown index 832dbd06a54..da2c74ab84f 100644 --- a/site/_posts/2013-09-14-jekyll-1-2-1-released.markdown +++ b/docs/_posts/2013-09-14-jekyll-1-2-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.2.1 Released' date: 2013-09-14 20:46:50 -0400 author: parkr version: 1.2.1 -categories: [release] +category: release --- Quick turnover, anyone? A [recent incompatibility with Liquid diff --git a/site/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown b/docs/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown similarity index 92% rename from site/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown rename to docs/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown index 1e3e44cee55..c85769948f1 100644 --- a/site/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown +++ b/docs/_posts/2013-10-28-jekyll-1-3-0-rc1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.3.0.rc1 Released' date: 2013-10-28 20:14:39 -0500 author: mattr- version: 1.3.0.rc1 -categories: [release] +category: release --- Jekyll 1.3.0 is going to be a big release! In order to make sure we diff --git a/site/_posts/2013-11-04-jekyll-1-3-0-released.markdown b/docs/_posts/2013-11-04-jekyll-1-3-0-released.markdown similarity index 97% rename from site/_posts/2013-11-04-jekyll-1-3-0-released.markdown rename to docs/_posts/2013-11-04-jekyll-1-3-0-released.markdown index 1e325117c28..14d1f089f7d 100644 --- a/site/_posts/2013-11-04-jekyll-1-3-0-released.markdown +++ b/docs/_posts/2013-11-04-jekyll-1-3-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.3.0 Released' date: 2013-11-04 21:46:02 -0600 author: mattr- version: 1.3.0 -categories: [release] +category: release --- It's been about six weeks since v1.2.0 and the Jekyll team is happy to diff --git a/site/_posts/2013-11-26-jekyll-1-3-1-released.markdown b/docs/_posts/2013-11-26-jekyll-1-3-1-released.markdown similarity index 94% rename from site/_posts/2013-11-26-jekyll-1-3-1-released.markdown rename to docs/_posts/2013-11-26-jekyll-1-3-1-released.markdown index 4b4c37d5fda..305a3b75077 100644 --- a/site/_posts/2013-11-26-jekyll-1-3-1-released.markdown +++ b/docs/_posts/2013-11-26-jekyll-1-3-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.3.1 Released' date: 2013-11-26 19:52:20 -0600 author: mattr- version: 1.3.1 -categories: [release] +category: release --- Just in time for the US holiday Thanksgiving, we're releasing version diff --git a/site/_posts/2013-12-07-jekyll-1-4-0-released.markdown b/docs/_posts/2013-12-07-jekyll-1-4-0-released.markdown similarity index 96% rename from site/_posts/2013-12-07-jekyll-1-4-0-released.markdown rename to docs/_posts/2013-12-07-jekyll-1-4-0-released.markdown index d7a0c14f914..07aa71970a0 100644 --- a/site/_posts/2013-12-07-jekyll-1-4-0-released.markdown +++ b/docs/_posts/2013-12-07-jekyll-1-4-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.4.0 Released' date: 2013-12-07 13:55:28 -0600 author: mattr- version: 1.4.0 -categories: [release] +category: release --- About a month after the release of Jekyll v1.3.0, we are releasing diff --git a/site/_posts/2013-12-09-jekyll-1-4-1-released.markdown b/docs/_posts/2013-12-09-jekyll-1-4-1-released.markdown similarity index 91% rename from site/_posts/2013-12-09-jekyll-1-4-1-released.markdown rename to docs/_posts/2013-12-09-jekyll-1-4-1-released.markdown index 63407158207..73a20a0f21b 100644 --- a/site/_posts/2013-12-09-jekyll-1-4-1-released.markdown +++ b/docs/_posts/2013-12-09-jekyll-1-4-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.4.1 Released' date: 2013-12-09 20:44:13 -0600 author: mattr- version: 1.4.1 -categories: [release] +category: release --- Another quick turnover, anyone? A [critical diff --git a/site/_posts/2013-12-16-jekyll-1-4-2-released.markdown b/docs/_posts/2013-12-16-jekyll-1-4-2-released.markdown similarity index 92% rename from site/_posts/2013-12-16-jekyll-1-4-2-released.markdown rename to docs/_posts/2013-12-16-jekyll-1-4-2-released.markdown index afc92147d11..3ca96a5b602 100644 --- a/site/_posts/2013-12-16-jekyll-1-4-2-released.markdown +++ b/docs/_posts/2013-12-16-jekyll-1-4-2-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.4.2 Released' date: 2013-12-16 19:48:13 -0500 author: parkr version: 1.4.2 -categories: [release] +category: release --- This release fixes [a regression][] where Maruku fenced code blocks were turned diff --git a/site/_posts/2014-01-13-jekyll-1-4-3-released.markdown b/docs/_posts/2014-01-13-jekyll-1-4-3-released.markdown similarity index 96% rename from site/_posts/2014-01-13-jekyll-1-4-3-released.markdown rename to docs/_posts/2014-01-13-jekyll-1-4-3-released.markdown index a97bcec496b..446c5134de9 100644 --- a/site/_posts/2014-01-13-jekyll-1-4-3-released.markdown +++ b/docs/_posts/2014-01-13-jekyll-1-4-3-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.4.3 Released' date: 2014-01-13 17:43:32 -0800 author: benbalter version: 1.4.3 -categories: [release] +category: release --- Jekyll 1.4.3 contains two **critical** security fixes. If you run Jekyll locally diff --git a/site/_posts/2014-03-24-jekyll-1-5-0-released.markdown b/docs/_posts/2014-03-24-jekyll-1-5-0-released.markdown similarity index 93% rename from site/_posts/2014-03-24-jekyll-1-5-0-released.markdown rename to docs/_posts/2014-03-24-jekyll-1-5-0-released.markdown index 5b103dc219c..7192d8b3022 100644 --- a/site/_posts/2014-03-24-jekyll-1-5-0-released.markdown +++ b/docs/_posts/2014-03-24-jekyll-1-5-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.5.0 Released' date: 2014-03-24 20:37:59 -0400 author: parkr version: 1.5.0 -categories: [release] +category: release --- As work continues on Jekyll 2.0.0, we felt it was important to address two key diff --git a/site/_posts/2014-03-27-jekyll-1-5-1-released.markdown b/docs/_posts/2014-03-27-jekyll-1-5-1-released.markdown similarity index 94% rename from site/_posts/2014-03-27-jekyll-1-5-1-released.markdown rename to docs/_posts/2014-03-27-jekyll-1-5-1-released.markdown index e8a4096a45a..71afc80d5c7 100644 --- a/site/_posts/2014-03-27-jekyll-1-5-1-released.markdown +++ b/docs/_posts/2014-03-27-jekyll-1-5-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 1.5.1 Released' date: 2014-03-27 22:43:48 -0400 author: parkr version: 1.5.1 -categories: [release] +category: release --- The hawk-eyed [@gregose](https://github.com/gregose) spotted a bug in our diff --git a/site/_posts/2014-05-06-jekyll-turns-2-0-0.markdown b/docs/_posts/2014-05-06-jekyll-turns-2-0-0.markdown similarity index 83% rename from site/_posts/2014-05-06-jekyll-turns-2-0-0.markdown rename to docs/_posts/2014-05-06-jekyll-turns-2-0-0.markdown index 82555514bf7..f2064d7547e 100644 --- a/site/_posts/2014-05-06-jekyll-turns-2-0-0.markdown +++ b/docs/_posts/2014-05-06-jekyll-turns-2-0-0.markdown @@ -1,9 +1,8 @@ --- -layout: news_item title: 'Jekyll turns 2.0.0' author: parkr version: 2.0.0 -categories: [release] +category: release --- A year ago to the day, [we released Jekyll 1.0.0][jekyll-1]. One year later, we present to you the next major version: Jekyll 2.0.0. @@ -13,9 +12,9 @@ Jam-packed with some [highly-requested features and bugfixes galore][changelog], 1. [Collections](/docs/collections/) - Collections allow you to define an unlimited number of custom document types (beyond just posts and pages) for different types of content you may want to author in Jekyll such as API documentation or a cookbook! 2. [Brand new site template](https://github.com/jekyll/jekyll/pull/2050#issuecomment-35938016) (thanks [@jglovier][]!) - Getting started with Jekyll just got a lot easier and a lot more beautiful. Just run `jekyll new ` and you're good to go. 3. [Native Sass & CoffeeScript support](/docs/assets/) - We love CSS and JavaScript as much as the next guy, but there will always be a special place in our hearts for Sass and CoffeeScript. We now offer native support for these file types — no more messing around with Rake or Grunt! -4. [YAML Front Matter defaults](/docs/configuration/#front-matter-defaults) - If you've set `layout: post` more than once in your life, you'll love this new feature: set front matter defaults for a given directory or type. -5. [Custom markdown processors](/docs/configuration/#custom-markdown-processors) - Always wanted to use your favourite home-grown Markdown converter, but couldn't with Jekyll? Now you can. Simply specify `markdown: MyConverterClass` and you're on your way. -6. [Addition of `where` and `group_by` Liquid filters](/docs/templates/#filters) - Simplifying your Liquid templates one filter at a time. The `where` filter selects from an array all items within which have a given value for a property. The `group_by` filter groups all items in an array which have the same value for a given property. +4. [Front Matter defaults](/docs/configuration/front-matter-defaults/) - If you've set `layout: post` more than once in your life, you'll love this new feature: set front matter defaults for a given directory or type. +5. [Custom markdown processors](/docs/configuration/markdown/) - Always wanted to use your favourite home-grown Markdown converter, but couldn't with Jekyll? Now you can. Simply specify `markdown: MyConverterClass` and you're on your way. +6. [Addition of `where` and `group_by` Liquid filters](/docs/liquid/filters/) - Simplifying your Liquid templates one filter at a time. The `where` filter selects from an array all items within which have a given value for a property. The `group_by` filter groups all items in an array which have the same value for a given property. 7. [Switch from Maruku to Kramdown as default markdown converter](https://github.com/jekyll/jekyll/pull/1988) - Maruku is dead. We've replaced it with the converter which has the closest feature parity: Kramdown! Check out our [changelog][] for a complete list of all (200+) changes. diff --git a/site/_posts/2014-05-08-jekyll-2-0-3-released.markdown b/docs/_posts/2014-05-08-jekyll-2-0-3-released.markdown similarity index 95% rename from site/_posts/2014-05-08-jekyll-2-0-3-released.markdown rename to docs/_posts/2014-05-08-jekyll-2-0-3-released.markdown index ac5e9d7538a..d693c51d2e1 100644 --- a/site/_posts/2014-05-08-jekyll-2-0-3-released.markdown +++ b/docs/_posts/2014-05-08-jekyll-2-0-3-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.0.3 Released' date: 2014-05-08 22:43:17 -0400 author: parkr version: 2.0.3 -categories: [release] +category: release --- Hey again! Just wanted to let you know we've released another version of Jekyll, jam-packed with bug fixes. diff --git a/site/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown b/docs/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown similarity index 61% rename from site/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown rename to docs/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown index 92b853954d8..6b9989c91e9 100644 --- a/site/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown +++ b/docs/_posts/2014-06-04-jekyll-stickers-1-dollar-stickermule.markdown @@ -1,12 +1,11 @@ --- -layout: news_item title: 'Pick Up your $1 Jekyll Sticker' date: 2014-06-04 15:46:53 -0400 author: parkr categories: [partners] --- -![Jekyll Sticker](/img/jekyll-sticker.jpg) +![Jekyll Sticker](/img/jekyll-sticker.png) You may have heard that [@cobyism](https://github.com/cobyism)'s excellent Jekyll logo has been made into a sticker. You may have sat idly by, wishing @@ -14,6 +13,6 @@ that you could have a sticker honoring your beloved Jekyll. The StickerMule team says, *"Pine no longer!"* StickerMule has **[discounted the price of Jekyll stickers down to $1 and are offering free (domestic) -shipping](http://www.stickermule.com/marketplace/825-jekyll-stickers)!** -Go grab one now on the StickerMule marketplace – [they'll look -swell on your favourite hardware.](https://twitter.com/parkr/status/430826309707902976/photo/1) +shipping](https://www.stickermule.com/marketplace/825-jekyll-stickers)!** +Go grab one now on the StickerMule marketplace – they'll look +swell on your favourite hardware. diff --git a/site/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown b/docs/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown similarity index 88% rename from site/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown rename to docs/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown index 0cfb31dd59f..7c9c2bb332b 100644 --- a/site/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown +++ b/docs/_posts/2014-06-28-jekyll-turns-21-i-mean-2-1-0.markdown @@ -1,13 +1,12 @@ --- -layout: news_item title: 'Jekyll Turns 21! Err... I mean 2.1.0.' date: 2014-06-28 17:26:59 -0400 author: parkr version: 2.1.0 -categories: [release] +category: release --- -Jekyll's finally [legal to drink in the States](http://en.wikipedia.org/wiki/Legal_drinking_age). +Jekyll's finally [legal to drink in the States](https://en.wikipedia.org/wiki/Legal_drinking_age). And he's done a lot of learning in the process! Here are some of the new things to look forward to: @@ -20,7 +19,7 @@ things to look forward to: - Add support for `hl_lines` in `highlight` tag (#2532) - Post categories now merge with directory, front matter, and defaults (#2373) - New `--skip_initial_build` flag for `jekyll serve` (#2477) -- A bajilion bug fixes and site updates! +- A bajillion bug fixes and site updates! Let's go party! diff --git a/site/_posts/2014-07-01-jekyll-2-1-1-released.markdown b/docs/_posts/2014-07-01-jekyll-2-1-1-released.markdown similarity index 95% rename from site/_posts/2014-07-01-jekyll-2-1-1-released.markdown rename to docs/_posts/2014-07-01-jekyll-2-1-1-released.markdown index 81423539690..c1a05015d66 100644 --- a/site/_posts/2014-07-01-jekyll-2-1-1-released.markdown +++ b/docs/_posts/2014-07-01-jekyll-2-1-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.1.1 Released' date: 2014-07-01 20:16:43 -0400 author: parkr version: 2.1.1 -categories: [release] +category: release --- This is a minor release for Jekyll 2.1.0. It fixes a couple bugs and diff --git a/site/_posts/2014-07-29-jekyll-2-2-0-released.markdown b/docs/_posts/2014-07-29-jekyll-2-2-0-released.markdown similarity index 92% rename from site/_posts/2014-07-29-jekyll-2-2-0-released.markdown rename to docs/_posts/2014-07-29-jekyll-2-2-0-released.markdown index ca7aee48870..ce8e672b222 100644 --- a/site/_posts/2014-07-29-jekyll-2-2-0-released.markdown +++ b/docs/_posts/2014-07-29-jekyll-2-2-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.2.0 Released' date: 2014-07-29 18:59:13 -0400 author: parkr version: 2.2.0 -categories: [release] +category: release --- Jekyll 2.2.0 contains a few key updates: diff --git a/site/_posts/2014-08-10-jekyll-2-3-0-released.markdown b/docs/_posts/2014-08-10-jekyll-2-3-0-released.markdown similarity index 95% rename from site/_posts/2014-08-10-jekyll-2-3-0-released.markdown rename to docs/_posts/2014-08-10-jekyll-2-3-0-released.markdown index 63fe2b45012..c40f850775a 100644 --- a/site/_posts/2014-08-10-jekyll-2-3-0-released.markdown +++ b/docs/_posts/2014-08-10-jekyll-2-3-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.3.0 Released' date: 2014-08-10 20:38:34 -0400 author: parkr version: 2.3.0 -categories: [release] +category: release --- This latest release of Jekyll includes a slew of enhancements and bug @@ -15,7 +14,7 @@ fixes. Some of the highlights: * Pages, Posts, and Drafts can now be converted by multiple converters. * Static files can now be safely included in collections. They'll be placed in a `collection.files` array. `collection.docs` still holds exclusively - content with YAML front matter. + content with front matter. * Sass files can once again be rendered by Liquid. However, neither Sass nor CoffeeScript can ever have a layout. Bonus: `scssify` and `sassify` Liquid filters. diff --git a/site/_posts/2014-09-09-jekyll-2-4-0-released.markdown b/docs/_posts/2014-09-09-jekyll-2-4-0-released.markdown similarity index 97% rename from site/_posts/2014-09-09-jekyll-2-4-0-released.markdown rename to docs/_posts/2014-09-09-jekyll-2-4-0-released.markdown index e8dda676295..4bcb3a770e6 100644 --- a/site/_posts/2014-09-09-jekyll-2-4-0-released.markdown +++ b/docs/_posts/2014-09-09-jekyll-2-4-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'A Wild Jekyll 2.4.0 Appeared!' date: 2014-09-09 21:10:33 -0700 author: parkr version: 2.4.0 -categories: [release] +category: release --- Well, lookie here! A new release of Jekyll! v2.4.0 contains lots of goodies, including some brilliant new additions: diff --git a/site/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown b/docs/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown similarity index 88% rename from site/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown rename to docs/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown index cc5de7c012b..45056f906d1 100644 --- a/site/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown +++ b/docs/_posts/2014-11-06-jekylls-midlife-crisis-jekyll-turns-2-5-0.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: "Jekyll's Mid-Life Crisis (Or, Jekyll turns 2.5.0)" date: 2014-11-05 10:48:22 -0800 author: parkr version: 2.5.0 -categories: [release] +category: release --- A new day, a new release! Jekyll just turned 2.5.0 and has gained a lot of @@ -14,7 +13,7 @@ milestone with a pretty big release. What's changed in 2.5.0? Here are some highlights: * Require plugins in the `:jekyll_plugins` Gemfile group (turned off with an environment variable) -* YAML Front Matter permalinks can now contain placeholders like `:name`. Check out all the placeholders on the [Permalinks docs page](/docs/permalinks/). +* Front matter permalinks can now contain placeholders like `:name`. Check out all the placeholders on the [Permalinks docs page](/docs/permalinks/). * The `jsonify` filter now deep-converts arrays to liquid. * Shorted `build` and `serve` commands with `b` and `s` aliases, respectively * WEBrick will now list your directory if it can't find an index file. @@ -29,8 +28,8 @@ about in [the changelog!](/docs/history/) As always, if you run into issues, please [check the issues]({{ site.repository }}/issues) and [create an issue if one doesn't exist for the bug you encountered]({{ site.repository }}/issues/new). -If you just need some help, the extraordinary [jekyll help team is here for -you!]({{ site.help_url }}) +If you just need some help, the extraordinary jekyll help team is here for +you! *When was the [first commit to Jekyll](https://github.com/jekyll/jekyll/commit/d189e05d236769c1e5594af9db4d6eacb86fc16e)? All the way back on October 19, 2008. It features interesting historical diff --git a/site/_posts/2014-11-08-jekyll-2-5-1-released.markdown b/docs/_posts/2014-11-08-jekyll-2-5-1-released.markdown similarity index 96% rename from site/_posts/2014-11-08-jekyll-2-5-1-released.markdown rename to docs/_posts/2014-11-08-jekyll-2-5-1-released.markdown index 3237e48d4d2..6d0814288c0 100644 --- a/site/_posts/2014-11-08-jekyll-2-5-1-released.markdown +++ b/docs/_posts/2014-11-08-jekyll-2-5-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.5.1 Released' date: 2014-11-09 09:47:52 -0800 author: parkr version: 2.5.1 -categories: [release] +category: release --- Hot on the heels of v2.5.0, this release brings relief to our Windows diff --git a/site/_posts/2014-11-12-jekyll-2-5-2-released.markdown b/docs/_posts/2014-11-12-jekyll-2-5-2-released.markdown similarity index 92% rename from site/_posts/2014-11-12-jekyll-2-5-2-released.markdown rename to docs/_posts/2014-11-12-jekyll-2-5-2-released.markdown index 3eab8998aa2..bd3d5eea2be 100644 --- a/site/_posts/2014-11-12-jekyll-2-5-2-released.markdown +++ b/docs/_posts/2014-11-12-jekyll-2-5-2-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 2.5.2 Released' date: 2014-11-12 18:49:08 -0800 author: parkr version: 2.5.2 -categories: [release] +category: release --- A very minor release, 2.5.2 fixes a bug with path sanitation that 2.5.1 diff --git a/site/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md b/docs/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md similarity index 92% rename from site/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md rename to docs/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md index 6d62c655e9b..51f55028b94 100644 --- a/site/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md +++ b/docs/_posts/2014-12-17-alfredxing-welcome-to-jekyll-core.md @@ -1,5 +1,4 @@ --- -layout: news_item title: 'Alfred Xing has joined the Jekyll core team' date: 2014-12-17 11:16:21 -0800 author: parkr @@ -24,4 +23,4 @@ place! Happy Jekylling! [@alfredxing]: https://github.com/alfredxing -[University of British Columbia]: http://ubc.ca +[University of British Columbia]: http://www.ubc.ca diff --git a/site/_posts/2014-12-22-jekyll-2-5-3-released.markdown b/docs/_posts/2014-12-22-jekyll-2-5-3-released.markdown similarity index 86% rename from site/_posts/2014-12-22-jekyll-2-5-3-released.markdown rename to docs/_posts/2014-12-22-jekyll-2-5-3-released.markdown index 7743fd8ed59..00ddca6de1e 100644 --- a/site/_posts/2014-12-22-jekyll-2-5-3-released.markdown +++ b/docs/_posts/2014-12-22-jekyll-2-5-3-released.markdown @@ -1,17 +1,16 @@ --- -layout: news_item title: 'Jekyll Release for the Holidays! v2.5.3 Out' date: 2014-12-22 09:03:30 -0500 author: parkr version: 2.5.3 -categories: [release] +category: release --- Happy Holidays, everyone. Jekyll v2.5.3 is a quick patch release, containing some minor fixes. See the [full history](/docs/history/) for more info. If you notice any problems, -please [let us know]({{ site.help_url }}). +please [let us know]({{ site.repository }}). This release also marks the start of Jekyll 3 development. I wrote about it over on my personal blog: [Jekyll 3 — The Road Ahead](https://byparker.com/blog/2014/jekyll-3-the-road-ahead/). diff --git a/site/_posts/2015-01-20-jekyll-meet-and-greet.markdown b/docs/_posts/2015-01-20-jekyll-meet-and-greet.markdown similarity index 97% rename from site/_posts/2015-01-20-jekyll-meet-and-greet.markdown rename to docs/_posts/2015-01-20-jekyll-meet-and-greet.markdown index ed273f9d337..eee8d5e7931 100644 --- a/site/_posts/2015-01-20-jekyll-meet-and-greet.markdown +++ b/docs/_posts/2015-01-20-jekyll-meet-and-greet.markdown @@ -1,5 +1,4 @@ --- -layout: news_item title: "Jekyll Meet & Greet at GitHub HQ" date: "2015-01-20 19:23:12 -0800" author: parkr diff --git a/site/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown b/docs/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown similarity index 95% rename from site/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown rename to docs/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown index 49b35b77d76..76128767b61 100644 --- a/site/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown +++ b/docs/_posts/2015-01-24-jekyll-3-0-0-beta1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 3.0.0.beta1 Released' date: 2015-01-24 00:42:31 -0800 author: parkr version: 3.0.0.beta1 -categories: [release] +category: release --- Hey! @@ -20,7 +19,7 @@ to get a feel for what changes are afoot. Key features: To install just run: -{% highlight bash %} +{% highlight shell %} $ gem install jekyll --pre {% endhighlight %} diff --git a/site/_posts/2015-02-26-introducing-jekyll-talk.markdown b/docs/_posts/2015-02-26-introducing-jekyll-talk.markdown similarity index 59% rename from site/_posts/2015-02-26-introducing-jekyll-talk.markdown rename to docs/_posts/2015-02-26-introducing-jekyll-talk.markdown index 90863c12eca..b486ef6c15b 100644 --- a/site/_posts/2015-02-26-introducing-jekyll-talk.markdown +++ b/docs/_posts/2015-02-26-introducing-jekyll-talk.markdown @@ -1,5 +1,4 @@ --- -layout: news_item title: 'Join the Discussion at Jekyll Talk' date: 2015-02-26 21:06:51 -0800 author: alfredxing @@ -10,6 +9,6 @@ We're super excited to announce the launch of [Jekyll Talk](https://talk.jekyllr The forum was set up by [@envygeeks](https://github.com/envygeeks) to build a community more accessible to Jekyll users and more suitable for general discussion. -There's already been a lot of interesting topics, including a [site showcase](https://talk.jekyllrb.com/t/showcase-sites-made-using-jekyll/18) and [a poll for Jekyll 3.0 priorities](https://talk.jekyllrb.com/t/poll-installation-priorities-for-3-0/106/9). +There's already been a lot of interesting topics, including a site showcase and a poll for Jekyll 3.0 priorities. -Come join the fun! \ No newline at end of file +Come join the fun! diff --git a/site/_posts/2015-10-26-jekyll-3-0-released.markdown b/docs/_posts/2015-10-26-jekyll-3-0-released.markdown similarity index 93% rename from site/_posts/2015-10-26-jekyll-3-0-released.markdown rename to docs/_posts/2015-10-26-jekyll-3-0-released.markdown index 0d27a458c19..36bf46a670b 100644 --- a/site/_posts/2015-10-26-jekyll-3-0-released.markdown +++ b/docs/_posts/2015-10-26-jekyll-3-0-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 3.0 Released' date: 2015-10-26 15:37:30 -0700 author: parkr version: 3.0 -categories: [release] +category: release --- The much-anticipated Jekyll 3.0 has been released! Key changes: @@ -22,7 +21,7 @@ The much-anticipated Jekyll 3.0 has been released! Key changes: - Lots of performance improvements - ... and lots more! -We also added a [Code of Conduct]({{ site.repository }}/blob/master/CONDUCT.md) to encourage a happier, nicer community where contributions and discussion is protected from negative behaviour. +We also added a [Code of Conduct](/docs/conduct/) to encourage a happier, nicer community where contributions and discussion is protected from negative behaviour. A huge shout-out to the amazing Jekyll Core Team members Jordon Bedwell, Alfred Xing, and Matt Rogers for all their hard work in making Jekyll 3 the best release yet. diff --git a/site/_posts/2015-11-17-jekyll-3-0-1-released.markdown b/docs/_posts/2015-11-17-jekyll-3-0-1-released.markdown similarity index 92% rename from site/_posts/2015-11-17-jekyll-3-0-1-released.markdown rename to docs/_posts/2015-11-17-jekyll-3-0-1-released.markdown index 71412c6ba54..f3e64839ca6 100644 --- a/site/_posts/2015-11-17-jekyll-3-0-1-released.markdown +++ b/docs/_posts/2015-11-17-jekyll-3-0-1-released.markdown @@ -1,10 +1,9 @@ --- -layout: news_item title: 'Jekyll 3.0.1 Released' date: 2015-11-17 22:04:39 -0800 author: parkr version: 3.0.1 -categories: [release] +category: release --- Hey, folks! Bunch of bug fixes here. Notables: @@ -16,7 +15,7 @@ Hey, folks! Bunch of bug fixes here. Notables: * All hooks should now be properly registered & documented And a bunch more changes which you can see over in the -[changelog](/docs/history). +[changelog](/docs/history/). Thanks to the 17 developers who contributed code and documentation to this patch release: Alfred Xing, Christian Trosell, Jordan Thornquest, Jordon diff --git a/docs/_posts/2016-01-20-jekyll-3-0-2-released.markdown b/docs/_posts/2016-01-20-jekyll-3-0-2-released.markdown new file mode 100644 index 00000000000..34c3affbaa2 --- /dev/null +++ b/docs/_posts/2016-01-20-jekyll-3-0-2-released.markdown @@ -0,0 +1,18 @@ +--- +title: 'Jekyll 3.0.2 Released' +date: 2016-01-20 14:08:18 -0800 +author: parkr +version: 3.0.2 +category: release +--- + +A crucial bug was found in v3.0.1 which caused invalid post dates to go +unnoticed in the build chain until the error that popped up was unhelpful. +v3.0.2 [throws errors as you'd expect](https://github.com/jekyll/jekyll/issues/4375) +when there is a post like `_posts/2016-22-01-future.md` or a post has an +invalid date like `date: "tuesday"` in their front matter. + +This should make the experience of working with Jekyll just a little +better. + +Happy Jekylling! diff --git a/docs/_posts/2016-01-24-jekyll-3-1-0-released.markdown b/docs/_posts/2016-01-24-jekyll-3-1-0-released.markdown new file mode 100644 index 00000000000..216a4f2a092 --- /dev/null +++ b/docs/_posts/2016-01-24-jekyll-3-1-0-released.markdown @@ -0,0 +1,49 @@ +--- +title: 'Jekyll 3.1.0 Released' +date: 2016-01-24 13:16:12 -0800 +author: parkr +version: 3.1.0 +category: release +--- + +Happy weekend! To make your weekend all the better, we have just released +v3.1.0 of Jekyll. + +There are _lots_ of great performance improvements, including a huge one +which is to use Liquid drops instead of hashes. Much of the slowness in +Jekyll is due to Jekyll making lots of objects it doesn't need to make. +By making these objects only as they're needed, we can speed up Jekyll +considerably! + +Some other highlights: + +* Fix: `permalink`s with non-HTML extensions will not be honored +* Fix: `jekyll clean` now accepts build flags like `--source`. +* Enhancement: `include` tags can now accept multiple liquid variables +* Feature: adds new `sample` liquid tag which gets random element from an array +* Fix: Jekyll will read in files with front matter that has extraneous +spaces after the first line +* Enhancement: extract the `title` attribute from the filename for +collection items without a date +* Fix: gracefully handle empty configuration files + +... and [a whole bunch more](/docs/history/#v3-1-0)! + +Please [file a bug]({{ site.repository }}/issues/new?title=Jekyll+3.1.0+Issue:) +if you encounter any issues! As always, [Jekyll Talk](https://talk.jekyllrb.com) +is the best place to get help if you're encountering a problem. + +Special thanks to all our amazing contributors who helped make v3.1.0 a +possibility: + +Alex J Best, Alexander Köplinger, Alfred Xing, Alistair Calder, Atul +Bhosale, Ben Orenstein, Chi Trung Nguyen, Conor O'Callaghan, Craig P. +Motlin, Dan K, David Burela, David Litvak Bruno, Decider UI, Ducksan Cho, +Florian Thomas, James Wen, Jordon Bedwell, Joseph Wynn, Kakoma, Liam +Bowers, Mike Neumegen, Nick Quaranto, Nielsen Ramon, Olivér Falvai, Pat +Hawks, Paul Robert Lloyd, Pedro Euko, Peter Suschlik, Sam Volin, Samuel +Wright, Sasha Friedenberg, Tim Cuthbertson, Vincent Wochnik, William +Entriken, Zshawn Syed, chrisfinazzo, ducksan cho, leethomas, +midnightSuyama, musoke, and rebornix + +Happy Jekylling! diff --git a/docs/_posts/2016-01-28-jekyll-3-1-1-released.markdown b/docs/_posts/2016-01-28-jekyll-3-1-1-released.markdown new file mode 100644 index 00000000000..925c9ff64d1 --- /dev/null +++ b/docs/_posts/2016-01-28-jekyll-3-1-1-released.markdown @@ -0,0 +1,32 @@ +--- +title: 'Jekyll 3.1.1 Released' +date: 2016-01-28 17:21:50 -0800 +author: parkr +version: 3.1.1 +category: release +--- + +This release squashes a few bugs :bug: :bug: :bug: noticed by a few +wonderful Jekyll users: + +* If your `permalink` ended with a `/`, your URL didn't have any extension, +even if you wanted one +* We now strip the BOM by default per Ruby's `IO.open`. +* `page.dir` will not always end in a slash. + +We also updated our [Code of Conduct](/docs/conduct/) to the latest version of +the Contributor Covenant. The update includes language to ensure that the +reporter of the incident remains confidential to non-maintainers and that +all complaints will result in an appropriate response. I care deeply about +Jekyll's community and will do everything in my power to ensure it is a +welcoming community. Feel free to reach out to me directly if you feel +there is a way we can improve the community for everyone! If you're +interested in more details, [there is a diff for +that](https://github.com/ContributorCovenant/contributor_covenant/blob/v1_4/diffs/1_3_vs_1_4.patch). + +See links to the PR's on [the history page](/docs/history/#v3-1-1). + +Thanks to Jordon Bedwell, chrisfinazzo, Kroum Tzanev, David Celis, and +Alfred Xing for their commits on this latest release! :sparkles: + +Happy Jekylling! diff --git a/docs/_posts/2016-02-08-jekyll-3-0-3-released.markdown b/docs/_posts/2016-02-08-jekyll-3-0-3-released.markdown new file mode 100644 index 00000000000..05c9cc220e0 --- /dev/null +++ b/docs/_posts/2016-02-08-jekyll-3-0-3-released.markdown @@ -0,0 +1,31 @@ +--- +title: 'Jekyll 3.0.3 Released' +date: 2016-02-08 10:39:08 -0800 +author: parkr +version: 3.0.3 +category: release +--- + +[GitHub Pages upgraded to Jekyll 3.0.2][1] last week. With a testbed of +over a million sites, this really put Jekyll 3 through the wringer. This +release addresses a handful of bugs that were surfaced as a result. The +fixes: + +* Fix problem where outputting to a folder would have two extensions +* Handle tildes (`~`) in filenames properly +* Fix issue when comparing documents without dates +* Include line numbers in liquid error output + +Read more on the [changelog](/docs/history/#v3-0-3) with links to the +related patches. + +Please keep [submitting bugs][2] as you find them! Please do take a look +[in our various help resources](/help/) before filing a bug and use [our +forum][3] for asking questions and getting help on a specific problem +you're having. + +Happy Jekylling! + +[1]: https://github.com/blog/2100-github-pages-now-faster-and-simpler-with-jekyll-3-0 +[2]: {{ site.repository }}/issues +[3]: https://talk.jekyllrb.com/ diff --git a/docs/_posts/2016-02-19-jekyll-3-1-2-released.markdown b/docs/_posts/2016-02-19-jekyll-3-1-2-released.markdown new file mode 100644 index 00000000000..df8bfd3ec6e --- /dev/null +++ b/docs/_posts/2016-02-19-jekyll-3-1-2-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.1.2 Released!' +date: 2016-02-19 15:24:00 -0800 +author: parkr +version: 3.1.2 +category: release +--- + +Happy Friday from sunny California! Today, we're excited to announce the release of Jekyll v3.1.2, which comes with some crucial bug fixes: + +* If a syntax error is encountered by Liquid, it will now print the line number. +* A nasty war between symbols and strings in our configuration hash caused kramdown syntax highlighting to break. That has been resolved; you stand victorious! +* A tilde at the beginning of a filename will no longer crash Jekyll. +* The `titleize` filter mistakenly dropped words that were already capitalized. Fixed! +* Permalinks which end in a slash will now always output as a folder with an `index.html` inside. + +Nitty-gritty details, like always, are available in the [history](/docs/history/). + +Thanks to those who contributed to this release: Alfred Xing, atomicules, bojanland, Brenton Horne, Carlos Garcés, Cash Costello, Chris, chrisfinazzo, Daniel Schildt, Dean Attali, Florian Thomas, Jordon Bedwell, Juuso Mikkonen, Katya Demidova, lonnen, Manabu Sakai, Michael Lee, Michael Lyons, Mitesh Shah, Nicolas Hoizey, Parker Moore, Pat Hawks, Prayag Verma, Robert Martin, Suriyaa Kudo, and toshi. diff --git a/docs/_posts/2016-03-10-making-it-easier-to-contribute-to-jekyll.md b/docs/_posts/2016-03-10-making-it-easier-to-contribute-to-jekyll.md new file mode 100644 index 00000000000..9d80604997e --- /dev/null +++ b/docs/_posts/2016-03-10-making-it-easier-to-contribute-to-jekyll.md @@ -0,0 +1,16 @@ +--- +title: Making it easier to contribute to Jekyll +description: We've made it easier to contribute to Jekyll by updating our contributing documentation and introducing Jekyll Affinity Teams, teams dedicated to specific aspects of the project. +author: benbalter +categories: [community] +--- + +Jekyll is an open source project, built one contribution at a time by community members just like you. These community contributions can come in many forms beyond just writing code, from reporting an issue or suggesting a new feature to improving documentation or providing feedback on proposed changes. + +If you've been looking to get involved with the Jekyll community, but didn't know, we've recently made it easier to contribute to Jekyll in two ways: + +First, we've completely rewritten [the project's contributing guidelines](https://jekyllrb.com/docs/contributing/), outlining [the various ways you can contribute](https://jekyllrb.com/docs/contributing/#ways-to-contribute), and including better instructions for [submitting proposed changes via GitHub.com](https://jekyllrb.com/docs/contributing/#submitting-a-pull-request-via-githubcom) or for [submitting your first code improvement](https://jekyllrb.com/docs/contributing/#code-contributions). And if you have any feedback, we'd love to hear it! Simply click the "improve this page" button in the top right corner of the contributing documentation. + +Second, this week, we created six community interest groups, we're calling [Jekyll affinity teams](https://teams.jekyllrb.com). If you're interested in a particular aspect of the project (or just want to learn more), you can join any one of these teams (or two, or three), to participate in discussions about potential bugs and proposed improvements. And the best part is there's no commitment. If you just want to listen, or if at any point you want to leave (or switch teams), that's totally fine. We won't say a thing. To learn more about the various affinity teams, or to join one (please do!), just head on over to [teams.jekyllrb.com](https://teams.jekyllrb.com/). + +We hope these changes will make it easier for you to make your first (or second, or third) contribution to Jekyll today. Thanks for helping to make Jekyll awesome! diff --git a/docs/_posts/2016-04-19-jekyll-3-0-4-released.markdown b/docs/_posts/2016-04-19-jekyll-3-0-4-released.markdown new file mode 100644 index 00000000000..218ec072620 --- /dev/null +++ b/docs/_posts/2016-04-19-jekyll-3-0-4-released.markdown @@ -0,0 +1,23 @@ +--- +title: 'Jekyll 3.0.4 Released' +date: 2016-04-19 10:26:12 -0700 +author: parkr +version: 3.0.4 +category: release +--- + +v3.0.4 is a patch release which fixes the follow two issues: + +- Front matter defaults may not have worked for collection documents and posts due to a problem where they were looked up by their URL rather than their path relative to the site source +- Configuration for the posts permalink might be borked when a user specified a value for `collections.posts.permalink` directly. This forced the use of `permalink` at the top level, which also affected pages. To configure a permalink _just for posts_, you can do so with: + +{% highlight yaml %} +collections: + posts: + output: true + permalink: /blog/:year/:title/ +{% endhighlight %} + +Both of these issues have been resolved. For more information, check out [the full history](/docs/history/#v3-0-4). + +Happy Jekylling! diff --git a/docs/_posts/2016-04-19-jekyll-3-1-3-released.markdown b/docs/_posts/2016-04-19-jekyll-3-1-3-released.markdown new file mode 100644 index 00000000000..1735f59036d --- /dev/null +++ b/docs/_posts/2016-04-19-jekyll-3-1-3-released.markdown @@ -0,0 +1,16 @@ +--- +title: 'Jekyll 3.1.3 Released' +date: 2016-04-19 10:26:16 -0700 +author: parkr +version: 3.1.3 +category: release +--- + +v3.1.3 is a patch release which fixes the follow two issues: + +- Front matter defaults may not have worked for collection documents and posts due to a problem where they were looked up by their URL rather than their path relative to the site source +- Running `jekyll serve` with SSL enabled was broken due to a bad configuration. + +Both of these issues have been resolved. For more information, check out [the full history](/docs/history/#v3-1-3). + +Happy Jekylling! diff --git a/docs/_posts/2016-04-26-jekyll-3-0-5-released.markdown b/docs/_posts/2016-04-26-jekyll-3-0-5-released.markdown new file mode 100644 index 00000000000..8dc23be4dde --- /dev/null +++ b/docs/_posts/2016-04-26-jekyll-3-0-5-released.markdown @@ -0,0 +1,24 @@ +--- +title: 'Jekyll 3.0.5 Released' +date: 2016-04-26 17:40:44 -0700 +author: parkr +version: 3.0.5 +category: release +--- + +This version fixes a bug affecting only v3.0.4 where autoregeneration was +*always* disabled when running Jekyll locally. This feature is a huge +reason why Jekyll (or any static site generator, for that matter) is a joy +to use. Sorry for the regression! + +If you're using GitHub Pages, [you can follow the progress of the upgrade +on the github/pages-gem repo](https://github.com/github/pages-gem/pull/285). + +As always, our [history doc](/docs/history/#v3-0-5) has links to the pull +requests and issues associated with the release for your perusal. + +We're looking forward to the upcoming release of v3.2 which [has some +excellent goodies](https://github.com/jekyll/jekyll/blob/master/History.markdown#head) +we think you'll love. + +Happy Jekylling! diff --git a/docs/_posts/2016-05-18-jekyll-3-1-4-released.markdown b/docs/_posts/2016-05-18-jekyll-3-1-4-released.markdown new file mode 100644 index 00000000000..e1ad1197f72 --- /dev/null +++ b/docs/_posts/2016-05-18-jekyll-3-1-4-released.markdown @@ -0,0 +1,25 @@ +--- +title: 'Jekyll 3.1.4 "Stability Sam" Released' +date: 2016-05-18 16:50:37 -0700 +author: parkr +version: 3.1.4 +category: release +--- + +Hey Jekyllites! + +Today, we released v3.1.4 in an effort to bring more stability to the v3.1.x series. This bugfix release consists of: + +* A fix for `layout` in Liquid where values would carry over from one document to the next +* A fix for `layout` in Liquid where a parent layout (e.g. `default` or `base`) would overwrite the metadata of the child layout (e.g. `post` or `special`). +* A fix where `page.excerpt` referencing its excerpt would cause an infinite loop of recursive horror. +* We added `Configuration.from` and the great permalink fix from [v3.0.4](/news/2016/04/19/jekyll-3-0-4-released/) to the v3.1.x series +* `site.collections` in Liquid is now sorted alphabetically by label, so `docs` shows up before `posts` reliably. + +The fixes for `layout` may not be seamless for everyone, but we believe they will be the "right thing to do" going forward. + +We are always striving to make Jekyll more straight-forward to use. Please do open an issue if you believe an aspect of Jekyll's user experience isn't up to par. + +For a full history of our changes, [see the changelog](/docs/history/#v3-1-4). + +As always, Happy Jekylling! diff --git a/docs/_posts/2016-05-18-jekyll-3-1-5-released.markdown b/docs/_posts/2016-05-18-jekyll-3-1-5-released.markdown new file mode 100644 index 00000000000..0dbdd5219f2 --- /dev/null +++ b/docs/_posts/2016-05-18-jekyll-3-1-5-released.markdown @@ -0,0 +1,16 @@ +--- +title: 'Jekyll 3.1.5 Released' +date: 2016-05-18 21:35:27 -0700 +author: parkr +version: 3.1.5 +category: release +--- + +There's always at least one bug, right? :) + +Hot on the trails of [v3.1.4](/news/2016/05/18/jekyll-3-1-4-released/), we +bring you v3.1.5! It fixes one bug around requiring the `ExcerptDrop`, +which only affects Linux. For the gory details, see [the pull +request for the fix](https://github.com/jekyll/jekyll/pull/4912). + +Happy Jekylling! diff --git a/docs/_posts/2016-05-19-jekyll-3-1-6-released.markdown b/docs/_posts/2016-05-19-jekyll-3-1-6-released.markdown new file mode 100644 index 00000000000..a12c14e1a0a --- /dev/null +++ b/docs/_posts/2016-05-19-jekyll-3-1-6-released.markdown @@ -0,0 +1,18 @@ +--- +title: 'Jekyll 3.1.6 Released' +date: 2016-05-19 12:48:14 -0700 +author: parkr +version: 3.1.6 +category: release +--- + +Upon releasing 3.1.5 and kicking the tires, we noticed a glaring bug: our +beloved `jsonify` filter doesn't work! With that, our work was cut out for +us and we decided a 3.1.6 was necessary. This release restores sanity to +our object-to-JSON generation in Liquid and we hope you enjoy. + +For the gory details, see [the pull +request](https://github.com/jekyll/jekyll/pull/4914) or [the +changelog](/docs/history/#v3-1-6). + +Happy Jekylling! diff --git a/docs/_posts/2016-06-03-update-on-jekyll-s-google-summer-of-code-projects.markdown b/docs/_posts/2016-06-03-update-on-jekyll-s-google-summer-of-code-projects.markdown new file mode 100644 index 00000000000..c3d01cddcbe --- /dev/null +++ b/docs/_posts/2016-06-03-update-on-jekyll-s-google-summer-of-code-projects.markdown @@ -0,0 +1,18 @@ +--- +title: "Jekyll's Google Summer of Code Project: The CMS You Always Wanted" +date: "2016-06-03 13:21:02 -0700" +author: parkr +categories: [community] +--- + +This year, Jekyll applied to be a part of [Google Summer of Code](https://summerofcode.withgoogle.com/how-it-works/). Students were able to propose any project related to Jekyll. With a gracious sponsorship from GitHub and the participation of myself, @benbalter and @jldec, Jekyll was able to accept two students for the 2016 season, @mertkahyaoglu and @rush-skills. + +These students are working on a project that fills a huge need for the community: _a graphical solution for managing your site's content._ Current plans include a fully-integrated admin which spins up when you run jekyll serve and provides a friendly web interface for creating and editing your content. The server and web interface will speak a common HTTP interface so either piece could be switched out for, e.g. a server which writes directly to a repository on GitHub. + +The strength of text files as the storage medium for content has been part of Jekyll's success. [Our homepage](/) lauds the absence of a traditional SQL database when using Jekyll – your content should be what demands your time, not pesky database downtime. Unfortunately, understanding of the structure of a Jekyll site takes some work, enough that for some users, it's prohibitive to using Jekyll to accomplish their publishing goals. + +Mert and Ankur both applied to take on this challenge and agreed to split the project, one taking on the web interface and the other taking on the backend. We're very excited to see a fully-functional CMS for Jekyll at the end of the summer produced by these excellent community members, and we hope you'll join us in cheering them on and sharing our gratitude for all their hard work. + +Thanks, as always, for being part of such a wonderful community that made this all possible. I'm honored to work with each of you to create something folks all around the globe find a joy to use. I look forward to our continued work to move Jekyll forward. + +As always, Happy Jekylling! diff --git a/docs/_posts/2016-07-26-jekyll-3-2-0-released.markdown b/docs/_posts/2016-07-26-jekyll-3-2-0-released.markdown new file mode 100644 index 00000000000..86440020666 --- /dev/null +++ b/docs/_posts/2016-07-26-jekyll-3-2-0-released.markdown @@ -0,0 +1,124 @@ +--- +title: 'Jekyll turns 3.2' +date: 2016-07-26 15:06:49 -0700 +author: parkr +version: 3.2.0 +category: release +--- + +Happy Day! Jekyll v3.2.0 is out, and packed full of goodies. + +Our flagship feature for this release has been **themes**. _Themes?!_, you +say? Yes, proper, versionable, releasable, first-class themes. We're pretty +stoked about it and we hope you like building and using them. For now, it +only supports layouts, includes, and sass, but we have plans to include +static assets like images and CSS/JS in a future release. [Read more about +it in the docs.](/docs/themes/) Our site template generated by `jekyll new` +now dogfoods this feature, using the [minima](https://github.com/jekyll/minima) theme. + +Some other notable changes: + +- Symlinks are allowed as long as they target a file in the site source +- Explicit support for Ruby 2.0.x was dropped +- Added an `:after_init` Hook +- Added a `where_exp` filter to provide more powerful filtering +- Added a `link` liquid tag which can be used to generate URLs for any +post or document based on its path relative to the site source +- ... and lots more! + +As always, there is [a full list of changes](/docs/history/#v3-2-0) for +your perusal. + +Every release is made possible by the countless hours of hard work that our +fellow community members put into sending patches, filing thoughtful +patches, and so on. These release took the work of over 80 people: + +- Aaron Sky +- Adam Hollett +- ajhit406 +- Aki +- Alex Hanselka +- Alex Hoyau +- Alex Ivkin +- Alex Kitchens +- Alex Plescan +- Alex Wood +- Anatoliy Yastreb +- Andrew Artajos +- Andrew Munsell +- AndrewCz +- Ankush Menat +- Anthony Smith +- Ben Balter +- Brian Jones +- Brint O'Hearn +- Chayoung You +- Chris Wells +- chrisfinazzo +- Clark Winkelmann +- Dan Allen +- David Von Lehman +- David Zhang +- Derek Gottlieb +- Enes Gönültaş +- EricH +- Erick Sasse +- Eugênio Cabral +- Florian Thomas +- Frank Taillandier +- Henry Goodman +- Henry Wright +- Hugo Duksis +- Hugo Giraudel +- Jack Reed +- Jamie Bilinski +- Jeff Kolesky +- Jens Willmer +- Jordon Bedwell +- Josh Waller +- Joshua Barnett +- Keegan Mullaney +- Kevin Miller +- Krzysztof Jurewicz +- Loren Rogers +- Marcos Brito +- Marcus Stollsteimer +- Matt Rogers +- Michaël Guitton +- Mike Linksvayer +- Mike Neumegen +- Nathan Hazout +- Nick +- No +- nscyclone +- Parker Moore +- Pat Hawks +- Pierre Fenoll +- Praveen Kumar +- Rares Vernica +- Saleem Rashid +- Sam Dutton +- Shengbin Meng +- Shinn Kondo +- Shinnosuke Kondo +- skim +- Sondre Nilsen +- Spencer A. Bywater +- Stephen Checkoway +- Suriyaa Kudo +- surrim +- TheLucasMoore +- Thomas Wood +- Tim Wisniewski +- Tom Fejfar +- Tony Garnock-Jones +- Vincent Wochnik +- XhmikosR +- Yanis Vieilly +- Yordis Prieto +- Zack Spencer + +We are so grateful to all of you for helping to put together a terrific +release. Thank you! + +Happy Jekylling! diff --git a/docs/_posts/2016-08-02-jekyll-3-2-1-released.markdown b/docs/_posts/2016-08-02-jekyll-3-2-1-released.markdown new file mode 100644 index 00000000000..d5af2a45ee9 --- /dev/null +++ b/docs/_posts/2016-08-02-jekyll-3-2-1-released.markdown @@ -0,0 +1,23 @@ +--- +title: 'Jekyll 3.2.1 Released with Fix for Windows' +date: 2016-08-02 13:20:11 -0700 +author: parkr +version: 3.2.1 +category: release +--- + +Well, 3.2.0 has been a success, but with one fatal flaw: it doesn't work on +Windows! Sorry, Windows users. Hot on the trail of 3.2.0, this release +should squash that :bug:. Sorry about that! + +This release also fixes an issue when using [gem-based themes](/docs/themes/) +where the theme was rejected if it existed behind a symlink. This is a +common setup for the various ruby version managers, and for Ruby installed +via Homebrew. Props to @benbalter for fixing that up. + +Thanks to the contributors for this release: Adam Petrie, Ben Balter, +Daniel Chapman, DirtyF, Gary Ewan Park, Jordon Bedwell, and Parker Moore. + +As always, you can see our full changelog on [the History page](/docs/history/). + +Happy Jekylling! diff --git a/docs/_posts/2016-08-24-jekyll-admin-initial-release.markdown b/docs/_posts/2016-08-24-jekyll-admin-initial-release.markdown new file mode 100644 index 00000000000..e256a5c72c7 --- /dev/null +++ b/docs/_posts/2016-08-24-jekyll-admin-initial-release.markdown @@ -0,0 +1,17 @@ +--- +title: "Jekyll Admin Initial Release" +date: "2016-08-25 09:50:00 +0300" +author: mertkahyaoglu +categories: [community] +--- + +[Jekyll's Google Summer of Code Project](https://jekyllrb.com/news/2016/06/03/update-on-jekyll-s-google-summer-of-code-projects/) has concluded. After three months of hard (but fun) work with my mentors @benbalter, @jldec, and @parkr, I'm proud to announce [Jekyll Admin](https://github.com/jekyll/jekyll-admin)'s [initial release](https://github.com/jekyll/jekyll-admin/releases/tag/v0.1.0). Jekyll admin is a Jekyll plugin that provides users with a traditional CMS-style graphical interface to author content and administer Jekyll sites. You can start to use it right away by following [these instructions](https://github.com/jekyll/jekyll-admin#installation). + +As a Google Summer of Code student, I feel very lucky to be part of a project that the community has been wanting for such a long time. The three-month Google Summer of Code period was a great journey. It was a lot of fun developing the project and seeing how it could help the community, and going forward, we are really excited to see where the project goes with the help of the amazing Jekyll community. + +I would like to thank my mentors who embraced me as their teammate and guided me throughout the process. They have put a lot of work and time to mentor me and helped me with everything. It was a great pleasure to work with them. I also would like to thank the wonderful Jekyll community for making Jekyll what it is today. It was amazing to see the community contribute to the project and give their feedback +prior to its release. I'm sure that they will support Jekyll Admin as much as they can and move Jekyll even further. + +Please let us know what you think about [Jekyll Admin](https://github.com/jekyll/jekyll-admin) and feel free to [contribute](https://github.com/jekyll/jekyll-admin/blob/master/.github/CONTRIBUTING.md). Your feedback and contributions are greatly appreciated. + +Happy (graphical) Jekylling! diff --git a/docs/_posts/2016-10-06-jekyll-3-3-is-here.md b/docs/_posts/2016-10-06-jekyll-3-3-is-here.md new file mode 100644 index 00000000000..458f896ccdd --- /dev/null +++ b/docs/_posts/2016-10-06-jekyll-3-3-is-here.md @@ -0,0 +1,109 @@ +--- +title: 'Jekyll 3.3 is here with better theme support, new URL filters, and tons more' +date: 2016-10-06 11:10:38 -0700 +author: parkr +version: 3.3.0 +category: release +--- + +There are tons of great new quality-of-life features you can use in 3.3. +Three key things you might want to try: + +### 1. Themes can now ship static & dynamic assets in an `/assets` directory + +In Jekyll 3.2, we shipped the ability to use a theme that was packaged as a +[gem](http://guides.rubygems.org/). 3.2 included support for includes, +layouts, and sass partials. In 3.3, we're adding assets to that list. + +In an effort to make theme management a bit easier, any files you put into +`/assets` in your theme will be read in as though they were part of the +user's site. This means you can ship SCSS and CoffeeScript, images and +webfonts, and so on -- anything you'd consider a part of the +*presentation*. Same rules apply here as in a Jekyll site: if it has YAML +front matter, it will be converted and rendered. No front matter, and +it will simply be copied over like a static asset. + +Note that if a user has a file of the same path, the theme content will not +be included in the site, i.e. a user's `/assets/main.scss` will be read and +processed if present instead of a theme's `/assets/main.scss`. + +See our [documentation on the subject]({{ "/docs/themes/#assets" | relative_url }}) +for more info. + +### 2. `relative_url` and `absolute_url` filters + +Want a clean way to prepend the `baseurl` or `url` in your config? These +new filters have you covered. When working locally, if you set your +`baseurl` to match your deployment environment, say `baseurl: "/myproject"`, +then `relative_url` will ensure that this baseurl is prepended to anything +you pass it: + +{% raw %} +```liquid +{{ "/docs/assets/" | relative_url }} => /myproject/docs/assets +``` +{% endraw %} + +By default, `baseurl` is set to `""` and therefore yields (never set to +`"/"`): + +{% raw %} +```liquid +{{ "/docs/assets/" | relative_url }} => /docs/assets +``` +{% endraw %} + +A result of `relative_url` will safely always produce a URL which is +relative to the domain root. A similar principle applies to `absolute_url`. +It prepends your `baseurl` and `url` values, making absolute URLs all the +easier to make: + +{% raw %} +```liquid +{{ "/docs/assets/" | absolute_url }} => https://jekyllrb.com/myproject/docs/assets +``` +{% endraw %} + +### 3. `site.url` is set by the development server + +When you run `jekyll serve` locally, it starts a web server, usually at +`http://localhost:4000`, that you use to preview your site during +development. If you are using the new `absolute_url` filter, or using +`site.url` anywhere, you have probably had to create a development config +which resets the `url` value to point to `http://localhost:4000`. + +No longer! When you run `jekyll serve`, Jekyll will build your site with +the value of the `host`, `port`, and SSL-related options. This defaults to +`url: http://localhost:4000`. When you are developing locally, `site.url` +will yield `http://localhost:4000`. + +This happens by default when running Jekyll locally. It will not be set if +you set `JEKYLL_ENV=production` and run `jekyll serve`. If `JEKYLL_ENV` is +any value except `development` (its default value), Jekyll will not +overwrite the value of `url` in your config. And again, this only applies +to serving, not to building. + +## A *lot* more! + +There are dozens of bug fixes and minor improvements to make your Jekyll +experience better than ever. With every Jekyll release, we strive to bring +greater stability and reliability to your everyday development workflow. + +As always, thanks to our many contributors who contributed countless hours +of their free time to making this release happen: + +Anatoliy Yastreb, Anthony Gaudino, Antonio, Ashwin Maroli, Ben Balter, +Charles Horn, Chris Finazzo, Daniel Chapman, David Zhang, Eduardo +Bouças, Edward Thomson, Eloy Espinaco, Florian Thomas, Frank Taillandier, +Gerardo, Heng Kwokfu, Heng, K. (Stephen), Jeff Kolesky, Jonathan Thornton, +Jordon Bedwell, Jussi Kinnula, Júnior Messias, Kyle O'Brien, Manmeet Gill, +Mark H. Wilkinson, Marko Locher, Mertcan GÖKGÖZ, Michal Švácha, Mike +Kasberg, Nadjib Amar, Nicolas Hoizey, Nicolas Porcel, Parker Moore, Pat +Hawks, Patrick Marsceill, Stephen Checkoway, Stuart Kent, XhmikosR, Zlatan +Vasović, mertkahyaoglu, shingo-nakanishi, and vohedge. + +[Full release notes]({{ "/docs/history/#v3-3-0" | relative_url }}) are available +for your perusal. If you notice any issues, please don't hesitate to file a +bug report. + +Happy Jekylling! diff --git a/docs/_posts/2016-11-14-jekyll-3-3-1-released.markdown b/docs/_posts/2016-11-14-jekyll-3-3-1-released.markdown new file mode 100644 index 00000000000..6c286ff614a --- /dev/null +++ b/docs/_posts/2016-11-14-jekyll-3-3-1-released.markdown @@ -0,0 +1,18 @@ +--- +title: 'Jekyll 3.3.1 Released' +date: 2016-11-14 14:29:59 -0800 +author: parkr +version: 3.3.1 +category: release +--- + +Hello! We have a bugfix release of Jekyll hot off the presses for you. Key +fixes to call out: + +1. Only warn about auto-regeneration issues on Windows instead of disabling +2. Exclude very specific `vendor/` subdirectories instead of all of `vendor/` +3. Allow permalink templates to have plaintext underscores + +..and lots more! Check out the [full history for more](/docs/history/#v3-3-1). + +Happy Jekylling! diff --git a/docs/_posts/2017-01-18-jekyll-3-4-0-released.markdown b/docs/_posts/2017-01-18-jekyll-3-4-0-released.markdown new file mode 100644 index 00000000000..bf1db93ff30 --- /dev/null +++ b/docs/_posts/2017-01-18-jekyll-3-4-0-released.markdown @@ -0,0 +1,42 @@ +--- +title: 'Jekyll turns 3.4.0' +date: 2017-01-18 14:19:13 -0500 +author: parkr +version: 3.4.0 +category: release +--- + +Hey there! We have a quick update of Jekyll for you to enjoy this January. +Packed full of bug fixes as usual, thanks to the tireless efforts of our +exceptional Jekyll community. Three changes to call out: + +1. If you're a big fan of [`where_by_exp`](/docs/liquid/filters/), you'll be an +even bigger fan of [`group_by_exp`](/docs/liquid/filters/). +2. Using a custom timezone in Jekyll on Windows? Yeah, sorry that hasn't ever worked + properly. We made it possible to accurately [set the timezone using IANA + timezone codes](/docs/installation/windows/#time-zone-management). +3. Documentation has been improved, notably on themes, includes and permalinks. + +And [lots and lots more!](/docs/history/#v3-4-0) + +This update was made possible by the dedicated efforts of our excellent +contributors: Ajay Karwal, Alexey Rogachev, Ashwin Maroli, +BlueberryFoxtrot, Chase, Chayoung You, Dean Attali, Dmitrii Evdokimov, Don +Denton, Eldritch Cheese, Fabrice Laporte, Florian Thomas, Frank +Taillandier, Hugo, Ivan Dmitrievsky, Joel Meyer-Hamme, Josh Habdas, Kenton +Hansen, Kevin Wojniak, Kurt Anderson, Longwelwind, Max Chadwick, Nicolas +Hoizey, Nursen, Parker Moore, Pat Hawks, Purplecarrot, Ricardo N Feliciano, +Rob Crocombe, Roger Ogden, Skylar Challand, Thiago Arrais, Tim Banks, Tom +Johnson, Tunghsiao Liu, XhmikosR, Zlatan Vasović, alexmalik, brainscript, +kimbaudi, muratayusuke, penny, and yoostk. + +As always, if you encounter bugs, please do [search the issues]({{ site.repository }}/issues) +and [file an issue]({{ site.repository }}/issues/new) if you aren't able to +find a resolution. We also have [our Jekyll Talk +forum](https://talk.jekyllrb.com) for those of you with general questions +about how to accomplish certain tasks with Jekyll. + +We have some exciting updates in store for v3.5, and we're hard at work on +those already. + +Happy Jekylling! diff --git a/docs/_posts/2017-03-02-jekyll-3-4-1-released.markdown b/docs/_posts/2017-03-02-jekyll-3-4-1-released.markdown new file mode 100644 index 00000000000..213e57a0a38 --- /dev/null +++ b/docs/_posts/2017-03-02-jekyll-3-4-1-released.markdown @@ -0,0 +1,106 @@ +--- +title: 'Jekyll 3.4.1, or "Unintended Consequences"' +date: 2017-03-02 14:20:26 -0500 +author: parkr +version: 3.4.1 +category: release +--- + +Conformity is a confounding thing. + +We write tests to ensure that a piece of functionality that works today +will work tomorrow, as further modifications are made to the codebase. This +is a principle of modern software development: every change must have a +test to guard against regressions to the functionality implemented by that +change. + +And yet, occasionally, our very best efforts to test functionality will be +thwarted. This is because of how our code produces unintended +functionality, which naturally goes untested. + +In our documentation, we tell users to name their posts with the following +format: + +```text +YYYY-MM-DD-title.extension +``` + +That format specifies exactly four numbers for the year, e.g. 2017, two +letters for the month, e.g. 03, and two letters for the day, e.g. 02. To +match this, we had the following regular expression: + +```ruby +%r!^(?:.+/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$! +``` + +You might already see the punchline. While our documentation specifies the +exact number of numbers that is required for each section of the date, our +regular expression does not enforce this precision. What happens if a user +doesn't conform to our documentation? + +We recently [received a bug report](https://github.com/jekyll/jekyll/issues/5603) +that detailed how the following file was considered a post: + +```text +84093135-42842323-42000001-b890-136270f7e5f1.md +``` + +Of course! It matches the above regular expression, but doesn't satisfy +other requirements about those numbers being a valid date (unless you're +living in a world that has 43 million months, and 42 million (and one) +days). So, we [modified the regular expression to match our +documentation](https://github.com/jekyll/jekyll/pull/5609): + +```ruby +%r!^(?:.+/)*(\d{4}-\d{2}-\d{2})-(.*)(\.[^.]+)$! +``` + +Our tests all passed and we were properly excluding this crazy date with 43 +million months and days. This change shipped in Jekyll v3.4.0 and all was +well. + +Well, not so much. + +A very common way to specify the month of February is `2`. This is true for +all single-digit months and days of the month. Notice anything about our +first regular expression versus our second? The second regular expression +imposes a **minimum**, as well as maximum, number of digits. This change +made Jekyll ignore dates with single-digit days and months. + +The first eight years of Jekyll's existence had allowed single-digit days +and months due to an imprecise regular expression. For some people, their +entire blog was missing, and there were no errors that told them why. + +After receiving a few bug reports, it became clear what had happened. +Unintended functionality of the last eight years had been broken. Thus, +v3.4.0 was broken for a non-negligible number of sites. With a test site +in-hand from @andrewbanchich, I tracked it down to this regular expression +and [reintroduced](https://github.com/jekyll/jekyll/pull/5920) a proper +minimum number of digits for each segment: + +```ruby +%r!^(?:.+/)*(\d{2,4}-\d{1,2}-\d{1,2})-(.*)(\.[^.]+)$! +``` + +And, I wrote a test. + +This change was quickly backported to v3.4.0 and here we are: releasing +v3.4.1. It will fix the problem for all users who were using single-digit +months and days. + +With this, I encourage all of you to look at your code for *unintended* +functionality and make a judgement call: if it's allowed, *should it be*? +If it should be allowed, make it *intended* functionality and test it! I +know I'll be looking at my code with much greater scrutiny going forward, +looking for unintended consequences. + +Many thanks to our Jekyll affinity team captains who helped out, including +@pathawks, @pnn, and @DirtyF. Thanks, too, to @ashmaroli for reviewing my +change with an eye for consistency and precision. This was certainly a team +effort. + +We hope Jekyll v3.4.1 brings your variable-digit dates back to their +previous glory. We certainly won't let that unintended functionality be +unintended any longer. + +As always, Happy Jekylling! diff --git a/docs/_posts/2017-03-09-jekyll-3-4-2-released.markdown b/docs/_posts/2017-03-09-jekyll-3-4-2-released.markdown new file mode 100644 index 00000000000..775be8c0388 --- /dev/null +++ b/docs/_posts/2017-03-09-jekyll-3-4-2-released.markdown @@ -0,0 +1,51 @@ +--- +title: 'Jekyll 3.4.2 Released' +date: 2017-03-09 15:41:57 -0500 +author: parkr +version: 3.4.2 +category: release +--- + +Another one-PR patch update, though without the same [lessons as for the +previous release]({% link _posts/2017-03-02-jekyll-3-4-1-released.markdown %}). + +This release includes a beneficial change for a number of plugins: +**static files now respect front matter defaults**. + +You might be asking yourself: "why would static files, files that are +static files explicitly because they *don't* have front matter, want +to respect front matter?" That's a great question. Let me illustrate +with an example. + +Let's look at `jekyll-sitemap`. This plugin generates a list of documents, +pages, and static files, and some metadata for them in an XML file for a +Google/Yahoo/Bing/DuckDuckGo crawler to consume. If you don't want a given +file in this list, you set `sitemap: false` in front matter. But +what about static files, which don't have front matter? Before this +release, they could not be excluded because they had no properties in YAML +other than [the ones we explicitly assigned](https://github.com/jekyll/jekyll/blob/v3.4.1/lib/jekyll/static_file.rb#L98-L106). +So if you had a PDF you didn't want to be in your sitemap, you couldn't use +`jekyll-sitemap`. + +With this release, you can now set [front matter +defaults](/docs/configuration/front-matter-defaults/) for static files: + +```yaml +defaults: + - + scope: + path: "pdfs/" + values: + sitemap: false +``` + +Now, for every file in the Liquid `site.static_files` loop which is in the +folder `pdfs/`, you'll see `sitemap` equal to `false`. + +Many thanks to @benbalter for coming up with the solution and ensuring +sitemaps everywhere are filled with just the right content. + +As always, if you notice any bugs, please search the issues and file one if +you can't find another related to your issue. + +Happy Jekylling! diff --git a/docs/_posts/2017-03-21-jekyll-3-4-3-released.markdown b/docs/_posts/2017-03-21-jekyll-3-4-3-released.markdown new file mode 100644 index 00000000000..7373961e2a0 --- /dev/null +++ b/docs/_posts/2017-03-21-jekyll-3-4-3-released.markdown @@ -0,0 +1,49 @@ +--- +title: 'Jekyll 3.4.3 Released' +date: 2017-03-21 08:52:53 -0500 +author: pathawks +version: 3.4.3 +category: release +--- + +Another one-PR patch update as we continue our quest to destroy all bugs. A +fairly technical debriefing follows, but the TLDR is that we have updated the +`uri_escape` filter to more closely follow the pre-v3.4.0 behavior. + +In [v3.4.0]({% link _posts/2017-01-18-jekyll-3-4-0-released.markdown %}), we +moved away from using the deprecated +[`URI.escape`](https://ruby-doc.org/stdlib-2.3.0/libdoc/uri/rdoc/URI/Escape.html#method-i-encode) +in favor of +[`Addressable::URI.encode`](http://www.rubydoc.info/gems/addressable/Addressable/URI#encode-class_method). +This is what powers our [`uri_escape` +filter](https://jekyllrb.com/docs/templates/). + +While this transition was mostly a smooth one, the two methods are not +identical. While `URI.escape` was happy to escape any string, +`Addressable::URI.encode` first turns the string into an `Addressable::URI` +object, and will then escape each component of that object. In most cases, this +difference was insignificant, but there were a few cases where this caused some +unintended regressions when encoding colons. + +While **Addressable** can understand that something like `"/example :page"` is a +relative URI, without the slash it cannot figure out how to turn +`"example :page"` into an `Addressable::URI` object. `URI.escape` had no such +objection. This lead to the following Liquid code working fine in Jekyll 3.3.x +but breaking in 3.4.0: + +{% raw %} +```liquid +{{ "example :page" | uri_escape }} +``` +{% endraw %} + +This was not an intended consequence of switching to **Addressable**. + +Fortunately, the solution was not complicated. **Addressable** has a method +[`Addressable::URI.normalize_component`](http://www.rubydoc.info/gems/addressable/Addressable/URI#normalize_component-class_method) +which will simply escape the characters in a string, much like `URI.escape`. + +Thanks to @cameronmcefee and @FriesFlorian for reporting +[this issue](https://github.com/jekyll/jekyll/issues/5954). + +Happy Jekylling! diff --git a/docs/_posts/2017-06-14-jekyll-3-5-0-released.markdown b/docs/_posts/2017-06-14-jekyll-3-5-0-released.markdown new file mode 100644 index 00000000000..7bb2a82c409 --- /dev/null +++ b/docs/_posts/2017-06-14-jekyll-3-5-0-released.markdown @@ -0,0 +1,38 @@ +--- +title: 'Jekyll turns 3.5, oh my!' +date: 2017-06-15 17:32:32 -0400 +author: parkr +version: 3.5.0 +category: release +--- + +Good news! Nearly 400 commits later, Jekyll 3.5.0 has been released into +the wild. Some new shiny things you might want to test out: + +- Jekyll now uses Liquid 4, the latest! It comes with whitespace control, new filters `concat` and `compact`, loop performance improvements and [many fixes](https://github.com/Shopify/liquid/blob/master/History.md#400--2016-12-14--branch-4-0-stable) +- Themes can specify runtime dependencies (in their gemspecs) and we'll require those. This makes it easier for theme writers to use plugins. +- Speaking of themes, we'll properly handle the discrepancy between a convertible file in the local site and a static file in the theme. Overriding a file locally now doesn't matter if it's convertible or static. +- Pages, posts, and other documents can now access layout variables via `{% raw %}{{ layout }}{% endraw %}`. +- The `gems` key in the `_config.yml` is now `plugins`. This is backwards-compatible, as Jekyll will gracefully upgrade `gems` to `plugins` if you use the former. +- Filters like `sort` now allow you to sort based on a subvalue, e.g. `{% raw %}{% assign sorted = site.posts | sort: "image.alt_text" %}{% endraw %}`. +- You can now create tab-separated data files. +- Using `layout: none` will now produce a file with no layout. Equivalent to `layout: null`, with the exception that `none` is a truthy value and won't be overwritten by front matter defaults. +- No more pesky errors if your URL contains a colon (sorry about those!) +- We now automatically exclude the `Gemfile` from the site manifest when compiling your site. No more `_site/Gemfile`! +- We fixed a bug where abbreviated post dates were ignored, e.g. `_posts/2016-4-4-april-fourth.md`. + +And [so much more!](/docs/history/) + +There was a huge amount of effort put into this release by our maintainers, +especially @pathawks, @DirtyF, and @pup. Huge thanks to them for ushering +this release along and keeping the contributions flowing! Jekyll wouldn't +work without the tireless dedication of our team captains & maintainers. +Thank you, all! + +A huge thanks as well to our contributors to this release: Adam Hollett, Aleksander Kuś, Alfred Myers, Anatoliy Yastreb, Antonio Argote, Ashton Hellwig, Ashwin Maroli, Ben Balter, BlueberryFoxtrot, Brent Yi, Chris Finazzo, Christoph Päper, Christopher League, Chun Fei Lung, Colin, David Zhang, Eric Leong, Finn Ellis, Florian Thomas, Frank Taillandier, Hendrik Schneider, Henry Kobin, Ivan Storck, Jakub Klímek, Jan Pobořil, Jeff Puckett, Jonathan Hooper, Kaligule, Kevin Funk, Krzysztof Szafranek, Liu Cheng, Lukasz Brodowski, Marc Bruins, Marcelo Canina, Martin Desrumaux, Mer, Nate, Oreonax, Parker Moore, Pat Hawks, Pedro Lamas, Phil Nash, Ricardo N Feliciano, Ricky Han, Roger Sheen, Ryan Lue, Ryan Streur, Shane Neuville, Sven Meyer, Tom Johnson, William Entriken, Yury V. Zaytsev, Zarino Zappia, dyang, jekylltools, sean delaney, zenHeart + +Please file any bugs with detailed replication instructions if you find any +bugs. Better yet, submit a patch if you find the bug in the code and know +how to fix it! :heart: + +Happy Jekylling! :tada: diff --git a/docs/_posts/2017-07-17-jekyll-3-5-1-released.markdown b/docs/_posts/2017-07-17-jekyll-3-5-1-released.markdown new file mode 100644 index 00000000000..96b76edcb34 --- /dev/null +++ b/docs/_posts/2017-07-17-jekyll-3-5-1-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.5.1 Released' +date: 2017-07-17 12:40:37 -0400 +author: parkr +version: 3.5.1 +category: release +--- + +We've released a few bugfixes in the form of v3.5.1 today: + +- Some plugins stopped functioning properly due to a NoMethodError for `registers` on NilClass. That's been fixed. +- A bug in `relative_url` when `baseurl` is `nil` caused URL's to come out wrong. Squashed. +- Static files' liquid representations should now have all the keys you were expecting when serialized into JSON. + +We apologize for the breakages! We're working diligently to improve how we test our plugins with Jekyll core to prevent breakages in the future. + +More details in [the history](/docs/history/#v3-5-1). Many thanks to all the contributors to Jekyll v3.5.1: Adam Voss, ashmaroli, Ben Balter, Coby Chapple, Doug Beney, Fadhil, Florian Thomas, Frank Taillandier, James, jaybe, Joshua Byrd, Kevin Plattret, & Robert Jäschke. + +Happy Jekylling! diff --git a/docs/_posts/2017-08-12-jekyll-3-5-2-released.markdown b/docs/_posts/2017-08-12-jekyll-3-5-2-released.markdown new file mode 100644 index 00000000000..84deb6f5b40 --- /dev/null +++ b/docs/_posts/2017-08-12-jekyll-3-5-2-released.markdown @@ -0,0 +1,23 @@ +--- +title: 'Jekyll 3.5.2 Released' +date: 2017-08-12 16:31:40 -0400 +author: parkr +version: 3.5.2 +category: release +--- + +3.5.2 is out with 6 great bug fixes, most notably one which should dramatically speed up generation of your site! In testing #6266, jekyllrb.com generation when from 18 seconds down to 8! Here is the full line-up of fixes: + + * Backport #6266 for v3.5.x: Memoize the return value of `Document#url` (#6301) + * Backport #6247 for v3.5.x: kramdown: symbolize keys in-place (#6303) + * Backport #6281 for v3.5.x: Fix `Drop#key?` so it can handle a nil argument (#6288) + * Backport #6280 for v3.5.x: Guard against type error in `absolute_url` (#6287) + * Backport #6273 for v3.5.x: delegate `StaticFile#to_json` to `StaticFile#to_liquid` (#6302) + * Backport #6226 for v3.5.x: `Reader#read_directories`: guard against an entry not being a directory (#6304 + +A [full history](/docs/history/#v3-5-2) is available for your perusal. As always, please file bugs if you encounter them! Opening a pull request with a failing test for your expected behaviour is the easiest way for us to address the issue since we have a reproducible example to test again. Short of that, please fill out our issue template to the best of your ability and we'll try to get to it quickly! + +Many thanks to our contributors without whom this release could not be +possible: Ben Balter & Kyle Zhao. + +Happy Jekylling! diff --git a/docs/_posts/2017-09-21-jekyll-3-6-0-released.markdown b/docs/_posts/2017-09-21-jekyll-3-6-0-released.markdown new file mode 100644 index 00000000000..3a36efbccf2 --- /dev/null +++ b/docs/_posts/2017-09-21-jekyll-3-6-0-released.markdown @@ -0,0 +1,17 @@ +--- +title: 'Jekyll turns 3.6!' +date: 2017-09-21 16:38:20 -0400 +author: parkr +version: 3.6.0 +category: release +--- + +Another much-anticipated release of Jekyll. This release comes with it Rouge 2 support, but note you can continue to use Rouge 1 if you'd prefer. We also now require Ruby 2.1.0 as 2.0.x is no longer supported by the Ruby team. + +Otherwise, it's a massive bug-fix release! A few bugs were found and squashed with our `Drop` implementation. We're using the Schwartzian transform to speed up our custom sorting (thanks, Perl community!). We now protect against images that are named like posts and we generally worked on guarding our code to enforce requirements, instead of assuming the input was as expected. + +Please let us know if you find any bugs! You can see [the full history here](/docs/history/#v3-6-0). + +Many thanks to our contributors who helped make this release possible: Aleksander Kuś, André Jaenisch, Antonio Argote, ashmaroli, Ben Balter, Bogdan, Bradley Meck, David Zhang, Florian Thomas, Frank Taillandier, Jordon Bedwell, Joshua Byrd, Kyle Zhao, lymaconsulting, Maciej Bembenista, Matt Sturgeon, Natanael Arndt, Ohad Schneider, Pat Hawks, Pedro Lamas, and Sid Verma. + +As always, Happy Jekylling! diff --git a/docs/_posts/2017-10-19-diversity-open-source.markdown b/docs/_posts/2017-10-19-diversity-open-source.markdown new file mode 100644 index 00000000000..a5cde6544b7 --- /dev/null +++ b/docs/_posts/2017-10-19-diversity-open-source.markdown @@ -0,0 +1,44 @@ +--- +title: "Diversity in Open Source, and Jekyll's role in it" +date: 2017-10-19 21:33:00 +0200 +author: oe +categories: [community] +--- + +Open Source has a problem with diversity. GitHub recently conducted a [survey](http://opensourcesurvey.org/2017) which revealed that 95% of the respondents were identifying as male. This is even worse than in the tech industry overall, where the percentage is only about 76%. Every other week, there seems to be another case of a maintainer engaging in targeted harassment against minorities. People somehow deem it completely okay to let these things slide, though. + +Fortunately, there's a couple of things we can do to make it easier and more comfortable for people that have never contributed to any open source project before, to contribute to our projects. + +## Add a Code of Conduct, and enforce it + +This might seem like one of the easiest steps to do, but it actually requires a lot of dedication to pull through with. Basically, a Code of Conduct is a document detailing what is and what isn't acceptable behavior in your project. A good Code of Conduct also details enforcement procedures, that means how the person violating the Code of Conduct gets dealt with. This is the point at which I've seen a looooot of projects fail. It's easy enough to copy-paste a Code of Conduct into your project, but it's more important to be clear on how to enforce it. Inconsistent —or worse, nonexistent— enforcement is just going to scare off newcomers even more! + +The most widely adopted Code of Conduct is the [Contributor Covenant](https://www.contributor-covenant.org/). It's a very good catch-all document, but it is a bit light in the enforcement section, so I'd recommend to flesh it out by yourself, be it by means of adding contact information or expanding the enforcement rules. + +No matter which Code of Conduct you pick, the most important thing is to actually _read it for yourself_. The worst thing in open source is a maintainer that doesn't know when they've violated their own Code of Conduct. + +## Document your contributing workflow + +The problem that puts people off the most is incomplete or missing documentation, as revealed through GitHub's [open source survey](http://opensourcesurvey.org/2017). A very popular myth in programming is that good code explains itself, which might be true, but only for the person writing it. It's important, especially once you put your project out there for the world to see, to document not only your code, but also the process by which you maintain it. Otherwise, it's going to be extremely hard for newcomers to even figure out where to begin contributing to your project. + +Jekyll has [an entire section of its docs](/docs/contributing/) dedicated to information on how to contribute for this very reason. Every documentation page has a link to directly edit and improve it on GitHub. It's also important to realize that not all contributions are code. It can be documentation, it can be reviewing pull requests, but it can also just be weighing into issues, and all of this should be recognized in the same way. At Jekyll, out of 397 total merged pull requests in the last year, __204__ were documentation pull requests! + +## Create newcomer-friendly issues + +For most people new to open source, the biggest hurdle is creating their first pull request. That's why initiatives such as [YourFirstPR](https://twitter.com/yourfirstpr) and [First Timers Only](http://www.firsttimersonly.com/) were started. Recently, [a GitHub bot that automatically creates first-timer friendly issues](https://github.com/hoodiehq/first-timers-bot) was launched, which makes it very easy for maintainers to convert otherwise small or trivial changes into viable pull requests that can be taken on by newcomers! So we decided to give it a shot, and we've created a couple of very easy `first timers only` issues: + +- [Issue #6437](https://github.com/jekyll/jekyll/issues/6437) +- [Issue #6438](https://github.com/jekyll/jekyll/issues/6438) +- [Issue #6439](https://github.com/jekyll/jekyll/issues/6439) + +(There's also an up-to-date listing of all of our `first timers only` issues [here](https://github.com/jekyll/jekyll/issues?q=is%3Aissue+is%3Aopen+label%3Afirst-time-only)) + +These issues are designed to be taken on only by someone who has had little to no exposure to contributing to open source before, and additionally, project maintainers offer support in case a question arises. + +Jekyll is a very big and popular open source project, and we hope that with these special issues, we can help people who haven't contributed to open source before to catch a footing in these unsteady waters. + +## Be nice + +I know this is a cliche and a overused phrase, but really, it works if you pull through with it. Come to terms with the fact that some people aren't as fast or reliable as you might want to think. Don't get angry when a contributor takes a day longer than you might like them to. Treat new contributors to your project with respect, but also with hospitality. Think twice before you send that comment with slurs in it. + +I've been contributing to open source for about 4 years now, and I've had my fair share of horrible, horrible experiences. But Jekyll has historically been a project that has always valued the people contributing to it over the code itself, and I hope we can keep it that way. I also hope that other project maintainers read this and take inspiration from this post. Every project should be more diverse. diff --git a/docs/_posts/2017-10-21-jekyll-3-6-2-released.markdown b/docs/_posts/2017-10-21-jekyll-3-6-2-released.markdown new file mode 100644 index 00000000000..ad6d37a008f --- /dev/null +++ b/docs/_posts/2017-10-21-jekyll-3-6-2-released.markdown @@ -0,0 +1,42 @@ +--- +title: 'Jekyll 3.6.2 Released' +date: 2017-10-21 21:31:40 +0200 +author: dirtyf +version: 3.6.2 +category: release +--- + +3.6.2 is out, it's a tiny patch release and we invite you to run `bundle update` +if you want to avoid possible build problems with: + +* some UTF-8 and UTF-16 encoded files, +* fully numeric layout names (we convert those to string for you now). + +Other changes include updates to our documentation, like this [complete +video series by Giraffe Academy](/tutorials/video-walkthroughs/) aimed at +complete beginners. A big thanks to Mike for this. + +And if you're wondering what happened to version 3.6.1, it was just our new +release maintainer getting familiar with the release process. 😄 + +We try to release patch releases as quickly as possible and we're already +working on the next minor version 3.7.0 that will allow you to store all your +collections in a single directory. Stay tuned. + +Theme developers are invited to test the brand new +[`jekyll-remote-theme`](https://github.com/benbalter/jekyll-remote-theme) plugin +and give their feedback to @benbalter. This plugin allows you to use any +GitHub hosted theme as a remote theme! + +Once again, many thanks to our contributors who helped make this release possible: +ashmaroli, bellvat, Frank Taillandier, i-give-up, Jan Piotrowski, Maximiliano +Kotvinsky, Oliver Steele and Pat Hawks. For some it was their [first +contribution to open-source]({% link +_posts/2017-10-19-diversity-open-source.markdown %}) 👏 + +As it's been nine years this week that Tom Preston-Werner started this project, +I also wanna seize this opportunity to thank [all of the 732 contributors](https://github.com/jekyll/jekyll/graphs/contributors) who +helped make it possible for Jekyll to power millions of websites around the world +today. + +Happy Birthday Jekyll! 🎂 diff --git a/docs/_posts/2018-01-02-jekyll-3-7-0-released.md b/docs/_posts/2018-01-02-jekyll-3-7-0-released.md new file mode 100644 index 00000000000..c83ce55518c --- /dev/null +++ b/docs/_posts/2018-01-02-jekyll-3-7-0-released.md @@ -0,0 +1,37 @@ +--- +title: "Jekyll 3.7.0 Released" +description: "Jekyll 3.7.0 brings LiveReload, a directory for your collections and much more…" +date: 2018-01-02 11:21:40 +0100 +author: DirtyF +version: 3.7.0 +category: release +--- + +We're happy to release a new minor for the new year. +Here are a few of the latest additions from our contributors: + + * LiveReload is available as an option during development: with `jekyll serve --livereload` no more manual page refresh. A big thanks to @awood for this feature and to @andreyvit, LiveReload author. + * New `collections_dir` configuration option allows you to store all your [collections](/docs/collections/) in a single folder. Your source root folder should now look cleaner :sparkles: . + * If you're using a [gem-based theme](/docs/themes/) in coordination with the `--incremental` option, you should notice some significant speed during the regeneration process, we did see build time went down **from 12s to 2s** with @mmistakes [minimal-mistakes theme](https://github.com/mmistakes/minimal-mistakes) during our tests. + * Jekyll will now check to determine whether host machine has internet connection. + * A new `latin` option is available to better [handle URLs slugs](/docs/liquid/filters/#options-for-the-slugify-filter). + * And of course many bug fixes and updates to our documentation — which you can now search thanks to our friends @Algolia. + * [Full history is here](/docs/history/#v3-7-0). + +This release wouldn't have been possible without all the following people: + +Aaron Borden, Alex Tsui, Alex Wood, Alexey Pelykh, Andrew Dassonville, Angelika Tyborska, Ankit Singhaniya, Ashwin Maroli, bellvat, Brandon Dusseau, Chris Finazzo, Doug Beney, Dr. Wolfram Schroers, Edward Shen, Florian Thomas, Frank Taillandier, Gert-jan Theunissen, Goulven Champenois, János Rusiczki, Jed Fox, Johannes Müller, Jon Anning, Jonathan Hooper, Jordon Bedwell, Junko Suzuki, Kacper Duras, Kenton Hansen, Kewin Dousse, Matt Rogers, Maximiliano Kotvinsky, mrHoliday, Olivia, Parker Moore, Pat Hawks, Sebastian Kulig, Vishesh Ruparelia, Xiaoiver and Yashu Mittal. + +A big thanks to everyone! + +Oh, one last thing… + +### :pray: upgrade your Ruby + +Prepare for the next major update, as next major version Jekyll 4.0 will drop support for Ruby 2.1 and 2.2. + +> Ruby 2.2 is now under the state of the security maintenance phase, until the end of the March of 2018. After the date, maintenance of Ruby 2.2 will be ended. We recommend you start planning migration to newer versions of Ruby, such as 2.4 or 2.3. — [Ruby Core Team](https://www.ruby-lang.org/en/news/2017/12/14/ruby-2-2-9-released/) + +We strongly encourage you to upgrade to at least Ruby 2.4.x [like our friends at GitHub Pages](https://pages.github.com/versions/) or even go with [Ruby 2.5](https://www.ruby-lang.org/en/news/2017/12/25/ruby-2-5-0-released/). + +Happy new year to all from the Jekyll team! diff --git a/docs/_posts/2018-01-25-jekyll-3-7-2-released.md b/docs/_posts/2018-01-25-jekyll-3-7-2-released.md new file mode 100644 index 00000000000..04d6bbc673e --- /dev/null +++ b/docs/_posts/2018-01-25-jekyll-3-7-2-released.md @@ -0,0 +1,67 @@ +--- +title: "Jekyll 3.7.2 Released" +date: 2018-01-25 22:22:22 +0530 +author: ashmaroli +version: 3.7.2 +category: release +--- + +Close on the heels of shipping 3.7.0, we were informed of a couple of +regressions due to the changes made in that release. In due time, Team Jekyll +set out to address those issues as early as possible. + +Days later here we're, announcing 3.7.2 (sorry for skipping 3.7.1, +RubyGems didn't want to play nice) that fixes numerous issues! :tada: +The highlights being: + + * A major regression in 3.7.0 was that when a Front Matter Default was + configured with a `scope["path"]` set to a directory, Jekyll would scan + that directory for any subfolders and files, for each document in that + `path`. + Though this is intended, it increases build times in proportion to the size + of the directory. + + We addressed this by having Jekyll scan the directory path only if the user + explicitly configures the `scope["path"]` using wildcards. + + Read our [documentation](/docs/configuration/front-matter-defaults/#glob-patterns-in-front-matter-defaults) + for more details. + + A huge shout-out to @mmistakes for bringing this to our notice and + additionally providing us with a test repository to aid in resolving the issue. + + * Another regression reported was related to our "Custom collections + directory" feature introduced in 3.7.0. + + Users setting `collection_dir` to a certain directory would have *altered* + paths to their posts still at the root of their site's source. This + roughly translated to 404 errors on URLs to their posts. + + Props to @localheinz for bringing this regression to our notice. + + We decided to resolve this by having Jekyll ignore posts and drafts at the + root of the site's source directory if the user customizes the + `collection_dir` setting. + + Ergo, if you set a custom location for your collections, please ensure you + move all of your collections into that directory. **This includes posts and + drafts as well**. Your links generated by + {% raw %}`{% post_url %}`{% endraw %} or {% raw %}`{% link %}`{% endraw %} + will adapt automatically. + + * We also found out that `gem "wdm"` boosts performance while directories are + being watched on Windows. So we recommend having it included in your Gemfile + for a better development experience on Windows. (Newly generated Gemfiles + will hereafter have that gem listed automatically :wink:) + +In addition to the above, numerous other minor fixes and documentation updates +have been made that should improve your Jekyll experience. All of which, would +not have been possible without our wonderful contributors: + +Alexandr, Andreas Möller, Ashwin Maroli, Chayoung You, Florian Thomas, +Frank Taillandier, Hendrik Schneider, Kacper Duras, Olivia, Parker Moore and +Paul Robert Lloyd. + +As always, you can see our full changelog on [the History page](/docs/history/). + +Happy Jekylling! :sparkles: diff --git a/docs/_posts/2018-02-19-meet-jekyll-s-new-lead-developer.markdown b/docs/_posts/2018-02-19-meet-jekyll-s-new-lead-developer.markdown new file mode 100644 index 00000000000..1e229facfb7 --- /dev/null +++ b/docs/_posts/2018-02-19-meet-jekyll-s-new-lead-developer.markdown @@ -0,0 +1,43 @@ +--- +layout: news_item +title: "Meet Jekyll's New Lead Developer" +date: "2018-02-19 20:48:09 -0500" +author: parkr +categories: [team] +--- + +Jekyll has a new Lead Developer: Olivia! + +After over 5 years of leading Jekyll, many releases from 0.12.1 to 3.6.0, and +countless conversations in GitHub Issues, Pull Requests, Jekyll Talk, and +more, I am passing on the torch as Lead Developer of Jekyll. + +Olivia has been working with the Jekyll community for some time now. You +may have seen her around in issues and pull requests on the various Jekyll +repositories. She started as a contributor, then joined the Core team as our +community lead. Olivia joined the Jekyll Core Team with experience in the +Node.js community, both online and as a volunteer organizer with JSConf EU. + +In my conversations with Olivia, it is clear that Jekyll's vision of +simplicity for the user ([no magic!](/philosophy/#1-no-magic)) and letting +users' [content be king](/philosophy/#3-content-is-king) will remain a top +priority. In just the last few weeks as the transition has been occurring, +we have seen some incredible work on performance that will make future +versions of Jekyll work better at scale. She will be prioritizing work on +innovative improvements to make Jekyll that much better for all of us. +Olivia balances an eye for quality with the need for shipping well. + +When Tom Preston-Werner met me at GitHub HQ 2.0 in January 2013 to pass on +the torch, I could never have dreamed of all the amazing experiences this +community would share with me over the next 5 years. From visiting @qrush +in Buffalo, NY for a hack night on Jekyll to attending a Jekyll planning +session hosted by @benbalter at GitHub to Google Summer of Code which gave +us jekyll-admin, I am eternally grateful to all of you for the opportunity +to lead this excellent community. I'm confident Olivia will continue to +lead Jekyll to even greater heights. + +As always, Happy Jekylling! + +Parker + +*Curious about who else runs this show? [Check out our excellent team.](/team/)* diff --git a/docs/_posts/2018-02-25-jekyll-3-7-3-released.markdown b/docs/_posts/2018-02-25-jekyll-3-7-3-released.markdown new file mode 100644 index 00000000000..d66afd634cf --- /dev/null +++ b/docs/_posts/2018-02-25-jekyll-3-7-3-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.7.3 Released' +date: 2018-02-25 13:02:08 +0530 +author: ashmaroli +version: 3.7.3 +category: release +--- + +Hello Jekyllers!! :wave: + +We're pleased to announce the release of `v3.7.3` which fixes a bug one might encounter while using `Jekyll - 3.7.x` along with a +Jekyll plugin that in turn uses the `I18n` library. + +When [v3.7.0]({% link _posts/2018-01-02-jekyll-3-7-0-released.md %}) enhanced our `slugify` filter with a `latin` option, we also +hardcoded a default fallback locale for the `I18n` library to avoid an exception raised in the event the library fails to find +any locale. This led to issues with third-party i18n plugins for Jekyll, especially since the default locale got assigned before +the plugin was loaded, irrespective of whether the `slugify` filter was used. + +Jekyll will henceforth set the default locale if and only if necessary. diff --git a/docs/_posts/2018-03-14-development-update.md b/docs/_posts/2018-03-14-development-update.md new file mode 100644 index 00000000000..f0eb1c5724f --- /dev/null +++ b/docs/_posts/2018-03-14-development-update.md @@ -0,0 +1,28 @@ +--- +title: "Jekyll 4.0 is on the Horizon!" +date: "2018-04-19 16:07:00 +0100" +author: oe +categories: [community] +--- + +With the release of Jekyll 3.8.0, it's been 2 and a half years since the last major release. Jekyll 3.0.0 was released in late October of 2015! That's a long time ago, and we've been working towards the next major release of Jekyll for a couple of months now. Here's a small preview of what's to come: + +- Dropping support for Ruby 2.1 and 2.2. Both versions have reached their EOL period. +- Dropping Pygments as a dependency. We're already defaulting to Rouge, and this removes the implicit Python dependency. (finally!) +- Making the `link` tag use relative URLs. This is a big breaking change, but it's the cleaner solution. + +We're open to more ideas, though. If the development cost isn't too high, or if someone volunteers to take care of the implementation, it's likely that your suggestion might make it into Jekyll 4.0. Head over to this [issue] for more details. Some interesting topics might be improving Internationalization support in Jekyll, creating convenience Liquid tags, et cetera. + +That being said, the development period of version 4.0 begins _now_. This means a couple of things: + +- New features will only be implemented in Jekyll 4.0. There will be no 3.9.0 or the like. +- Same with bug fixes, unless they concern something introduced in Jekyll 3.7 or 3.8, in which case we will backport the fixes and release a patch version. +- Now is a great time to finally take on the feature you've wanted to see in Jekyll for ages! Just open an issue or experiment with the code to get going! + +As for a release date, we're currently aiming for late summer, around September or so. However, keep in mind that this project is purely volunteer-run, and as such, delays might occur and we might not hit that release date. + +Finally, this is a great time for newcomers to open-source to make their first contribution. We'll be doing our best to mark recommended contributions and create newcomer-friendly issues, as well as to provide mentoring throughout the contribution process (although we'd like to think that we're already pretty proficient at that). So if you've always been hesitant about contributing to a large open-source project, Jekyll is a good place to start! + +Happy Jekylling! :wave: + +[issue]: https://github.com/jekyll/jekyll/issues/6948 diff --git a/docs/_posts/2018-03-15-jekyll-3-8-0-released.markdown b/docs/_posts/2018-03-15-jekyll-3-8-0-released.markdown new file mode 100644 index 00000000000..14e2d61a283 --- /dev/null +++ b/docs/_posts/2018-03-15-jekyll-3-8-0-released.markdown @@ -0,0 +1,43 @@ +--- +title: 'Jekyll 3.8.0 Released' +date: 2018-04-19 19:45:15 +0530 +author: ashmaroli +version: 3.8.0 +category: release +--- + +Aloha Jekyllers!! :wave: + +After months of toiling on the codebase and shipping a couple of release-candidates, the Jekyll Team is delighted to finally +present `v3.8.0`, packed with optimizations, improvements, some new features and a couple of bug-fixes. Yay!!! + +Under the hood, Jekyll has undergone many minor changes that will allow it to run more performantly in the coming years. :smiley: +Rest assured, our users should see minor improvements in their site's build times. + +Speaking of improvements, users running a site containing a huge amount of posts or those who like to use our `where` filter +frequently in a single template, are going to see a massive reduction in their total build times!! :tada: + +Hold on, this version is not just about optimizations, there are some new features as well..: + * Detect non-existent variables and filters specified in a template by enabling `strict_variables` and `strict_filters` under the + `liquid` key in your config file. + * Allow *date filters* to output ordinal days. + * `jekyll doctor` now warns you if you have opted for custom `collections_dir` but placed `_posts` directory outside that + directory. + +..and yes, a couple of bug-fixes, notably: + * Jekyll now handles future-dated documents properly. + * Jekyll is able to handle Liquid blocks intelligently in excerpts. + * A few methods that were *not meant to be publically accessible* have been entombed properly. + * A few bugs that still plagued our `collections_dir` feature from `v3.7` got crushed. + +As always, the full list of changes since last release can be viewed [here](/docs/history/#v3-8-0). + +A big thanks to the following people who contributed to our repository with pull-requests that improved our codebase, documentation +and tests: + +Ana María Martínez Gómez, Antonio Argote, Ashwin Maroli, Awjin Ahn, Ben Balter, Benjamin Høegh, Christian Oliff, Damien Solodow, +David Zhang, Delson Lima, Eric Cornelissen, Florian Thomas, Frank Taillandier, Heinrich Hartmann, Jakob Vad Nielsen, John Eismeier, +Kacper Duras, KajMagnus, Mario Cekic, Max Vilimpoc, Michael H, Mike Kasberg, Parker Moore, Pat Hawks, Paweł Kuna, Robert Riemann, +Roger Rohrbach, Semen Zhydenko, Stefan Dellmuth, Tim Carry, olivia, and steelman. + +Happy Jekylling!! :sparkles: diff --git a/docs/_posts/2018-05-01-jekyll-3-8-1-released.markdown b/docs/_posts/2018-05-01-jekyll-3-8-1-released.markdown new file mode 100644 index 00000000000..cb8c7a5b971 --- /dev/null +++ b/docs/_posts/2018-05-01-jekyll-3-8-1-released.markdown @@ -0,0 +1,20 @@ +--- +title: 'Jekyll 3.8.1 Released' +date: 2018-05-01 11:56:01 -0500 +author: pathawks +version: 3.8.1 +category: release +--- + +Happy May Day :tada: + +The Jekyll team is happy to announce the release of `v3.8.1`, which fixes +a couple of bugs that were introduced two weeks ago in `v3.8.0`. If you have +experienced trouble regarding post excerpts or non-published posts, this release +should be the remedy. Thanks to @Chaosed0 and @domLocalHeroes for originally +reporting these issues, and to @ashmaroli for fixing them so quickly. + +As a reminder, we have started work on Jekyll 4.0. If there are any +features that you would love to see added to Jekyll, or any pain points you +would like to see removed, please do add your ideas to the [Jekyll 4.0 idea +list](https://github.com/jekyll/jekyll/issues/6948). diff --git a/docs/_posts/2018-05-18-jekyll-3-8-2-released.markdown b/docs/_posts/2018-05-18-jekyll-3-8-2-released.markdown new file mode 100644 index 00000000000..d54a9820824 --- /dev/null +++ b/docs/_posts/2018-05-18-jekyll-3-8-2-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.8.2 Released' +date: 2018-05-19 10:30:00 -0500 +author: pathawks +version: 3.8.2 +category: release +--- + +Hello Jekyllers!! + +Today we are releasing `v3.8.2`, which fixes the way Jekyll generates excerpts +for posts when the first paragraph of the post contains Liquid tags that take +advantage of [Liquid's whitespace control feature][Liquid whitespace]. + +Big thanks to @kylebarbour, who first reported this issue and also very quickly +submitted a fix. Also thanks to @nickskalkin for making sure that we are using +the latest version of Rubocop to lint our code. + +[Liquid whitespace]: https://shopify.github.io/liquid/basics/whitespace/ diff --git a/docs/_posts/2018-06-04-jekyll-3-8-3-released.markdown b/docs/_posts/2018-06-04-jekyll-3-8-3-released.markdown new file mode 100644 index 00000000000..a2a7056ced1 --- /dev/null +++ b/docs/_posts/2018-06-04-jekyll-3-8-3-released.markdown @@ -0,0 +1,13 @@ +--- +title: 'Jekyll 3.8.3 Released' +date: 2018-06-05 09:00:00 -0500 +author: pathawks +version: 3.8.3 +category: release +--- + +This release fixes a regression in 3.8 where collections with `published: false` +do not show when using the `--unpublished` flag. + +Thanks to @philipbelesky for reporting and fixing this issue; collections with +`published: false` now behave the same way as Posts. diff --git a/docs/_posts/2018-08-01-jekyll-sponsoring.markdown b/docs/_posts/2018-08-01-jekyll-sponsoring.markdown new file mode 100644 index 00000000000..1f223df61e4 --- /dev/null +++ b/docs/_posts/2018-08-01-jekyll-sponsoring.markdown @@ -0,0 +1,78 @@ +--- +title: "Sponsoring Jekyll's development" +date: 2018-08-01 15:00:00 +0200 +author: oe +categories: [community] +--- + +_(TL;DR: We're open for sponsorships on our [OpenCollective page](https://opencollective.com/jekyll))_ + +Hi Jekyllers, + +As you may know, Jekyll is a completely free and open source project. We offer +our software and its related plugins and documentation at no cost because we +believe that good software should not cost anything. We're not planning on +changing that, but today I want to talk about a different monetary aspect of +open source. + +Open source developers being paid for the work they do is a rare sight. Most +open source software is effectively the result of hundreds and thousands of +hours of free labor provided by individuals who are passionate enough to work +outside of their day job to create software that, ironically, is being used by +almost every company that offers digital services. It's a problem that has +gotten more attention in recent years, with the open source community becoming +more diverse and more and more companies actively investing in providing +monetary support for open source developers. + +Jekyll has always been a product of volunteers. Rarely has someone been paid to +implement a certain plugin or feature. Today, we're excited to announce that we +will finally be able to fund our contributors! __We are opening an +OpenCollective to receive individual and corporate sponsorships__. +This is not unheard of, [Hugo](http://gohugo.io) is also funded by sponsorships, +as are many other similar projects, such as +[webpack](https://opencollective.com/webpack), +[Babel](https://opencollective.com/babel) or +[RuboCop](https://opencollective.com/rubocop). + +OpenCollective is a service that makes it easy for open source projects to +receive funding from individuals and companies alike. It's specifically designed +for open source and many other projects already use it for funding. + +Sponsoring is, for us, a method to finally realize some of the more ambitious +goals we've had with the project for years. The closest thing we want to realize +is to __release Jekyll 4.0, and to make it as polished as we can__. In the +future, we would also like to work on other things that will improve the Jekyll +ecosystem. Here's a couple of ideas: + +- Create a comprehensive official plugin and theme directory site +- Improve tooling built around measuring and improving Jekyll's performance +- Improve maintenance for official plugins +- Including the community into official decisions; making Jekyll more friendly to folks in the community + +Again, these are just some ideas, but with the help of sponsoring, they are now +one step closer to being realized :heart: + +
+ Forestry +
+ +With that, we would like to announce our very first sponsor: +[__Forestry.io__](https://forestry.io)! +Forestry is a CMS that integrates with your Jekyll sites and lets you update +content using a beautiful interface, and then automatically commits it back to +your GitHub repository. We're excited to have them on board on a new, exciting +step of our journey. + +Will anything change for Jekyll users? The answer is no - this step does not +impact the Jekyll software in any aspect. In fact, you might see positive +changes, such as more features and better performance. Surprisingly, that's what +happens when you properly fund people for their work! + +If you have been a long time user for Jekyll and would like to give something +back to the project, you can consider a small monthly donation to our +[OpenCollective page](http://opencollective.com/jekyll). If your company heavily +relies on Jekyll, do consider sponsoring us! + +Contact [matt@jekyllrb.com](mailto:matt@jekyllrb.com) and we'll figure something out together. + +Thanks for sticking with us, and happy Jekylling! :tada: diff --git a/docs/_posts/2018-09-19-security-fixes-for-3-6-3-7-3-8.markdown b/docs/_posts/2018-09-19-security-fixes-for-3-6-3-7-3-8.markdown new file mode 100644 index 00000000000..9f92e803f86 --- /dev/null +++ b/docs/_posts/2018-09-19-security-fixes-for-3-6-3-7-3-8.markdown @@ -0,0 +1,26 @@ +--- +title: "Security Fixes for series 3.6, 3.7 and 3.8" +date: 2018-09-19 18:00:00 +0530 +author: ashmaroli +category: release +version: 3.8.4 +--- + +Hi Jekyllers, + +We have patched a **critical vulnerability** reported to GitHub a couple of weeks ago and have released a set of new gems to +bring that patch to you. The vulnerability allowed arbitrary file reads with the cunning use of the `include:` setting in the +config file. + +By simply including a symlink in the `include` array allowed the symlinked file to be read into the build when they shouldn't +actually be read in any circumstance.   +Further details regarding the patch can be viewed at the [pull request URL]({{ site.repository }}/pull/7224) + +The patch has been released as versions `3.6.3`, `3.7.4` and `3.8.4`.   +Thanks to @parkr `v3.7.4` was released a couple of weeks prior and has been bundled with `github-pages-v192`. + + +Please keep in mind that this issue affects _all previously released Jekyll versions_. If you have not had +a good reason to upgrade to `3.6`, `3.7` or `3.8` yet, we advise that you do so at the earliest. + +As always, Happy Jekylling! :sparkles: diff --git a/docs/_posts/2018-11-04-jekyll-3-8-5-released.markdown b/docs/_posts/2018-11-04-jekyll-3-8-5-released.markdown new file mode 100644 index 00000000000..c854051e2e0 --- /dev/null +++ b/docs/_posts/2018-11-04-jekyll-3-8-5-released.markdown @@ -0,0 +1,16 @@ +--- +title: 'Jekyll 3.8.5 Released' +date: 2018-11-04 20:58:20 +0100 +author: oe +version: 3.8.5 +category: release +--- + +This release fixes a bug where multiple Liquid tags were not supported in +excerpts. + +Thanks to @ashmaroli for fixing this issue in [#7250]. + +Happy Jekylling! + +[#7250]: https://github.com/jekyll/jekyll/pull/7250 diff --git a/docs/_posts/2019-03-18-jekyll-4-0-0-pre-alpha1-released.markdown b/docs/_posts/2019-03-18-jekyll-4-0-0-pre-alpha1-released.markdown new file mode 100644 index 00000000000..ffa900aa74c --- /dev/null +++ b/docs/_posts/2019-03-18-jekyll-4-0-0-pre-alpha1-released.markdown @@ -0,0 +1,42 @@ +--- +title: Jekyll 4.0.0.pre.alpha1 Released +date: 2019-03-18 18:17:31 +0100 +author: dirtyf +version: 4.0.0.pre.alpha1 +category: release +--- + +Dear Jekyllers, + +Time has come to release a first alpha for Jekyll 4! + +This pre version fixes many bugs, and should improve your build times. Some of you already shared [really](https://forestry.io/blog/how-i-reduced-my-jekyll-build-time-by-61/) [good](https://boris.schapira.dev/2018/11/jekyll-build-optimization/) results. We hope your Jekyll sites will also benefit from these optimizations. + +If you're a plugin developer, we definitely need your feedback, especially if your plugin does not work with v4. + +Jekyll now exposes a [caching API](/tutorials/cache-api/), that some plugins could benefit from. + +Also be aware that it's a new *major* version, and it comes with a few breaking changes, notably : + +1. We dropped support for [Ruby 2.3 who goes EOL at the end of the month](https://www.ruby-lang.org/en/downloads/). + GitHub Pages runs Ruby 2.5.x, services like Netlify or Forestry already upgraded to latest Ruby 2.6.x. +2. `link` tag now include `relative_url` filter, hurray [no more need to prepend `{% raw %}{{ site.baseurl }}{% endraw %}` ](https://github.com/jekyll/jekyll/pull/6727). +3. [`{% raw %}{% highlight %}{% endraw %}` now behaves like `{% raw %}{% raw %}{% endraw %}`](https://github.com/jekyll/jekyll/pull/6821), so you can no longer use `include` tags within. +4. We dropped support for Pygments, RedCarpet and rdiscount. +5. We bumped kramdown to v2. + +Checkout the complete [changelog](https://github.com/jekyll/jekyll/releases/tag/v4.0.0.pre.alpha1) for more details. + +To test this pre version run: + +```sh +gem install jekyll --pre +``` + +Please test this version thoroughly and file bugs as you encounter them. + +Thanks to our dear contributors for helping making Jekyll better: + +Aidan Fitzgerald, Akshat Kedia, Alex Wood, Alexey Kopytko, Alexey Pelykh, Ali Thompson, Ana María Martínez Gómez, Ananthakumar, Andreas Möller, Andrew Lyndem, Andy Alt, Anne Gentle, Anny, Arjun Thakur, Arthur Attwell, Ashwin Maroli, Behrang, Belhassen Chelbi, Ben Keith, Ben Otte, Bilawal Hameed, Boris Schapira, Boris van Hoytema, Brett C, Chris Finazzo, Christian Oliff, Damien Solodow, Dan Allen, Dan Friedman, Daniel Höpfl, David J. Malan, Denis McDonald, Derek Smart, Derpy, Dusty Candland, ExE Boss, Frank Taillandier, Gareth Cooper, Grzegorz Kaczorek, Isaac Goodman, Jacob Byers, Jakob Krigovsky, Jan Pobořil, Joe Shannon, Jordan Morgan, Jorie Tappa, Josue Caraballo, Justin Vallelonga, Jörg Steinsträter, Karel Bílek, Keith Mifsud, Kelly-Ann Green, Ken Salomon, Kevin Plattret, Kyle Barbour, Lars Kanis, Leandro Facchinetti, Luis Enrique Perez Alvarez, Luis Guillermo Yáñez, Ma HongJun, Manu Mathew, Mario, Martin Scharm, Matt Massicotte, Matthew Rathbone, Maxwell Gerber, Mertcan Yücel, Michael Hiiva, Mike Kasberg, Mike Neumegen, Monica Powell, Nicolas Hoizey, Nikhil Swaminathan, Nikita Skalkin, Olivia Hugger, Parker Moore, Pat Hawks, Patrick Favre-Bulle, Paul Kim, Philip Belesky, Preston Lim, Ralph, Robert Riemann, Rosário Pereira Fernandes, Samuel Gruetter, Scott Killen, Sri Pravan Paturi, Stephan Fischer, Stephen Weiss, Steven Westmoreland, Sundaram Kalyan Vedala, Thanos Kolovos, Timo Schuhmacher, Tobias, Tom Harvey, Tushar Prajapati, Victor Afanasev, Vitor Oliveira, Wouter Schoot, XhmikosR, Zhang Xiangze, _94gsc, argv-minus-one, chrisfinazzo, ikeji, jess, jpasholk, makmm, mo khan, ninevra, penguinpet, 김정환, 104fps + +Happy Jekylling everyone! diff --git a/docs/_posts/2019-07-02-jekyll-3-8-6-released.markdown b/docs/_posts/2019-07-02-jekyll-3-8-6-released.markdown new file mode 100644 index 00000000000..f05cd7cd981 --- /dev/null +++ b/docs/_posts/2019-07-02-jekyll-3-8-6-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.8.6 Released' +date: 2019-07-02 11:21:02 -0400 +author: parkr +version: 3.8.6 +categories: [release] +--- + +We have another patch release in the 3.8 series! This time, we have one security patch +and a handful of bug patches, including: + +- Filter symlinks from theme gems +- Fix excerpt handling of some Liquid tags +- Handle case where a theme directory doesn't exist +- A few internal optimizations to reduce memory overhead + +... and a few more! You can check out the patches and see all the details in [the release notes](/docs/history/#v3-8-6) + +Happy Jekylling! diff --git a/docs/_posts/2019-08-04-jekyll-4-0-0-pre-beta1-released.markdown b/docs/_posts/2019-08-04-jekyll-4-0-0-pre-beta1-released.markdown new file mode 100644 index 00000000000..64f16975b13 --- /dev/null +++ b/docs/_posts/2019-08-04-jekyll-4-0-0-pre-beta1-released.markdown @@ -0,0 +1,41 @@ +--- +title: Jekyll 4.0.0.pre.beta1 Released +date: 2019-08-04 10:43:31 -0500 +author: mattr- +version: 4.0.0.pre.beta1 +categories: [release] +redirect_from: /news/2019/07/20/jekyll-4-0-0-pre-beta1-released/ +--- + +Dear Jekyllers, + +It's time for another pre-release of Jekyll 4! 🎉 + +This pre-release moves us further down the path of releasing Jekyll 4.0.0. All the same goodies [from the last pre-release](/news/2019/03/18/jekyll-4-0-0-pre-alpha1-released/) are here, along with a few more things I want to highlight: + +Jekyll 4.0 is a new *major* version and it comes with a few breaking changes, notably : + +1. We dropped support for [Ruby 2.3 which EOL at the end of March 2019](https://www.ruby-lang.org/en/downloads/). + GitHub Pages runs Ruby 2.5.x, services like Netlify or Forestry already upgraded to latest Ruby 2.6.x. +2. `link` tag now include `relative_url` filter, hurray [no more need to prepend `{% raw %}{{ site.baseurl }}{% endraw %}` ](https://github.com/jekyll/jekyll/pull/6727). +3. [`{% raw %}{% highlight %}{% endraw %}` now behaves like `{% raw %}{% raw %}{% endraw %}`](https://github.com/jekyll/jekyll/pull/6821), so you can no longer use `include` tags within. +4. We dropped support for Pygments, RedCarpet and rdiscount. +5. We bumped kramdown to v2. + +If you're a plugin developer, we still need your feedback! Your plugin may not work with version 4 and we'd like to fix those issues before we release. + +Checkout the complete [changelog](https://github.com/jekyll/jekyll/releases/tag/v4.0.0.pre.beta1) for more details. + +To test this pre version run: + +```sh +gem install jekyll --pre +``` + +Please test this version thoroughly and file bugs as you encounter them. + +Thanks to our dear contributors for helping making Jekyll better: + +Aidan Fitzgerald, Akshat Kedia, Alex Wood, Alexey Kopytko, Alexey Pelykh, Ali Thompson, Ana María Martínez Gómez, Ananthakumar, Andreas Möller, Andrew Lyndem, Andy Alt, Anne Gentle, Anny, Arjun Thakur, Arthur Attwell, Ashwin Maroli, Behrang, Belhassen Chelbi, Ben Keith, Ben Otte, Bilawal Hameed, Boris Schapira, Boris van Hoytema, Brett C, Chris Finazzo, Christian Oliff, Damien Solodow, Dan Allen, Dan Friedman, Daniel Höpfl, David J. Malan, Denis McDonald, Derek Smart, Derpy, Dusty Candland, ExE Boss, Frank Taillandier, Gareth Cooper, Grzegorz Kaczorek, Isaac Goodman, Jacob Byers, Jakob Krigovsky, Jan Pobořil, Joe Shannon, Jordan Morgan, Jorie Tappa, Josue Caraballo, Justin Vallelonga, Jörg Steinsträter, Karel Bílek, Keith Mifsud, Kelly-Ann Green, Ken Salomon, Kevin Plattret, Kyle Barbour, Lars Kanis, Leandro Facchinetti, Luis Enrique Perez Alvarez, Luis Guillermo Yáñez, Ma HongJun, Manu Mathew, Mario, Martin Scharm, Matt Massicotte, Matthew Rathbone, Maxwell Gerber, Mertcan Yücel, Michael Hiiva, Mike Kasberg, Mike Neumegen, Monica Powell, Nicolas Hoizey, Nikhil Swaminathan, Nikita Skalkin, Olivia Hugger, Parker Moore, Pat Hawks, Patrick Favre-Bulle, Paul Kim, Philip Belesky, Preston Lim, Ralph, Robert Riemann, Rosário Pereira Fernandes, Samuel Gruetter, Scott Killen, Sri Pravan Paturi, Stephan Fischer, Stephen Weiss, Steven Westmoreland, Sundaram Kalyan Vedala, Thanos Kolovos, Timo Schuhmacher, Tobias, Tom Harvey, Tushar Prajapati, Victor Afanasev, Vitor Oliveira, Wouter Schoot, XhmikosR, Zhang Xiangze, _94gsc, argv-minus-one, chrisfinazzo, ikeji, jess, jpasholk, makmm, mo khan, ninevra, penguinpet, 김정환, 104fps + +Happy Jekylling everyone! diff --git a/docs/_posts/2019-08-19-jekyll-4-0-0-released.markdown b/docs/_posts/2019-08-19-jekyll-4-0-0-released.markdown new file mode 100644 index 00000000000..fe3a84ee012 --- /dev/null +++ b/docs/_posts/2019-08-19-jekyll-4-0-0-released.markdown @@ -0,0 +1,139 @@ +--- +title: 'Jekyll 4.0.0 Released' +date: 2019-08-20 10:00:00 -0500 +author: mattr- +version: 4.0.0 +category: release +--- + +Hi! 👋 I bring some good news! Jekyll 4.0.0 is finally here! 🎉 + +There's quite a bit in this release to unpack, so let me hit the high points quickly: + - Ruby 2.4.0 or greater is now required. + - Rouge 3.0 or greater is now required for syntax highlighting. + - Jekyll builds should be much faster. + - Kramdown 2.1 is now the default markdown engine. + - Sass processing should be faster. + - We dropped support for a lot of stuff, specifically: + - Pygments + - RedCarpet + - RDiscount + + +Alright, so with the high points out of the way, let's get into the details a little bit. + +### Cache all the things! 💰 + +While some optimizations first made an appearance with Jekyll 3.8.0, Jekyll 4.0 takes +it to another level altogether. + +Jekyll 4.0 caches the processing done by Liquid in memory. So every Liquid +template is processed only as required. If you have 10 pages depending on a +single layout, the layout is cached and that data is then rendered as per the +10 different contexts of the individual files. + +There's also a disk cache! Jekyll can now cache data to disk to avoid repeated +processing of content that doesn't change between build sessions. Currently, +this is limited to markdown. So while the very first build will take a certain +amount of time, consequent builds for content that hasn't changed will take +much less time due to the disk-cache. Disk caching is disabled for `safe` mode, +however. + +### Super-powered content transformations 💪 + +We've upgraded Sass support so it should be faster. There's also +support for sourcemaps now! Under the hood, our Sass support uses the `SassC` +library now, which is supported directly by the Sass team, which should mean +better support for everybody in the long run. + +Kramdown is updated to version 2.1. This also brings with it a bunch of changes +to the Kramdown configuration, as the Kramdown team have extracted a fair +number of features into separate gems. Support for GitHub Flavored Markdown is +enabled by default, but if you're using another Kramdown extension in your +site, you'll likely need to update your plugin configuration. See the [upgrade +guide](/docs/upgrading/3-to-4/) for more details. + +The `link` and `post_url` tags no longer need `site.baseurl` prepended every +time they're used. Those tags now use our `relative_url` filter to take care of +this for you. Existing uses of the prepending pattern will break though! +Sorry! :sweat_smile: + +A few other smaller features when it comes to content: + - The `link` tag understands Liquid variables in the same fashion our + `include` tag does now. + - Disable Liquid processing for a particular page / document by adding + `render_with_liquid: false` to its front matter. + - Liquid's binary `and` and `or` operations can be used in the `where_exp` + filter for more powerful filtering + +There's some goodies for theme community as well. Developers may now bundle a +`config.yml` into their theme-gem to provide some boilerplate configurations for +the theme. Like other resources in the theme, these configuration values can also +be customized at the user's end. + + +Check out the [full history](/docs/history/#v4-0-0) and the various pull requests +for more details on all the enhancements and bug-fixes. + +### Upgrading 📈 + +First, read the [upgrade guide](/docs/upgrading/3-to-4/)! + +Next, Edit your project's `Gemfile` to test Jekyll v4.x: + +```ruby +gem 'jekyll', '~> 4.0' +``` + +Then run `bundle update` to update all dependencies. Unless you're using +third-party plugins that haven't yet added support for Jekyll 4.0, you should be +good to go. + +Plugins and themes authors must relax the jekyll dependency in their `gemspec` file +to allow for Jekyll v4.0: + +`spec.add_runtime_dependency "jekyll", ">= 3.6", "< 5.0"` + +If your favorite plugin hasn't relaxed that dependency yet, please gently +encourage them to do so. :slightly_smiling_face: + +### Have questions❓ + +Please reach out on our [community forum](https://talk.jekyllrb.com) + + +### Thank you!! 🙇 + +Jekyll would not be possible without the many people who have taken the time to write issues, submit pull requests, create themes, answer questions for other users, or make their own sites using our project. Thanks to all of you who contribute, no matter how small you think your contribution might have been. + +In addition, special thanks to the 139 contributors who made this +release possible via a pull request submission (in alphabetical order): Aidan +Fitzgerald, Akshat Kedia, Ale Muñoz, Alex Wood, +Alexey Kopytko, Alexey Pelykh, Ali Thompson, Ana María Martínez Gómez, +Ananthakumar, Andreas Möller, Andrew Lyndem, Andrew Marcuse, Andy Alt, Anne +Gentle, Anny, Anuj Bhatnagar, argv-minus-one, Arjun Thakur, Arthur Attwell, +Ashwin Maroli, Behrang, Belhassen Chelbi, Ben Keith, Ben Otte, Bilawal Hameed, +Bjorn Krols, Boris Schapira, Boris van Hoytema, Brett C, Chris Finazzo, Chris +Oliver, chrisfinazzo, Christian Oliff, Christoph Päper, Damien Solodow, Dan +Allen, Dan Friedman, Daniel Höpfl, David J. Malan, David Kennell, David Zhang, +Denis McDonald, Derek Smart, Derpy, Dusty Candland, Edgar Tinajero, Elvio +Vicosa, ExE Boss, Fons van der Plas, Frank Taillandier, Gareth Cooper, Grzegorz +Kaczorek, Haris Bjelic, Hodong Kim, ikeji, Isaac Goodman, Jacob Byers, Jakob +Krigovsky, James Rhea, Jan Pobořil, jess, jingze_lu, Joe Shannon, Jordan Morgan, +Jörg Steinsträter, Jorie Tappa, Josue Caraballo, jpasholk, Justin Vallelonga, +Karel Bílek, Keith Mifsud, Kelly-Ann Green, Ken Salomon, Kevin Plattret, krissy, +Kyle Barbour, Lars Kanis, Leandro Facchinetti, Liam Rosenfeld, Luis Enrique +Perez Alvarez, Luis Guillermo Yáñez, Ma HongJun, makmm, Manu Mathew, Mario, +Martin Scharm, Matt Kraai, Matt Massicotte, Matt Rogers, Matthew Rathbone, +Maxwell Gerber, Mertcan Yücel, Michael Bishop, Michael Hiiva, Michelle Greer, +Mike Kasberg, Mike Neumegen, mo khan, Monica Powell, Nicolas Hoizey, Nikhil +Benesch, Nikhil Swaminathan, Nikita Skalkin, Niklas Eicker, ninevra, Olivia +Hugger, Parker Moore, Pat Hawks, Patrick Favre-Bulle, Paul Kim, penguinpet, +Philip Belesky, Preston Lim, Ralph, Robert Riemann, Rosário Pereira Fernandes, +Sadik Kuzu, Samuel Gruetter, Scott Killen, Sri Pravan Paturi, Stephan Fischer, +Stephen Weiss, Steven Westmoreland, strangehill, Sundaram Kalyan Vedala, Thanos +Kolovos, Timo Schuhmacher, Tobias, Tom Harvey, Tushar Prajapati, Victor Afanasev, +Vinicius Flores, Vitor Oliveira, Wouter Schoot, XhmikosR, Yi Feng Xie, Zhang +Xiangze, 김정환, 104fps. + +Happy Jekylling everyone! diff --git a/docs/_posts/2020-05-08-jekyll-4-0-1-released.markdown b/docs/_posts/2020-05-08-jekyll-4-0-1-released.markdown new file mode 100644 index 00000000000..f0d56359e70 --- /dev/null +++ b/docs/_posts/2020-05-08-jekyll-4-0-1-released.markdown @@ -0,0 +1,23 @@ +--- +title: 'Jekyll 4.0.1 Released' +date: 2020-05-08 18:00:00 +0100 +author: dirtyf +version: 4.0.1 +category: release +--- + +Jekyll 4.0.1 is out and fixes a few issues reported by the community since 4.0. + +- When using Ruby 2.7, you won't get any more warnings in your console when running Jekyll. (This fix is also backported in [Jekyll 3.8.7](https://github.com/jekyll/jekyll/releases/tag/v3.8.7)). +- Liquid variables are now properly cached. +- Jekyll build will no longer fail for collections with a custom permalink containing static files. +- Jekyll filters now properly recognize integers. + +👀 A [release changelog](https://github.com/jekyll/jekyll/releases/tag/v4.0.1) is available for your perusal. + +🙏 Many thanks to our contributors without whom this release could not be +possible: @ashmaroli and [Ivan Gromov](https://github.com/summerisgone) + +Expect more fixes and improvements on the next minor release! + +Happy Jekylling! diff --git a/docs/_posts/2020-05-27-jekyll-4-1-0-released.markdown b/docs/_posts/2020-05-27-jekyll-4-1-0-released.markdown new file mode 100644 index 00000000000..28b2dead320 --- /dev/null +++ b/docs/_posts/2020-05-27-jekyll-4-1-0-released.markdown @@ -0,0 +1,74 @@ +--- +title: 'Jekyll 4.1.0 Released' +date: 2020-05-27 15:20:30 +0530 +author: ashmaroli +version: 4.1.0 +category: release + +filters_linked_to: +- where expression +- find expression +- find +- number of words +--- + +Hello Jekyllers! + +It's time for yet another release that includes enhancements, optimizations and bug-fixes. Highlights of this release +are: + +* Jekyll now supports rendering excerpts for *pages* in addition to documents and posts. +* The [`where_exp`][where-expression-filter] filter got enhanced. Earlier, one could just use either `and` or `or` once +per expression. Now, one may use those binary operators multiple times in the filter's expression. +* Jekyll has a new set of filters based on *its flavor* of the `where` and `where_exp` filters. Named +[`find`][find-filter] and [`find_exp`][find-expression-filter] filters respectively, they work similar to their ancestors +except that they return **the first object** that satisfies the given conditions. +* Jekyll's [`number_of_words`][number-of-words-filter] filter can now take an optional argument to better count words +of text containing Chinese, Japanese or Korean characters. +* One may now use `:slugified_categories` in their permalink configurations to generate a more apt URL (categories are +downcased and non-alphanumeric characters replaced by dashes) for their for posts and documents. +* The logic for *slugifying* a given string has been enhanced to support more Unicode characters. +* If you face issues from Jekyll importing a config file bundled within a theme, you can now disable the import entirely +by setting `ignore_theme_config: true` in your site's configuration file. +* If you face issues from Jekyll's disk-caching feature, you can now disable the mechanism without opting to build in +`safe` mode, by either setting `disable_disk_cache: true` in your configuration file or by passing the CLI switch +`--disable-disk-cache` to `jekyll build` or `jekyll serve` commands. +* When you build a site with the `--profile` switch, Jekyll will now additionally output a small table showing the amount +of time taken during various stages of the *build process*. +* Jekyll's development server now supports certificates based on Elliptic-curve cryptography. + +For the interest of plugin authors: +* Excerpts won't be generated for `Jekyll::Page` subclasses automatically unless such instances have an `excerpt` key in +their `data` hash. + +For the interest of gem-based theme authors: +* From `v4.1.0` onwards, a newly generated theme workspace (via `jekyll new-theme ...`) will have the gemspec configured +to bundle a `_config.yml` at the root of the workspace. If you don't wish to include the configuration file in the +released gem, please remove `|_config\.yml` from the regular expression in the gemspec. + +{% for filter in page.filters_linked_to %} +{% assign filter_slug = filter | slugify %} +[{{ filter_slug }}-filter]: {{ filter_slug | prepend: '/docs/liquid/filters/#' | relative_url }} +{% endfor %} + +### Have questions? + +Please reach out on our [community forum](https://talk.jekyllrb.com) + + +### Thank you!! :bow: + +We are thankful to our community for all the contributions that helped shape this release. +Special thanks to the following 78 contributors (in alphabetical order) who made this release possible and took the time +to submit a pull request: + +Aaron Adams, Aaron K Redshaw, Alexandre Zanni, Anindita Basu, Arthur Zey, Artyom Tokachev, Ashwin Maroli, Atlas Cove, +Ben Stolovitz, Billy Kong, Christian Oliff, codenitpicker, csquare, Damien St Pierre, Daniel Leidert, David Zhang, +ddocs, dgolant, dkalev, Dmitry Egorov, dotnetCarpenter, Edward Thomson, Eric Knibbe, Frank Taillandier, Gabriel Rubens, +Gareth Mcshane, Grzegorz Kaczorek, guanicoe, Harry Wood, HTeuMeuLeu, iBug, İsmail Arılık, Itay Shakury, Ivan Gromov, +Ivan Raszl, J·Y, James Buckley, Jason Taylor, JC, jeffreytse, Johan Wigert, jonas-krummenacher, Justin Jia, +Kayce Basques, Kieran Barker, Leo, Liam Bigelow, lizharris, Lizzy Kate, Luis Puente, Mark Bennett, Matt Penna, +Matt Rogers, matt swanson, Max Chadwick, michaelcurrin, Mike Kasberg, Mike Neumegen, Muhammed Salih, Nikhil Benesch, +Paramdeo Singh, Patrik Eriksson, Phil Nash, Philip Eriksson, R.P. Pedraza, Radoslav Karlík, Riccardo Porreca, +sharath Kumar, Simone Arpe, Takashi Udagawa, Tobias Klüpfel, Toby Glei, vhermecz, Viktor Szakats, Ward Sandler, wzy, +XhmikosR, Zlatan Vasović. diff --git a/docs/_posts/2020-06-24-jekyll-4-1-1-released.markdown b/docs/_posts/2020-06-24-jekyll-4-1-1-released.markdown new file mode 100644 index 00000000000..599578ece02 --- /dev/null +++ b/docs/_posts/2020-06-24-jekyll-4-1-1-released.markdown @@ -0,0 +1,38 @@ +--- +title: 'Jekyll 4.1.1 Released' +date: 2020-06-24 16:45:35 +0530 +author: ashmaroli +version: 4.1.1 +category: release +--- + +Jekyll 4.1.0 brought two notable changes: *Page-excerpts* and *Liquid Drop for Page objects*. +However these seemingly benign changes had unexpected adverse side-effects which did not figure in our tests. + +The Core team decided that the best way forward is to revert introduction of the Liquid drop for Pages but push back +generating excerpts for pages behind a flag until `v5.0`. + +Page-excerpts are henceforth an opt-in experimental feature which can be enabled by setting `page_excerpts: true` in +your configuration file. Due to its experimental nature, we have narrowed the scope for page-excerpts to limit their +negative effect on builds. Excerpts will not be generated for pages that *do not* output into an HTML file even if +`page_excerpts: true` has been set in the configuration file. + +Another known issue with page-excerpts is that an infinite loop is created in certain use-cases such as any construct +that involves iterating through `site.pages` directly within a `Jekyll::Page` instance. A couple of examples would be +having a variant of either of the following code blocks inside a page source, say `index.markdown` or `about.markdown`: + +{% raw %} + +```liquid +{% for entry in site.pages %} + {{ entry.name }} +{% endfor %} +``` + +```liquid +{{ site.pages | sort: 'title' }} +``` + +{% endraw %} + +Therefore, we advise caution when opting to use the page-excerpt feature. diff --git a/docs/_posts/2020-08-05-jekyll-3-9-0-released.markdown b/docs/_posts/2020-08-05-jekyll-3-9-0-released.markdown new file mode 100644 index 00000000000..f2e79e3cad2 --- /dev/null +++ b/docs/_posts/2020-08-05-jekyll-3-9-0-released.markdown @@ -0,0 +1,28 @@ +--- +title: 'Jekyll 3.9.0 Released' +author: parkr +version: 3.9.0 +categories: [release] +--- + +Jekyll 3.9.0 allows use of kramdown v2, the latest series of kramdown. + +If you choose to upgrade, please note that the GitHub-Flavored Markdown +parser and other features of kramdown v1 are now distributed via +separate gems. If you would like to continue using these features, you will +need to add the gems to your `Gemfile`. They are as follows: + +- GFM parser – `kramdown-parser-gfm` +- coderay syntax highlighter – `kramdown-syntax-coderay` +- mathjaxnode math engine – `kramdown-math-mathjaxnode` +- sskatex math engine – `kramdown-math-sskatex` +- katex math engine – `kramdown-math-katex` +- ritex math engine – `kramdown-math-ritex` +- itex2mml math engine – `kramdown-math-itex2mml` + +Jekyll will require the given gem when the configuration requires it, and +will show a helpful message when a dependency is missing. + +You can check out the patches and see all the details in [the release notes](/docs/history/#v3-9-0) + +Happy Jekylling! diff --git a/docs/_posts/2020-12-14-jekyll-4-2-0-released.markdown b/docs/_posts/2020-12-14-jekyll-4-2-0-released.markdown new file mode 100644 index 00000000000..b77ccbf4f81 --- /dev/null +++ b/docs/_posts/2020-12-14-jekyll-4-2-0-released.markdown @@ -0,0 +1,31 @@ +--- +title: "Jekyll 4.2.0 Released" +date: 2020-12-14 14:12:20 +0530 +author: ashmaroli +version: 4.2.0 +category: release +--- + +Greetings Jekyllers! Jekyll v4.2.0 is out! + +This release gives you a new hook named `:post_convert` that allows modifying rendered HTML contents before they are +placed into the designated layout(s). + +Detecting files that get written into the same destination path has been a part of the diagnostics from `jekyll doctor` +for quite some time now. However, v4.2 has integrated that feature into the build process itself. + +On the topic of log output, the `--verbose` output got a bit more verbose. Instead of just showing *documents* that are +being read, the output will now also show *pages* and *layouts* that are being read into the site. + +Additionally, we have stopped overriding the `site.url` to `http://localhost:4000` in absolute URLs while developing +via `jekyll serve`. + +As always, you can go through [the full list of changes](/docs/history/#v4-2-0) if you are interested in the various +memory-allocation optimizations made to Jekyll. + +Special thanks to our community members who helped improving Jekyll codebase and documentation from v4.1.1: +Adam Alton, Alex Malaszkiewicz, Alexey Pelykh, Brittany Joiner, bytecode1024, Christopher Brown, Chuck Houpt, +Corey Megown, Dan Nemenyi, Enrico Tolotto, fauno, Felix Breidenstein, Francesco Bianco, Frank Taillandier, +Gabriel Staples, iBug, Jacobo Vidal, jaybe@jekyll, jesuslerma, jnozsc, joelkennedy, Joe Marshall, Liam Cooke, +Lou Rectoret, Malathi, m-naumann, Nicholas Paxford, Nikita Skalkin, Parker Moore, Pratyaksh Gautam, Rachel Cheyfitz, +SaintMalik, Seeker, Shannon Kularathna, Steven Xu, Takuya N, Thelonius Kort and Toby Glei. diff --git a/docs/_posts/2021-04-08-jekyll-3-9-1-released.markdown b/docs/_posts/2021-04-08-jekyll-3-9-1-released.markdown new file mode 100644 index 00000000000..6449d45d9a8 --- /dev/null +++ b/docs/_posts/2021-04-08-jekyll-3-9-1-released.markdown @@ -0,0 +1,28 @@ +--- +title: 'Jekyll 3.9.1 Released' +date: 2021-04-08 10:51:12 -0400 +author: parkr +version: 3.9.1 +categories: [release] +--- + +This patch release of the 3.9 series is released to fix a bug where the +`include` tag does not allow valid filename characters. For example, this +would previously fail: + +{% raw %} +```text +{% include my-logo@2x.svg %} +``` +{% endraw %} + +This release adds support for the following characters in filenames: + +- `@` +- `-` +- `(` and `)` +- `+` +- `~` +- `#` + +Happy Jekylling! diff --git a/docs/_posts/2021-09-14-goodbye-dear-frank.markdown b/docs/_posts/2021-09-14-goodbye-dear-frank.markdown new file mode 100644 index 00000000000..60d352a9243 --- /dev/null +++ b/docs/_posts/2021-09-14-goodbye-dear-frank.markdown @@ -0,0 +1,32 @@ +--- +title: 'Goodbye, Dear Frank.' +date: 2021-09-14 11:28:02 -0500 +author: ashmaroli +categories: [team, community] +--- + +Over the weekend, the Jekyll core team learned of the passing of one of our own: *Frank Taillandier*, popularly known +by his GitHub username @DirtyF. + +Ruby not being his forte, he chose to avoid code-level changes and instead focus on what he did best — *engage with +the community*. + +He helped resolve complaints reported on the GitHub issue tracker, ensured that Jekyll documentation remained simple for +novice users yet detailed enough for advanced users seeking additional information. + +He also served as the administrator for Jekyll's public [discourse forum](https://talk.jekyllrb.com/) where he not only +addressed queries from users and provided tips to improve Jekyll workflow, he also shared feedback on Jekyll sites +created by the community, and used the forum as a platform to gather feedback on unreleased iterations of Jekyll and +in-house plugins. + +Abreast with latest developments in the Web-verse, Frank was always quick to introduce technologies that vastly improved +maintenance in the Jekyll organization. He was instrumental in setting up deploy previews for patches to Jekyll's +documentation site and later wiring GitHub Actions to handle continuous integrations for Jekyll and in-house projects. + +In spite of spiritually moving away from Jekyll during the later part of his career, choosing to concentrate efforts on +furthering JAMstack projects, he greatly remained active on Jekyll's development channel on Slack relaying key feedback +from the community or discuss concerns regarding the future of Jekyll at length. + +Having untimely left Jekyll and our community with an unfillable void, he will be missed immensely. :broken_heart: + +Rest in Peace, friend and colleague. :bouquet: diff --git a/docs/_posts/2021-09-27-jekyll-4-2-1-released.markdown b/docs/_posts/2021-09-27-jekyll-4-2-1-released.markdown new file mode 100644 index 00000000000..bb9a46c676c --- /dev/null +++ b/docs/_posts/2021-09-27-jekyll-4-2-1-released.markdown @@ -0,0 +1,40 @@ +--- +title: "Jekyll 4.2.1 Released" +date: 2021-09-27 14:45:46 +0530 +author: ashmaroli +version: 4.2.1 +category: release +--- + +Hello Jekyllers! + +The Jekyll team is happy to announce the release of `v4.2.1` which fixes a couple of +regressions introduced in `v4.2.0` and another bug inherited from Jekyll 3. + +In `v4.2.0`, we decided to stop overriding {% raw %}`{{ site.url }}`{% endraw %} with +the *localhost* address when running the command `jekyll serve` with the default +*development* mode. While the intent behind the change was to avoid forcing users to +generate a *production build* separately by invoking `jekyll build`, it however had an +unforeseen consequence — absolute URLs for assets now pointed to +resources that were at times not yet been deployed to the configured `site.url`. That +broke the users' local development workflow. + +`v4.2.0` also added a series of optimizations surrounding the generation of Liquid +representation for a site's standalone pages and layouts. However, that prevented +{% raw %}`{{ page.content }}`{% endraw %} and other mutable attributes from reflecting +the latest state of the requested attribute, thereby breaking the render of all resources +that were dependent on such mutable attributes. + +The last fix included in this release addresses the issue where incremental regeneration +ignored changes to documents in collections when the site is configured to use a custom +`collections_dir` for all collections. + +Special thanks to @benik for helping us understand the regression caused by the decision +to stop overriding `site.url` and proposing to revert the change. Another special thanks +to @pdmosses for helping us discover the regression surrounding Liquid representation of +pages by providing with a test repository. + +
+ :bouquet: + Dedicated to our colleague Frank who passed away recently :bouquet: +
diff --git a/docs/_posts/2022-03-03-jekyll-4-2-2-released.markdown b/docs/_posts/2022-03-03-jekyll-4-2-2-released.markdown new file mode 100644 index 00000000000..d175aa2027e --- /dev/null +++ b/docs/_posts/2022-03-03-jekyll-4-2-2-released.markdown @@ -0,0 +1,30 @@ +--- +title: "Jekyll 4.2.2 Released" +date: 2022-03-03 19:15:20 +0530 +author: ashmaroli +version: 4.2.2 +category: release +--- + +Hello Jekyllers! + +Jekyll 4.2.2 has been released. Unlike prior releases, this is a simple maintenance release and may be skipped. + +For those who are still curious about the current release, here is some technical context: The previous `jekyll-4.2.1` package was built and +published using a Windows system. A side-effect of that action was that every file bundled into the gem ended up with Windows-style CRLF +line-endings instead of Unix-style LF line-endings. + +For our end-users, this difference holds no significance. However, a third-party entity vendoring the release faced a roadblock. The executable +program `jekyll` apparently misplaced the executable bit because of the change in line-endings. + +To that end, the Jekyll team decided to use the GitHub Actions service to build and publish releases. In-house plugins have already published +releases via this route serving as trials. Henceforth, and unless explicitly reported, all Jekyll releases will be built on GitHub Actions' +Ubuntu platform and published to Rubygems by @jekyllbot irrespective of the maintainer overseeing the release. + +That is all for now. +Happy Jekyllin'!! + +*P.S.: Jekyll 4.3.0 will be bringing you some new features very soon.. Also, our sass-converter plugin has been [enhanced][sass-220] to support +modern improvements to Sass.* + +[sass-220]: https://github.com/jekyll/jekyll-sass-converter/tree/v2.2.0#sass-embedded diff --git a/docs/_posts/2022-03-27-jekyll-3-9-2-released.markdown b/docs/_posts/2022-03-27-jekyll-3-9-2-released.markdown new file mode 100644 index 00000000000..5ea445dbb5f --- /dev/null +++ b/docs/_posts/2022-03-27-jekyll-3-9-2-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 3.9.2 Released' +date: 2022-03-27 13:20:00 -0700 +author: parkr +version: 3.9.2 +categories: [release] +--- + +Hey Jekyllers, + +Quick bug-fix release for you all today: + +1. Ruby 3.0 and 3.1 support :tada: (you will need to run `bundle add webrick` for `jekyll serve` to work) +2. `jekyll serve` will no longer inject a charset into the MIME type for +binary types +3. Incremental regeneration now handles includes in collection files + correctly + +That's all, Happy Jekylling! diff --git a/docs/_posts/2022-10-20-jekyll-4-3-0-released.markdown b/docs/_posts/2022-10-20-jekyll-4-3-0-released.markdown new file mode 100644 index 00000000000..752e79658c4 --- /dev/null +++ b/docs/_posts/2022-10-20-jekyll-4-3-0-released.markdown @@ -0,0 +1,88 @@ +--- +title: 'Jekyll 4.3.0 Released' +date: 2022-10-20 10:20:22 -0500 +author: ashmaroli +version: 4.3.0 +category: release +--- + +Hello Jekyllers! + +The Jekyll team is happy to announce the release of `v4.3.0` shipping with some nice improvements and bug-fixes. + +## Improvements + +### Dependencies + +- Gem `webrick` is now a listed dependency. You no longer have to add the gem to your Gemfile when using Jekyll with +Ruby 3.0 or newer. +- You may now use Rouge v4 or continue using Rouge v3.x by explicitly mentioning the version in your Gemfile. +- Support for gem `tzinfo` v2 and non-half-hour offsets have been added. +- You will be able to use v3 of `jekyll-sass-converter` when it ships. + +### Builds + +- Added support for bundling and loading data files from within a theme-gem similar to existing theme-gem contents. +- Changes to data files at source will now be respected during incremental builds. +- `site.static_files` now include static files within a collection. +- You may now configure converters for CSV data. +- `.jekyll-cache` or its equivalent custom cache directory will be automatically ignored by Git. +- Vendor the current latest mime-types dataset for use with local development server. + +{% raw %} +### Liquid Templates + +- `basename` attribute of documents are now exposed to Liquid as `name`, for example `{{ page.name }}`. Excerpts delegate +to associated document attribute. +- Top-level variable `{{ theme }}` introduced to expose gemspec details of theme-gem. (Valid only when using theme-gem) +{% endraw %} + +## Bug-fixes + +Some noteworthy bug-fixes include: + +- Respect `BUNDLE_GEMFILE` when loading Jekyll plugins via Bundler. +- Prevent loading versions older than kramdown-2.3.1 as a security measure. +- Trigger livereloading even if the site has *no pages*. +- Ensure the expected class of theme config is returned following a merger. +- Enable BOM encoding only if configured encoding is 'UTF-8'. +- Respect server protocol while injecting livereload script. +- The table output for `--profile` stops printing incorrect "TOTALS" row. + +[The full list of changes](/docs/history/#v4-3-0) may be perused if interested. + +As always, we are grateful to the many contributors that helped improve the project codebase and documentation: + +Ashwin Maroli, Frank Taillandier, Matt Rogers, Parker Moore, Kelvin M. Klann, Josh Soref, Youssef Boulkaid, +Emily Grace Seville, Robert Martin, jaybe@jekyll, Ben Keith, Jonathan Darrer, Kaben, Mike Kasberg, Moncef Belyamani, +Phil Ross, Sesh Sadasivam, Adam Bell, Alaz Tetik, Alex Malaszkiewicz, Alex Saveau, Andreas Deininger, Andrew Davis, +Andrew Gutekanst, Andrii Abramov, Aram Akhavan, Atlas Cove, Attaphong Rattanaveerachanon, Ben Whetton, Chris Keefe, +Clayton Smith, Craig H Maynard, Curious Cat, Daniel Haim, Daniel Kehoe, Daryl Hepting, David Bruant, David Zhang, +Edson Jiménez, Eric Cousineau, Gary, Giuseppe Bertone, Ikko Ashimine, JJ, JT, Jeff Wilcox, Jeffrey Veen, +Jesse van der Pluijm, John Losito, Kantanat-Stamp, Kirstin Heidler, Korbs, Laurence Andrews, Liam Bigelow, Maik Riechert, +Meet Gor, Meg Gutshall, Michael Gerzabek, MichaelCordingley, Miguel Brandão, Nahin Khan, Nemo, Nicholas Paxford, +Nick Coish, Otto Urpelainen, Parikshit87, Phil Kirlin, Qasim Qureshi, Ricardo N Feliciano, Rishi Raj Jain, SNVMK, +SaintMalik, Sampath Sukesh Ravolaparthi, Shannon Kularathna, Shyam Mohan K, Takuya N, Tejas Bubane, Toshimaru, Tyler887, +Vinhas Kevin, alena-ko, fauno, lm, lucafrance, nusu, shorty, なつき + +--- + +### Announcement + +I would like to inform you that following this release, Jekyll will start developing towards a v5.0 milestone that will +**definitely contain breaking changes**. I have set up a [tentative roadmap at the GitHub repository][roadmap] to give everyone +a glimpse of the PROBABLE OUTCOME. Towards that end, we will no longer accept documentation fixes on `master`. The `4.3-stable` +branch will be used to build and deploy the site for https://jekyllrb.com. + +Jekyll 3.x series is now under security-maintenance phase. Only security patches will be released when necessary. + +Jekyll 4.x series will continue receiving bug-fixes and security-patches only. Depending on the state of progress towards v5.0, +there will be *at least* one minor version release serving as a transitionary version containing deprecations and bridge code +to ease the eventual upgrade to v5.0. + +[roadmap]: {{ site.repository }}/issues/9156 + +--- + +That is all for now. +Happy Jekyllin'!! diff --git a/docs/_posts/2022-10-26-jekyll-4-3-1-released.markdown b/docs/_posts/2022-10-26-jekyll-4-3-1-released.markdown new file mode 100644 index 00000000000..77cd9625de2 --- /dev/null +++ b/docs/_posts/2022-10-26-jekyll-4-3-1-released.markdown @@ -0,0 +1,21 @@ +--- +title: 'Jekyll 4.3.1 Released' +date: 2022-10-26 19:09:42 +0530 +author: ashmaroli +version: 4.3.1 +category: release +--- + +Hello Jekyllers! + +We're shipping `v4.3.1` containing fixes for two issues with v4.3.0: + - Jekyll now respects user-defined `name` attribute for collection documents when accessed in Liquid templates. + - Revert the changes made to trigger incremental rebuilds when data files are changed. + +Thanks to the users who took the time to report the issues to us. +Happy Jekyllin' + +P.S. Development towards v5 has taken a back seat as of now. I plan on releasing a v4.4.0 instead. +That said, please feel free to comment on the [tentative roadmap to v5][roadmap]. + +[roadmap]: {{ site.repository }}/issues/9156 diff --git a/docs/_posts/2022-12-21-jekyll-sass-converter-3.0-released.markdown b/docs/_posts/2022-12-21-jekyll-sass-converter-3.0-released.markdown new file mode 100644 index 00000000000..d49fdd07f72 --- /dev/null +++ b/docs/_posts/2022-12-21-jekyll-sass-converter-3.0-released.markdown @@ -0,0 +1,71 @@ +--- +title: Jekyll Sass Converter 3.0 Released +date: 2022-12-21 17:52:15 +0530 +author: ashmaroli +category: community +--- + +Jekyll Sass Converter 3.0 shipped recently and is available to those using Jekyll 4.3 and above. This release contains major changes. +Specifically, the plugin has **stopped using `sassc` for converting your Sass partials and stylesheets** into CSS files. +Instead, the converter now uses the `sass-embedded` gem acting as an interface to Dart Sass, which is the current primary +implementation of Sass under active development. The secondary implementation `libsass` which the `sassc` gem interfaced +with has been deprecated by its developers. + +However, Dart Sass isn't *fully compatible* with older Ruby Sass workflow. + +## Requirements + +- Minimum Ruby Version: `Ruby 2.6.0` (all platforms). +- Minimum Rubygems Version: `3.3.22` (for Linux-based platforms). + +## Migration Guide + +### Dropped `implmentation` Option + +In `v3.0.x`, `sass-embedded` is the only supported Sass implmentation, and therefore the config option +`sass.implementation` introduced in `v2.2.0` has been removed. + + +### Dropped `add_charset` Option + +The converter will no longer emit `@charset "UTF-8";` or a `U+FEFF` (byte-order marker) for `sassify` and `scssify` +Jekyll filters and hence the redundant option `sass.add_charset` is no longer active. + + +### Dropped `line_comments` Option + +`sass-embedded` does not support `sass.line_comments` option. + + +### Dropped support of importing files with non-standard extension names + +`sass-embedded` only allows importing files that have extension names of `.sass`, `.scss` or `.css`. SCSS syntax in +files with `.css` extension name will result in a syntax error. + + +### Dropped support of importing files relative to site source + +In `v2.x`, the Converter allowed imports using paths relative to site source directory, even if the site source +directory is not present in Sass' `load_paths` option. This is a side effect of a bug in the converter, which will remain as is in +`v2.x` due to its usage in the wild. + +In `v3.x`, imports using paths relative to site source directory will not work out of box. To allow these imports, `.` +(meaning current directory, or site source directory) need to be explicitly listed under `load_paths` option. + + +### Dropped support of importing files with the same filename as their parent file + +In `v2.x`, the Converter allowed imports of files with the same filename as their parent file from `sass_dir` or +`load_paths`. This is a side effect of a bug in the Converter, which will remain as is in `v2.x` due to its usage in the +wild. + +In `v3.x`, imports using the same filename of parent file will create a circular import. To fix such imports, rename +either of the files, or use complete relative path from the parent file. + + +### Behavioral Differences in Sass Implementation + +There are a few intentional behavioral differences between Dart Sass and Ruby Sass. Please refer +[Behavioral Differences from Ruby Sass][behavioral-differences] for details. + +[behavioral-differences]: https://github.com/sass/dart-sass#behavioral-differences-from-ruby-sass diff --git a/docs/_posts/2023-01-20-jekyll-4-3-2-released.markdown b/docs/_posts/2023-01-20-jekyll-4-3-2-released.markdown new file mode 100644 index 00000000000..cfc69ee4fc2 --- /dev/null +++ b/docs/_posts/2023-01-20-jekyll-4-3-2-released.markdown @@ -0,0 +1,27 @@ +--- +title: 'Jekyll 4.3.2 Released' +date: 2023-01-20 23:00:00 +0530 +author: ashmaroli +version: 4.3.2 +category: release +--- + +Hello Jekyllers! + +This is a small release containing fixes for some issues that came to our attention after the +release of v4.3.1: + - Our `link` tag had a significant performance regression with the release of v4.3.0 solely due + to a change related to `Jekyll::Site#each_site_file`. The new patch restores previous performance + while maintaining the enhancements introduced in v4.3.0. + - The tables printed out on running a build with the `--profile` did not stop including the + misleading `TOTALS` row as advertised in the release-notes for v4.3.0. The row has been removed + completely now. + - `jekyll-sass-converter-3.0.0` that shipped in the interim was not happy with our blank-site + scaffolding (from running `jekyll new --blank`) having a `main.scss` stylesheet template + *import* a Sass partial *also named* `main.scss`. So the partial has been renamed to `base.scss`. + +That's about it for this release. Depending on whether you use the features patched in this release, +you may either wait for v4.4.0 (releasing in the near future) to update your Gemfile or, download +the latest release right away! :) + +Happy Jekyllin'!! diff --git a/docs/_posts/2023-01-29-jekyll-3-9-3-released.markdown b/docs/_posts/2023-01-29-jekyll-3-9-3-released.markdown new file mode 100644 index 00000000000..71177fb55aa --- /dev/null +++ b/docs/_posts/2023-01-29-jekyll-3-9-3-released.markdown @@ -0,0 +1,15 @@ +--- +title: 'Jekyll 3.9.3 Released' +date: 2023-01-29 18:30:22 2023 -0800 +author: parkr +version: 3.9.3 +categories: [release] +--- + +Jekyll 3.9.3 is a bug fix release loosening version restrictions for +dependencies `i18n` and `tzinfo` gems. You can now use Jekyll v3.9 with +newer versions of these gems! + +More details in [the full release notes]({% link _docs/history.md %}#v3-9-3). + +Happy Jekylling! diff --git a/docs/_posts/2023-12-27-jekyll-4-3-3-released.markdown b/docs/_posts/2023-12-27-jekyll-4-3-3-released.markdown new file mode 100644 index 00000000000..9435f864d27 --- /dev/null +++ b/docs/_posts/2023-12-27-jekyll-4-3-3-released.markdown @@ -0,0 +1,19 @@ +--- +title: 'Jekyll 4.3.3 Released' +date: 2023-12-27 11:15:00 -0600 +author: mattr- +version: 4.3.3 +category: release +--- + +Hello Jekyllers! + +This is a very small release containing two things: + + - A fix for using Jekyll with Ruby 3.3 and the new `logger` gem included with that release. + - A test fix for newer versions of Ruby for packagers that run the test suite + as part of their packaging process. + +Nothing new in the way of features for this release. You'll need to wait for v4.4 for that. 😄 + +Happy Jekylling!! diff --git a/docs/_posts/2023-12-28-jekyll-3-9-4-released.markdown b/docs/_posts/2023-12-28-jekyll-3-9-4-released.markdown new file mode 100644 index 00000000000..544dd99a711 --- /dev/null +++ b/docs/_posts/2023-12-28-jekyll-3-9-4-released.markdown @@ -0,0 +1,14 @@ +--- +title: 'Jekyll 3.9.4 Released' +date: 2023-12-28 14:45:05 -0800 +author: parkr +version: 3.9.4 +categories: [release] +--- + +Hey Jekyllers! + +This release, 3.9.4, is to bring Ruby 3.3 support to Jekyll. You can find +the details in [the changelog]({% link _docs/history.md %}#v3-9-4). + +Happy Jekylling! diff --git a/docs/_posts/2024-06-23-jekyll-3-10-0-released.markdown b/docs/_posts/2024-06-23-jekyll-3-10-0-released.markdown new file mode 100644 index 00000000000..e9f1a5a8263 --- /dev/null +++ b/docs/_posts/2024-06-23-jekyll-3-10-0-released.markdown @@ -0,0 +1,16 @@ +--- +title: 'Jekyll 3.10.0 Released' +date: 2024-06-23 21:56:58 -0700 +author: parkr +version: 3.10.0 +categories: [release] +--- + +As Ruby continues to march on, the maintainers have made the decision to +drop some previously-bundled gems. This release makes Jekyll depend +directly on those gems so that whether your Ruby installation has them +bundled or not, your experience can continue uninterrupted. + +More details [are in the changelog]({% link _docs/history.md %}#v3-10-0). + +Happy Jekylling! diff --git a/docs/_posts/2024-09-16-jekyll-4-3-4-released.markdown b/docs/_posts/2024-09-16-jekyll-4-3-4-released.markdown new file mode 100644 index 00000000000..457e87c9e90 --- /dev/null +++ b/docs/_posts/2024-09-16-jekyll-4-3-4-released.markdown @@ -0,0 +1,18 @@ +--- +title: 'Jekyll 4.3.4 Released' +date: 2024-09-16 21:34:22 +0530 +author: ashmaroli +version: 4.3.4 +category: release +--- + +Hello Jekyllers! + +Publishing a small bug-fix release with the following patches: + +* Relax version-constraint on gem `wdm` in Gemfile created by `jekyll new`. +* Patch `Jekyll::Drops::ThemeDrop#root` to render absolute path to theme-gem only if `JEKYLL_ENV` is explicitly set + to string `development`. + +That is all for now. +Happy Jekyllin'!! diff --git a/docs/_posts/2025-01-27-jekyll-4-4-0-released.markdown b/docs/_posts/2025-01-27-jekyll-4-4-0-released.markdown new file mode 100644 index 00000000000..d912fbcbdeb --- /dev/null +++ b/docs/_posts/2025-01-27-jekyll-4-4-0-released.markdown @@ -0,0 +1,39 @@ +--- +title: 'Jekyll 4.4.0 Released' +date: 2025-01-27 20:45:32 +0530 +author: ashmaroli +version: 4.4.0 +category: release +--- + +Greetings Jekyllers, Jekyll v4.4.0 has been published! + +This release comes with the following notable changes since v4.3.x: + +* Liquid tag `highlight` now allows marking specific lines in the code-block. +* Allow customizing the port that the vendored livereload script listens to, either via command-line flag + `--livereload-port NUM` or via setting desired value to key `livereload_port` in configuration file. +* Acknowledge paths passed to CLI flag `--livereload-ignore` or list of paths defined under configuration key + `livereload_ignore` in order prevent automatic browser-refreshes on change to those paths. +* Support for Ruby versions older than Ruby 2.7.0 has been dropped. Regardless, we recommend using Ruby 3.2.0 or newer + to reduce inconveniences with installing newer versions of various plugins for Jekyll. +* In order to improve the out-of-the-box experience with newer versions of Ruby, we have added gems `base64`, `csv` as + runtime-dependencies. Consequently, those gems will be automatically installed with Jekyll and made available for use + on issuing `bundle exec jekyll `. *Users on older versions of Jekyll will have to manually add the gems to + their Gemfile to resolve dependency errors*. +* Gem `json` has been added as a runtime-dependency as well to provide consistent behavior across different platforms and + different Ruby versions. +* Version constraint on `mercenary` gem has been relaxed to automatically allow future releases. + +Special thanks to my co-maintainers and members from our community who were instrumental in improving Jekyll codebase, +documentation and development workflow since the release of v4.3: + +Akira Taguchi, Andy Coates, Daniel Haim, David Silveira, Gabriel B. Nunes, Gaelan Lloyd, Gourav Khunger, IFcoltransG, +James Hoctor, Joe Mahoney, Joel Coffman, Jonas Jared Jacek, Jorge, Josh Soref, José Romero, Juan Vásquez, KenHV, Khalila, +Koichi ITO, Krisztian Zsolt Sallai, Maciek Palmowski, Mamoru TASAKA, Matt Rogers, Michael Nordmeyer, Mike Slinn, +Moncef Belyamani, Muhab Abdelreheem, Olle Jonsson, Olly Headey, Otto Liljalaakso, Parker Moore, QuinnG8, Ram Vasuthevan, +Robert Austin, Robert Love, Sean M. Collins, Seth Falco, Seth Louis, Shruti Dalvi, Silent, Simon Wagar, Sutou Kouhei, +Tomáš Hübelbauer, Valeriy Van, Virgil Ierubino, Vít Ondruch, William Entriken, William Underwood, a story, halorrr, +iulianOnofrei (U-lee-aan), masaki, naoki kodama, nisbet-hubbard, plgagne, velle, waqarnazir, なつき and 林博仁 Buo-ren Lin + +Happy Jekyllin'!! diff --git a/docs/_posts/2025-01-29-jekyll-4-4-1-released.markdown b/docs/_posts/2025-01-29-jekyll-4-4-1-released.markdown new file mode 100644 index 00000000000..f0e1000148e --- /dev/null +++ b/docs/_posts/2025-01-29-jekyll-4-4-1-released.markdown @@ -0,0 +1,10 @@ +--- +title: 'Jekyll 4.4.1 Released' +date: 2025-01-29 18:15:32 +0530 +author: ashmaroli +version: 4.4.1 +category: release +--- + +Publishing a patch release to restore existing behavior around defining front matter defaults +where a scope with path containing glob patterns are lax in matching paths on disk. diff --git a/docs/_sass/_docsearch.scss b/docs/_sass/_docsearch.scss new file mode 100644 index 00000000000..46d75e73340 --- /dev/null +++ b/docs/_sass/_docsearch.scss @@ -0,0 +1,579 @@ +.searchbox { + display: inline-block; + position: relative; + width: 200px; + height: 32px !important; + padding-top: 1px; + white-space: nowrap; + box-sizing: border-box; + visibility: visible !important; +} + +.searchbox .algolia-autocomplete { + display: block; + width: 100%; + height: 100%; +} + +.searchbox__wrapper { + width: 100%; + height: 100%; + z-index: 999; + position: relative; +} + +.searchbox__input { + display: inline-block; + box-sizing: border-box; + transition: box-shadow 0.4s ease, background 0.4s ease; + border: 0; + border-radius: 16px; + box-shadow: inset 0 0 0 1px #cccccc; + background: #ffffff !important; + padding: 0; + padding-right: 26px; + padding-left: 32px; + width: 100%; + height: 100%; + vertical-align: middle; + white-space: normal; + font-size: 12px; + appearance: none; +} + +.searchbox__input::-webkit-search-decoration, .searchbox__input::-webkit-search-cancel-button, .searchbox__input::-webkit-search-results-button, .searchbox__input::-webkit-search-results-decoration { + display: none; +} + +.searchbox__input:hover { + box-shadow: inset 0 0 0 1px #b3b3b3; +} + +.searchbox__input:focus, .searchbox__input:active { + outline: 0; + box-shadow: inset 0 0 0 1px #aaaaaa; + background: #ffffff; +} + +.searchbox__input::placeholder { + color: #aaaaaa; +} + +.searchbox__submit { + position: absolute; + top: 0; + margin: 0; + border: 0; + border-radius: 16px 0 0 16px; + background-color: rgba(69, 142, 225, 0); + padding: 0; + width: 32px; + height: 100%; + vertical-align: middle; + text-align: center; + font-size: inherit; + user-select: none; + right: inherit; + left: 0; +} + +.searchbox__submit::before { + display: inline-block; + margin-right: -4px; + height: 100%; + vertical-align: middle; + content: ''; +} + +.searchbox__submit:hover, .searchbox__submit:active { + cursor: pointer; +} + +.searchbox__submit:focus { + outline: 0; +} + +.searchbox__submit svg { + width: 14px; + height: 14px; + vertical-align: middle; + fill: #6d7e96; +} + +.searchbox__reset { + display: block; + position: absolute; + top: 8px; + right: 8px; + margin: 0; + border: 0; + background: none; + cursor: pointer; + padding: 0; + font-size: inherit; + user-select: none; + fill: rgba(0, 0, 0, 0.5); +} + +.searchbox__reset.hide { + display: none; +} + +.searchbox__reset:focus { + outline: 0; +} + +.searchbox__reset svg { + display: block; + margin: 4px; + width: 8px; + height: 8px; +} + +.searchbox__input:valid ~ .searchbox__reset { + display: block; + animation-name: sbx-reset-in; + animation-duration: 0.15s; +} + +@keyframes sbx-reset-in { + 0% { + transform: translate3d(-20%, 0, 0); + opacity: 0; + } + 100% { + transform: none; + opacity: 1; + } +} + +.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu { + right: 0 !important; + left: inherit !important; +} + +.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before { + right: 48px; +} + +.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu { + left: 0 !important; + right: inherit !important; +} + +.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before { + left: 48px; +} + +.algolia-autocomplete .ds-dropdown-menu { + position: relative; + top: -6px; + border-radius: 4px; + margin: 6px 0 0; + padding: 0; + text-align: left; + height: auto; + position: relative; + background: transparent; + border: none; + z-index: 999; + max-width: 600px; + min-width: 500px; + box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1); +} + +.algolia-autocomplete .ds-dropdown-menu:before { + display: block; + position: absolute; + content: ''; + width: 14px; + height: 14px; + background: #fff; + z-index: 1000; + top: -7px; + border-top: 1px solid #d9d9d9; + border-right: 1px solid #d9d9d9; + transform: rotate(-45deg); + border-radius: 2px; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { + position: relative; + z-index: 1000; + margin-top: 8px; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover { + text-decoration: none; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestion { + cursor: pointer; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple { + background-color: rgba(69, 142, 225, 0.05); +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content { + background-color: rgba(69, 142, 225, 0.05); +} + +.algolia-autocomplete .ds-dropdown-menu [class^='ds-dataset-'] { + position: relative; + border: solid 1px #d9d9d9; + background: #fff; + border-radius: 4px; + overflow: auto; + padding: 0 8px 8px; +} + +.algolia-autocomplete .ds-dropdown-menu * { + box-sizing: border-box; +} + +.algolia-autocomplete .algolia-docsearch-suggestion { + display: block; + position: relative; + padding: 0 8px; + background: #fff; + color: #02060c; + overflow: hidden; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { + color: #174d8c; + background: rgba(143, 187, 237, 0.1); + padding: 0.1em 0.05em; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 +.algolia-docsearch-suggestion--highlight, +.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 +.algolia-docsearch-suggestion--highlight { + padding: 0 0 1px; + background: inherit; + box-shadow: inset 0 -2px 0 0 rgba(69, 142, 225, 0.8); + color: inherit; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + padding: 0 0 1px; + background: inherit; + box-shadow: inset 0 -2px 0 0 rgba(69, 142, 225, 0.8); + color: inherit; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content { + display: block; + float: right; + width: 70%; + position: relative; + padding: 5.33333px 0 5.33333px 10.66667px; + cursor: pointer; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ddd; + left: -1px; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { + position: relative; + border-bottom: 1px solid #ddd; + display: none; + margin-top: 8px; + padding: 4px 0; + font-size: 1em; + color: #33363d; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { + width: 100%; + float: left; + padding: 8px 0 0 0; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { + float: left; + width: 30%; + padding-left: 0; + text-align: right; + position: relative; + padding: 5.33333px 10.66667px; + color: #a4a7ae; + font-size: 0.9em; + word-wrap: break-word; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before { + content: ''; + position: absolute; + display: block; + top: 0; + height: 100%; + width: 1px; + background: #ddd; + right: 0; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline { + display: none; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { + margin-bottom: 4px; + color: #02060c; + font-size: 0.9em; + font-weight: bold; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text { + display: block; + line-height: 1.2em; + font-size: 0.85em; + color: #63676d; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--no-results { + width: 100%; + padding: 8px 0; + text-align: center; + font-size: 1.2em; +} + +.algolia-autocomplete .algolia-docsearch-suggestion--no-results::before { + display: none; +} + +.algolia-autocomplete .algolia-docsearch-suggestion code { + padding: 1px 5px; + font-size: 90%; + border: none; + color: #222222; + background-color: #ebebeb; + border-radius: 3px; + font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; +} + +.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight { + background: none; +} + +.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header { + display: block; +} + +.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary { + display: block; +} + +@media all and (min-width: 768px) { + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column { + display: block; + } +} + +@media all and (max-width: 768px) { + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column { + display: inline-block; + width: auto; + text-align: left; + float: left; + padding: 0; + color: #02060c; + font-size: 0.9em; + font-weight: bold; + text-align: left; + opacity: 0.5; + } + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before { + display: none; + } + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after { + content: '|'; + } + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content { + display: inline-block; + width: auto; + text-align: left; + float: left; + padding: 0; + } + .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before { + display: none; + } +} + +.algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion { + border-bottom: solid 1px #eee; + padding: 8px; + margin: 0; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content { + width: 100%; + padding: 0; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content::before { + display: none; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header { + margin: 0; + padding: 0; + display: block; + width: 100%; + border: none; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0 { + opacity: 0.6; + font-size: 0.85em; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1 { + opacity: 0.6; + font-size: 0.85em; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1::before { + background-image: url('data:image/svg+xml;utf8,'); + content: ''; + width: 10px; + height: 10px; + display: inline-block; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper { + width: 100%; + float: left; + margin: 0; + padding: 0; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content, .algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline { + display: none !important; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title { + margin: 0; + color: #458ee1; + font-size: 0.9em; + font-weight: normal; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title::before { + content: '#'; + font-weight: bold; + color: #458ee1; + display: inline-block; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text { + margin: 4px 0 0; + display: block; + line-height: 1.4em; + padding: 5.33333px 8px; + background: #f8f8f8; + font-size: 0.85em; + opacity: 0.8; +} + +.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + color: #3f4145; + font-weight: bold; + box-shadow: none; +} + +.algolia-autocomplete .algolia-docsearch-footer { + width: 134px; + height: 20px; + z-index: 2000; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} + +.algolia-autocomplete .algolia-docsearch-footer--logo { + background-image: url("data:image/svg+xml,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M78.988.938h16.594a2.968 2.968 0 0 1 2.966 2.966V20.5a2.967 2.967 0 0 1-2.966 2.964H78.988a2.967 2.967 0 0 1-2.966-2.964V3.897A2.961 2.961 0 0 1 78.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 0 0-1.574-.199c-.295 0-.596.021-.897.069a2.699 2.699 0 0 0-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874c-.41.089-1.034.19-1.868.314-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 0 1-1.471-.636 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525.26-.45.608-.819 1.047-1.106.445-.287.95-.492 1.532-.615a8.8 8.8 0 0 1 1.82-.185 8.404 8.404 0 0 1 1.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 0 0-.384-.73 1.784 1.784 0 0 0-.724-.493 3.164 3.164 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 0 0-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 0 1 2.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 0 0-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 0 0-.814.24 1.46 1.46 0 0 0-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483.158.56.233 1.175.233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 0 1-1.471-.635 3.085 3.085 0 0 1-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 0 1 2.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 0 0-.109-.875 1.873 1.873 0 0 0-.384-.731 1.784 1.784 0 0 0-.724-.492 3.165 3.165 0 0 0-1.143-.205c-.616 0-1.177.075-1.69.164-.514.089-.938.191-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 0 1 2.073-.177zm-8.034-1.271a1.626 1.626 0 0 1-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 0 1-1.128 1.906 4.986 4.986 0 0 1-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 0 1-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 0 1-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 0 1 1.15-1.892 5.133 5.133 0 0 1 1.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423.685.286 1.274.69 1.753 1.216a5.644 5.644 0 0 1 1.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 0 0-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 0 1-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 0 1-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 0 1 2.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z' fill='%235468FF'/%3E%3Cpath d='M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 0 0-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503-.276-.127-.47-.218-.582-.271a13.67 13.67 0 0 1-.55-.287 4.275 4.275 0 0 1-.567-.351 6.92 6.92 0 0 1-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 0 1-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 0 0-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 0 0-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 0 0-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 0 1-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z' fill='%235D6494'/%3E%3Cpath d='M89.632 5.967v-.772a.978.978 0 0 0-.978-.977h-2.28a.978.978 0 0 0-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 0 1 1.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 0 0-1.382 0l-.465.465a.973.973 0 0 0 0 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 0 0-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 0 1-4.49-4.482 4.488 4.488 0 0 1 4.49-4.482 4.488 4.488 0 0 1 4.489 4.482 4.484 4.484 0 0 1-4.49 4.482m0-10.85a6.363 6.363 0 1 0 0 12.729c3.518 0 6.372-2.85 6.372-6.368a6.358 6.358 0 0 0-6.371-6.36' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E%0A"); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; + overflow: hidden; + text-indent: -9000px; + padding: 0 !important; + width: 100%; + height: 100%; + display: block; +} + +// Overrides + +.searchbox { + .searchbox__input { + padding: 6px 5px 5px 29px; + font-size: 0.75em; + border: none; + border-radius: 5px; + color: #555; + background-color: #333 !important; + box-shadow: 0 0 1px 0 #555; + + &::-webkit-input-placeholder { + color: #aaa; + } + &:-ms-input-placeholder { + color: #aaa; + } + &::placeholder { + color: #aaa; + } + + &:focus, &:active { + color: #eaeaea; + background-color: #252525 !important; + } + } +} + +.searchbox__submit svg { fill: #fc0 } +.searchbox__reset svg { fill: #999 } + +.algolia-autocomplete { + .ds-dropdown-menu { + font-size: 1rem; + text-shadow: none; + + .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content { + background-color: rgba(221, 221, 221, 0.5); + } + } + + .algolia-docsearch-suggestion--category-header { + background-color: #444; + color: #ddd; + padding: 0.35em; + } + + .algolia-docsearch-suggestion--subcategory-column { + color: #444; + } + + .algolia-docsearch-suggestion--highlight { + background-color: #fc0; + color: #222; + } + + .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 #fc0; + } +} diff --git a/docs/_sass/_font-awesome.scss b/docs/_sass/_font-awesome.scss new file mode 100644 index 00000000000..84e4cb80014 --- /dev/null +++ b/docs/_sass/_font-awesome.scss @@ -0,0 +1,28 @@ +@font-face { + font-family: 'FontAwesome'; + font-weight: normal; + font-style: normal; + font-display: swap; + src: url('../fonts/FontAwesome.eot?9h6hxj'); + src: url('../fonts/FontAwesome.eot?9h6hxj#iefix') format('embedded-opentype'), + url('../fonts/FontAwesome.woff?9h6hxj') format('woff'), + url('../fonts/FontAwesome.ttf?9h6hxj') format('truetype'), + url('../fonts/FontAwesome.svg?9h6hxj#FontAwesome') format('svg'); +} + +.fa { + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.fa-link:before { + content: "\f0c1"; +} + +.fa-pencil:before { + content: "\f040"; +} diff --git a/docs/_sass/_fonts.scss b/docs/_sass/_fonts.scss new file mode 100644 index 00000000000..ea0c8de03af --- /dev/null +++ b/docs/_sass/_fonts.scss @@ -0,0 +1,90 @@ +// *.woff2 support: Chrome 26+, Opera 23+, FireFox 3.6 +// *.woff support: Chrome 6+, Firefox 3.6+, IE9+, Safari 5.1+ + +// Lato Light (300) +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 300; + src: local('Lato Light'), local('Lato-Light'), + url('../fonts/lato-v14-latin-300.woff2') format('woff2'), + url('../fonts/lato-v14-latin-300.woff') format('woff'); + font-display: swap; +} + +// Lato Light, Italic (300) +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 300; + src: local('Lato Light Italic'), local('Lato-LightItalic'), + url('../fonts/lato-v14-latin-300italic.woff2') format('woff2'), + url('../fonts/lato-v14-latin-300italic.woff') format('woff'); + font-display: swap; +} + +// Lato Regular (400) +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 400; + src: local('Lato Regular'), local('Lato-Regular'), + url('../fonts/lato-v14-latin-regular.woff2') format('woff2'), + url('../fonts/lato-v14-latin-regular.woff') format('woff'); + font-display: swap; +} + +// Lato Regular, Italic (400) +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 400; + src: local('Lato Italic'), local('Lato-Italic'), + url('../fonts/lato-v14-latin-italic.woff2') format('woff2'), + url('../fonts/lato-v14-latin-italic.woff') format('woff'); + font-display: swap; +} + +// Lato Bold (700) +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 700; + src: local('Lato Bold'), local('Lato-Bold'), + url('../fonts/lato-v14-latin-700.woff2') format('woff2'), + url('../fonts/lato-v14-latin-700.woff') format('woff'); + font-display: swap; +} + +// Lato Bold, Italic (700) +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 700; + src: local('Lato Bold Italic'), local('Lato-BoldItalic'), + url('../fonts/lato-v14-latin-700italic.woff2') format('woff2'), + url('../fonts/lato-v14-latin-700italic.woff') format('woff'); + font-display: swap; +} + +// Lato Black (900) +@font-face { + font-family: 'Lato'; + font-style: normal; + font-weight: 900; + src: local('Lato Black'), local('Lato-Black'), + url('../fonts/lato-v14-latin-900.woff2') format('woff2'), + url('../fonts/lato-v14-latin-900.woff') format('woff'); + font-display: swap; +} + +// Lato Black, Italic (900) +@font-face { + font-family: 'Lato'; + font-style: italic; + font-weight: 900; + src: local('Lato Black Italic'), local('Lato-BlackItalic'), + url('../fonts/lato-v14-latin-900italic.woff2') format('woff2'), + url('../fonts/lato-v14-latin-900italic.woff') format('woff'); + font-display: swap; +} diff --git a/site/_sass/_gridism.scss b/docs/_sass/_gridism.scss similarity index 95% rename from site/_sass/_gridism.scss rename to docs/_sass/_gridism.scss index 61698efc939..4c4ce3219f0 100644 --- a/site/_sass/_gridism.scss +++ b/docs/_sass/_gridism.scss @@ -27,7 +27,7 @@ .grid .unit:first-child { padding-left: 20px; } .grid .unit:last-child { padding-right: 20px; } -/* Nested grids already have padding though, so let’s nuke it */ +/* Nested grids already have padding though, so let's nuke it */ .unit .unit:first-child { padding-left: 0; } .unit .unit:last-child { padding-right: 0; } .unit .grid:first-child > .unit { padding-top: 0; } @@ -89,11 +89,12 @@ becomes smaller */ .unit img { max-width: 100%; + height: auto; } /* Responsive Stuff */ @media screen and (max-width: 568px) { - /* Stack anything that isn’t full-width on smaller screens + /* Stack anything that isn't full-width on smaller screens and doesn't provide the no-stacking-on-mobiles class */ .grid:not(.no-stacking-on-mobiles) > .unit { width: 100% !important; diff --git a/site/_sass/_mixins.scss b/docs/_sass/_mixins.scss similarity index 100% rename from site/_sass/_mixins.scss rename to docs/_sass/_mixins.scss diff --git a/docs/_sass/_normalize.scss b/docs/_sass/_normalize.scss new file mode 100644 index 00000000000..fa4e73dd418 --- /dev/null +++ b/docs/_sass/_normalize.scss @@ -0,0 +1,447 @@ +/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers (opinionated). + */ + +body { + margin: 0; +} + +/** + * Add the correct display in IE 9-. + */ + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ + +figcaption, +figure, +main { /* 1 */ + display: block; +} + +/** + * Add the correct margin in IE 8. + */ + +figure { + margin: 1em 40px; +} + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ + +a { + background-color: transparent; /* 1 */ + -webkit-text-decoration-skip: objects; /* 2 */ +} + +/** + * 1. Remove the bottom border in Chrome 57- and Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ + +b, +strong { + font-weight: inherit; +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font style in Android 4.3-. + */ + +dfn { + font-style: italic; +} + +/** + * Add the correct background and color in IE 9-. + */ + +mark { + background-color: #ff0; + color: #000; +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +audio, +video { + display: inline-block; +} + +/** + * Add the correct display in iOS 4-7. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Remove the border on images inside links in IE 10-. + */ + +img { + border-style: none; +} + +/** + * Hide the overflow in IE. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ + +button, +html [type="button"], /* 1 */ +[type="reset"], +[type="submit"] { + -webkit-appearance: button; /* 2 */ +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Remove the default vertical scrollbar in IE. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ + +details, /* 1 */ +menu { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Scripting + ========================================================================== */ + +/** + * Add the correct display in IE 9-. + */ + +canvas { + display: inline-block; +} + +/** + * Add the correct display in IE. + */ + +template { + display: none; +} + +/* Hidden + ========================================================================== */ + +/** + * Add the correct display in IE 10-. + */ + +[hidden] { + display: none; +} diff --git a/docs/_sass/_pygments.scss b/docs/_sass/_pygments.scss new file mode 100644 index 00000000000..1ce7387e673 --- /dev/null +++ b/docs/_sass/_pygments.scss @@ -0,0 +1,86 @@ +.highlight { + .hll { background-color: #ffffcc } + .err { color: #ce342c } /* Error */ + .c { color: #818181 } /* Comment */ + .g { color: #ffffff } /* Generic */ + .k { color: #ff4287 } /* Keyword */ + .l { color: #ffffff } /* Literal */ + .n { color: #ffffff } /* Name */ + .o { color: #ffffff } /* Operator */ + .x { color: #ffffff } /* Other */ + .p { color: #ffffff } /* Punctuation */ + .cm { color: #818181 } /* Comment.Multiline */ + .cp { color: #d1c2f4 } /* Comment.Preproc */ + .c1 { color: #818181 } /* Comment.Single */ + .cs { color: #818181 } /* Comment.Special */ + .gd { color: #ce342c } /* Generic.Deleted */ + .ge { color: #c000c0; text-decoration: underline } /* Generic.Emph */ + .gr { color: #c0c0c0; font-weight: bold; background-color: #c00000 } /* Generic.Error */ + .gh { color: #ffffff } /* Generic.Heading */ + .gi { color: #27b42c } /* Generic.Inserted */ + span.go { color: #add8e6; font-weight: bold; background-color: #4d4d4d } /* Generic.Output, qualified with span to prevent applying this style to the Go language, see #1153. */ + .gp { color: #ffffff } /* Generic.Prompt */ + .gs { color: #ffffff } /* Generic.Strong */ + .gu { color: #ffffff } /* Generic.Subheading */ + .gt { color: #c0c0c0; font-weight: bold; background-color: #c00000 } /* Generic.Traceback */ + .kc { color: #ff4287 } /* Keyword.Constant */ + .kd { color: #ff4287 } /* Keyword.Declaration */ + .kn { color: #ff4287 } /* Keyword.Namespace */ + .kp { color: #ff4287 } /* Keyword.Pseudo */ + .kr { color: #ff4287 } /* Keyword.Reserved */ + .kt { color: #bdb76b } /* Keyword.Type */ + .ld { color: #ffffff } /* Literal.Date */ + .m { color: #ffffff } /* Literal.Number */ + .s { color: #ffe580 } /* Literal.String */ + .na { color: #b6e382 } /* Name.Attribute */ + .nb { color: #ffffff } /* Name.Builtin */ + .nc { color: #b6e382 } /* Name.Class */ + .no { color: #87ceeb } /* Name.Constant */ + .nd { color: #ffffff } /* Name.Decorator */ + .ni { color: #ffdead } /* Name.Entity */ + .ne { color: #ffffff } /* Name.Exception */ + .nf { color: #ffffff } /* Name.Function */ + .nl { color: #ffffff } /* Name.Label */ + .nn { color: #ffffff } /* Name.Namespace */ + .nx { color: #ffffff } /* Name.Other */ + .py { color: #ffffff } /* Name.Property */ + .nt { color: #ff4287 } /* Name.Tag */ + .nv { color: #ffffff } /* Name.Variable */ + .ow { color: #ffffff } /* Operator.Word */ + .w { color: #ffffff } /* Text.Whitespace */ + .mf { color: #ffffff } /* Literal.Number.Float */ + .mh { color: #ffffff } /* Literal.Number.Hex */ + .mi { color: #ffffff } /* Literal.Number.Integer */ + .mo { color: #ffffff } /* Literal.Number.Oct */ + .sb { color: #ffffff } /* Literal.String.Backtick */ + .sc { color: #ffffff } /* Literal.String.Char */ + .sd { color: #ffffff } /* Literal.String.Doc */ + .s2 { color: #ffe580 } /* Literal.String.Double */ + .se { color: #ffffff } /* Literal.String.Escape */ + .sh { color: #ffffff } /* Literal.String.Heredoc */ + .si { color: #ffffff } /* Literal.String.Interpol */ + .sx { color: #ffffff } /* Literal.String.Other */ + .sr { color: #ffffff } /* Literal.String.Regex */ + .s1 { color: #ffe580 } /* Literal.String.Single */ + .ss { color: #a47bea } /* Literal.String.Symbol */ + .bp { color: #ffffff } /* Name.Builtin.Pseudo */ + .vc { color: #98fb98 } /* Name.Variable.Class */ + .vg { color: #98fb98 } /* Name.Variable.Global */ + .vi { color: #ffffff } /* Name.Variable.Instance */ + .il { color: #ffffff } /* Literal.Number.Integer.Long */ + .bash .nv { + user-select: none; + } +} + +.language-liquid { + .highlight { + .p { color: #87ceeb } + .kr { color: #87ceeb } + .nf { color: #b899ff } + .nt { color: #87ceeb } + .nv { color: #b6e382 } + } +} + +.language-sh .highlight * { color: #eaeaea } diff --git a/site/_sass/_style.scss b/docs/_sass/_style.scss similarity index 74% rename from site/_sass/_style.scss rename to docs/_sass/_style.scss index 5980d248b7c..a4408a4d4b1 100644 --- a/site/_sass/_style.scss +++ b/docs/_sass/_style.scss @@ -1,23 +1,37 @@ /* Base */ -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; +@charset "utf-8"; + +html { box-sizing: border-box; } +*, +*:before, +*:after { + box-sizing: inherit; +} + body { - font: 300 21px Lato, 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-family: 'Lato', 'Helvetica Neue', Helvetica, Arial, sans-serif; + font-size: 21px; + font-weight: 300; color: #ddd; background-color: #333; - border-top: 5px solid #fc0; @include box-shadow(inset 0 3px 30px rgba(0,0,0,.3)); text-shadow: 0 1px 3px rgba(0,0,0,.5); - -webkit-font-feature-settings: "kern" 1; - -moz-font-feature-settings: "kern" 1; - -o-font-feature-settings: "kern" 1; - font-feature-settings: "kern" 1; - font-kerning: normal; + + // Not legible with 300 weight + // -moz-osx-font-smoothing: grayscale; + // -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + + -webkit-font-feature-settings: 'kern' on, 'liga' on, 'calt' on, 'onum', 'pnum'; + -moz-font-feature-settings: 'kern' on, 'liga' on, 'calt' on, 'onum', 'pnum'; + -ms-font-feature-settings: 'kern' on, 'liga' on, 'calt' on, 'onum', 'pnum'; + -o-font-feature-settings: 'kern' on, 'liga' on, 'calt' on, 'onum', 'pnum'; + font-feature-settings: 'kern' on, 'liga' on, 'calt' on, 'onum', 'pnum'; + margin: 0; } .clear { @@ -45,32 +59,53 @@ footer { /* Header */ header { + padding: 15px; + background: darken(#333, 3%); h1, nav { display: inline-block; } + .flexbox { + display: flex; + height: 50px; + + & > * { margin: auto } + } + + .logo { + display: block; + img { margin-top: -7px } + } + + .search .svg-icons { display: none } } -nav { +nav, .meta { ul { padding: 0; margin: 0; + white-space: nowrap; + display: inline-block; } li { display: inline-block; } } -.main-nav { - margin-top: 52px; +.meta ul { + margin-left: 10px; + + li { vertical-align: middle; } +} + +.main-nav, .meta { li { - margin-right: 10px; a { @include border-radius(5px); font-weight: 900; - font-size: 14px; + font-size: 0.75em; padding: 0.5em 1em; text-shadow: none; text-transform: uppercase; @@ -94,8 +129,8 @@ nav { } } } - .mobile-nav { + padding: 0 5px; ul { overflow: hidden; @@ -110,9 +145,9 @@ nav { color: #fc0; text-align: center; text-transform: uppercase; - font-size: 14px; + font-size: 0.625em; font-weight: 900; - padding: 5px; + padding: 10px 5px; @include border-radius(5px); } @@ -152,56 +187,63 @@ h6:hover .header-link { opacity: 1; } -@media (max-width: 768px) { - .main-nav ul { - text-align: right; +@media (max-width: 580px) { + header { + .flexbox { height: auto } + .logo img { margin-top: 0 } } } +@media (max-width: 699px) { + .searchbox { display: none } +} +@media (max-width: 768px) { + .main-nav ul { text-align: right } +} @media (max-width: 830px) { .main-nav { .show-on-mobiles { display: inline; } .hide-on-mobiles { display: none; } } } +@media (max-width: 890px) { + .meta { display: none; } +} /* Footer */ footer { - background-color: #212121; - font-size: 16px; - padding-bottom: 5px; - color: #c0c0c0; margin-top: 40px; + padding-bottom: 5px; + font-size: 15px; + font-weight: 400; + color: #999999; + background-color: #212121; a { - color: #fff; + color: #dddddd; &:hover { - img { opacity: 1; } } } - .align-right { - - p { display: inline-block; } - } + p { margin-block: 12px } img { display: inline-block; - position: relative; - top: 8px; - margin-left: 5px; - opacity: .8; + width: 84px; + height: auto; + margin-left: 2px; padding: 1px; - @include transition(opacity .2s); + vertical-align: bottom; + opacity: 0.5; + @include transition(opacity 0.2s); } } @media (max-width: 568px) { footer { - .one-third p { margin-bottom: 0; } - .two-thirds p { margin-top: -20px; } + p { margin-block: 6px } } } @@ -400,7 +442,9 @@ article { } @media (max-width: 480px) { - article ul { padding-left: 20px; } + article { + ul, ol { padding-left: 20px } + } } @media (max-width: 568px) { @@ -454,6 +498,9 @@ aside { top: 0; left: -30px; } + &.current a { + color: #f90; + } } } @@ -537,8 +584,22 @@ aside { } .docs-nav-mobile select { - color: #000; + padding: 5px; width: 100%; + font-size: 0.85em; + color: #000; + background: #ddd; + border-color: transparent; + @include border-radius(5px); + + &:focus { + outline: none; + } + + option { + font-size: 0.9em; + padding: 3px; + } } /* News */ @@ -613,24 +674,67 @@ article h2:first-child { margin-top: 0; } } .post-date, -.post-author { margin-left: 10px; } +.post-author { margin-left: 15px; } +.post-author .author-name { margin-left: 8px } .news article + article { - margin-top: -10px; - @include border-radius(0 0 10px 10px); + margin-top: -6px; + padding-top: 15px; + padding-bottom: 15px; border-top: 1px solid #555; + border-radius: 0; @include box-shadow(0 -1px 0 #2f2f2f); + + h2.post-title { + margin-bottom: 0.45em; + } + .post-date { margin-left: 0 } +} + +/* Tutorials */ + +.tutorial-header { + float: none; + margin-bottom: 30px; + padding: 0 0 15px; + background: transparent; + border-bottom: 1px solid #545454; + .improve { padding-top: 14px } + .tutorial-title { + display: block; + width: calc(100% - 160px); + font-size: 1.75em + } +} + +.tutorial-meta { + @extend .post-meta; + font-weight: 400; + text-shadow: none; + .tutorial-date, + .tutorial-author { + display: inline-block; + height: 24px + } +} + +.tutorial-date { + vertical-align: sub +} +.tutorial-author { + margin-left: 15px; + .author-name { vertical-align: middle } } -/* Code Highlighting */ +/* Code Highlighting */ pre, code { white-space: pre; display: inline-block; margin: 0; - font: 14px/1.8em Menlo, Consolas, "Courier New", Courier, "Liberation Mono", monospace; + font: 14px/1.625em Menlo, Consolas, "Courier New", Courier, "Liberation Mono", monospace; padding: 0 0.5em; } @@ -639,20 +743,36 @@ code { } .highlight, +a > code, p > pre, p > code, p > nobr > code, li > code, +li> pre, h5 > code, .note > code { - background-color: #2b2b2b; + background-color: #272727; color: #fff; + max-width: 100%; + overflow-x: auto; + vertical-align: middle; @include border-radius(5px); @include box-shadow(inset 0 1px 10px rgba(0,0,0,.3), 0 1px 0 rgba(255,255,255,.1), 0 -1px 0 rgba(0,0,0,.5)); } +a > code { color: inherit } + +.note .highlight { + width: 94%; + pre code { + font-size: 0.9em; + background-color: transparent; + box-shadow: none; + } +} + .note code { background-color: #333; background-color: rgba(0,0,0,0.2); @@ -661,13 +781,31 @@ h5 > code, font-size: 0.8em; } +.code-block { + margin: 10px 0; + code { background: none; } +} + .highlight { margin: 1em 0; - padding: 10px 0; width: 100%; overflow: auto; } +pre.highlight, +.highlight > pre { + padding: 10px 0.5em; +} + +.highlighter-rouge .highlight { + @extend .highlight; + margin: 0; +} + +div.highlighter-rouge + div.highlighter-rouge { + margin: 30px 0 0; +} + /* HTML Elements */ h1, h2, h3, h4, h5, h6 { margin: 0; } @@ -788,7 +926,12 @@ tbody td { background-image: linear-gradient(to bottom, rgba(255,255,255,0.1) 0%,rgba(255,255,255,0) 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1affffff', endColorstr='#00ffffff',GradientType=0 ); - p { + ul { + padding-left: 1em; + } + + p, + ul { font-size: 16px; code { font-size: 14px; } @@ -816,6 +959,15 @@ code.output { margin-bottom: 2px; } +table#builtin-hooks { + td { + text-align: center; + &:first-of-type { + max-width: 330px + } + } +} + /* Note types */ .note { @@ -886,6 +1038,16 @@ code.output { } } +p.note { + color: #fff; + font-weight: 400; + font-size: .75em; + + &:after { + line-height: 1.21; + } +} + .info { background-color: #0389aa; background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAzODlhYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDYxN2YiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+); @@ -958,6 +1120,30 @@ code.output { text-shadow: 0 1px 0 rgba(255,255,255,.25); } +/* Version badge */ + +.version-badge { + margin-left: .25em; + padding: 0.2em; + font-size: .75em; + font-weight: 400; + background-color: #fc0; + color: #222; + text-shadow: none; + vertical-align: middle; + border-radius: 3.75px; +} + +.note { + .version-badge { + font-size: 0.9rem; + padding: 0.1em 0.2em; + background-color: rgba(0,0,0,0.2); + color: #fff; + box-shadow: inset 0 1px 10px rgba(0,0,0,0.3),0 1px 0 rgba(255,255,255,0.1),0 -1px 0 rgba(0,0,0,0.5); + } +} + /* Responsive tables */ @media (max-width: 768px) { @@ -982,6 +1168,40 @@ code.output { } } +.videoWrapper { + position: relative; + padding-bottom: 52.4%; + padding-top: 25px; + height: 0; +} + +.videoWrapper iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.imageWrapper { + width: 100%; + height: 0; + padding-bottom: 62.623762376237624%; /* You define this doing height / width * 100% */ + position: relative; + background: #717171; + display: block; + + img { + width: 100%; + position: absolute; + opacity: 0; + } + img.b-loaded { + opacity: 1; + transition: opacity .5s; + } +} + /* Helper class taken from Bootstrap. Hides an element to all devices except screen readers. @@ -996,3 +1216,135 @@ code.output { clip: rect(0, 0, 0, 0); border: 0; } + +.result { + padding: 12px; +} + +.image-description { + margin: -20px 0 20px; + padding: 10px 15px; + font-size: 0.81em; + text-align: justify; + background: #5c5c5c; + + pre, code { + font-size: 0.75em; + background: #454545; + } +} + +.language-sh { + margin-top: 5px; + margin-bottom: 5px; + position: relative; + &:before { + display: inline-table; + padding: 8px; + width: 100%; + padding: 5px 0; + font: 400 16px/24px 'Helvetica Neue', Helvetica, Arial, sans-serif; + color: #444; + text-shadow: 0 1px 0 rgba(255,255,255,.5); + background-color: #f7f7f7; + background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2Y3ZjdmNyIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjclIiBzdG9wLWNvbG9yPSIjY2ZjZmNmIiBzdG9wLW9wYWNpdHk9IjEiLz4KICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2FhYWFhYSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgPC9saW5lYXJHcmFkaWVudD4KICA8cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSJ1cmwoI2dyYWQtdWNnZy1nZW5lcmF0ZWQpIiAvPgo8L3N2Zz4=); + background-image: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), color-stop(7%, #cfcfcf), to(#aaaaaa)); + background-image: -webkit-linear-gradient(top, #f7f7f7 0%, #cfcfcf 7%, #aaaaaa 100%); + background-image: -moz-linear-gradient(top, #f7f7f7 0%, #cfcfcf 7%, #aaaaaa 100%); + background-image: -o-linear-gradient(top, #f7f7f7 0%, #cfcfcf 7%, #aaaaaa 100%); + background-image: linear-gradient(to bottom, #ddd 0%,#999 84%,#bbb 100%); + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7f7f7', endColorstr='#aaaaaa',GradientType=0 ); + text-align: center; + content: "terminal"; + @include border-radius(3px 3px 0 0); + @include box-shadow(0 3px 10px rgba(0,0,0,.5)); + } + .highlight { + @include border-radius(0 0 3px 3px); + } + div.highlight { + border: 1px solid; + border-color: transparent #bbb #bbb #bbb; + @include box-shadow(0 3px 10px rgba(0,0,0,.5)); + } + pre.highlight { + min-height: 48px; + background: #1c1c1c; + } + code { + font-size: 15px + } +} + +.showcase { + display: flex; + list-style: none; + padding: 0; + margin: 0; + flex-wrap: wrap; + justify-content: space-between; + + li { + flex: 1 1 300px; + box-sizing: border-box; + margin: 10px; + figure { + margin: 0; + } + figcaption { + text-align: center; + } + &.spacer { + height: 0; + margin: 0; + } + } +} + +.step-nav { + background: #2b2b2b; + border-radius: 5px; + color: #fc0; + padding: 8px 45px; + + li { + margin: 0; + padding: 0; + + &.current, &.current a { + color: #f90; + font-weight: bold; + } + } +} + +ol div.highlighter-rouge { + margin: 8px 0 10px 0; +} + +.disclaimer-ribbon { + position: relative; + width: calc(100% + 100px); + margin: 45px -50px 0; + padding: 5px 20px; + font-size: 0.725em; + font-weight: 600; + color: #efc98f; + background: #695949; + &:before, &:after { + position: absolute; + top: -9px; + content: ""; + display: table; + border: 5px solid; + z-index: -1; + } + &:before { + left: 0; + border-color: transparent #b28b70 #b28b70 transparent; + } + &:after { + right: 0; + border-color: transparent transparent #b28b70 #b28b70; + } +} diff --git a/docs/_tutorials/cache-api.md b/docs/_tutorials/cache-api.md new file mode 100644 index 00000000000..b354ed0b4ab --- /dev/null +++ b/docs/_tutorials/cache-api.md @@ -0,0 +1,86 @@ +--- +title: Cache API +author: pathawks +date: 2018-08-17 12:56:24 -0400 +--- + +Jekyll includes a caching API, which is used both internally as well as exposed +for plugins, which can be used to cache the output of deterministic functions to +speed up site generation. This cache will be persistent across builds, but +cleared when Jekyll detects any changes to `_config.yml`. + +## Jekyll::Cache.new(name) → new_cache + +If there has already been a cache created with `name`, this will return a +reference to that existing Cache. Otherwise, create a new Cache called `name`. + +If this Cache will be used by a Gem-packaged plugin, `name` should either be the +name of the Gem, or prefixed with the name of the Gem followed by `::` (if a +plugin expects to use multiple Caches). If this Cache will be used internally by +Jekyll, `name` should be the name of the class that is using the Cache (ie: +`"Jekyll::Converters::Markdown"`). + +Cached objects are shared between all Caches created with the same `name`, but +are _not_ shared between Caches with different names. There can be an object +stored with key `1` in `Jekyll::Cache.new("a")` and an object stored with key +`1` in `Jekyll::Cache.new("b")` and these will not point to the same cached +object. This way, you do not need to ensure that keys are globally unique. + +## getset(key) {block} + +This is the most common way to utilize the Cache. + +`block` is a bit of code that takes a lot of time to compute, but always +generates the same output given a particular input (like converting Markdown to +HTML). `key` is a `String` (or an object with `to_s`) that uniquely identifies +the input to the function. + +If `key` already exists in the Cache, it will be returned and `block` will never +be executed. If `key` does not exist in the Cache, `block` will be executed and +the result will be added to the Cache and returned. + +```ruby +def cache + @@cache ||= Jekyll::Cache.new("ConvertMarkdown") +end + +def convert_markdown_to_html(markdown) + cache.getset(markdown) do + expensive_conversion_method(markdown) + end +end +``` + +In the above example, `expensive_conversion_method` will only be called once for +any given `markdown` input. If `convert_markdown_to_html` is called a second +time with the same input, the cached output will be returned. + +Because posts will frequently remain unchanged from one build to the next, this +is an effective way to avoid performing the same computations each time the site +is built. + +## clear + +This will clear all cached objects from a particular Cache. The Cache will be +empty, both in memory and on disk. + +### The following methods will probably only be used in special circumstances + +## cache[key] → value + +Fetches `key` from Cache and returns its `value`. Raises if `key` does not exist +in Cache. + +## cache[key] = value + +Adds `value` to Cache under `key`. +Returns nothing. + +## key?(key) → true or false + +Returns `true` if `key` already exists in Cache. False otherwise. + +## delete(key) + +Removes `key` from Cache. +Returns nothing. diff --git a/docs/_tutorials/convert-site-to-jekyll.md b/docs/_tutorials/convert-site-to-jekyll.md new file mode 100644 index 00000000000..8577074426c --- /dev/null +++ b/docs/_tutorials/convert-site-to-jekyll.md @@ -0,0 +1,540 @@ +--- +title: Convert an HTML site to Jekyll +author: tomjoht +date: 2017-02-10 21:58:56 -0800 +--- + +If you're looking for themes for your Jekyll site, you don't have to restrict yourself to existing Jekyll themes. It's pretty easy to convert almost any static HTML files into a Jekyll website. + +In many ways, any site that is currently a static site is *already* a Jekyll website. Jekyll just allows you to automate parts of the site (like inserting pages into templates, rendering lists for navigation, generating feeds and sitemaps, and more) as it processes the files. + +Understanding how to convert any HTML site into Jekyll templates will open your world to many more options for Jekyll themes. Instead of [searching online for *Jekyll themes*](https://duckduckgo.com/?q=Jekyll+themes), you can choose from the large variety of HTML templates for your site, quickly Jekyll-ize the HTML templates as you need to, and build the output with Jekyll. + +Although websites can have sophisticated features and controls, we'll keep things simple in this tutorial. + +## What is a Jekyll Website? + +First, let's start with a grounding in the basics. Stripping a Jekyll site down to an extremely basic level will help clarify what happens in a Jekyll site. If you haven't already installed the jekyll gem, [install it]({% link _docs/installation.md %}). + +We'll start with a *basic Jekyll site* consisting of three files: + +``` +. +├── _config.yml +├── _layouts +│   └── default.html +└── index.md +``` + +Manually create these three files in a folder called `my_jekyll_site` or whatever suits you the most, and place `default.html` inside a folder named `_layouts`. + +```sh +touch _config.yml index.md default.html +mkdir _layouts && mv default.html _layouts +``` + +Fire up your favorite editor, and populate the contents of the `default.html` and `index.md` files as follows: + +**_config.yml** + +```yaml +name: My Jekyll Website +``` + +**_layouts/default.html** + +{% raw %} +```html + + + + {{ content }} + + +``` +{% endraw %} + +**index.md** + +{% raw %} +```markdown +--- +title: My page +layout: default +--- + +# {{ page.title }} + +Content is written in [Markdown](https://learnxinyminutes.com/docs/markdown/). +Plain text format allows you to focus on your **content**. + + +``` +{% endraw %} + +Now `cd` to `my_jekyll_site` and serve the site with the built-in server: + +```sh +cd my_jekyll_site +jekyll serve +``` + +{: .note .info} +If you have a Gemfile, [use Bundler](/docs/ruby-101/#bundler) by typing `bundle exec jekyll serve` instead. + +When you serve the site, you get a preview URL such as `http://127.0.0.1:4000/` (which is the same as `http://localhost:4000/`). The site's files are built into the `_site` folder by default. + +This is a Jekyll site at the most basic functional level. Here's what is happening: + + * The `_config.yml` file contains settings that Jekyll uses as it processes your site. An empty config file will use default values for building a Jekyll site. For example, to convert [Markdown](https://learnxinyminutes.com/docs/markdown/) to HTML, Jekyll will automatically use the [kramdown Markdown filter](https://rubygems.org/gems/kramdown/), without any need to specify it. + * Jekyll looks for files with [front matter tags]({% link _docs/front-matter.md %}) (the two sets of dashed lines `---` like those in `index.md`) and processes the files (populating site variables, rendering any [Liquid](https://shopify.github.io/liquid/), and converting Markdown to HTML). + * Jekyll pushes the content from all pages and posts into the {% raw %}`{{ content }}`{% endraw %} variable in the layout specified (`default`) in the front matter tags. + * The processed files get written as `.html` files in the `_site` directory. + +You can read more about how Jekyll processes the files in [order of Interpretation]({% link _tutorials/orderofinterpretation.md %}). + +With this basic understanding of how a Jekyll site works, you can convert almost any HTML theme for Jekyll. The following sections will take you through a step-by-step tutorial to do so. + +## 1. Create a template for your default layout + +Find your HTML theme and save it as a `default` layout. If you're converting or cloning an existing site, you can right-click the page and view the source code. + +For example, suppose you're cloning your company site to create a documentation site with the same branding. Or suppose you have a personal site that you built with HTML and now want to make it a Jekyll site. Get the HTML source code for your site. + +{: .note .info} +Regardless of the site, do check the license and make sure you have permission to copy and use the code. + +Copy and paste the source code into a file called `default.html`. Put the `default.html` file inside the `_layouts` folder. This will be the default layout template for your pages and posts — that is, each page or post will use this layout when Jekyll builds the site. + +Note that in looking for templates, you want the HTML output of the template. If the template has PHP tags or other dynamic scripts, these dynamic elements will need to be converted to HTML or to [Liquid](https://shopify.github.io/liquid/). Liquid is [Jekyll templating system](/docs/liquid/) to retrieve dynamic content. + +Open `default.html` into your browser locally to ensure the site looks and behaves like it does online. You will likely need to adjust CSS, JS, and image paths so they work. + +For example, if the paths were relative on the site you copied, you'll need to either download the same assets into your Jekyll site or use absolute paths to the same assets in the cloud. (Syntax such as `src="//` requires a prefix such as `src="http://` to work in your local browser.) + +Jekyll provides some [filters](/docs/liquid/filters/) to prepend a site URL before path. For example, you could preface your stylesheet like this: + +{% raw %} +```liquid +{{ "/assets/style.css" | relative_url }} +``` +{% endraw %} + +The `relative_url` filter will prepend the [`baseurl`](https://byparker.com/blog/2014/clearing-up-confusion-around-baseurl/) value from your config file (as `blog` for instance) to the input. This is useful if your site is hosted at a subpath rather than at the root of the domain (for example, `http://mysite.com/blog/`). + +You can also use an `absolute_url` filter. This filter will prepend the `url` *and* `baseurl` value to the input: + +{% raw %} +```liquid +{{ "/assets/style.css" | absolute_url }} +``` +{% endraw %} + +Again, both `url` and `baseurl` can be defined in your site's config file, like this: + +```yaml +url: http://mysite.com +baseurl: /blog +``` + +The result in the output will be `http://mysite.com/blog/assets/style.css`. + +Note that the `url` property of any page begins with a forward slash (`/`), so omit this at the end of your `url` or `baseurl` property. + +You don't have to prepend filters to link paths like this. You could also use relative links across your entire site. However you decide to code the paths to your assets, make sure they render correctly. + +Does your local `default.html` page look good in your browser? Are all images, styles, and other elements showing up correctly? If so, great. Keep going. You can use this template as the layout for all your pages and posts or create as many templates as you need. + +In the next section, you'll blank out the content of the layout and replace it with placeholder tags that get populated dynamically with your Jekyll pages. + +## 2. Identify the content part of the layout + +In `default.html`, find where the page content begins (usually at `h1` or `h2` tags). Replace the title that appears inside these tags with {% raw %}`{{ page.title }}`{% endraw %}. + +Remove the content part (keep everything else: navigation menu, sidebar, footer, etc.) and replace it with {% raw %}`{{ content }}`{% endraw %}. + +Check the layout again in your browser and make sure you didn't corrupt or alter it up by inadvertently removing a crucial `div` tag or other element. The only change should be to the title and page content, which are now blanked out or showing the placeholder tag. + +## 3. Create a couple of files with front matter tags + +Create a couple of files (`index.md` and `about.md`) in your root directory. + +In your `index.md` file, add some front matter tags containing a `title` and `layout` property, like this: + +```markdown +--- +title: Home +layout: default +--- + +Some page content here... +``` + +Create another page for testing called `about.md` with similar front matter tags. + +{: .note .info} +If you don't specify a layout in your pages, Jekyll will simply render that page as an unstyled basic HTML page. + +## 4. Add a configuration file + +Add a `_config.yml` file in your root directory. In `_config.yml`, you can optionally specify the markdown filter you want. By default, the [GitHub Flavored Markdown (GFM) processor](https://github.com/kramdown/parser-gfm) for [kramdown](https://kramdown.gettalong.org/) is used. If no other filter is specified, your config file will automatically apply the following as a [default](/docs/configuration/default/) setting: + +```yaml +markdown: kramdown +kramdown: + input: GFM +``` + +You can find additional [Markdown Options](/docs/configuration/markdown/) in the Jekyll docs, though it's unlikely that you'll need them. + +## 5. Test your pages + +Now run `jekyll serve` and toggle between your `index.html` and `about.html` pages. The default layout should load for both pages. + +You've now extracted your content out into separate files and defined a common layout for pages. + +You could define any number of layouts you want for pages. Then just identify the layout you want that particular page to use. For example: + +```yaml +--- +title: Sample page +layout: homepage +--- +``` + +This page would then use the `homepage.html` template in the `_layouts` folder. + +You can even set [default front matter tags](/docs/configuration/front-matter-defaults/) for pages, posts, or [collections]({% link _docs/collections.md %}) in your `_config.yml` file so that you don't have to specify the layout in the front matter variables. Anyways, setting defaults is beyond the scope of this tutorial, let's get back to work. + +## 6. Configure site variables + +You already configured the page title using {% raw %}`{{ page.title }}`{% endraw %} tags. But there are more `title` tags to populate. Pages also have a [`title`](https://moz.com/learn/seo/title-tag) tag that appears in the browser tab or window. Typically you put the page title followed by the site title here. + +In your `default.html` layout, look for the `title` tags below your `head` tags: + +``` +ACME Website +``` + +Insert the following site variables: + +{% raw %} +```liquid +{{ page.title }} | {{ site.title }} +``` +{% endraw %} + +Open `_config.yml` and add a `title` property for your site's name. + +```yaml +title: ACME Website +``` + +Any properties you add in your `_config.yml` file are accessible through the `site` namespace. Similarly, any properties in your page's front matter are accessible through the `page` namespace. Use dot notation after `site` or `page` to access the value. + +Stop your Jekyll server with Ctrl + C and restart it. Verify that the `title` tags are populating correctly. + +{: .note .info} +Every time you modify your config file, you have to restart Jekyll for the changes to take effect. When you modify other files, Jekyll automatically picks up the changes when it rebuilds. + +If you have other variables to populate in your site, rinse and repeat. + +## 7. Show posts on a page + +It's common to show a list of posts on the homepage. First, let's create some posts so that we have something to showcase. + +Add some posts in a `_posts` folder following the standard `YYYY-MM-DD-title.md` post format: + + * `2017-01-02-my-first-post.md` + * `2017-01-15-my-second-post.md` + * `2017-02-08-my-third-post.md` + +In each post, add some basic content: + +```markdown +--- +title: My First Post +layout: default +--- + +Some sample content... +``` + +Now let's create a layout that will display the posts. Create a new file in `_layouts` called `home.html` and add the following logic: + +{% raw %} +```liquid +--- +layout: default +--- + +{{ content }} +
    +{% for post in site.posts %} +
  • {{ post.title}} + +
  • +{% endfor %} +
+``` +{% endraw %} + +Create a file called `blog.md` in your root directory and specify the `home` layout: + +```yaml +--- +title: Blog +layout: home +--- +``` + +In this case, contents of `blog.md` will be pushed into the {% raw %}`{{ content }}`{% endraw %} tag in the `home` layout. Then the `home` layout will be pushed into the {% raw %}`{{ content }}`{% endraw %} tag of the `default` layout. + +### How layouts work + +When a layout specifies another layout, it means the content of the first layout will be stuffed into the {% raw %}`{{ content }}`{% endraw %} tag of the second layout. As an analogy, think of Russian dolls that fit into each other. Each layout fits into another layout that it specifies. + +The following diagram shows how layouts work in Jekyll: + +Concept of Jekyll layouts + +{: .image-description} +In this example, the content from a Markdown document `document.md` that specifies `layout: docs` gets pushed into the {% raw %}`{{ content }}`{% endraw %} tag of the layout file `docs.html`. Because the `docs` layout itself specifies `layout: page`, the content from `docs.html` gets pushed into the {% raw %}`{{ content }}`{% endraw %} tag in the layout file `page.html`. Finally because the `page` layout specifies `layout: default`, the content from `page.html` gets pushed into the {% raw %}`{{ content }}`{% endraw %} tag of the layout file `default.html`. + +You don't need multiple layouts. You could just use one: `default`. You have options for how you design your site. In general, it's common to define one layout for pages and another layout for posts, but for both of these layouts to inherit the `default` template (which usually defines the top and bottom parts of the site). + +In your browser, go to `blog.html` and see the list of posts. +Note that you don't have to use the method described here. You could have simply added the `for` loop to any page, such as `index.md`, to display these posts. But given that you may have more complex logic for other features, it can be helpful to store your logic in templates separate from the page area where you frequently type your content. + +{: .note .info} +At minimum, a layout should contain {% raw %}`{{ content }}`{% endraw %}, which acts as a receiver for the *content* to be rendered. + +### For loops + +By the way, let's pause here to look at the `for` loop logic a little more closely. [For loops in Liquid](https://shopify.github.io/liquid/tags/iteration/) are one of the most commonly used Liquid tags. *For loops* let you iterate through content in your Jekyll site and build out a result. The `for` loop also has [certain properties available](https://help.shopify.com/themes/liquid/objects/for-loops) (like first or last iteration) based on the loop's position in the loop as well. + +We've only scratched the surface of what you can do with `for` loops in retrieving posts. For example, if you wanted to display posts from a specific category, you could do so by adding a `categories` property to your post's front matter and then look in those categories. Further, you could limit the number of results by adding a `limit` property. Here's an example: + +{% raw %} +```liquid +
    +{% for post in site.categories.podcasts limit:3 %} +
  • {{ post.title}} + +
  • +{% endfor %} +
+``` +{% endraw %} + +This loop would get the latest three posts that have a category called `podcasts` in the front matter. + +## 8. Configure navigation + +Now that you've configured posts, let's configure page navigation. Most websites have some navigation either in the sidebar or header area. + +In this tutorial, we'll assume you've got a simple list of pages you want to generate. If you only have a handful of pages, you could list them by using a `for` loop to iterate through the `site.pages` object and then order them by a front matter property. + +Identify the part of your code where the list of pages appears. Usually this is a `
    ` element with various child `
  • ` elements. Replace the code with the following: + +{% raw %} +```liquid +
      + {% assign mypages = site.pages | sort: "order" %} + {% for page in mypages %} +
    • {{ page.title }}
    • + {% endfor %} +
    +``` +{% endraw %} + +This example assumes each page would have front matter containing both a `title` and `order` property like this: + +```yaml +--- +title: My page +order: 2 +--- +``` + +Here the `order` property will define how the pages get sorted, with `1` appearing first in the list. + +You could also iterate through a list of pages that you maintain in a separate data file. This might be more appropriate if you have a lot of pages, or you have other properties about the pages you want to store. + +To manage page links this way, create a folder in your Jekyll project called `_data`. In this folder, create a file called e.g. `navigation.yml` with this content: + +```yaml +- title: Sample page 1 + url: /page-1-permalink/ + +- title: Sample page 2 + url: /page-2-permalink/ + +- title: Sample page 3 + url: /page-3-permalink/ +``` + +{: .note .info} +If you never wrote any YAML before, you'll get quickly familiar with it. Take a look at [what you can do with YAML](https://learnxinyminutes.com/docs/yaml/). + +You can store additional properties for each item in this data file as desired. Arrange the list items in the order you want them to appear. + +To print the list of pages from the data file, use code like this: + +{% raw %} +```liquid + +``` +{% endraw %} + +If you have more sophisticated requirements around navigation, such as when building a documentation site, see the [detailed tutorial on navigation](/tutorials/navigation/). + +## 9. Simplify your site with includes + +Let's suppose your `default.html` file is massive and hard to work with. You can break up your layout by putting some of the HTML code in *include* files. + +Add a folder called `_includes` in your root directory. In that folder, add a file there called `sidebar.html`. + +Remove your sidebar code from your `default.html` layout and insert it into the `sidebar.html` file. + +Where the sidebar code previously existed in `default.html`, pull in your "include" like this: + +{% raw %} +```liquid +{% include sidebar.html %} +``` +{% endraw %} + +You can break up other elements of your theme like this, such as your header or footer. Then you can apply these common elements to other layout files. This way you won't have duplicate code. + +## 10. RSS feed + +Your Jekyll site needs an RSS feed. Here's the [basic RSS feed syntax](http://www.w3schools.com/xml/xml_rss.asp). To create an RSS file in Jekyll, create a file called `feed.xml` in your root directory and add the following: + +{% raw %} +```liquid +--- +layout: null +--- + + + + + + {{ site.title }} + {{ site.url }} + + {{ site.description }} + {{ site.time | date_to_rfc822 }} + {% for post in site.posts %} + + {{ post.title }} + + {{ post.url | prepend: site.url }} + + + {{ post.content | escape | truncate: '400' }} + + {{ post.date | date_to_rfc822 }} + + {{ post.url | prepend: site.url }} + + + {% endfor %} + + +``` +{% endraw %} + +Make sure your `_config.yml` file has properties for `title`, `url`, and `description`. + +This code uses a `for` loop to look through your last 20 posts. The content from the posts gets escaped and truncated to the last 400 characters using [Liquid filters](https://help.shopify.com/themes/liquid/filters). + +In your `default.html` layout, look for a reference to the RSS or Atom feed in your header, and replace it with a reference to the file you just created. For example: + +{% raw %} +```liquid + +``` +{% endraw %} + +You can also auto-generate your posts feed by adding a gem called [`jekyll-feed`](https://help.github.com/articles/atom-rss-feeds-for-github-pages/). This gem will also work on GitHub Pages. + +## 11. Add a sitemap + +Finally, add a [site map](https://www.sitemaps.org/protocol.html). Create a `sitemap.xml` file in your root directory and add this code: + +{% raw %} +```liquid +--- +layout: null +search: exclude +--- + + + + + {% for page in site.pages %} + + {{page.url}} + {{site.time | date: '%Y-%m-%d' }} + daily + 0.5 + + {% endfor %} + + {% for post in site.posts %} + + {{post.url}} + {{site.time | date: '%Y-%m-%d' }} + daily + 0.5 + + {% endfor %} + + +``` +{% endraw %} + +Again, we're using a `for` loop here to iterate through all posts and pages to add them to the sitemap. + +You can also auto-generate your sitemap by adding a gem called [`jekyll-sitemap`](https://help.github.com/articles/sitemaps-for-github-pages/). This gem will also work on GitHub Pages. + +## 12. Add external services + +For other services you might need (such as contact forms, search, comments, and more), [look for third-party services](https://serverless.css-tricks.com/services/major). We listed some [integrations on our resources page](/resources/#integrations) but in todays's world of SaaS and APis the list is endless. + +Your Jekyll pages consist of HTML, CSS, and JavaScript, so pretty much any code you need to embed will work without a problem. + +As you integrate code for these services, note that **if a page in your Jekyll site doesn't have front matter tags, Jekyll won't process any of the content in that page.** The page will just be passed to the `_site` folder when you build your site. + +If you do want Jekyll to process some page content (for example, to populate a variable that you define in your site's config file), just add front matter tags to the page. If you don't want any layout applied to the page, specify `layout: null` like this: + +```yaml +--- +layout: null +--- +``` + +## 13. Conclusion + +Although websites can implement more sophisticated features and functionality, we've covered the basics in this tutorial. You now have a fully functional Jekyll site. + +To deploy your site, consider using [GitHub Pages](https://pages.github.com/), [Netlify](https://www.netlify.com/), [Vercel](https://vercel.com), [Render](https://render.com), [Amazon AWS S3](https://aws.amazon.com/s3/) using the [s3_website plugin](https://github.com/laurilehmijoki/s3_website), or just FTP your files to your web server. + +You can also package your layouts, includes and assets into a Ruby `gem` and [make it a Jekyll theme](/docs/themes/). + +## Additional resources + +Here are some additional tutorials on creating Jekyll sites: + + * [Convert a static site to Jekyll](http://jekyll.tips/jekyll-casts/converting-a-static-site-to-jekyll/) + * [Building a Jekyll Site – Part 1 of 3: Converting a Static Website To Jekyll](https://css-tricks.com/building-a-jekyll-site-part-1-of-3/) diff --git a/docs/_tutorials/csv-to-table.md b/docs/_tutorials/csv-to-table.md new file mode 100644 index 00000000000..7b7c315f6a8 --- /dev/null +++ b/docs/_tutorials/csv-to-table.md @@ -0,0 +1,213 @@ +--- +title: Tabulate CSV Data +author: MichaelCurrin +date: 2020-04-01 20:30:00 +0200 +--- + +This tutorial shows how to use Jekyll to read a CSV and render the data as an HTML table. + +This approach will: + +- use the CSV's first row as the HTML table header. +- use remaining rows for the body of the table. +- preserve the order of the columns from the original CSV. +- be flexible enough to work with _any_ valid CSV that is referenced. + +There is no need to specify what the names of the columns are, or how many columns there are. +The trick to this tutorial is that, when we iterate over the row data, we pick up the _first row_ +and unpack that so we can get the header names. + +Follow the steps below to convert a sample CSV of authors into an HTML table. + + +## 1. Create a CSV + +Create a CSV file in your [Data files]({{ '/docs/datafiles/' | relative_url }}) directory so +that Jekyll will pick it up. A sample path and CSV data are shown below: + +`_data/authors.csv` + +``` +First name,Last name,Age,Location +John,Doe,35,United States +Jane,Doe,29,France +Jack,Hill,25,Australia +``` + +That data file will now be available in Jekyll like this: + +{% raw %} +```liquid +{{ site.data.authors }} +``` +{% endraw %} + + +## 2. Add a table + +Choose an HTML or markdown file where you want your table to be shown. + +For example: `table_test.md` + +```yaml +--- +title: Table test +--- +``` + +### Inspect a row + +Grab the first row and see what it looks like using the `inspect` filter. + +{% raw %} +```liquid +{% assign row = site.data.authors[0] %} +{{ row | inspect }} +``` +{% endraw %} + + +The result will be a _hash_ (an object consisting of key-value pairs) which looks like this: + +```ruby +{ + "First name"=>"John", + "Last name"=>"Doe", + "Age"=>"35", + "Location"=>"United States" +} +``` + +Note that Jekyll _does_ in fact preserve the order here, based on the original CSV. + + +### Unpack a row + +A simple solution would be to hardcode the field names when looking up the row values by key. + +{% raw %} +```liquid +{{ row["First name"] }} +{{ row["Last name"] }} +``` +{% endraw %} + +But we prefer a solution that will work for _any_ CSV, without specifying the column names upfront. +So we iterate over the `row` object using a `for` loop: + +{% raw %} +```liquid +{% assign row = site.data.authors[0] %} +{% for pair in row %} + {{ pair | inspect }} +{% endfor %} +``` +{% endraw %} + +This produces the following. Note the first item in each pair is the _key_ and the second will be +the _value_. + +``` +["First name", "John"] +["Last name", "Doe"] +["Age", "35"] +["Location", "United States"] +``` + +### Create a table header row + +Here we make a table with a single table row (`tr`), made up of table header (`th`) tags. We find +the header name by getting the first element (at index `0`) from `pair`. We ignore the second +element as we don't need the value yet. + +{% raw %} +```liquid + + {% for row in site.data.authors %} + {% if forloop.first %} + + {% for pair in row %} + + {% endfor %} + + {% endif %} + {% endfor %} +
    {{ pair[0] }}
    +{% endraw %} +``` + +For now, we do not display any content from the second row onwards. We achieve this by using +`forloop.first`, since this will return true for the _first_ row and false otherwise. + + +### Add table data rows + +In this section we add the data rows to the table. Now, we use the second element of `pair` +to find the value. + +For convenience, we render using the `tablerow` tag - this works like a `for` loop, but the inner +data will be rendered with `tr` and `td` HTML tags for us. Unfortunately, there is no equivalent for +the header row, so we must write that out in full, as in the previous section. + +{% raw %} +```liquid +--- +title: Table test +--- + + + {% for row in site.data.authors %} + {% if forloop.first %} + + {% for pair in row %} + + {% endfor %} + + {% endif %} + + {% tablerow pair in row %} + {{ pair[1] }} + {% endtablerow %} + {% endfor %} +
    {{ pair[0] }}
    +``` +{% endraw %} + + +With the code above, the complete table would look like this: + + + + + + + + + + + + + + + + + + + + + + + + + + +
    First nameLast nameAgeLocation
    JohnDoe35United States
    JaneDoe29France
    JackHill25Australia
    + +That's it - you can now turn a CSV into an HTML table using Jekyll. + +## Next steps + +- Change the field names in the CSV. +- Choose a different CSV. +- Add CSS styling to your table. +- Render the table using a JSON or YAML input file. diff --git a/docs/_tutorials/custom-404-page.md b/docs/_tutorials/custom-404-page.md new file mode 100644 index 00000000000..62cc8d4b345 --- /dev/null +++ b/docs/_tutorials/custom-404-page.md @@ -0,0 +1,72 @@ +--- +title: Custom 404 Page +author: ashmaroli +date: 2017-03-11 17:23:24 +0530 +--- + +You can easily serve custom 404 error pages with Jekyll to replace the default **Error 404 -- File Not Found** page displayed when one tries to access a broken link on your site. + +## On GitHub Pages + +Any `404.html` at the **root of your `_site` directory** will be served automatically by GitHub Pages and the local WEBrick development server. + +Simply add a `404.md` or `404.html` at the root of your site's source directory and include front matter data to use the theme's base layout. + +If you plan to organize your files under subdirectories, the error page should have the following Front Matter Data, set: `permalink: /404.html`. This is to ensure that the compiled `404.html` resides at the root of your processed site, where it'll be picked by the server. + +```markdown +--- +# example 404.md + +layout: default +permalink: /404.html +--- + +# 404 + +Page not found! :( +``` + +## Hosting on Apache Web Servers + +Apache Web Servers load a configuration file named [`.htaccess`](http://www.htaccess-guide.com/) that modifies the functionality of these servers. + +Simply add the following to your `.htaccess` file. + +```apache +ErrorDocument 404 /404.html +``` + +With an `.htaccess` file, you have the freedom to place your error page within a subdirectory. + +```apache +ErrorDocument 404 /error_pages/404.html +``` + +Where the path is relative to your site's domain. + +More info on configuring Apache Error Pages can found in [official documentation](https://httpd.apache.org/docs/current/mod/core.html#errordocument). + +## Hosting on Nginx server + +The procedure is just as simple as configuring Apache servers, but slightly different. + +The nginx configuration file depends on the system in which it is installed. In most systems, it is the `nginx.conf` file, which is usually located inside `/etc/nginx/` or `/etc/nginx/conf/`. However, in other systems like Ubuntu, you would have to look for a `default` nginx configuration file, containing server related information, which is usually located inside `/etc/nginx/sites-available/` or `/etc/nginx/sites-enabled/`. Add the following to your nginx configuration file, _i.e._ either to `nginx.conf` file or to `default` file: + +```nginx +server { + error_page 404 /404.html; + location = /404.html { + internal; + } +} +``` + +If the `server` block already exists, only add the code inside the `server` block given above. +The `location` directive prevents users from directly browsing the 404.html page. + +More info on nginx error page can be found on [nginx official documentation](http://nginx.org/en/docs/http/ngx_http_core_module.html#error_page). + +

    + Proceed with caution while editing the configuration file. +

    diff --git a/docs/_tutorials/index.md b/docs/_tutorials/index.md new file mode 100644 index 00000000000..430b1c7218e --- /dev/null +++ b/docs/_tutorials/index.md @@ -0,0 +1,32 @@ +--- +title: Tutorials +permalink: /tutorials/home/ +redirect_from: /tutorials/index.html +--- + +In contrast to [Docs]({{ '/docs/home/' | relative_url }}), Tutorials provide more detailed, narrative instruction that cover a variety of Jekyll topics and scenarios. Tutorials might contain the following: + +* Step-by-step processes through particular scenarios or challenges +* Full walk-throughs using sample data, showing inputs and results from the sample data +* Detailed explanation about the pros and cons for different Jekyll strategies +* End-to-end instruction in developing a complete feature on a Jekyll site +* Instruction that combines various techniques from across the docs + +In short, tutorials aren't the core reference information in docs. They walk users through processes from beginning to end. + +{: .note .info} +The Tutorials section is new, so there aren't many tutorials yet. You can add a tutorial here to help populate this section. + +Some of these techniques might even guide you through a supporting tool, script, service, or other hack used with your Jekyll site. Feel free to include tutorials involving external services with Jekyll as well. However, note that Jekyll in no way endorses any third-party tools mentioned in tutorials. + +## How to contribute a tutorial + +We welcome your tutorial contributions. To add your tutorial: + +1. Fork the Jekyll project by clicking the **Fork** button in the upper-right corner of the [jekyll/jekyll project GitHub repo](https://github.com/jekyll/jekyll/). +2. Add your tutorial in the `_tutorials` collection. +3. Make sure your tutorial has the same front matter items as other tutorial items. +5. Add a reference to your tutorial filename in `_data/tutorials.yml`. This allows your tutorial to appear in the Tutorials sidebar. +6. Follow the regular git workflow to submit the pull request. + +When you submit your pull request, the Jekyll documentation team will review your contribution and either merge it or suggest edits. diff --git a/docs/_tutorials/navigation.md b/docs/_tutorials/navigation.md new file mode 100644 index 00000000000..5375532cede --- /dev/null +++ b/docs/_tutorials/navigation.md @@ -0,0 +1,672 @@ +--- +title: Navigation +author: tomjoht +date: 2017-01-24 15:38:17 -0800 +--- + +If your Jekyll site has a lot of pages, you might want to create navigation for the pages. Instead of hard-coding navigation links, you can programmatically retrieve a list of pages to build the navigation for your site. + +Although there's already information about [interacting with data files]({% link _docs/datafiles.md %}) in other Jekyll docs, this tutorial dives into building more robust navigation for your site. + +There are two primary ways of retrieving pages on a Jekyll site: + +* **Retrieve pages listed in a YAML data source**. Store the page data in a YAML (or JSON or CSV) file in the `_data` folder, loop through the YAML properties, and insert the values into your theme. +* **Retrieve pages by looping through the page front matter**. Look through the front matter of your pages to identify certain properties, return those pages, and insert the pages' front matter values into your theme. + +The examples that follow start with a basic navigation scenario and add more sophisticated elements to demonstrate different ways of returning the pages. In every scenario, you'll see 3 elements: + +* YAML +* Liquid +* Result + +The YAML file in the `_data` directory is called `samplelist.yml`. + +The scenarios are as follows: + +* TOC +{:toc} + +## Scenario 1: Basic List + +You want to return a basic list of pages. + +**YAML** + +```yaml +docs_list_title: ACME Documentation +docs: + +- title: Introduction + url: introduction.html + +- title: Configuration + url: configuration.html + +- title: Deployment + url: deployment.html +``` + +**Liquid** + +{% raw %} +```liquid +

    {{ site.data.samplelist.docs_list_title }}

    +
      + {% for item in site.data.samplelist.docs %} +
    • {{ item.title }}
    • + {% endfor %} +
    +``` +{% endraw %} + +**Result** +
    +

    ACME Documentation

    + +
    + +{: .note .info} +For the results in these fictitious samples, `#` is manually substituted for the actual link value (to avoid 404 errors.) + +When you use a `for` loop, you choose how you want to refer to the items you're looping through. The variable you choose (in this case, `item`) becomes how you access the properties of each item in the list. Dot notation is used to get a property of the item (for example, `item.url`). + +The YAML content has two main types of formats that are relevant here: + +* mapping +* list + +`docs_list_title: ACME Documentation` is a mapping. You access the value with `site.data.samplelist.docs_list_title`. + +`docs:` is a list. The list begins each item with a hyphen. Unlike with mappings, you usually don't access list properties directly as you do with mappings. If you want to access a specific item in the list, you must identify the position in the list you want, following typical array notation. For example, `site.data.samplelist.docs[0]` would access the first item in the list. However, this is rarely done. + +With lists, you usually use `for` loops to cycle through the list of items and do something with each item. With navigation menus, you usually insert each list item into `li` tags based on the navigation structure you're using in your HTML theme. + +Each hyphen (`-`) indicates another item in the list. This example just has two properties with each list item: `title` and `url`. You can include as many properties as you want for each item. The order of properties at each position in the list doesn't matter. + +## Scenario 2: Sorted list + +Suppose you wanted to sort the list by the `title`. To do this, convert the reference to the `docs` collection to a variable, and then apply Liquid's `sort` filter to the variable: + +**Liquid** + +{% raw %} +```liquid +{% assign doclist = site.data.samplelist.docs | sort: 'title' %} +
      +{% for item in doclist %} +
    1. {{ item.title }}
    2. +{% endfor %} +
    +``` +{% endraw %} + +**Result** + + + +The items now appear in alphabetical order. The `sort` property in the Liquid filter applies to the `title`, which is an actual property in the list. If `title` weren't a property, we would need to sort by another property. + +See the [Liquid array filter](https://help.shopify.com/themes/liquid/filters/array-filters) for more filter options. Note that you can't simply use this syntax: + +{% raw %} +```liquid +{% for item in site.data.samplelist.docs | sort: "title" %}{% endfor %} +``` +{% endraw %} + +You have to convert `site.data.samplelist.docs` to a variable first using either `assign` or `capture` tags. + +## Scenario 3: Two-level navigation list + +Suppose you want a more robust list that incorporates multiple sections of heading titles and subitems. To do this, add an additional level to each list item to store this information: + +**YAML** + +```yaml +toc: + - title: Group 1 + subfolderitems: + - page: Thing 1 + url: /thing1.html + - page: Thing 2 + url: /thing2.html + - page: Thing 3 + url: /thing3.html + - title: Group 2 + subfolderitems: + - page: Piece 1 + url: /piece1.html + - page: Piece 2 + url: /piece2.html + - page: Piece 3 + url: /piece3.html + - title: Group 3 + subfolderitems: + - page: Widget 1 + url: /widget1.html + - page: Widget 2 + url: /widget2.html + - page: Widget 3 + url: /widget3.html +``` + +**Liquid** + +{% raw %} +```liquid +{% for item in site.data.samplelist.toc %} +

    {{ item.title }}

    + + {% endfor %} +``` +{% endraw %} + +**Result** +
    +

    Group 1

    + + +

    Group 2

    + + +

    Group 3

    + +
    + +In this example, `Group 1` is the first list item. Within that list item, its subpages are included as a property that itself contains a list (`subfolderitems`). + +The Liquid code looks through the first level with `for item in site.data.samplelist.toc`, and then looks through the second-level property with `for entry in item.subfolderitems`. Just as `item` is an arbitrary name for the items we're looping through, so is `entry`. + +## Scenario 4: Three-level navigation list + +Building on the previous section, let's add one more level of depth (`subsubfolderitems`) to the list. The formatting will get more complex here, but the principles are the same. + +**YAML** + +```yaml +toc2: + - title: Group 1 + subfolderitems: + - page: Thing 1 + url: /thing1.html + - page: Thing 2 + url: /thing2.html + subsubfolderitems: + - page: Subthing 1 + url: /subthing1.html + - page: Subthing 2 + url: /subthing2.html + - page: Thing 3 + url: /thing3.html + - title: Group 2 + subfolderitems: + - page: Piece 1 + url: /piece1.html + - page: Piece 2 + url: /piece2.html + - page: Piece 3 + url: /piece3.html + subsubfolderitems: + - page: Subpiece 1 + url: /subpiece1.html + - page: Subpiece2 + url: /subpiece2.html + - title: Group 3 + subfolderitems: + - page: Widget 1 + url: /widget1.html + subsubfolderitems: + - page: Subwidget 1 + url: /subwidget1.html + - page: Subwidget 2 + url: /subwidget2.html + - page: Widget 2 + url: /widget2.html + - page: Widget 3 + url: /widget3.html +``` + +**Liquid** + +{% raw %} +```liquid +
    +{% if site.data.samplelist.toc2[0] %} + {% for item in site.data.samplelist.toc2 %} +

    {{ item.title }}

    + {% if item.subfolderitems[0] %} +
      + {% for entry in item.subfolderitems %} +
    • {{ entry.page }} + {% if entry.subsubfolderitems[0] %} + + {% endif %} +
    • + {% endfor %} +
    + {% endif %} + {% endfor %} +{% endif %} +
    +``` +{% endraw %} + +**Result** + +
    +
    +

    Group 1

    + +

    Group 2

    + +

    Group 3

    + +
    +
    + +In this example, `if site.data.samplelist.toc2[0]` is used to ensure that the YAML level actually contains items. If there isn't anything at the `[0]` position, we can skip looking in this level. + +
    +
    ProTip: Line up for loops and if statements
    +

    To keep the code clear, line up the beginning and ending Liquid tags, such as the for loops and if statements. This way you know when the open tags have been closed. If the code will appear in a Markdown page, keep the opening and closing HTML tags flush against the left edge so that the Markdown filter won't treat the content as a code sample. If necessary, you can wrap the entire code sample in a div tag to ensure the code has HTML tags that bookend the code.

    +
    + +## Scenario 5: Using a page variable to select the YAML list + +Suppose your sidebar will differ based on various documentation sets. You might have 3 different products on your site, and so you want 3 different sidebars — each unique for that product. + +You can store the name of the sidebar list in your page front matter and then pass that value into the list dynamically. + +**Page front matter** + +```yaml +--- +title: My page +sidebar: toc +--- +``` + +**Liquid** + +{% raw %} +```liquid +
      + {% for item in site.data.samplelist[page.sidebar] %} +
    • {{ item.title }}
    • + {% endfor %} +
    +``` +{% endraw %} + +**Result** + + + +In this scenario, we want to pass values from the page's front matter into a `for` loop that contains a variable. When the assigned variable isn't a string but rather a data reference, you must use brackets (instead of curly braces) to refer to the front matter's value. + +For more information, see [Expressions and Variables](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers#expressions-and-variables) in Liquid's documentation. Brackets are used in places where dot notation can't be used. You can also read more details in this [Stack Overflow answer](http://stackoverflow.com/questions/4968406/javascript-property-access-dot-notation-vs-brackets/4968448#4968448). + +## Scenario 6: Applying the active class for the current page + +In addition to inserting items from the YAML data file into your list, you also usually want to highlight the current link if the user is viewing that page. You do this by inserting an `active` class for items that match the current page URL. + +**CSS** + +```css +.result li.active a { + color: lightgray; + cursor: default; +} +``` + +**Liquid** + +{% raw %} +```liquid +{% for item in site.data.samplelist.docs %} +
  • + {{ item.title }} +
  • +{% endfor %} +``` +{% endraw %} + +**Result** + + + + + +In this case, assume `Deployment` is the current page. + +To make sure the `item.url` (stored in the YAML file) matches the `page.url`, it can be helpful to print the {% raw %}`{{ page.url }}`{% endraw %} to the page. + +## Scenario 7: Including items conditionally + +You might want to include items conditionally in your list. For example, maybe you have multiple site outputs and only want to include the sidebar item for certain outputs. You can add properties in each list item and then use those properties to conditionally include the content. + +**YAML** + +```yaml +docs2_list_title: ACME Documentation +docs2: + +- title: Introduction + url: introduction.html + version: 1 + +- title: Configuration + url: configuration.html + version: 1 + +- title: Deployment + url: deployment.html + version: 2 +``` + +**Liquid** + +{% raw %} +```liquid +
      + {% for item in site.data.samplelist.docs2 %} + {% if item.version == 1 %} +
    • {{ item.title }}
    • + {% endif %} + {% endfor %} +
    +``` +{% endraw %} + +**Result** + + + +The `Deployment` page is excluded because its `version` is `2`. + +## Scenario 8: Retrieving items based on front matter properties + +If you don't want to store your navigation items in a YAML file in your `_data` folder, you can use `for` loops to look through the front matter of each page or collection and get the content based on properties in the front matter. + +In this scenario, suppose we have a collection called `_docs`. Collections are often better than pages because they allow you to narrow the list of what you're looping through. (Try to avoid scenarios where you loop through large numbers of items, since it will increase your build time. [Collections]({% link _docs/collections.md %}) help you narrow the scope.) + +In our scenario, there are 6 docs in the `docs` collection: Sample 1, Sample 2, Topic 1, Topic 2, Widget 1, and Widget 2. + +Each doc in the collection contains at least 3 properties in the front matter: + +* `title` +* `category` +* `order` + +The front matter for each page is as follows (consolidated here for brevity): + +```yaml +--- +Title: Sample 1 +category: getting-started +order: 1 +--- + +--- +Title: Sample 2 +category: getting-started +order: 2 +--- + +--- +Title: Topic 1 +category: configuration +order: 1 +--- + +--- +Title: Topic 2 +category: configuration +order: 2 +--- + +--- +Title: Widget 1 +category: deployment +order: 1 +--- + +--- +Title: Widget 2 +category: deployment +order: 2 +--- +``` + +Note that even though `category` is used in the doc front matter, `category` is not a built-in variable like it is with posts. In other words, you cannot look directly inside `category` with `site.docs.category`. + +If you wanted to simply get all docs in the collection for a specific category, you could use a `for` loop with an `if` condition to check for a specific category: + +{% raw %} +```liquid +

    Getting Started

    +
      + {% for doc in site.docs %} + {% if doc.category == "getting-started" %} +
    • {{ doc.title }}
    • + {% endif %} + {% endfor %} +
    +``` +{% endraw %} + +The result would be as follows: + +
    +

    Getting Started

    + +
    + +This might be useful if you're setting up a knowledge base and have dozens of topics in each category, with each category displaying on its own page. + +But let's say you want to sort the items by category and group them under the category name, without hard-coding the category names. To achieve this, you could use two filters: + +* `group_by` +* `sort` + +Here's the code for getting lists of pages grouped under their corresponding category headers: + +**Liquid** + +{% raw %} +```liquid +{% assign mydocs = site.docs | group_by: 'category' %} +{% for cat in mydocs %} +

    {{ cat.name | capitalize }}

    +
      + {% assign items = cat.items | sort: 'order' %} + {% for item in items %} +
    • {{ item.title }}
    • + {% endfor %} +
    +{% endfor %} +``` +{% endraw %} + +**Result** + +
    +

    Getting-started

    + +

    Configuration

    + +

    Deployment

    + +
    + +Let's walk through the code. First, we assign a variable (`mydocs`) to the collection content (`site.docs`). + +The `group_by` filter groups the collection content by `category`. More specifically, the `group_by` filter converts `mydocs` into an array with `name`, `items`, and `size` properties, somewhat like this: + +```json +[ + {"name": "getting-started", "items": [Sample 1, Sample 2],"size": 2}, + {"name": "configuration", "items": [Topic 1, Topic 2], "size": 2}, + {"name": "deployment", "items": [Widget 1, Widget 2], "size": 2} +] +``` + +Using `for cat in mydocs`, we look through each item in the `mydocs` array and print the category `name`. + +After getting the category name, we assign the variable `items` for the docs and use the `sort` filter to arrange the docs by their `order` property. The dot notation `cat.items` is used because we're accessing the content in the `items` array. The `sort` filter orders the items by their numbers in ascending order. + +The `for item in items` loop looks through each `item` and gets the `title` and `url` to form the list item link. + +For more details on the `group_by` filter, see [Jekyll's Templates documentation](https://jekyllrb.com/docs/templates/) as well as [this Siteleaf tutorial](https://www.siteleaf.com/blog/advanced-liquid-group-by/). For more details on the `sort` filter, see [sort](https://shopify.github.io/liquid/filters/sort/) in Liquid's documentation. + +Whether you use properties in your doc's front matter to retrieve your pages or a YAML data file, in both cases you can programmatically build a more robust navigation for your site. + +## Scenario 9: Nested tree navigation with recursion + +Suppose you want a nested tree navigation of any depth. We can achieve this by recursively looping through our tree of navigation links. + +**YAML** + +```yaml +nav: + - title: Deployment + url: deployment.html + subnav: + - title: Heroku + url: heroku.html + subnav: + - title: Jekyll on Heroku + url: jekyll-on-heroku.html + - title: Help + url: help.html +``` + +**Liquid** + +First, we'll create an include that we can use for rendering the navigation tree. This file would be `_includes/nav.html` + +{% raw %} +```liquid +
      + {% for item in include.nav %} +
    • {{ item.title }} + {% if item.subnav %} + {% include nav.html nav=item.subnav %} + {% endif %} +
    • + {% endfor %} +
    +``` +{% endraw %} + +To render this in your layout or pages, you would simply include the template and pass in the `nav` parameter. In this case, we'll use the `page.nav` to grab it from the yaml frontmatter. + +{% raw %} +```liquid +{% include nav.html nav=page.nav %} +``` +{% endraw %} + +Our include will use this first, then look through each item for a `subnav` property to recursively render the nested lists. + +**Result** +
    + +
    diff --git a/docs/_tutorials/orderofinterpretation.md b/docs/_tutorials/orderofinterpretation.md new file mode 100644 index 00000000000..b3ec9227b1f --- /dev/null +++ b/docs/_tutorials/orderofinterpretation.md @@ -0,0 +1,159 @@ +--- +title: Order of interpretation +author: tomjoht +date: 2017-01-29 21:45:03 -0800 +--- + +Jekyll's main job is to convert your raw text files into a static website. It does this by rendering Liquid, Markdown, and other transforms as it generates the static HTML output. + +In this conversion process, it's important to understand Jekyll's order of interpretation. By "order of interpretation," we mean what gets rendered, in what order, and what rules get applied in converting content. + +If an element isn't converting, you can troubleshoot the problem by analyzing the order of interpretation. + +## Order of interpretations + +Jekyll converts your site in the following order: + +1. **Site variables**. Jekyll looks across your files and populates [site variables]({% link _docs/variables.md %}), such as `site`, `page`, `post`, and collection objects. (From these objects, Jekyll determines the values for permalinks, tags, categories, and other details.) + +2. **Liquid**. Jekyll processes any [Liquid](https://github.com/Shopify/liquid) formatting in pages that contain [front matter]({% link _docs/front-matter.md %}). You can identify Liquid as follows: + * **Liquid tags** start with {% raw %}`{%`{% endraw %} and end with a {% raw %}`%}`{% endraw %}. For example: {% raw %}`{% highlight %}`{% endraw %} or {% raw %}`{% seo %}`{% endraw %}. Tags can define blocks or be inline. Block-defining tags will also come with a corresponding end tag — for example, {% raw %}`{% endhighlight %}`{% endraw %}. + * **Liquid variables** start and end with double curly braces. For example: {% raw %}`{{ site.myvariable }}`{% endraw %} or {% raw %}`{{ content }}`{% endraw %}. + * **Liquid filters** start with a pipe character (`|`) and can only be used within **Liquid variables** after the variable string. For example: the `relative_url` filter in {% raw %}`{{ "css/main.css" | relative_url }}`{% endraw %}. + +3. **Markdown**. Jekyll converts Markdown to HTML using the Markdown filter specified in your config file. Files must have a Markdown file extension and front matter in order for Jekyll to convert them. + +4. **Layout**. Jekyll pushes content into the layouts specified by the page's front matter (or as specified in the config file). The content from each page gets pushed into the {% raw %}`{{ content }}`{% endraw %} tags within the layouts. + +5. **Files**. Jekyll writes the generated content into files in the [directory structure]({% link _docs/structure.md %}) in `_site`. Pages, posts, and collections get structured based on their [permalink]({% link _docs/permalinks.md %}) setting. Directories that begin with `_` (such as `_includes` and `_data`) are usually hidden in the output. + +## Scenarios where incorrect configurations create problems + +For the most part, you don't have to think about the order of interpretation when building your Jekyll site. These details only become important to know when something isn't rendering. + +The following scenarios highlight potential problems you might encounter. These problems come from misunderstanding the order of interpretation and can be easily fixed. + +### Variable on page not rendered because variable is assigned in layout + +In your layout file (`_layouts/default.html`), suppose you have a variable assigned: + +{% raw %} +```liquid +{% assign myvar = "joe" %} +``` +{% endraw %} + +On a page that uses the layout, you reference that variable: + +{% raw %} +```liquid +{{ myvar }} +``` +{% endraw %} + +The variable won't render because the page's order of interpretation is to render Liquid first and later process the Layout. When the Liquid rendering happens, the variable assignment isn't available. + +To make the code work, you could put the variable assignment into the page's front matter. + +### Markdown in include file not processed + +Suppose you have a Markdown file at `_includes/mycontent.md`. In the Markdown file, you have some Markdown formatting: + +```markdown +This is a list: +* first item +* second item +``` + +You include the file into an HTML file as follows: + +{% raw %} +```liquid +{% include mycontent.md %} +``` +{% endraw %} + +The Markdown is not processed because first the Liquid (`include` tag) gets processed, inserting `mycontent.md` into the HTML file. *Then* the Markdown would get processed. + +But because the content is included into an *HTML* page, the Markdown isn't rendered. The Markdown filter processes content only in Markdown files. + +To make the code work, use HTML formatting in includes that are inserted into HTML files. + +Note that `highlight` tags don't require Markdown to process. Suppose your include contains the following: + +{% raw %} +```liquid +{% highlight javascript %} +console.log('alert'); +{% endhighlight %} +``` +{% endraw %} + +The `highlight` tag *is* Liquid. (Liquid passes the content to Rouge for syntax highlighting.) As a result, this code will actually convert to HTML with syntax highlighting. Jekyll does not need the Markdown filter to process `highlight` tags. + +### Liquid mixed with JavaScript isn't rendered + +Suppose you try to mix Liquid's `assign` tag with JavaScript, like this: + +{% raw %} +```javascript + + +

    + + +``` +{% endraw %} + +This won't work because the `assign` tag is only available during the Liquid rendering phase of the site. In this JavaScript example, the script executes when a user clicks a button ("Click me") on the HTML page. At that time, the Liquid logic is no longer available, so the `assign` tag wouldn't return anything. + +However, you can use Jekyll's site variables or Liquid to *populate* a script that is executed at a later time. For example, suppose you have the following property in your front matter: `someContent: "This is some content"`. You could do this: + +{% raw %} +```javascript + + +

    + + +``` +{% endraw %} + +When Jekyll builds the site, this `someContent` property populates the script's values, converting {% raw %}`{{ page.someContent }}`{% endraw %} to `"This is some content"`. + +The key to remember is that Liquid renders when Jekyll builds your site. Liquid is not available at run-time in the browser when a user executes an event. + +## Note about using Liquid in YAML + +There's one more detail to remember: Liquid does not render when embedded in YAML files or front matter. (This isn't related to order of interpretation, but it's worth mentioning because it's a common question about element rendering.) + +For example, suppose you have a `highlight` tag in your `_data/mydata.yml` file: + +{% raw %} +```liquid +myvalue: > + {% highlight javascript %} + console.log('alert'); + {% endhighlight %} +``` +{% endraw %} + +On a page, you try to insert the value: + +{% raw %} +```liquid +{{ site.data.mydata.myvalue }} +``` +{% endraw %} + +This would render only as a string rather than a code sample with syntax highlighting. To make the code render, consider using an include instead. diff --git a/docs/_tutorials/using-jekyll-with-bundler.md b/docs/_tutorials/using-jekyll-with-bundler.md new file mode 100644 index 00000000000..c11df30ef1e --- /dev/null +++ b/docs/_tutorials/using-jekyll-with-bundler.md @@ -0,0 +1,125 @@ +--- +title: Using Jekyll with Bundler +author: mkasberg +date: 2018-03-06 21:33:25 -0700 +--- + +> Bundler provides a consistent environment for Ruby projects by tracking and +> installing the exact gems and versions that are needed. + +[Bundler](https://bundler.io) can be a great tool to use with Jekyll. Because it +tracks dependencies on a per-project basis, it is particularly useful if you +need to run different versions of Jekyll in different projects. + +In addition, because it can (optionally) install dependencies in the project +folder, it can help you avoid permissions issues you might otherwise run into. +The usual way to use Jekyll is to install Jekyll to the system's default gem +installation directory and then run `jekyll new`. In this tutorial, we'll show +you how to create a new Jekyll project using Bundler and without installing gems +outside the project directory. + +
    +
    This is not the simplest way to start using Jekyll
    +

    + This tutorial helps you get Jekyll set up using Bundler, and optionally + without any system-wide gem installations. If prefer installing the jekyll + command to your default gem installation directory, you might want the + Quickstart. +

    +
    + +## Before You Begin + +To complete this tutorial, you'll need to have +[Ruby](https://www.ruby-lang.org/en/) and [Bundler](https://bundler.io/) +installed. You can find the installation instructions on their websites. + +## Initialize Bundler + +The first thing to do is create a new directory for your project and run +`bundle init`. This creates a new Bundler project (by creating an empty +Gemfile). + +```sh +mkdir my-jekyll-website +cd my-jekyll-website +bundle init +``` + +## Configure Bundler Install Path + +This step is optional. In this step, we're going to configure Bundler to install +gems in the `./vendor/bundle/` project subdirectory. The advantage of doing this +is that bundler will install gems within your project folder instead of the +location used by `gem install`. This can help you avoid permissions errors you +might otherwise get during gem installation, depending how you installed Ruby. +If you skip this step, Bundler will install your dependencies to the location +used by `gem install`. + + +```sh +bundle config set --local path 'vendor/bundle' +``` + +
    +
    Bundler Config is Persistent
    +

    + This step is only required once per project. Bundler saves your config in + ./.bundle/config, so future gems will be installed to the same + location. +

    +
    + +## Add Jekyll + +Now, we're going to use Bundler to add Jekyll as a dependency of our new +project. This command will add the Jekyll gem to our Gemfile and install it to +the `./vendor/bundle/` folder (or your default gem installation directory if you +didn't set a custom path). + +```sh +bundle add jekyll +``` + +## Create A Jekyll Scaffold + +Now that Jekyll is installed, we can use it to create the scaffolding for our +site. We need the `--force` parameter because our folder isn't empty - it +already has some Bundler files in it. We run the `bundle install` separately +because Jekyll gets confused if the Gemfile already exists. + +```sh +bundle exec jekyll new --force --skip-bundle . +bundle install +``` + +## Serve the Site + +Your new website is ready! You can serve the website with +`bundle exec jekyll serve` and visit it at +[http://127.0.0.1:4000](http://127.0.0.1:4000). From here, you're ready to +continue developing the site on your own. All of the normal Jekyll commands are +available to you, but you should prefix them with `bundle exec` so that Bundler +runs the version of Jekyll that is installed in your project folder. + +## Commit to Source Control + +If you're storing your new site in version control, you'll want to ignore the +`./vendor/` and `./.bundle/` folders since they contain user- or +platform-specific information. New users will be able to install the correct +dependencies based on `Gemfile` and `Gemfile.lock`, which should both be checked +in. You can use this `.gitignore` to get started, if you want. + +**.gitignore** + +``` +# Ignore metadata generated by Jekyll +_site/ +.sass-cache/ +.jekyll-cache/ +.jekyll-metadata + +# Ignore folders generated by Bundler +.bundle/ +vendor/ +``` diff --git a/docs/_tutorials/video-walkthroughs.md b/docs/_tutorials/video-walkthroughs.md new file mode 100644 index 00000000000..521bd5e1d37 --- /dev/null +++ b/docs/_tutorials/video-walkthroughs.md @@ -0,0 +1,33 @@ +--- +title: Video Walkthroughs +author: giraffeacademy +date: 2017-10-02 15:20:08 -0400 +--- + +[Giraffe Academy](https://www.youtube.com/c/GiraffeAcademy) has a series of videos that will walk you through the basics of using Jekyll. In this series you'll learn everything from installing Jekyll on your computer and setting up your first site, to using more complex features like variables, layouts and conditionals. + +
    + +
    + +## List of Lessons + +1. [Introduction to Jekyll (see above)](https://www.youtube.com/watch?v=T1itpPvFWHI&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=1) +2. [Mac Installation](https://www.youtube.com/watch?v=WhrU9m82Wm8&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=2) +3. [Windows Installation](https://www.youtube.com/watch?v=LfP7Y9Ja6Qc&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=3) +4. [Creating a Site](https://www.youtube.com/watch?v=pxua_1vyFck&index=4&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +5. [Front Matter](https://www.youtube.com/watch?v=ZtEbGztktvc&index=5&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +6. [Writing Posts](https://www.youtube.com/watch?v=gsYqPL9EFwQ&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=6) +7. [Working With Drafts](https://www.youtube.com/watch?v=X8jXkW3k2Jg&index=7&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +8. [Creating Pages](https://www.youtube.com/watch?v=1na-IWfv08M&index=8&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +9. [Permalinks](https://www.youtube.com/watch?v=938jDG_YPdc&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=9) +10. [Front Matter Defaults](https://www.youtube.com/watch?v=CLCaJJ1zUHU&index=10&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +11. [Themes](https://www.youtube.com/watch?v=NoRS2D-cyko&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=11) +12. [Layouts](https://www.youtube.com/watch?v=bDQsGdCWv4I&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=12) +13. [Variables](https://www.youtube.com/watch?v=nLJBF2KiOZw&index=13&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +14. [Includes](https://www.youtube.com/watch?v=HfcJeRby2a8&index=14&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +15. [Looping Through Posts](https://www.youtube.com/watch?v=6N1X5XffuUA&index=15&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +16. [Conditionals](https://www.youtube.com/watch?v=iNZBEki_x6o&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=16) +17. [Data Files](https://www.youtube.com/watch?v=M6b0KmLB-pM&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=17) +18. [Static Files](https://www.youtube.com/watch?v=knWjmVlVpso&index=18&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB) +19. [Hosting on GitHub Pages](https://www.youtube.com/watch?v=fqFjuX4VZmU&list=PLLAZ4kZ9dFpOPV5C5Ay0pHaa0RJFhcmcB&index=19) diff --git a/site/css/screen.scss b/docs/css/screen.scss similarity index 77% rename from site/css/screen.scss rename to docs/css/screen.scss index 2eff7f89df7..766f964b016 100644 --- a/site/css/screen.scss +++ b/docs/css/screen.scss @@ -6,4 +6,6 @@ @import "gridism"; @import "pygments"; @import "font-awesome"; +@import "fonts"; +@import "docsearch"; @import "style"; diff --git a/site/favicon.ico b/docs/favicon.ico similarity index 100% rename from site/favicon.ico rename to docs/favicon.ico diff --git a/docs/fonts/FontAwesome.eot b/docs/fonts/FontAwesome.eot new file mode 100644 index 00000000000..4f0b1de2bd3 Binary files /dev/null and b/docs/fonts/FontAwesome.eot differ diff --git a/docs/fonts/FontAwesome.svg b/docs/fonts/FontAwesome.svg new file mode 100644 index 00000000000..32ad8fb7502 --- /dev/null +++ b/docs/fonts/FontAwesome.svg @@ -0,0 +1,12 @@ + + + +Generated by IcoMoon + + + + + + + + \ No newline at end of file diff --git a/docs/fonts/FontAwesome.ttf b/docs/fonts/FontAwesome.ttf new file mode 100644 index 00000000000..47e2443e990 Binary files /dev/null and b/docs/fonts/FontAwesome.ttf differ diff --git a/docs/fonts/FontAwesome.woff b/docs/fonts/FontAwesome.woff new file mode 100644 index 00000000000..bec5c4fe77c Binary files /dev/null and b/docs/fonts/FontAwesome.woff differ diff --git a/docs/fonts/lato-v14-latin-300.woff b/docs/fonts/lato-v14-latin-300.woff new file mode 100644 index 00000000000..ab45ab76bac Binary files /dev/null and b/docs/fonts/lato-v14-latin-300.woff differ diff --git a/docs/fonts/lato-v14-latin-300.woff2 b/docs/fonts/lato-v14-latin-300.woff2 new file mode 100644 index 00000000000..136337fdc2c Binary files /dev/null and b/docs/fonts/lato-v14-latin-300.woff2 differ diff --git a/docs/fonts/lato-v14-latin-300italic.woff b/docs/fonts/lato-v14-latin-300italic.woff new file mode 100644 index 00000000000..0287996f125 Binary files /dev/null and b/docs/fonts/lato-v14-latin-300italic.woff differ diff --git a/docs/fonts/lato-v14-latin-300italic.woff2 b/docs/fonts/lato-v14-latin-300italic.woff2 new file mode 100644 index 00000000000..fd1977b68a9 Binary files /dev/null and b/docs/fonts/lato-v14-latin-300italic.woff2 differ diff --git a/docs/fonts/lato-v14-latin-700.woff b/docs/fonts/lato-v14-latin-700.woff new file mode 100644 index 00000000000..1d9d75bc6a5 Binary files /dev/null and b/docs/fonts/lato-v14-latin-700.woff differ diff --git a/docs/fonts/lato-v14-latin-700.woff2 b/docs/fonts/lato-v14-latin-700.woff2 new file mode 100644 index 00000000000..d88f1af8c8a Binary files /dev/null and b/docs/fonts/lato-v14-latin-700.woff2 differ diff --git a/docs/fonts/lato-v14-latin-700italic.woff b/docs/fonts/lato-v14-latin-700italic.woff new file mode 100644 index 00000000000..f79d9a994ac Binary files /dev/null and b/docs/fonts/lato-v14-latin-700italic.woff differ diff --git a/docs/fonts/lato-v14-latin-700italic.woff2 b/docs/fonts/lato-v14-latin-700italic.woff2 new file mode 100644 index 00000000000..c351d88d811 Binary files /dev/null and b/docs/fonts/lato-v14-latin-700italic.woff2 differ diff --git a/docs/fonts/lato-v14-latin-900.woff b/docs/fonts/lato-v14-latin-900.woff new file mode 100644 index 00000000000..6f251d9e794 Binary files /dev/null and b/docs/fonts/lato-v14-latin-900.woff differ diff --git a/docs/fonts/lato-v14-latin-900.woff2 b/docs/fonts/lato-v14-latin-900.woff2 new file mode 100644 index 00000000000..a5abe367ec6 Binary files /dev/null and b/docs/fonts/lato-v14-latin-900.woff2 differ diff --git a/docs/fonts/lato-v14-latin-900italic.woff b/docs/fonts/lato-v14-latin-900italic.woff new file mode 100644 index 00000000000..6922b8fec98 Binary files /dev/null and b/docs/fonts/lato-v14-latin-900italic.woff differ diff --git a/docs/fonts/lato-v14-latin-900italic.woff2 b/docs/fonts/lato-v14-latin-900italic.woff2 new file mode 100644 index 00000000000..0d0f984e7c5 Binary files /dev/null and b/docs/fonts/lato-v14-latin-900italic.woff2 differ diff --git a/docs/fonts/lato-v14-latin-italic.woff b/docs/fonts/lato-v14-latin-italic.woff new file mode 100644 index 00000000000..169e8cf544b Binary files /dev/null and b/docs/fonts/lato-v14-latin-italic.woff differ diff --git a/docs/fonts/lato-v14-latin-italic.woff2 b/docs/fonts/lato-v14-latin-italic.woff2 new file mode 100644 index 00000000000..2688dc6f7ac Binary files /dev/null and b/docs/fonts/lato-v14-latin-italic.woff2 differ diff --git a/docs/fonts/lato-v14-latin-regular.woff b/docs/fonts/lato-v14-latin-regular.woff new file mode 100644 index 00000000000..97ab144d9fd Binary files /dev/null and b/docs/fonts/lato-v14-latin-regular.woff differ diff --git a/docs/fonts/lato-v14-latin-regular.woff2 b/docs/fonts/lato-v14-latin-regular.woff2 new file mode 100644 index 00000000000..b14c76cab32 Binary files /dev/null and b/docs/fonts/lato-v14-latin-regular.woff2 differ diff --git a/docs/icomoon-selection.json b/docs/icomoon-selection.json new file mode 100644 index 00000000000..2696104e2e1 --- /dev/null +++ b/docs/icomoon-selection.json @@ -0,0 +1,96 @@ +{ + "IcoMoonType": "selection", + "icons": [ + { + "icon": { + "paths": [ + "M207.429 877.714l52-52-134.286-134.286-52 52v61.143h73.143v73.143h61.143zM506.286 347.429c0-7.429-5.143-12.571-12.571-12.571-3.429 0-6.857 1.143-9.714 4l-309.714 309.714c-2.857 2.857-4 6.286-4 9.714 0 7.429 5.143 12.571 12.571 12.571 3.429 0 6.857-1.143 9.714-4l309.714-309.714c2.857-2.857 4-6.286 4-9.714zM475.429 237.714l237.714 237.714-475.429 475.429h-237.714v-237.714zM865.714 292.571c0 19.429-8 38.286-21.143 51.429l-94.857 94.857-237.714-237.714 94.857-94.286c13.143-13.714 32-21.714 51.429-21.714s38.286 8 52 21.714l134.286 133.714c13.143 13.714 21.143 32.571 21.143 52z" + ], + "width": 865.7188571428571, + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "pencil" + ], + "defaultCode": 61504, + "grid": 14 + }, + "attrs": [], + "properties": { + "name": "pencil", + "id": 64, + "order": 3, + "prevSize": 28, + "code": 61504 + }, + "setIdx": 0, + "setId": 0, + "iconIdx": 64 + }, + { + "icon": { + "paths": [ + "M832 694.857c0-14.857-5.714-28.571-16-38.857l-118.857-118.857c-10.286-10.286-24.571-16-38.857-16-16.571 0-29.714 6.286-41.143 18.286 18.857 18.857 41.143 34.857 41.143 64 0 30.286-24.571 54.857-54.857 54.857-29.143 0-45.143-22.286-64-41.143-12 11.429-18.857 24.571-18.857 41.714 0 14.286 5.714 28.571 16 38.857l117.714 118.286c10.286 10.286 24.571 15.429 38.857 15.429s28.571-5.143 38.857-14.857l84-83.429c10.286-10.286 16-24 16-38.286zM430.286 292c0-14.286-5.714-28.571-16-38.857l-117.714-118.286c-10.286-10.286-24.571-16-38.857-16s-28.571 5.714-38.857 15.429l-84 83.429c-10.286 10.286-16 24-16 38.286 0 14.857 5.714 28.571 16 38.857l118.857 118.857c10.286 10.286 24.571 15.429 38.857 15.429 16.571 0 29.714-5.714 41.143-17.714-18.857-18.857-41.143-34.857-41.143-64 0-30.286 24.571-54.857 54.857-54.857 29.143 0 45.143 22.286 64 41.143 12-11.429 18.857-24.571 18.857-41.714zM941.714 694.857c0 43.429-17.714 85.714-48.571 116l-84 83.429c-30.857 30.857-72.571 47.429-116 47.429-44 0-85.714-17.143-116.571-48.571l-117.714-118.286c-30.857-30.857-47.429-72.571-47.429-116 0-45.143 18.286-88 50.286-119.429l-50.286-50.286c-31.429 32-73.714 50.286-118.857 50.286-43.429 0-85.714-17.143-116.571-48l-118.857-118.857c-31.429-31.429-48-72.571-48-116.571 0-43.429 17.714-85.714 48.571-116l84-83.429c30.857-30.857 72.571-47.429 116-47.429 44 0 85.714 17.143 116.571 48.571l117.714 118.286c30.857 30.857 47.429 72.571 47.429 116 0 45.143-18.286 88-50.286 119.429l50.286 50.286c31.429-32 73.714-50.286 118.857-50.286 43.429 0 85.714 17.143 116.571 48l118.857 118.857c31.429 31.429 48 72.571 48 116.571z" + ], + "width": 950.8571428571428, + "attrs": [], + "isMulticolor": false, + "isMulticolor2": false, + "tags": [ + "chain", + "link" + ], + "defaultCode": 61633, + "grid": 14 + }, + "attrs": [], + "properties": { + "name": "chain, link", + "id": 170, + "order": 2, + "prevSize": 28, + "code": 61633 + }, + "setIdx": 0, + "setId": 0, + "iconIdx": 170 + } + ], + "height": 1024, + "metadata": { + "name": "FontAwesome" + }, + "preferences": { + "showGlyphs": true, + "showCodes": true, + "showQuickUse": true, + "showQuickUse2": true, + "showSVGs": true, + "fontPref": { + "prefix": "fa-", + "metadata": { + "fontFamily": "FontAwesome", + "majorVersion": 1, + "minorVersion": 0 + }, + "metrics": { + "emSize": 1024, + "baseline": 6.25, + "whitespace": 50 + }, + "embed": false, + "showSelector": true, + "selector": "class", + "classSelector": ".fa" + }, + "imagePref": { + "prefix": "icon-", + "png": true, + "useClassSelector": true, + "color": 0, + "bgColor": 16777215 + }, + "historySize": 100 + } +} \ No newline at end of file diff --git a/docs/img/article-footer.png b/docs/img/article-footer.png new file mode 100644 index 00000000000..eeb74411cd0 Binary files /dev/null and b/docs/img/article-footer.png differ diff --git a/site/img/footer-arrow.png b/docs/img/footer-arrow.png similarity index 100% rename from site/img/footer-arrow.png rename to docs/img/footer-arrow.png diff --git a/docs/img/footer-logo.png b/docs/img/footer-logo.png new file mode 100644 index 00000000000..e64790b38e2 Binary files /dev/null and b/docs/img/footer-logo.png differ diff --git a/docs/img/forestry-logo.svg b/docs/img/forestry-logo.svg new file mode 100644 index 00000000000..4b4beda3ff4 --- /dev/null +++ b/docs/img/forestry-logo.svg @@ -0,0 +1,19 @@ + diff --git a/docs/img/jekyll-og.png b/docs/img/jekyll-og.png new file mode 100644 index 00000000000..508c42a28e4 Binary files /dev/null and b/docs/img/jekyll-og.png differ diff --git a/site/img/jekyll-sticker.jpg b/docs/img/jekyll-sticker.jpg similarity index 88% rename from site/img/jekyll-sticker.jpg rename to docs/img/jekyll-sticker.jpg index de3eb1b1c76..b51680cdedb 100644 Binary files a/site/img/jekyll-sticker.jpg and b/docs/img/jekyll-sticker.jpg differ diff --git a/docs/img/jekyll-sticker.png b/docs/img/jekyll-sticker.png new file mode 100644 index 00000000000..09e5cbf5b12 Binary files /dev/null and b/docs/img/jekyll-sticker.png differ diff --git a/docs/img/jekylllayoutconcept.png b/docs/img/jekylllayoutconcept.png new file mode 100644 index 00000000000..e7fa6d7ada6 Binary files /dev/null and b/docs/img/jekylllayoutconcept.png differ diff --git a/docs/img/logo-2x.png b/docs/img/logo-2x.png new file mode 100644 index 00000000000..57af994c61a Binary files /dev/null and b/docs/img/logo-2x.png differ diff --git a/site/img/logo-rss.png b/docs/img/logo-rss.png similarity index 100% rename from site/img/logo-rss.png rename to docs/img/logo-rss.png diff --git a/site/img/octojekyll.png b/docs/img/octojekyll.png similarity index 100% rename from site/img/octojekyll.png rename to docs/img/octojekyll.png diff --git a/docs/img/spacer.gif b/docs/img/spacer.gif new file mode 100644 index 00000000000..4bcc753a12e Binary files /dev/null and b/docs/img/spacer.gif differ diff --git a/docs/img/twitter-card.png b/docs/img/twitter-card.png new file mode 100644 index 00000000000..b828c1a9d11 Binary files /dev/null and b/docs/img/twitter-card.png differ diff --git a/site/js/html5shiv.min.js b/docs/js/html5shiv.min.js similarity index 90% rename from site/js/html5shiv.min.js rename to docs/js/html5shiv.min.js index d4c731ad544..1a01c94ba47 100644 --- a/site/js/html5shiv.min.js +++ b/docs/js/html5shiv.min.js @@ -1,4 +1,4 @@ /** -* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed */ -!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); \ No newline at end of file +!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); diff --git a/site/js/respond.min.js b/docs/js/respond.min.js similarity index 100% rename from site/js/respond.min.js rename to docs/js/respond.min.js diff --git a/docs/latest_version.txt b/docs/latest_version.txt new file mode 100644 index 00000000000..cca25a93cd0 --- /dev/null +++ b/docs/latest_version.txt @@ -0,0 +1 @@ +4.4.1 diff --git a/docs/pages/404.html b/docs/pages/404.html new file mode 100644 index 00000000000..c561ecdff0e --- /dev/null +++ b/docs/pages/404.html @@ -0,0 +1,29 @@ +--- +layout: error +permalink: /404.html +sitemap: false +--- + +
    +
    +
    +

    Huh. It seems that page is
    Hyde-ing...

    +
    +
    +
    + +
    +
    +
    +

    The resource you requested was not found. Here are some links to help you find your way:

    + +
    +
    +
    diff --git a/site/index.html b/docs/pages/index.html similarity index 69% rename from site/index.html rename to docs/pages/index.html index a8bda742851..971b8187dda 100644 --- a/site/index.html +++ b/docs/pages/index.html @@ -1,7 +1,7 @@ --- layout: default -title: Jekyll • Simple, blog-aware, static sites overview: true +permalink: / ---
    @@ -11,26 +11,26 @@
-
+
@@ -46,7 +46,7 @@

Get up and running in seconds.

~ $ - gem install jekyll + gem install bundler jekyll

~ @@ -61,7 +61,7 @@

Get up and running in seconds.

~/my-awesome-site $ - jekyll serve + bundle exec jekyll serve

# => Now browse to http://localhost:4000 @@ -76,11 +76,11 @@

Get up and running in seconds.

- Free Jekyll hosting on GitHub Pages + Free Jekyll hosting on GitHub Pages

Free hosting with GitHub Pages

-

Sick of dealing with hosting companies? GitHub Pages are powered by Jekyll, so you can easily deploy your site using GitHub for free—custom domain name and all.

- Learn more about GitHub Pages → +

Sick of dealing with hosting companies? GitHub Pages is powered by Jekyll, so you can easily deploy your site using GitHub for free—custom domain name and all.

+ Learn more about GitHub Pages →
diff --git a/docs/pages/jekyllconf.md b/docs/pages/jekyllconf.md new file mode 100644 index 00000000000..2b6ac792e06 --- /dev/null +++ b/docs/pages/jekyllconf.md @@ -0,0 +1,25 @@ +--- +layout: page +title: JekyllConf +permalink: /jekyllconf/ +--- + +[JekyllConf](https://jekyllconf.com) is a free, online conference for all things Jekyll hosted by [CloudCannon](https://cloudcannon.com). Each year members of the Jekyll community speak about interesting use cases, tricks they've learned, or meta Jekyll topics. + +## Featured + +{% assign random = site.time | date: "%s%N" | modulo: site.data.jekyllconf-talks.size %} +{% assign featured = site.data.jekyllconf-talks[random] %} + +**{{ featured.topic }}** - [*{{ featured.speaker }}*](https://twitter.com/{{ featured.twitter_handle }}) +
+ +
+ +{% assign talks = site.data.jekyllconf-talks | group_by: 'year' %} +{% for year in talks reversed %} +## {{ year.name }} +{% for talk in year.items %} + * [**{{ talk.topic }}**](https://youtu.be/{{ talk.youtube_id }}) - [*{{ talk.speaker }}*](https://twitter.com/{{ talk.twitter_handle }}) +{% endfor %} +{% endfor %} diff --git a/docs/pages/news.html b/docs/pages/news.html new file mode 100644 index 00000000000..c010d2d3a0e --- /dev/null +++ b/docs/pages/news.html @@ -0,0 +1,14 @@ +--- +layout: news +title: News +permalink: /news/ +author: all +--- + +{% for post in site.posts -%} + {% if forloop.index == 1 -%} + {% include news_item.html -%} + {% else -%} + {% include news_item_archive.html -%} + {% endif -%} +{% endfor -%} diff --git a/docs/pages/philosophy.md b/docs/pages/philosophy.md new file mode 100644 index 00000000000..93021fbe163 --- /dev/null +++ b/docs/pages/philosophy.md @@ -0,0 +1,52 @@ +--- +layout: page +title: Philosophy +permalink: /philosophy/ +--- + +Jekyll offers a unique philosophy when approaching the problem of static +site generation. This core philosophy drives development and product +decisions. When a contributor, maintainer, or user asks herself what Jekyll +is about, the following principles should come to mind: + +### 1. No Magic + +Jekyll is not magic. A user should be able to understand the underlying +processes that make up the Jekyll build without much reading. It should +do only what you ask it to and nothing more. When a user takes a certain +action, the outcome should be easily understandable and focused. + +### 2. It "Just Works" + +The out-of-the-box experience should be that it "just works." Run +`gem install jekyll` and it should build any Jekyll site that it's given. +Features like auto-regeneration and settings like the markdown renderer +should represent sane defaults that work perfectly for the vast majority of +cases. The burden of initial configuration should not be placed on the user. + +### 3. Content is King + +Why is Jekyll so loved by content creators? It focuses on content first and +foremost, making the process of publishing content on the Web easy. Users +should find the management of their content enjoyable and simple. + +### 4. Stability + +If a user's site builds today, it should build tomorrow. +Backwards-compatibility should be strongly preferred over breaking changes. +Breaking changes should be made to support a strong practical goal, and +breaking changes should never be made to drive forward "purity" of the +codebase, or other changes purely to make the maintainers' lives easier. +Breaking changes provide a significant amount of friction between upgrades +and reduce the confidence of users in this software, and should thus be +avoided unless absolutely necessary. +Upon breaking changes, provide a clear path for users to upgrade. + +### 5. Small & Extensible + +The core of Jekyll should be simple and small, and extensibility should be +a first-class feature to provide added functionality from community +contributors. The core should be kept to features used by at least 90% of +users–everything else should be provided as a plugin. New features should +be shipped as plugins and focus should be put on creating extensible core +API's to support rich plugins. diff --git a/docs/pages/redirects/github.html b/docs/pages/redirects/github.html new file mode 100644 index 00000000000..6042d0d068a --- /dev/null +++ b/docs/pages/redirects/github.html @@ -0,0 +1,4 @@ +--- +permalink: /github.html +redirect_to: https://github.com/jekyll/jekyll +--- diff --git a/docs/pages/redirects/issues.html b/docs/pages/redirects/issues.html new file mode 100644 index 00000000000..677605101a1 --- /dev/null +++ b/docs/pages/redirects/issues.html @@ -0,0 +1,4 @@ +--- +permalink: /issues.html +redirect_to: https://github.com/jekyll/jekyll/issues +--- diff --git a/docs/pages/releases.html b/docs/pages/releases.html new file mode 100644 index 00000000000..f8416c07e11 --- /dev/null +++ b/docs/pages/releases.html @@ -0,0 +1,14 @@ +--- +layout: news +title: Releases +permalink: /news/releases/ +author: all +--- + +{% for post in site.categories.release -%} + {% if forloop.index == 1 -%} + {% include news_item.html -%} + {% else -%} + {% include news_item_archive.html -%} + {% endif -%} +{% endfor -%} diff --git a/docs/pages/resources.md b/docs/pages/resources.md new file mode 100644 index 00000000000..5f08a1a5eb4 --- /dev/null +++ b/docs/pages/resources.md @@ -0,0 +1,102 @@ +--- +layout: page +title: Resources +permalink: /resources/ +redirect_from: + - /docs/resources/ +--- +Jekyll's growing community produces wide variety of themes, plugins, tutorials +and other resources that can be helpful. Below is a collection of links to +some of the most popular Jekyll resources. + +## Themes +- [GitHub.com #jekyll-theme repos](https://github.com/topics/jekyll-theme) +- [jamstackthemes.dev](https://jamstackthemes.dev/ssg/jekyll/) +- [jekyllthemes.org](http://jekyllthemes.org/) +- [jekyllthemes.io](https://jekyllthemes.io/) +- [builtatlightspeed.com](https://builtatlightspeed.com/category/jekyll) + +See also: [docs/themes](/docs/themes/). + +## Plugins +- [jekyll-plugin topic on GitHub](https://github.com/topics/jekyll-plugin) +- [Planet Jekyll](https://github.com/planetjekyll/awesome-jekyll-plugins) + +## Guides + +- [Community tutorials]({{ '/tutorials/home/' | relative_url }}) +- [Deploy Jekyll 4 on GitHub Pages]({{ '/docs/continuous-integration/github-actions/' | relative_url }}) +- [Deploy Jekyll on Vercel](https://github.com/vercel/vercel/tree/master/examples/jekyll) +- [Deploy Jekyll 4 on Netlify](https://www.netlify.com/blog/2020/04/02/a-step-by-step-guide-jekyll-4.0-on-netlify/) +- [CloudCannon Academy](https://learn.cloudcannon.com/) is a set of resources created by [CloudCannon](https://cloudcannon.com/) to help folks get up and running with Jekyll. They cover all skill levels, and even include some great video tutorials. +- [Jekyll Cheatsheet](https://learn.cloudcannon.com/jekyll-cheat-sheet/) is a single-page resource for Jekyll filters, variables, and the like. + +## Integrations + +Use a SaaS service as a backend for functionality on your Jekyll site + +### Comments + - [Staticman](https://staticman.net): Add user-generated content to a Jekyll site (free and open source) + - [Talkyard](https://blog-comments.talkyard.io/): Embedded comments for Jekyll and others (free and open source, or hosted serverless) + +### Content Management + - [CloudCannon](https://cloudcannon.com/): The Cloud CMS for Jekyll + - [Contentful](https://github.com/contentful/jekyll-contentful-data-import): Content infrastructure for digital teams + - [TinaCMS.io](https://tina.io/): Tina is an open-source, Git-backed headless content management system (CMS) that empowers both developers and content creators to collaborate seamlessly on a single platform + - [Decap CMS](https://decapcms.org/): Decap CMS (formerly Netlify CMS) is an open source content management system for your Git workflow that enables you to provide editors with a friendly UI and intuitive workflows + - [GitCMS](https://gitcms.dev/): Built for markdown-first content sites with a friendly Notion-like interface, a structured editorial publishing workflow, and MCP support which turns ChatGPT/Claude into content agent. + - [Siteleaf](https://www.siteleaf.com/): Built for developers, Loved by everyone + - [Kentico Kontent](https://rubygems.org/gems/kontent-jekyll/): A headless CMS with full control over content presentation + +### E-commerce + - [MemberSpace](https://www.memberspace.com/integrations/jekyll-membership/): Add memberships and paywall functionality to a Jekyll site + - [Snipcart](https://snipcart.com/blog/static-site-e-commerce-part-2-integrating-snipcart-with-jekyll): Add a shopping cart to a Jekyll site + +### Forms + - [Arengu](https://www.arengu.com) + - [Getform](https://getform.io) + - [99Inbound](https://www.99inbound.com) + - [Formcake](https://formcake.com) + - [Formcarry](https://formcarry.com) + - [Formingo](https://www.formingo.co/guides/jekyll?utm_source=github&utm_medium=jekyll-docs&utm_campaign=Jekyll%20Documentation) + - [FormKeep](https://formkeep.com/guides/contact-form-jekyll?utm_source=github&utm_medium=jekyll-docs&utm_campaign=contact-form-jekyll) + - [Formspark](https://formspark.io/) + - [Formspree (open source)](https://formspree.io/) + - [formX](https://formx.stream) + - [Form.taxi](https://form.taxi/en/backend) + - [Simple Form](https://getsimpleform.com/) + - [SmartForms](https://smartforms.dev/) + - [Typeform](https://www.typeform.com/templates/c/forms/) + +### Search + - [Algolia](https://blog.algolia.com/instant-search-blog-documentation-jekyll-plugin/): Add a powerful instant search to your Jekyll site + - [Elastic Site Search](http://elastic.co/products/site-search/service?ultron=resources&blade=jekyll&hulk=referral): Another option for adding search to your Jekyll site, built on Elasticsearch + - [Bonsai Search](https://docs.bonsai.io/article/217-jekyll): The easiest way to use Elasticsearch for your Jekyll site + - [CloudSh](https://cloudsh.com/generators/how-to-setup-search-on-jekyll/): Website search with a few lines of JavaScript + +## Editors plugins + +- Visual Studio Code has [various jekyll related plugins](https://marketplace.visualstudio.com/search?term=tag%3Ajekyll&target=VSCode&category=All%20categories&sortBy=Installs) and supports [autocompletion for configuration file](http://json.schemastore.org/jekyll). +- [jekyll-atom](https://atom.io/packages/jekyll): A collection of snippets and tools for Jekyll in Atom +- [markdown-writer](https://atom.io/packages/markdown-writer): An Atom package for Jekyll. It can create new posts/drafts, manage tags/categories, insert link/images and add many useful key mappings. +- [sublime-jekyll](https://github.com/23maverick23/sublime-jekyll): A Sublime Text package for Jekyll static sites. This package should help creating Jekyll sites and posts easier by providing access to key template tags and filters, as well as common completions and a current date/datetime command (for dating posts). You can install this package manually via GitHub, or via [Package Control](https://packagecontrol.io/packages/Jekyll). +- [vim-jekyll](https://github.com/parkr/vim-jekyll): A vim plugin to generate new posts and run `jekyll build` all without leaving vim. +- [WordPress2Jekyll](https://wordpress.org/plugins/wp2jekyll/): A WordPress plugin that allows you to use WordPress as your editor and (automatically) export content into Jekyll. WordPress2Jekyll attempts to marry these two systems together in order to make a site that can be easily managed from all devices. + +## Posts + +- [How I'm using Jekyll in 2016](https://mademistakes.com/articles/using-jekyll-2016/) +- [Talkyard comments instructions for Jekyll](https://jekyll-demo.talkyard.io/2018/01/09/installation-instructions.html) +- [Static Comments with Jekyll & Staticman](https://mademistakes.com/articles/improving-jekyll-static-comments/) +- [Adding Ajax pagination to Jekyll](https://eduardoboucas.com/blog/2014/11/05/adding-ajax-pagination-to-jekyll.html) +- ['About this Website', by Carter Allen](http://cartera.me/2010/08/12/about-this-website/) + + > "Jekyll is everything that I ever wanted in a blogging engine. Really. It isn't perfect, but what's excellent about it is that if there's something wrong, I know exactly how it works and how to fix it. It runs on the your machine only, and is essentially an added "build" step between you and the browser. I coded this entire site in TextMate using standard HTML5 and CSS3, and then at the end I added just a few little variables to the markup. Presto-chango, my site is built and I am at peace with the world." + +- A way to [extend Jekyll](https://github.com/rfelix/jekyll_ext) without forking and modifying the Jekyll gem codebase and some [portable Jekyll extensions](https://github.com/rfelix/jekyll_ext/wiki/Extensions) that can be reused and shared. +- [Using your Rails layouts in Jekyll](https://numbers.brighterplanet.com/2010/08/09/sharing-rails-views-with-jekyll) + +## Forks + +- [Time to Visit Bridgetown](https://www.bridgetownrb.com/news/time-to-visit-bridgetown/) +- [Creating a Faster Jekyll](https://sigpipe.macromates.com/2018/creating-a-faster-jekyll/) diff --git a/docs/pages/showcase.html b/docs/pages/showcase.html new file mode 100644 index 00000000000..61c2d6d7472 --- /dev/null +++ b/docs/pages/showcase.html @@ -0,0 +1,23 @@ +--- +layout: page +title: Showcase +permalink: /showcase/ +redirect_from: + - /docs/sites/ +--- + +

Jekyll powers many company websites; here are a few nice ones:

+ + diff --git a/docs/pages/team.md b/docs/pages/team.md new file mode 100644 index 00000000000..279df20a485 --- /dev/null +++ b/docs/pages/team.md @@ -0,0 +1,35 @@ +--- +layout: page +title: The Jekyll Team +permalink: /team/ +--- + +## Core Team + +_The Jekyll Core Team's responsibility is to ensure the development and +community around the Jekyll ecosystem thrive._ + +* Ashwin (@ashmaroli) +* Matt (@mattr-) + +## Security Team + +_The Jekyll Security Team's responsibility is to triage, validate, and +patch security vulnerabilities reported to them._ + +* Parker (@parkr) +* Ashwin (@ashmaroli) +* Matt (@mattr-) + +## Emeritus Core Team Members + +_Emeritus Core Team Members were once members of Jekyll's Core Team._ + +* Alfred (@alfredxing) +* Ben (@benbalter) +* Frank (@DirtyF) +* Nick (@qrush) +* Olivia +* Parker (@parkr) +* Pat (@pathawks) +* Tom (@mojombo) diff --git a/site/README.md b/docs/readme.md similarity index 50% rename from site/README.md rename to docs/readme.md index 27cd67c6b9d..76cdd694473 100644 --- a/site/README.md +++ b/docs/readme.md @@ -1,16 +1,23 @@ # Jekyll docs site -This directory contains the code for the Jekyll docs site, [jekyllrb.com](http://jekyllrb.com/). +This directory contains the code for the Jekyll docs site, [jekyllrb.com](https://jekyllrb.com/). ## Contributing -For information about contributing, see the [Contributing page](http://jekyllrb.com/docs/contributing/). +For information about contributing, see the [Contributing page](https://jekyllrb.com/docs/contributing/). ## Running locally You can preview your contributions before opening a pull request by running from within the directory: -1. `bundle install` +1. `bundle install --without test test_legacy benchmark` 2. `bundle exec rake site:preview` It's just a jekyll site, afterall! :wink: + +## Updating Font Awesome + +1. Go to +2. Choose Import Icons and load `icomoon-selection.json` +3. Choose Generate Font → Download +4. Copy the font files and adapt the CSS to the paths we use in Jekyll diff --git a/exe/jekyll b/exe/jekyll new file mode 100755 index 00000000000..07e13717771 --- /dev/null +++ b/exe/jekyll @@ -0,0 +1,57 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +STDOUT.sync = true + +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) + +require "jekyll" +require "mercenary" + +Jekyll::PluginManager.require_from_bundler + +Jekyll::Deprecator.process(ARGV) + +Mercenary.program(:jekyll) do |p| + p.version Jekyll::VERSION + p.description "Jekyll is a blog-aware, static site generator in Ruby" + p.syntax "jekyll [options]" + + p.option "source", "-s", "--source [DIR]", "Source directory (defaults to ./)" + p.option "destination", "-d", "--destination [DIR]", + "Destination directory (defaults to ./_site)" + p.option "safe", "--safe", "Safe mode (defaults to false)" + p.option "plugins_dir", "-p", "--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]", Array, + "Plugins directory (defaults to ./_plugins)" + p.option "layouts_dir", "--layouts DIR", String, + "Layouts directory (defaults to ./_layouts)" + p.option "profile", "--profile", "Generate a Liquid rendering profile" + + Jekyll::External.require_if_present(Jekyll::External.blessed_gems) do |g, ver_constraint| + cmd = g.split("-").last + p.command(cmd.to_sym) do |c| + c.syntax cmd + c.action do + Jekyll.logger.abort_with "You must install the '#{g}' gem" \ + " version #{ver_constraint} to use the 'jekyll #{cmd}' command." + end + end + end + + Jekyll::Command.subclasses.each { |c| c.init_with_program(p) } + + p.action do |args, _| + if args.empty? + Jekyll.logger.error "A subcommand is required." + puts p + abort + else + subcommand = args.first + unless p.has_command? subcommand + Jekyll.logger.abort_with "fatal: 'jekyll #{args.first}' could not" \ + " be found. You may need to install the jekyll-#{args.first} gem" \ + " or a related gem to be able to use this subcommand." + end + end + end +end diff --git a/features/cache.feature b/features/cache.feature new file mode 100644 index 00000000000..156b35ca453 --- /dev/null +++ b/features/cache.feature @@ -0,0 +1,46 @@ +Feature: Cache + As a developer who likes to create plugins + I want to be able to cache certain aspects across multiple builds + And retrieve the cached aspects when needed + + Scenario: Default Cache directory + Given I have an "index.md" page that contains "{{ site.title }}" + And I have a configuration file with "title" set to "Hello World" + When I run jekyll build + Then I should get a zero exit status + And the .jekyll-cache directory should exist + And the .jekyll-cache/Jekyll/Cache/Jekyll--Cache directory should exist + And the _site directory should exist + And I should see "

Hello World

" in "_site/index.html" + + Scenario: Custom Cache directory + Given I have an "index.md" page that contains "{{ site.title }}" + And I have a configuration file with: + | key | value | + | title | Hello World | + | cache_dir | .foo-cache | + When I run jekyll build + Then I should get a zero exit status + And the .foo-cache directory should exist + And the .foo-cache/Jekyll/Cache/Jekyll--Cache directory should exist + But the .jekyll-cache directory should not exist + And the _site directory should exist + And I should see "

Hello World

" in "_site/index.html" + + Scenario: Disk usage in safe mode + Given I have an "index.md" page that contains "{{ site.title }}" + And I have a configuration file with "title" set to "Hello World" + When I run jekyll build --safe + Then I should get a zero exit status + But the .jekyll-cache directory should not exist + And the _site directory should exist + And I should see "

Hello World

" in "_site/index.html" + + Scenario: Disabling disk usage in non-safe mode + Given I have an "index.md" page that contains "{{ site.title }}" + And I have a configuration file with "title" set to "Hello World" + When I run jekyll build --disable-disk-cache + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Hello World

" in "_site/index.html" + But the .jekyll-cache directory should not exist diff --git a/features/collections.feature b/features/collections.feature index d97918bd27d..8e3f482b24e 100644 --- a/features/collections.feature +++ b/features/collections.feature @@ -6,16 +6,20 @@ Feature: Collections Scenario: Unrendered collection Given I have an "index.html" page that contains "Collections: {{ site.methods }}" And I have fixture collections + And I have a "_methods/static-file.txt" file that contains "Static Content {{ site.title }}" And I have a configuration file with "collections" set to "['methods']" When I run jekyll build - Then the _site directory should exist - And I should see "Collections:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

\n

Signs are nice

\n

Jekyll.sanitized_path is used to make sure your path is in your source.

\n

Run your generators! default

\n

Page without title.

\n

Run your generators! default

" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + But the _site/methods directory should not exist And the "_site/methods/configuration.html" file should not exist + And the "_site/methods/static-file.txt" file should not exist Scenario: Rendered collection - Given I have an "index.html" page that contains "Collections: {{ site.collections }}" + Given I have an "index.html" page that contains "Collections: output => {{ site.collections[0].output }} label => {{ site.collections[0].label }}" And I have an "collection_metadata.html" page that contains "Methods metadata: {{ site.collections[0].foo }} {{ site.collections[0] }}" And I have fixture collections + And I have a "_methods/static-file.txt" file that contains "Static Content {{ site.title }}" And I have a "_config.yml" file with content: """ collections: @@ -24,11 +28,13 @@ Feature: Collections foo: bar """ When I run jekyll build - Then the _site directory should exist - And I should see "Collections: {\"output\"=>true" in "_site/index.html" - And I should see "\"label\"=>\"methods\"," in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And I should see "Collections: output => true" in "_site/index.html" + And I should see "label => methods" in "_site/index.html" And I should see "Methods metadata: bar" in "_site/collection_metadata.html" And I should see "

Whatever: foo.bar

" in "_site/methods/configuration.html" + And I should see "Static Content {{ site.title }}" in "_site/methods/static-file.txt" Scenario: Rendered collection at a custom URL Given I have an "index.html" page that contains "Collections: {{ site.collections }}" @@ -41,11 +47,12 @@ Feature: Collections permalink: /:collection/:path/ """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "

Whatever: foo.bar

" in "_site/methods/configuration/index.html" Scenario: Rendered document in a layout - Given I have an "index.html" page that contains "Collections: {{ site.collections }}" + Given I have an "index.html" page that contains "Collections: output => {{ site.collections[0].output }} label => {{ site.collections[0].label }} foo => {{ site.collections[0].foo }}" And I have a default layout that contains "
Tom Preston-Werner
{{content}}" And I have fixture collections And I have a "_config.yml" file with content: @@ -56,9 +63,11 @@ Feature: Collections foo: bar """ When I run jekyll build - Then the _site directory should exist - And I should see "Collections: {\"output\"=>true" in "_site/index.html" - And I should see "\"label\"=>\"methods\"," in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And I should see "Collections: output => true" in "_site/index.html" + And I should see "label => methods" in "_site/index.html" + And I should see "foo => bar" in "_site/index.html" And I should see "

Run your generators! default

" in "_site/methods/site/generate.html" And I should see "
Tom Preston-Werner
" in "_site/methods/site/generate.html" @@ -71,8 +80,10 @@ Feature: Collections - methods """ When I run jekyll build + Then I should get a zero exit status Then the _site directory should exist - And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" + And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks + And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks Scenario: Collections specified as an hash Given I have an "index.html" page that contains "Collections: {% for method in site.methods %}{{ method.relative_path }} {% endfor %}" @@ -83,8 +94,277 @@ Feature: Collections - methods """ When I run jekyll build + Then I should get a zero exit status Then the _site directory should exist - And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" + And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks + And I should see "Collections: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks + + Scenario: Rendered collection with document with future date + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + | Fido | 2120-12-31 | content for Fido. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "content for Rover" in "_site/puppies/rover.html" + And the "_site/puppies/fido.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/fido.html" file should exist + + Scenario: Access rendered collection with future dated document via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + | Fido | 2120-12-31 | content for Fido. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + """ + And I have a "index.html" page that contains "Newest puppy: {% assign puppy = site.puppies.last %}{{ puppy.title }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Newest puppy: Fido" in "_site/index.html" + But the "_site/puppies/fido.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "Newest puppy: Fido" in "_site/index.html" + And the "_site/puppies/fido.html" file should exist + + Scenario: Access rendered and published collection documents via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | published | + | Rover | 2007-12-31 | content for Rover. | true | + | Figor | 2007-12-31 | content for Figor. | false | + | Snowy | 2199-12-31 | content for Snowy. | true | + | Hardy | 2199-12-31 | content for Hardy. | false | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + """ + And I have a "index.md" page that contains "{% for puppy in site.puppies %}
{{ puppy.title }}
{% endfor %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + But I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + And I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + But I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + But the "_site/puppies/snowy.html" file should exist + + Scenario: Unrendered collection with future dated document + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + | Fido | 2120-12-31 | content for Fido. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: false + """ + And I have a "foo.txt" file that contains "random static file" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/fido.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/fido.html" file should not exist + + Scenario: Access unrendered collection with future dated document via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + | Fido | 2120-12-31 | content for Fido. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: false + """ + And I have a "index.html" page that contains "Newest puppy: {% assign puppy = site.puppies.last %}{{ puppy.title }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Newest puppy: Fido" in "_site/index.html" + But the "_site/puppies/fido.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "Newest puppy: Fido" in "_site/index.html" + And the "_site/puppies/fido.html" file should not exist + + Scenario: Access unrendered but publishable collection documents via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | published | + | Rover | 2007-12-31 | content for Rover. | true | + | Figor | 2007-12-31 | content for Figor. | false | + | Snowy | 2199-12-31 | content for Snowy. | true | + | Hardy | 2199-12-31 | content for Hardy. | false | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: false + """ + And I have a "index.md" page that contains "{% for puppy in site.puppies %}
{{ puppy.title }}
{% endfor %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + But I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + And I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + But I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + + Scenario: Access rendered collection with future date and unpublished flag via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | published | + | Rover | 2007-12-31 | content for Rover. | true | + | Figor | 2007-12-31 | content for Figor. | false | + | Snowy | 2199-12-31 | content for Snowy. | true | + | Hardy | 2199-12-31 | content for Hardy. | false | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + """ + And I have a "index.md" page that contains "{% for puppy in site.puppies %}
{{ puppy.title }}
{% endfor %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + But I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + And I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --unpublished + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should see "
Figor
" in "_site/index.html" + But I should see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/figor.html" file should exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --unpublished --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should see "
Figor
" in "_site/index.html" + But I should see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should exist + And the "_site/puppies/snowy.html" file should exist + And the "_site/puppies/figor.html" file should exist + And the "_site/puppies/hardy.html" file should exist + + Scenario: Access unrendered collection with future date and unpublished flag via Liquid + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | published | + | Rover | 2007-12-31 | content for Rover. | true | + | Figor | 2007-12-31 | content for Figor. | false | + | Snowy | 2199-12-31 | content for Snowy. | true | + | Hardy | 2199-12-31 | content for Hardy. | false | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: false + """ + And I have a "index.md" page that contains "{% for puppy in site.puppies %}
{{ puppy.title }}
{% endfor %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + But I should see "
Snowy
" in "_site/index.html" + And I should not see "
Figor
" in "_site/index.html" + And I should not see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --unpublished + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should see "
Figor
" in "_site/index.html" + But I should see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist + When I run jekyll build --unpublished --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "
Rover
" in "_site/index.html" + And I should see "
Snowy
" in "_site/index.html" + And I should see "
Figor
" in "_site/index.html" + But I should see "
Hardy
" in "_site/index.html" + And the "_site/puppies/rover.html" file should not exist + And the "_site/puppies/snowy.html" file should not exist + And the "_site/puppies/figor.html" file should not exist + And the "_site/puppies/hardy.html" file should not exist Scenario: All the documents Given I have an "index.html" page that contains "All documents: {% for doc in site.documents %}{{ doc.relative_path }} {% endfor %}" @@ -95,11 +375,13 @@ Feature: Collections - methods """ When I run jekyll build + Then I should get a zero exit status Then the _site directory should exist - And I should see "All documents: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" + And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/um_hi.md" in "_site/index.html" if platform supports symlinks + And I should see "All documents: _methods/3940394-21-9393050-fifif1323-test.md _methods/collection/entries _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/trailing-dots...md _methods/yaml_with_dots.md" in "_site/index.html" if platform does not support symlinks Scenario: Documents have an output attribute, which is the converted HTML - Given I have an "index.html" page that contains "First document's output: {{ site.documents.first.output }}" + Given I have an "index.html" page that contains "Second document's output: {{ site.documents[2].output }}" And I have fixture collections And I have a "_config.yml" file with content: """ @@ -107,8 +389,24 @@ Feature: Collections - methods """ When I run jekyll build + Then I should get a zero exit status Then the _site directory should exist - And I should see "First document's output:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

" in "_site/index.html" + And I should see "Second document's output:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

" in "_site/index.html" + + Scenario: Documents have an output attribute, which is the converted HTML based on site.config + Given I have an "index.html" page that contains "Second document's output: {{ site.documents[2].output }}" + And I have fixture collections + And I have a "_config.yml" file with content: + """ + kramdown: + guess_lang: false + collections: + - methods + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Second document's output:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

" in "_site/index.html" Scenario: Filter documents by where Given I have an "index.html" page that contains "{% assign items = site.methods | where: 'whatever','foo.bar' %}Item count: {{ items.size }}" @@ -119,11 +417,12 @@ Feature: Collections - methods """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Item count: 2" in "_site/index.html" Scenario: Sort by title - Given I have an "index.html" page that contains "{% assign items = site.methods | sort: 'title' %}1. of {{ items.size }}: {{ items.first.output }}" + Given I have an "index.html" page that contains "{% assign items = site.methods | sort: 'title' %}2. of {{ items.size }}: {{ items[2].output }}" And I have fixture collections And I have a "_config.yml" file with content: """ @@ -131,11 +430,13 @@ Feature: Collections - methods """ When I run jekyll build - Then the _site directory should exist - And I should see "1. of 7:

Page without title.

" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And I should see "2. of 10:

Page without title.

" in "_site/index.html" if platform supports symlinks + And I should see "2. of 9:

Page without title.

" in "_site/index.html" if platform does not support symlinks Scenario: Sort by relative_path - Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{% for method in methods %}{{ method.title }}, {% endfor %}" + Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{{ methods | map:"title" | join: ", " }}" And I have fixture collections And I have a "_config.yml" file with content: """ @@ -143,5 +444,216 @@ Feature: Collections - methods """ When I run jekyll build + Then I should get a zero exit status Then the _site directory should exist - And I should see "Collections: Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, , Site#generate," in "_site/index.html" + And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, Site#generate, YAML with Dots" in "_site/index.html" if platform supports symlinks + And I should see "Collections: this is a test!, Collection#entries, Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, Initialize, Ellipsis Path, YAML with Dots" in "_site/index.html" if platform does not support symlinks + + Scenario: Sort all entries by a Front Matter key defined in all entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections: + tutorials: + output: true + sort_by: lesson + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Let's Roll!, Dive-In and Publish Already!, Tip of the Iceberg, Extending with Plugins, Graduation Day" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Getting Started" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" + + Scenario: Sort all entries by a Front Matter key defined in only some entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections: + tutorials: + output: true + sort_by: approx_time + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "'approx_time' not defined" in the build output + And I should see "Collections: Extending with Plugins, Let's Roll!, Getting Started, Graduation Day, Dive-In and Publish Already!, Tip of the Iceberg" in "_site/index.html" + And I should see "Previous: Getting Started" in "_site/tutorials/graduation-day.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/graduation-day.html" + + Scenario: Manually sort entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections: + tutorials: + output: true + order: + - getting-started.md + - tip-of-the-iceberg.md + - lets-roll.md + - dive-in-and-publish-already.md + - graduation-day.md + - random-plugins.md + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Tip of the Iceberg, Let's Roll!, Dive-In and Publish Already!, Graduation Day, Extending with Plugins" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" + + Scenario: Manually sort some entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections: + tutorials: + output: true + order: + - getting-started.md + - lets-roll.md + - dive-in-and-publish-already.md + - graduation-day.md + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Let's Roll!, Dive-In and Publish Already!, Graduation Day, Extending with Plugins, Tip of the Iceberg" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Previous: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Getting Started" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" + + Scenario: Rendered collection with date/dateless filename + Given I have an "index.html" page that contains "Collections: {% for method in site.thanksgiving %}{{ method.title }} {% endfor %}" + And I have fixture collections + And I have a "_config.yml" file with content: + """ + collections: + thanksgiving: + output: true + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Thanksgiving Black Friday" in "_site/index.html" + And I should see "Happy Thanksgiving" in "_site/thanksgiving/2015-11-26-thanksgiving.html" + And I should see "Black Friday" in "_site/thanksgiving/black-friday.html" + + Scenario: Rendered collection with custom permalinks and static file contents + Given I have fixture collections + And I have a "_config.yml" file with content: + """ + collections: + methods: + output: true + permalink: /:collection/:name + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I have no front matter." in "_site/methods/extensionless_static_file" + + Scenario: Rendered collection with an extensionless document + Given I have fixture collections + And I have a "_config.yml" file with content: + """ + collections: + methods: + output: true + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I have no file extension but I should still be a part of the collection." in "_site/methods/collection/entries" + + Scenario: Rendered collection with an extensionless document in a strict site + Given I have fixture collections + And I have a _posts directory + And I have an "_posts/2019-12-26-extensioned.md" file that contains "Hello!" + And I have an "_posts/2019-12-26-extensionless" file that contains "Aloha!" + And I have an "index.md" page that contains "{{ site.posts | map: 'title' }}" + And I have a "_config.yml" file with content: + """ + strict_front_matter: true + collections: + methods: + output: true + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I have no file extension but I should still be a part of the collection." in "_site/methods/collection/entries" + And I should see "Extensioned" in "_site/index.html" + But I should not see "Extensionless" in "_site/index.html" diff --git a/features/collections_dir.feature b/features/collections_dir.feature new file mode 100644 index 00000000000..712b21175c8 --- /dev/null +++ b/features/collections_dir.feature @@ -0,0 +1,435 @@ +Feature: Collections Directory + As a hacker who likes to structure content without clutter + I want to be able to organize my collections under a single directory + And render them from there + + Scenario: Custom collections_dir containing only posts + And I have a collections/_posts directory + And I have the following post within the "collections" directory: + | title | date | content | + | Gathered Post | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections_dir: collections + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Random Content." in "_site/2009/03/27/gathered-post.html" + + Scenario: Rendered collection in custom collections_dir also containing posts + Given I have a collections/_puppies directory + And I have the following document under the "puppies" collection within the "collections" directory: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + And I have a collections/_posts directory + And I have the following post within the "collections" directory: + | title | date | content | + | Gathered Post | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: collections + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And I should see "Random Content." in "_site/2009/03/27/gathered-post.html" + + Scenario: Rendered collection in custom collections_dir with posts at the site root + Given I have a collections/_puppies directory + And I have the following document under the "puppies" collection within the "collections" directory: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + And I have a _posts directory + And I have the following post: + | title | date | content | + | Post At Root | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: collections + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And the "_site/2009/03/27/post-at-root.html" file should not exist + And the _site/_posts directory should not exist + + Scenario: Rendered collection in custom collections_dir also containing drafts + Given I have a collections/_puppies directory + And I have the following document under the "puppies" collection within the "collections" directory: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + And I have a collections/_drafts directory + And I have the following draft within the "collections" directory: + | title | date | content | + | Gathered Draft | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: collections + """ + When I run jekyll build --drafts + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And I should see "Random Content." in "_site/2009/03/27/gathered-draft.html" + And the _site/collections directory should not exist + + Scenario: Rendered collection in custom collections_dir with drafts at the site root + Given I have a collections/_puppies directory + And I have the following document under the "puppies" collection within the "collections" directory: + | title | date | content | + | Rover | 2007-12-31 | content for Rover. | + And I have a _drafts directory + And I have the following draft: + | title | date | content | + | Draft At Root | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: collections + """ + When I run jekyll build --drafts + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And the "_site/2009/03/27/draft-at-root.html" file should not exist + + Scenario: A complex site with collections posts and drafts at various locations + Given I have a gathering/_puppies directory + And I have a gathering/_posts directory + And I have a gathering/_drafts directory + And I have a _puppies directory + And I have a _posts directory + And I have a _drafts directory + And I have the following document under the "puppies" collection within the "gathering" directory: + | title | date | content | + | Rover in Gathering | 2007-12-31 | content for Rover. | + And I have the following document under the puppies collection: + | title | date | content | + | Rover At Root | 2007-12-31 | content for Rover. | + And I have the following post within the "gathering" directory: + | title | date | content | + | Post in Gathering | 2009-03-27 | Totally nothing. | + And I have the following post: + | title | date | content | + | Post At Root | 2009-03-27 | Totally nothing. | + And I have the following draft within the "gathering" directory: + | title | date | content | + | Draft In Gathering | 2009-03-27 | This is a draft. | + And I have the following draft: + | title | date | content | + | Draft At Root | 2009-03-27 | This is a draft. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: gathering + """ + And I have a "gathering/_puppies/static_file.txt" file that contains "Static content." + And I have a gathering/_puppies/nested directory + And I have a "gathering/_puppies/nested/static_file.txt" file that contains "Nested Static content." + When I run jekyll build --drafts + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover-in-gathering.html" file should exist + And the "_site/2009/03/27/post-in-gathering.html" file should exist + And the "_site/2009/03/27/draft-in-gathering.html" file should exist + And the "_site/2009/03/27/draft-at-root.html" file should not exist + And the "_site/puppies/rover-at-root.html" file should not exist + And I should see exactly "Static content." in "_site/puppies/static_file.txt" + And I should see exactly "Nested Static content." in "_site/puppies/nested/static_file.txt" + And the _site/gathering directory should not exist + And the _site/_posts directory should not exist + + Scenario: Rendered collection with a document that includes a relative document + Given I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | INTRO | 2007-12-31 | excerpt for all docs. | + | Rover | 2007-12-31 | {% include_relative intro.md %} | + And I have a _posts directory + And I have the following post: + | title | date | content | + | Gathered Post | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And I should see "excerpt for all docs." in "_site/puppies/rover.html" + And I should see "Random Content." in "_site/2009/03/27/gathered-post.html" + + Scenario: Rendered collection in custom collections_dir with a document that includes a relative document + Given I have a collections/_puppies directory + And I have the following documents under the "puppies" collection within the "collections" directory: + | title | date | content | + | INTRO | 2007-12-31 | excerpt for all docs. | + | Rover | 2007-12-31 | {% include_relative intro.md %} | + And I have a collections/_posts directory + And I have the following post within the "collections" directory: + | title | date | content | + | Gathered Post | 2009-03-27 | Random Content. | + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + + collections_dir: collections + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/puppies/rover.html" file should exist + And I should see "excerpt for all docs." in "_site/puppies/rover.html" + And I should see "Random Content." in "_site/2009/03/27/gathered-post.html" + + Scenario: Front matter defaults and custom collections directory + Given I have a gathering/_players/managers directory + And I have a gathering/_players/recruits directory + And I have a gathering/_players/standby directory + And I have the following documents nested inside "managers" directory under the "players" collection within the "gathering" directory: + | title | content | + | Tony Stark | content for Tony. | + | Steve Rogers | content for Steve. | + And I have the following documents nested inside "recruits" directory under the "players" collection within the "gathering" directory: + | title | content | + | Peter Parker | content for Peter. | + | Wanda Maximoff | content for Wanda. | + And I have the following documents nested inside "standby" directory under the "players" collection within the "gathering" directory: + | title | content | + | Thanos | content for Thanos. | + | Loki | content for Loki. | + And I have a "_config.yml" file with content: + """ + collections_dir: gathering + collections: ["players"] + defaults: + - scope: + path: "" + type: players + values: + recruit: false + manager: false + villain: false + - scope: + path: gathering/_players/standby/thanos.md + type: players + values: + villain: true + - scope: + path: gathering/_players/managers/* + type: players + values: + manager: true + - scope: + path: gathering/_players/recruits/* + type: players + values: + recruit: true + """ + And I have a "index.md" file with content: + """ + --- + --- + {% for player in site.players %} +

{{ player.title }}: Manager: {{ player.manager }}

+

{{ player.title }}: Recruit: {{ player.recruit }}

+

{{ player.title }}: Villain: {{ player.villain }}

+ {% endfor %} + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Tony Stark: Manager: true

" in "_site/index.html" + And I should see "

Tony Stark: Recruit: false

" in "_site/index.html" + And I should see "

Tony Stark: Villain: false

" in "_site/index.html" + And I should see "

Peter Parker: Manager: false

" in "_site/index.html" + And I should see "

Peter Parker: Recruit: true

" in "_site/index.html" + And I should see "

Peter Parker: Villain: false

" in "_site/index.html" + And I should see "

Steve Rogers: Manager: true

" in "_site/index.html" + And I should see "

Steve Rogers: Recruit: false

" in "_site/index.html" + And I should see "

Steve Rogers: Villain: false

" in "_site/index.html" + And I should see "

Wanda Maximoff: Manager: false

" in "_site/index.html" + And I should see "

Wanda Maximoff: Recruit: true

" in "_site/index.html" + And I should see "

Wanda Maximoff: Villain: false

" in "_site/index.html" + And I should see "

Thanos: Manager: false

" in "_site/index.html" + And I should see "

Thanos: Recruit: false

" in "_site/index.html" + And I should see "

Thanos: Villain: true

" in "_site/index.html" + And I should see "

Loki: Manager: false

" in "_site/index.html" + And I should see "

Loki: Recruit: false

" in "_site/index.html" + And I should see "

Loki: Villain: false

" in "_site/index.html" + + Scenario: Sort all entries by a Front Matter key defined in all entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections in "gathering" directory + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections_dir: gathering + collections: + tutorials: + output: true + sort_by: lesson + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Let's Roll!, Dive-In and Publish Already!, Tip of the Iceberg, Extending with Plugins, Graduation Day" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Getting Started" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" + + Scenario: Sort all entries by a Front Matter key defined in only some entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections in "gathering" directory + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections_dir: gathering + collections: + tutorials: + output: true + sort_by: approx_time + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "'approx_time' not defined" in the build output + And I should see "Collections: Extending with Plugins, Let's Roll!, Getting Started, Graduation Day, Dive-In and Publish Already!, Tip of the Iceberg" in "_site/index.html" + And I should see "Previous: Getting Started" in "_site/tutorials/graduation-day.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/graduation-day.html" + + Scenario: Manually sort entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections in "gathering" directory + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections_dir: gathering + collections: + tutorials: + output: true + order: + - getting-started.md + - tip-of-the-iceberg.md + - lets-roll.md + - dive-in-and-publish-already.md + - graduation-day.md + - random-plugins.md + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Tip of the Iceberg, Let's Roll!, Dive-In and Publish Already!, Graduation Day, Extending with Plugins" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" + + Scenario: Manually sort some entries + Given I have an "index.html" page that contains "Collections: {{ site.tutorials | map: 'title' | join: ', ' }}" + And I have fixture collections in "gathering" directory + And I have a _layouts directory + And I have a "_layouts/tutorial.html" file with content: + """ + {% if page.previous %}Previous: {{ page.previous.title }}{% endif %} + + {% if page.next %}Next: {{ page.next.title }}{% endif %} + """ + And I have a "_config.yml" file with content: + """ + collections_dir: gathering + collections: + tutorials: + output: true + order: + - getting-started.md + - lets-roll.md + - dive-in-and-publish-already.md + - graduation-day.md + + defaults: + - scope: + path: "" + type: tutorials + values: + layout: tutorial + + """ + When I run jekyll build + Then I should get a zero exit status + Then the _site directory should exist + And I should see "Collections: Getting Started, Let's Roll!, Dive-In and Publish Already!, Graduation Day, Extending with Plugins, Tip of the Iceberg" in "_site/index.html" + And I should not see "Previous: Graduation Day" in "_site/tutorials/lets-roll.html" + And I should not see "Previous: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + And I should not see "Next: Tip of the Iceberg" in "_site/tutorials/lets-roll.html" + But I should see "Previous: Getting Started" in "_site/tutorials/lets-roll.html" + And I should see "Next: Dive-In and Publish Already!" in "_site/tutorials/lets-roll.html" diff --git a/features/create_sites.feature b/features/create_sites.feature index 898115c2344..550f07e1444 100644 --- a/features/create_sites.feature +++ b/features/create_sites.feature @@ -6,14 +6,29 @@ Feature: Create sites Scenario: Blank site Given I do not have a "test_blank" directory When I run jekyll new test_blank --blank - Then the test_blank/_layouts directory should exist + Then the test_blank/_data directory should exist + And the test_blank/_drafts directory should exist + And the test_blank/_includes directory should exist + And the test_blank/_layouts directory should exist And the test_blank/_posts directory should exist - And the "test_blank/index.html" file should exist + And the test_blank/_sass directory should exist + And the test_blank/assets/css directory should exist + And the "test_blank/_layouts/default.html" file should exist + And the "test_blank/_sass/base.scss" file should exist + And the "test_blank/assets/css/main.scss" file should exist + And the "test_blank/_config.yml" file should exist + And the "test_blank/index.md" file should exist + When I run jekyll build --source test_blank --destination test_blank/_site + Then I should get a zero exit status + And the test_blank/_site directory should exist + And I should see "Start developing" in "test_blank/_site/index.html" + And I should see "body {" in "test_blank/_site/assets/css/main.css" Scenario: Basic site Given I have an "index.html" file that contains "Basic Site" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site" in "_site/index.html" Scenario: Basic site with a post @@ -22,7 +37,8 @@ Feature: Create sites | title | date | content | | Hackers | 2009-03-27 | My First Exploit | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "My First Exploit" in "_site/2009/03/27/hackers.html" Scenario: Basic site with layout and a page @@ -30,7 +46,8 @@ Feature: Create sites And I have an "index.html" page with layout "default" that contains "Basic Site with Layout" And I have a default layout that contains "Page Layout: {{ content }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: Basic Site with Layout" in "_site/index.html" Scenario: Basic site with layout and a post @@ -41,7 +58,8 @@ Feature: Create sites | Wargames | 2009-03-27 | default | The only winning move is not to play. | And I have a default layout that contains "Post Layout: {{ content }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post Layout:

The only winning move is not to play.

" in "_site/2009/03/27/wargames.html" Scenario: Basic site with layout inside a subfolder and a post @@ -52,7 +70,8 @@ Feature: Create sites | Wargames | 2009-03-27 | post/simple | The only winning move is not to play. | And I have a post/simple layout that contains "Post Layout: {{ content }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post Layout:

The only winning move is not to play.

" in "_site/2009/03/27/wargames.html" Scenario: Basic site with layouts, pages, posts and files @@ -75,7 +94,8 @@ Feature: Create sites | entry3 | 2009-05-27 | post | content for entry3. | | entry4 | 2009-06-27 | post | content for entry4. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page : Site contains 2 pages and 4 posts" in "_site/index.html" And I should see "No replacement \{\{ site.posts.size \}\}" in "_site/about.html" And I should see "" in "_site/another_file" @@ -90,7 +110,8 @@ Feature: Create sites And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}" And I have an "_includes/about.textile" file that contains "Generated by Jekyll" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html" Scenario: Basic site with subdir include tag @@ -99,7 +120,8 @@ Feature: Create sites And I have an info directory And I have an "info/index.html" page that contains "Basic Site with subdir include tag: {% include about.textile %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site with subdir include tag: Generated by Jekyll" in "_site/info/index.html" Scenario: Basic site with nested include tag @@ -108,7 +130,8 @@ Feature: Create sites And I have an "_includes/jekyll.textile" file that contains "Jekyll" And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html" Scenario: Basic site with internal post linking @@ -120,19 +143,22 @@ Feature: Create sites | entry1 | 2007-12-31 | post | content for entry1. | | entry2 | 2008-01-01 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "URL: /2008/01/01/entry2/" in "_site/index.html" Scenario: Basic site with whitelisted dotfile Given I have an ".htaccess" file that contains "SomeDirective" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "SomeDirective" in "_site/.htaccess" Scenario: File was replaced by a directory Given I have a "test" file that contains "some stuff" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist When I delete the file "test" Given I have a test directory And I have a "test/index.html" file that contains "some other stuff" @@ -146,13 +172,15 @@ Feature: Create sites And I have a "secret.html" page with published "false" that contains "Unpublished page" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/index.html" file should exist And the "_site/public.html" file should exist But the "_site/secret.html" file should not exist When I run jekyll build --unpublished - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/index.html" file should exist And the "_site/public.html" file should exist And the "_site/secret.html" file should exist @@ -161,12 +189,31 @@ Feature: Create sites Given I have a _posts directory And I have the following post: | title | date | layout | content | - | entry1 | 2020-12-31 | post | content for entry1. | + | entry1 | 2040-12-31 | post | content for entry1. | | entry2 | 2007-12-31 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "content for entry2" in "_site/2007/12/31/entry2.html" - And the "_site/2020/12/31/entry1.html" file should not exist + And the "_site/2040/12/31/entry1.html" file should not exist When I run jekyll build --future - Then the _site directory should exist - And the "_site/2020/12/31/entry1.html" file should exist + Then I should get a zero exit status + And the _site directory should exist + And the "_site/2040/12/31/entry1.html" file should exist + + Scenario: Basic site with layouts, posts and related posts + Given I have a _layouts directory + And I have a page layout that contains "Page {{ page.title }}: {{ content }}" + And I have a post layout that contains "Post {{ page.title }}: {{ content }}Related posts: {{ site.related_posts | size }}" + And I have an "index.html" page with layout "page" that contains "Site contains {{ site.pages.size }} pages and {{ site.posts.size }} posts; Related posts: {{ site.related_posts | size }}" + And I have a _posts directory + And I have the following posts: + | title | date | layout | content | + | entry1 | 2009-03-27 | post | content for entry1. | + | entry2 | 2009-04-27 | post | content for entry2. | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Page : Site contains 1 pages and 2 posts; Related posts: 0" in "_site/index.html" + And I should see "Post entry1:

content for entry1.

\nRelated posts: 1" in "_site/2009/03/27/entry1.html" + And I should see "Post entry2:

content for entry2.

\nRelated posts: 1" in "_site/2009/04/27/entry2.html" diff --git a/features/data.feature b/features/data.feature index e44be8a5cf6..41f476a4996 100644 --- a/features/data.feature +++ b/features/data.feature @@ -59,6 +59,20 @@ Feature: Data And I should see "Jack" in "_site/index.html" And I should see "Leon" in "_site/index.html" + Scenario: autoload *.tsv files in _data directory + Given I have a _data directory + And I have a "_data/members.tsv" file with content: + """ + name age + Jack 28 + Leon 34 + """ + And I have an "index.html" page that contains "{% for member in site.data.members %}{{member.name}}{% endfor %}" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "Jack" in "_site/index.html" + And I should see "Leon" in "_site/index.html" + Scenario: autoload *.yml files in _data directory with space in file name Given I have a _data directory And I have a "_data/team members.yml" file with content: diff --git a/features/drafts.feature b/features/drafts.feature index 5d7982ecfc4..5a7f49f39d2 100644 --- a/features/drafts.feature +++ b/features/drafts.feature @@ -10,7 +10,8 @@ Feature: Draft Posts | title | date | layout | content | | Recipe | 2009-03-27 | default | Not baked yet. | When I run jekyll build --drafts - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Not baked yet." in "_site/recipe.html" Scenario: Don't preview a draft @@ -21,7 +22,8 @@ Feature: Draft Posts | title | date | layout | content | | Recipe | 2009-03-27 | default | Not baked yet. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/recipe.html" file should not exist Scenario: Don't preview a draft that is not published @@ -32,7 +34,8 @@ Feature: Draft Posts | title | date | layout | published | content | | Recipe | 2009-03-27 | default | false | Not baked yet. | When I run jekyll build --drafts - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/recipe.html" file should not exist Scenario: Use page.path variable @@ -42,5 +45,6 @@ Feature: Draft Posts | title | date | layout | content | | Recipe | 2009-03-27 | simple | Post path: {{ page.path }} | When I run jekyll build --drafts - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post path: _drafts/recipe.markdown" in "_site/recipe.html" diff --git a/features/embed_filters.feature b/features/embed_filters.feature index d6f99fc7655..32f0fe7e7c7 100644 --- a/features/embed_filters.feature +++ b/features/embed_filters.feature @@ -11,7 +11,8 @@ Feature: Embed filters | Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. | And I have a default layout that contains "{{ site.time | date_to_xmlschema }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see today's date in "_site/2009/03/27/star-wars.html" Scenario: Escape text for XML @@ -22,7 +23,8 @@ Feature: Embed filters | Star & Wars | 2009-03-27 | default | These aren't the droids you're looking for. | And I have a default layout that contains "{{ page.title | xml_escape }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Star & Wars" in "_site/2009/03/27/star-wars.html" Scenario: Calculate number of words @@ -33,7 +35,8 @@ Feature: Embed filters | Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. | And I have a default layout that contains "{{ content | number_of_words }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "7" in "_site/2009/03/27/star-wars.html" Scenario: Convert an array into a sentence @@ -44,7 +47,8 @@ Feature: Embed filters | Star Wars | 2009-03-27 | default | [scifi, movies, force] | These aren't the droids you're looking for. | And I have a default layout that contains "{{ page.tags | array_to_sentence_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html" Scenario: Markdownify a given string @@ -55,7 +59,8 @@ Feature: Embed filters | Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. | And I have a default layout that contains "By {{ '_Obi-wan_' | markdownify }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "By

Obi-wan

" in "_site/2009/03/27/star-wars.html" Scenario: Sort by an arbitrary variable @@ -68,38 +73,89 @@ Feature: Embed filters | Page-2 | default | 6 | Something | And I have a default layout that contains "{{ site.pages | sort:'value' | map:'title' | join:', ' }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see exactly "Page-2, Page-1" in "_site/page-1.html" And I should see exactly "Page-2, Page-1" in "_site/page-2.html" Scenario: Sort pages by the title Given I have a _layouts directory + And I have the following pages: + | title | layout | content | + | Dog | default | Run | + | Bird | default | Fly | And I have the following page: - | title | layout | content | - | Dog | default | Run | - And I have the following page: - | title | layout | content | - | Bird | default | Fly | - And I have the following page: - | layout | content | - | default | Jump | + | layout | content | + | default | Jump | And I have a default layout that contains "{% assign sorted_pages = site.pages | sort: 'title' %}The rule of {{ sorted_pages.size }}: {% for p in sorted_pages %}{{ p.content | strip_html | strip_newlines }}, {% endfor %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see exactly "The rule of 3: Jump, Fly, Run," in "_site/bird.html" Scenario: Sort pages by the title ordering pages without title last Given I have a _layouts directory + And I have the following pages: + | title | layout | content | + | Dog | default | Run | + | Bird | default | Fly | And I have the following page: - | title | layout | content | - | Dog | default | Run | - And I have the following page: - | title | layout | content | - | Bird | default | Fly | - And I have the following page: - | layout | content | - | default | Jump | + | layout | content | + | default | Jump | And I have a default layout that contains "{% assign sorted_pages = site.pages | sort: 'title', 'last' %}The rule of {{ sorted_pages.size }}: {% for p in sorted_pages %}{{ p.content | strip_html | strip_newlines }}, {% endfor %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see exactly "The rule of 3: Fly, Run, Jump," in "_site/bird.html" + + Scenario: Filter posts by given property and value + Given I have a _posts directory + And I have the following posts: + | title | date | content | property | + | Bird | 2019-03-13 | Chirp | [nature, sounds] | + | Cat | 2019-03-14 | Meow | [sounds] | + | Dog | 2019-03-15 | Bark | | + | Elephant | 2019-03-16 | Asiatic | wildlife | + | Goat | 2019-03-17 | Mountains | "" | + | Horse | 2019-03-18 | Mustang | [] | + | Iguana | 2019-03-19 | Reptile | {} | + | Jaguar | 2019-03-20 | Reptile | {foo: lorem, bar: nature} | + And I have a "string-value.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', 'wildlife' %} + {{ pool | map: 'title' | join: ', ' }} + """ + And I have a "string-value-array.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', 'sounds' %} + {{ pool | map: 'title' | join: ', ' }} + """ + And I have a "string-value-hash.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', 'nature' %} + {{ pool | map: 'title' | join: ', ' }} + """ + And I have a "nil-value.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', nil %} + {{ pool | map: 'title' | join: ', ' }} + """ + And I have an "empty-liquid-literal.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', empty %} + {{ pool | map: 'title' | join: ', ' }} + """ + And I have a "blank-liquid-literal.md" page with content: + """ + {% assign pool = site.posts | reverse | where: 'property', blank %} + {{ pool | map: 'title' | join: ', ' }} + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see exactly "

Elephant

" in "_site/string-value.html" + And I should see exactly "

Bird, Cat

" in "_site/string-value-array.html" + And I should see exactly "

Bird

" in "_site/string-value-hash.html" + And I should see exactly "

Dog

" in "_site/nil-value.html" + And I should see exactly "

Dog, Goat, Horse, Iguana

" in "_site/empty-liquid-literal.html" + And I should see exactly "

Dog, Goat, Horse, Iguana

" in "_site/blank-liquid-literal.html" diff --git a/features/frontmatter_defaults.feature b/features/frontmatter_defaults.feature index a9a64ae2818..47d81abb2ba 100644 --- a/features/frontmatter_defaults.feature +++ b/features/frontmatter_defaults.feature @@ -12,7 +12,8 @@ Feature: frontmatter defaults And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {layout: "pretty"}}]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "THIS IS THE LAYOUT:

just some post

" in "_site/2013/09/11/default-layout.html" And I should see "THIS IS THE LAYOUT: just some page" in "_site/index.html" @@ -24,7 +25,8 @@ Feature: frontmatter defaults And I have an "index.html" page that contains "just {{page.custom}} by {{page.author}}" And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {custom: "some special data", author: "Ben"}}]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "

some special data

\n
Ben
" in "_site/2013/09/11/default-data.html" And I should see "just some special data by Ben" in "_site/index.html" @@ -48,7 +50,8 @@ Feature: frontmatter defaults And I have a configuration file with "defaults" set to "[{scope: {path: "special"}, values: {layout: "subfolder", description: "the special section"}}, {scope: {path: ""}, values: {layout: "root", description: "the webpage"}}]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "root:

info on the webpage

" in "_site/2013/10/14/about.html" And I should see "subfolder:

info on the special section

" in "_site/special/2013/10/14/about.html" And I should see "root: Overview for the webpage" in "_site/index.html" @@ -71,11 +74,32 @@ Feature: frontmatter defaults And I have a configuration file with "defaults" set to "[{scope: {path: "special"}, values: {layout: "main"}}, {scope: {path: "special/_posts"}, values: {layout: "main"}}, {scope: {path: "_posts"}, values: {layout: "main"}}]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "main:

content of site/2013/10/14/about.html

" in "_site/2013/10/14/about.html" And I should see "main:

content of site/special/2013/10/14/about1.html

" in "_site/special/2013/10/14/about1.html" And I should see "main:

content of site/special/2013/10/14/about2.html

" in "_site/special/2013/10/14/about2.html" + Scenario: Use frontmatter scopes for subdirectories + Given I have a _layouts directory + And I have a main layout that contains "main: {{ content }}" + + And I have a _posts/en directory + And I have the following post under "en": + | title | date | content | + | helloworld | 2014-09-01 | {{page.lang}} is the current language | + And I have a _posts/de directory + And I have the following post under "de": + | title | date | content | + | hallowelt | 2014-09-01 | {{page.lang}} is the current language | + + And I have a configuration file with "defaults" set to "[{scope: {path: "_posts/en"}, values: {layout: "main", lang: "en"}}, {scope: {path: "_posts/de"}, values: {layout: "main", lang: "de"}}]" + + When I run jekyll build + Then the _site directory should exist + And I should see "main:

en is the current language

" in "_site/2014/09/01/helloworld.html" + And I should see "main:

de is the current language

" in "_site/2014/09/01/hallowelt.html" + Scenario: Override frontmatter defaults by type Given I have a _posts directory And I have the following post: @@ -132,7 +156,8 @@ Feature: frontmatter defaults myval: "Test" """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Value: Test" in "_site/slides/slide1.html" Scenario: Override frontmatter defaults inside a collection @@ -159,7 +184,8 @@ Feature: frontmatter defaults myval: "Test" """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Value: Override" in "_site/slides/slide2.html" Scenario: Deep merge frontmatter defaults diff --git a/features/highlighting.feature b/features/highlighting.feature new file mode 100644 index 00000000000..28d168c0a24 --- /dev/null +++ b/features/highlighting.feature @@ -0,0 +1,45 @@ +Feature: Syntax Highlighting + As a hacker who likes to blog + I want to share code snippets in my blog + And make them pretty for all the world to see + + Scenario: highlighting an apache configuration + Given I have an "index.html" page with content: + """ + {% highlight apache %} + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^(.*)$ index.php [QSA,L] + {% endhighlight %} + """ + When I run jekyll build + Then I should get a zero exit-status + And I should see "RewriteCond" in "_site/index.html" + + Scenario: marking lines 1 and 2 in a Ruby code block with valid syntax + Given I have an "index.html" page with content: + """ + {% highlight ruby mark_lines="1 2" %} + module Jekyll + module Tags + class HighlightBlock < Liquid::Block + {% endhighlight %} + """ + When I run jekyll build + Then I should get a zero exit-status + And I should see "module Jekyll" in "_site/index.html" + And I should see " module Tags" in "_site/index.html" + And I should see "class HighlightBlockPage heading + {{ content }} + """ + And I have a "page.md" page with layout "page" that contains "### Heading" + And I have a _plugins directory + And I have a "_plugins/ext.rb" file with content: + """ + Jekyll::Hooks.register :pages, :post_convert do |page| + page.content = page.content.gsub('h3', 'h4') + end + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Page heading

" in "_site/page.html" + And I should see "

Heading

" in "_site/page.html" + Scenario: Modify page contents before writing to disk Given I have a _plugins directory And I have a "index.html" page that contains "WRAP ME" @@ -138,7 +164,8 @@ Feature: Hooks | title | date | layout | content | | entry1 | 2015-03-14 | nil | {{ page.harold }} | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "pbagrag sbe ragel1." in "_site/2015/03/14/entry1.html" Scenario: Alter the payload for certain posts @@ -164,6 +191,34 @@ Feature: Hooks Then I should see "old post" in "_site/2015/03/14/entry1.html" And I should see "new post" in "_site/2015/03/15/entry2.html" + Scenario: Modify the converted HTML content of a post before rendering layout + Given I have a _layouts directory + And I have a "_layouts/post.html" file with content: + """ +

Page heading

+ {{ content }} + """ + And I have a _posts directory + And I have a "_posts/2016-01-01-example.md" file with content: + """ + --- + layout: post + --- + ### Heading + """ + And I have a _plugins directory + And I have a "_plugins/ext.rb" file with content: + """ + Jekyll::Hooks.register :posts, :post_convert do |post| + post.content = post.content.gsub('h3', 'h4') + end + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Page heading

" in "_site/2016/01/01/example.html" + And I should see "

Heading

" in "_site/2016/01/01/example.html" + Scenario: Modify post contents before writing to disk Given I have a _plugins directory And I have a "_plugins/ext.rb" file with content: @@ -229,7 +284,7 @@ Feature: Hooks owner.output = "1 #{owner.output.chomp}" end Jekyll::Hooks.register :pages, :post_render, priority: :high do |owner| - # high runs last + # high runs first owner.output = "2 #{owner.output.chomp}" end Jekyll::Hooks.register :pages, :post_render do |owner| @@ -237,13 +292,13 @@ Feature: Hooks owner.output = "3 #{owner.output.chomp}" end Jekyll::Hooks.register :pages, :post_render, priority: :low do |owner| - # low runs first + # low runs last owner.output = "4 #{owner.output.chomp}" end """ And I have a "index.html" page that contains "WRAP ME" When I run jekyll build - Then I should see "2 3 1 4 WRAP ME" in "_site/index.html" + Then I should see "4 3 1 2 WRAP ME" in "_site/index.html" Scenario: Alter a document right after it is initialized Given I have a _plugins directory @@ -268,9 +323,90 @@ Feature: Hooks {{ site.memes.first.text }} """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "all your base are belong to us" in "_site/index.html" + Scenario: Modify the converted HTML content of a document before rendering layout + Given I have a _layouts directory + And I have a "_layouts/meme.html" file with content: + """ +

Page heading

+ {{ content }} + """ + And I have a "_config.yml" file with content: + """ + collections: + memes: + output: true + """ + And I have a _memes directory + And I have a "_memes/doc1.md" file with content: + """ + --- + layout: meme + text: all your base + --- + ### {{ page.text }} + """ + And I have a _plugins directory + And I have a "_plugins/ext.rb" file with content: + """ + Jekyll::Hooks.register :documents, :post_convert do |document| + document.content = document.content.gsub('h3', 'h4') + end + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Page heading

" in "_site/memes/doc1.html" + And I should see "

all your base

" in "_site/memes/doc1.html" + + Scenario: Modify the converted HTML content of document of a particular collection before rendering layout + Given I have a _layouts directory + And I have a "_layouts/meme.html" file with content: + """ +

Page heading

+ {{ content }} + """ + And I have a "_config.yml" file with content: + """ + collections: + memes: + output: true + """ + And I have a _memes directory + And I have a "_memes/doc1.md" file with content: + """ + --- + layout: meme + text: all your base + --- + ### {{ page.text }} + """ + And I have a _posts directory + And I have a "_posts/2016-01-01-example.md" file with content: + """ + --- + layout: meme + text: all your base + --- + ### {{ page.text }} + """ + And I have a _plugins directory + And I have a "_plugins/ext.rb" file with content: + """ + Jekyll::Hooks.register :memes, :post_convert do |document| + document.content = document.content.gsub('h3', 'h4') + end + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

Page heading

" in "_site/memes/doc1.html" + And I should see "

all your base

" in "_site/memes/doc1.html" + But I should see "

all your base

" in "_site/2016/01/01/example.html" + Scenario: Update a document after rendering it, but before writing it to disk Given I have a _plugins directory And I have a "_plugins/ext.rb" file with content: @@ -294,7 +430,8 @@ Feature: Hooks {{ page.text }} """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "

all your base are belong to us" in "_site/memes/doc1.html" Scenario: Perform an action after every document is written @@ -322,5 +459,31 @@ Feature: Hooks {{ page.text }} """ When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Wrote document 0" in "_site/document-build.log" + + Scenario: Set a custom payload['page'] property + Given I have a _plugins directory + And I have a "_plugins/ext.rb" file with content: + """ + Jekyll::Hooks.register :pages, :pre_render do |page, payload| + payload['page']['foo'] = "hello world" + end + """ + And I have a _layouts directory + And I have a "_layouts/custom.html" file with content: + """ + --- + --- + {{ content }} {% include foo.html %} + """ + And I have a _includes directory + And I have a "_includes/foo.html" file with content: + """ + {{page.foo}} + """ + And I have an "index.html" page with layout "custom" that contains "page content" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "page content\n hello world" in "_site/index.html" diff --git a/features/include_relative_tag.feature b/features/include_relative_tag.feature new file mode 100644 index 00000000000..9e84f30a5e3 --- /dev/null +++ b/features/include_relative_tag.feature @@ -0,0 +1,79 @@ +Feature: include_relative Tag + In order to share content across several closely related pages + As a hacker who likes to blog + I want to be able to include snippets in my site's pages and documents relative to current file + + Scenario: Include a file relative to a post + Given I have a _posts directory + And I have a _posts/snippets directory + And I have the following post: + | title | date | content | + | Star Wars | 2018-09-02 | {% include_relative snippets/welcome_para.md %} | + And I have an "_posts/snippets/welcome_para.md" file that contains "Welcome back Dear Reader!" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" + + Scenario: Include a nested file relative to a post + Given I have a _posts directory + And I have a _posts/snippets directory + And I have a _posts/snippets/welcome_para directory + And I have the following post: + | title | date | content | + | Star Wars | 2018-09-02 | {% include_relative snippets/welcome_para.md %} | + And I have an "_posts/snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" + And I have an "_posts/snippets/welcome_para/greeting.md" file that contains "Welcome back" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" + + Scenario: Include a nested file relative to a post as an excerpt + Given I have a _posts directory + And I have a _posts/snippets directory + And I have a _posts/snippets/welcome_para directory + And I have a "_posts/2018-09-02-star-wars.md" file with content: + """ + {% include_relative snippets/welcome_para.md %} + + Hello World + """ + And I have an "_posts/snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" + And I have an "_posts/snippets/welcome_para/greeting.md" file that contains "Welcome back" + And I have an "index.md" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Welcome back Dear Reader!" in "_site/2018/09/02/star-wars.html" + And I should see "Welcome back Dear Reader!" in "_site/index.html" + + Scenario: Include a nested file relative to a page at root + Given I have a snippets directory + And I have a snippets/welcome_para directory + And I have a "index.md" page that contains "{% include_relative snippets/welcome_para.md %}" + And I have a "snippets/welcome_para.md" file that contains "{% include_relative snippets/welcome_para/greeting.md %} Dear Reader!" + And I have a "snippets/welcome_para/greeting.md" file that contains "Welcome back" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Welcome back Dear Reader!" in "_site/index.html" + + Scenario: Include multiple files relative to a page at root + Given I have an "apple.md" page with foo "bar" that contains "{{ page.path }}, {{ page.foo }}" + And I have an "banana.md" page with content: + """ + {% include_relative apple.md %} + {% include_relative cherry.md %} + + {{ page.path }} + """ + And I have an "cherry.md" page with foo "lipsum" that contains "{{ page.path }}, {{ page.foo }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

apple.md, bar

" in "_site/apple.html" + And I should see "
\n

foo: bar" in "_site/banana.html" + And I should see "


\n

foo: lipsum" in "_site/banana.html" + And I should see "

cherry.md, lipsum

" in "_site/cherry.html" + But I should not see "foo: lipsum" in "_site/cherry.html" diff --git a/features/include_tag.feature b/features/include_tag.feature index 427c1bb4f0c..f4d8b8105af 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -15,11 +15,12 @@ Feature: Include tags | Ignore params if unused | 2013-03-21 | html | {% include ignore.html date="today" %} | | List multiple parameters | 2013-03-21 | html | {% include params.html date="today" start="tomorrow" %} | | Dont keep parameters | 2013-03-21 | html | {% include ignore.html param="test" %}\n{% include header.html %} | - | Allow params with spaces and quotes | 2013-04-07 | html | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} | + | Allow params with spaces and quotes | 2013-04-07 | html | {% include params.html cool="param with spaces" super="\\"quoted\\"" single='has "quotes"' escaped='\\'single\\' quotes' %} | | Parameter syntax | 2013-04-12 | html | {% include params.html param1_or_2="value" %} | | Pass a variable | 2013-06-22 | html | {% assign var = 'some text' %}{% include params.html local=var title=page.title %} | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "
My awesome blog header: myparam
" in "_site/2013/03/21/include-files.html" And I should not see "myparam" in "_site/2013/03/21/ignore-params-if-unused.html" And I should see "
  • date = today
  • " in "_site/2013/03/21/list-multiple-parameters.html" @@ -44,7 +45,8 @@ Feature: Include tags | include_file2 | parametrized.html | And I have an "index.html" page that contains "{% include {{site.include_file1}} %} that {% include {{site.include_file2}} what='parameters' %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "a snippet that works with parameters" in "_site/index.html" Scenario: Include a variable file in a loop @@ -53,7 +55,8 @@ Feature: Include tags And I have an "_includes/two.html" file that contains "two" And I have an "index.html" page with files "[one.html, two.html]" that contains "{% for file in page.files %}{% include {{file}} %} {% endfor %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "one two" in "_site/index.html" Scenario: Include a file with variables and filters @@ -64,7 +67,8 @@ Feature: Include tags | include_file | one | And I have an "index.html" page that contains "{% include {{ site.include_file | append: '.html' }} %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "one included" in "_site/index.html" Scenario: Include a file with partial variables @@ -75,7 +79,8 @@ Feature: Include tags | include_file | one | And I have an "index.html" page that contains "{% include {{ site.include_file }}.html %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "one included" in "_site/index.html" Scenario: Include a file and rebuild when include content is changed @@ -83,9 +88,44 @@ Feature: Include tags And I have an "_includes/one.html" file that contains "include" And I have an "index.html" page that contains "{% include one.html %}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "include" in "_site/index.html" When I wait 1 second Then I have an "_includes/one.html" file that contains "include content changed" When I run jekyll build Then I should see "include content changed" in "_site/index.html" + + Scenario: Include a file with multiple variables + Given I have an _includes directory + And I have an "_includes/header-en.html" file that contains "include" + And I have an "index.html" page that contains "{% assign name = 'header' %}{% assign locale = 'en' %}{% include {{name}}-{{locale}}.html %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "include" in "_site/index.html" + + Scenario: Include a file-path with non-alphanumeric character sequences + Given I have an _includes directory + And I have an "_includes/header-en.html" file that contains "include" + And I have an "index.html" page that contains "{% include ./header-en.html %}" + When I run jekyll build + Then I should get a non-zero exit status + And I should see "Invalid syntax for include tag." in the build output + When I have an "index.html" page that contains "{% include foo/.header-en.html %}" + When I run jekyll build + Then I should get a non-zero exit status + And I should see "Invalid syntax for include tag." in the build output + When I have an "index.html" page that contains "{% include //header-en.html %}" + When I run jekyll build + Then I should get a non-zero exit status + And I should see "Invalid syntax for include tag." in the build output + When I have an "index.html" page that contains "{% include ..header-en.html %}" + When I run jekyll build + Then I should get a non-zero exit status + And I should see "Invalid syntax for include tag." in the build output + When I have an "index.html" page that contains "{% include header-en.html %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "include" in "_site/index.html" diff --git a/features/incremental_rebuild.feature b/features/incremental_rebuild.feature index fb95e0c5421..2d22d2e1940 100644 --- a/features/incremental_rebuild.feature +++ b/features/incremental_rebuild.feature @@ -11,10 +11,12 @@ Feature: Incremental rebuild | Wargames | 2009-03-27 | default | The only winning move is not to play. | And I have a default layout that contains "Post Layout: {{ content }}" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post Layout:

    The only winning move is not to play.

    " in "_site/2009/03/27/wargames.html" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post Layout:

    The only winning move is not to play.

    " in "_site/2009/03/27/wargames.html" Scenario: Generate a metadata file @@ -25,12 +27,14 @@ Feature: Incremental rebuild Scenario: Rebuild when content is changed Given I have an "index.html" file that contains "Basic Site" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site" in "_site/index.html" When I wait 1 second Then I have an "index.html" file that contains "Bacon Site" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Bacon Site" in "_site/index.html" Scenario: Rebuild when layout is changed @@ -38,12 +42,14 @@ Feature: Incremental rebuild And I have an "index.html" page with layout "default" that contains "Basic Site with Layout" And I have a default layout that contains "Page Layout: {{ content }}" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: Basic Site with Layout" in "_site/index.html" When I wait 1 second Then I have a default layout that contains "Page Layout Changed: {{ content }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout Changed: Basic Site with Layout" in "_site/index.html" Scenario: Rebuild when an include is changed @@ -51,10 +57,48 @@ Feature: Incremental rebuild And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}" And I have an "_includes/about.textile" file that contains "Generated by Jekyll" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html" When I wait 1 second Then I have an "_includes/about.textile" file that contains "Regenerated by Jekyll" When I run jekyll build -I - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Basic Site with include tag: Regenerated by Jekyll" in "_site/index.html" + + Scenario: Rebuild when a dependency of document in custom collection_dir is changed + Given I have a _includes directory + And I have a configuration file with "collections_dir" set to "collections" + And I have a collections/_posts directory + And I have the following post within the "collections" directory: + | title | date | layout | content | + | Wargames | 2009-03-27 | default | Basic Site with include tag: {% include about.html %} | + And I have an "_includes/about.html" file that contains "Generated by Jekyll" + When I run jekyll build -I + Then I should get a zero exit status + And the _site directory should exist + And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/2009/03/27/wargames.html" + When I wait 1 second + Then I have an "_includes/about.html" file that contains "Regenerated by Jekyll" + When I run jekyll build -I + Then I should get a zero exit status + And the _site directory should exist + And I should see "Basic Site with include tag: Regenerated by Jekyll" in "_site/2009/03/27/wargames.html" + + Scenario: A themed-site and incremental regeneration + Given I have a configuration file with "theme" set to "test-theme" + And I have an "index.md" page that contains "Themed site" + When I run jekyll build --incremental --verbose + Then I should get a zero exit status + And the _site directory should exist + And I should see "Rendering: index.md" in the build output + And I should see "Themed site" in "_site/index.html" + When I wait 1 second + And I have an "about.md" page that contains "About Themed site" + When I run jekyll build --incremental --verbose + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Rendering: index.md" in the build output + But I should see "Themed site" in "_site/index.html" + And I should see "About Themed site" in "_site/about.html" diff --git a/features/layout_data.feature b/features/layout_data.feature new file mode 100644 index 00000000000..8a10ce87f83 --- /dev/null +++ b/features/layout_data.feature @@ -0,0 +1,90 @@ +Feature: Layout data + As a hacker who likes to avoid repetition + I want to be able to embed data into my layouts + In order to make the layouts slightly dynamic + + Scenario: Use custom layout data + Given I have a _layouts directory + And I have a "_layouts/999.html" file with content: + """ + --- + --- + {{ content }} layout content + """ + And I have an "index.html" page with layout "custom" that contains "page content" + And I have an "index.html" file with content: + """ + --- + layout: 999 + --- + page content + """ + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "page content layout content" in "_site/index.html" + + Scenario: Use custom layout data + Given I have a _layouts directory + And I have a "_layouts/custom.html" file with content: + """ + --- + foo: my custom data + --- + {{ content }} foo: {{ layout.foo }} + """ + And I have an "index.html" page with layout "custom" that contains "page content" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "page content\n foo: my custom data" in "_site/index.html" + + Scenario: Inherit custom layout data + Given I have a _layouts directory + And I have a "_layouts/custom.html" file with content: + """ + --- + layout: base + foo: my custom data + --- + {{ content }} + """ + And I have a "_layouts/base.html" file with content: + """ + {{ content }} foo: {{ layout.foo }} + """ + And I have an "index.html" page with layout "custom" that contains "page content" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "page content\n foo: my custom data" in "_site/index.html" + + Scenario: Inherit custom layout data and clear when not present + Given I have a _layouts directory + And I have a "_layouts/default.html" file with content: + """ + --- + bar: i'm default + --- + {{ content }} foo: '{{ layout.foo }}' bar: '{{ layout.bar }}' + """ + And I have a "_layouts/special.html" file with content: + """ + --- + layout: default + foo: my special data + bar: im special + --- + {{ content }} + """ + And I have a "_layouts/page.html" file with content: + """ + --- + layout: default + bar: im page + --- + {{ content }} + """ + And I have an "index.html" page with layout "special" that contains "page content" + And I have an "jekyll.html" page with layout "page" that contains "page content" + When I run jekyll build + Then the "_site/index.html" file should exist + And I should see "page content\n foo: 'my special data' bar: 'im special'" in "_site/index.html" + And I should see "page content\n foo: '' bar: 'im page'" in "_site/jekyll.html" diff --git a/features/link_tag.feature b/features/link_tag.feature new file mode 100644 index 00000000000..3ea8cf6484e --- /dev/null +++ b/features/link_tag.feature @@ -0,0 +1,78 @@ +Feature: Link Tag + As a hacker who likes to write a variety of content + I want to be able to link to pages and documents + And render them without much hassle + + Scenario: Basic site with two pages + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Home]({% link index.md %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Home

    " in "_site/about.html" + + Scenario: Basic site with custom page-permalinks + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page with permalink "/about/" that contains "[Home]({% link index.md %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Home

    " in "_site/about/index.html" + + Scenario: Basic site with custom site-wide-permalinks + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Home]({% link index.md %})" + And I have a configuration file with "permalink" set to "pretty" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Home

    " in "_site/about/index.html" + + Scenario: Basic site with two pages and custom baseurl + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Home]({% link index.md %})" + And I have a configuration file with "baseurl" set to "/blog" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Home

    " in "_site/about.html" + + Scenario: Basic site with two pages and custom baseurl and permalinks + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Home]({% link index.md %})" + And I have a "_config.yml" file with content: + """ + baseurl: /blog + permalink: pretty + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Home

    " in "_site/about/index.html" + + Scenario: Linking to a ghost file + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Contact]({% link contact.md %})" + When I run jekyll build + Then I should get a non-zero exit status + And the _site directory should not exist + And I should see "Could not find document 'contact.md' in tag 'link'" in the build output + + Scenario: Complex site with a variety of files + Given I have an "index.md" page that contains "[About my projects]({% link about.md %})" + And I have an "about.md" page that contains "[Latest Hack]({% link _posts/2018-02-15-metaprogramming.md %})" + And I have a _posts directory + And I have an "_posts/2018-02-15-metaprogramming.md" page that contains "[Download This]({% link script.txt %})" + And I have a "script.txt" file that contains "Static Alert!" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    About my projects

    " in "_site/index.html" + And I should see "

    Latest Hack

    " in "_site/about.html" + And I should see "

    Download This

    " in "_site/2018/02/15/metaprogramming.html" + And I should see "Static Alert!" in "_site/script.txt" diff --git a/features/markdown.feature b/features/markdown.feature index c0eeb25d3f4..71b13ad969f 100644 --- a/features/markdown.feature +++ b/features/markdown.feature @@ -11,7 +11,8 @@ Feature: Markdown | title | date | content | type | | Hackers | 2009-03-27 | # My Title | markdown | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Index" in "_site/index.html" And I should see "

    My Title

    " in "_site/2009/03/27/hackers.html" And I should see "

    My Title

    " in "_site/index.html" @@ -20,13 +21,14 @@ Feature: Markdown Given I have a configuration file with: | key | value | | paginate | 5 | - | gems | [jekyll-paginate] | + | plugins | [jekyll-paginate] | And I have an "index.html" page that contains "Index - {% for post in paginator.posts %} {{ post.content }} {% endfor %}" And I have a _posts directory And I have the following post: | title | date | content | type | | Hackers | 2009-03-27 | # My Title | markdown | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Index" in "_site/index.html" And I should see "

    My Title

    " in "_site/index.html" diff --git a/features/pagination.feature b/features/pagination.feature index b8b89ed09cc..e818985066c 100644 --- a/features/pagination.feature +++ b/features/pagination.feature @@ -7,7 +7,7 @@ Feature: Site pagination Given I have a configuration file with: | key | value | | paginate | | - | gems | [jekyll-paginate] | + | plugins | [jekyll-paginate] | And I have a _layouts directory And I have an "index.html" page that contains "{{ paginator.posts.size }}" And I have a _posts directory @@ -35,7 +35,7 @@ Feature: Site pagination | paginate | 1 | | paginate_path | /blog/page-:num | | permalink | /blog/:year/:month/:day/:title | - | gems | [jekyll-paginate] | + | plugins | [jekyll-paginate] | And I have a blog directory And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}" And I have a _posts directory @@ -63,7 +63,7 @@ Feature: Site pagination | paginate | 1 | | paginate_path | /blog/page/:num | | permalink | /blog/:year/:month/:day/:title | - | gems | [jekyll-paginate] | + | plugins | [jekyll-paginate] | And I have a blog directory And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}" And I have an "index.html" page that contains "Don't pick me!" diff --git a/features/permalinks.feature b/features/permalinks.feature index 74f2e409f7b..86c2c94efc4 100644 --- a/features/permalinks.feature +++ b/features/permalinks.feature @@ -10,7 +10,8 @@ Feature: Fancy permalinks | None Permalink Schema | 2009-03-27 | Totally nothing. | And I have a configuration file with "permalink" set to "none" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally nothing." in "_site/none-permalink-schema.html" Scenario: Use pretty permalink schema @@ -20,7 +21,8 @@ Feature: Fancy permalinks | Pretty Permalink Schema | 2009-03-27 | Totally wordpress. | And I have a configuration file with "permalink" set to "pretty" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally wordpress." in "_site/2009/03/27/pretty-permalink-schema/index.html" Scenario: Use pretty permalink schema for pages @@ -29,7 +31,8 @@ Feature: Fancy permalinks And I have an "sitemap.xml" page that contains "Totally uhm, sitemap" And I have a configuration file with "permalink" set to "pretty" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally index" in "_site/index.html" And I should see "Totally awesome" in "_site/awesome/index.html" And I should see "Totally uhm, sitemap" in "_site/sitemap.xml" @@ -41,7 +44,8 @@ Feature: Fancy permalinks | Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. | And I have a configuration file with "permalink" set to "/blog/:year/:month/:day/:title/" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally custom." in "_site/blog/2009/03/27/custom-permalink-schema/index.html" Scenario: Use custom permalink schema with category @@ -51,7 +55,8 @@ Feature: Fancy permalinks | Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. | And I have a configuration file with "permalink" set to "/:categories/:title.html" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally custom." in "_site/stuff/custom-permalink-schema.html" Scenario: Use custom permalink schema with squished date @@ -61,20 +66,22 @@ Feature: Fancy permalinks | Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. | And I have a configuration file with "permalink" set to "/:month-:day-:year/:title.html" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally custom." in "_site/03-27-2009/custom-permalink-schema.html" Scenario: Use custom permalink schema with date and time - Given I have a _posts directory + Given I have a configuration file with: + | key | value | + | permalink | "/:year:month:day:hour:minute:second.html" | + | timezone | UTC | + And I have a _posts directory And I have the following post: | title | category | date | content | | Custom Permalink Schema | stuff | 2009-03-27 22:31:07 | Totally custom. | - And I have a configuration file with: - | key | value | - | permalink | "/:year:month:day:hour:minute:second.html" | - | timezone | UTC | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally custom." in "_site/20090327223107.html" Scenario: Use per-post permalink @@ -83,7 +90,8 @@ Feature: Fancy permalinks | title | date | permalink | content | | Some post | 2013-04-14 | /custom/posts/1/ | bla bla | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the _site/custom/posts/1 directory should exist And I should see "bla bla" in "_site/custom/posts/1/index.html" @@ -93,7 +101,8 @@ Feature: Fancy permalinks | title | date | permalink | content | | Some post | 2013-04-14 | /custom/posts/some.html | bla bla | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the _site/custom/posts directory should exist And I should see "bla bla" in "_site/custom/posts/some.html" @@ -102,7 +111,8 @@ Feature: Fancy permalinks And I have an "_posts/2009-03-27-Pretty-Permalink-Schema.md" page that contains "Totally wordpress" And I have a configuration file with "permalink" set to "pretty" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally wordpress." in "_site/2009/03/27/Pretty-Permalink-Schema/index.html" Scenario: Use custom permalink schema with cased file name @@ -110,7 +120,8 @@ Feature: Fancy permalinks And I have an "_posts/2009-03-27-Custom-Schema.md" page with title "Custom Schema" that contains "Totally awesome" And I have a configuration file with "permalink" set to "/:year/:month/:day/:slug/" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally awesome" in "_site/2009/03/27/custom-schema/index.html" Scenario: Use pretty permalink schema with title containing underscore @@ -118,5 +129,70 @@ Feature: Fancy permalinks And I have an "_posts/2009-03-27-Custom_Schema.md" page with title "Custom Schema" that contains "Totally awesome" And I have a configuration file with "permalink" set to "pretty" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Totally awesome" in "_site/2009/03/27/Custom_Schema/index.html" + + Scenario: Use a non-HTML file extension in the permalink + Given I have a _posts directory + And I have an "_posts/2016-01-18-i-am-php.md" page with permalink "/2016/i-am-php.php" that contains "I am PHP" + And I have a "i-am-also-php.md" page with permalink "/i-am-also-php.php" that contains "I am also PHP" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I am PHP" in "_site/2016/i-am-php.php" + And I should see "I am also PHP" in "_site/i-am-also-php.php" + + Scenario: Using the same permalink twice + Given I have a "cool.md" page with permalink "/amazing.html" that contains "I am cool" + And I have an "awesome.md" page with permalink "/amazing.html" that contains "I am also awesome" + And I have an "amazing.html" file with content: + """ + Hello World + I'm a static file + """ + And I have a "_config.yml" file with content: + """ + collections: + puppies: + output: true + permalink: /:collection/:year/:month/:day/:title:output_ext + """ + And I have a _puppies directory + And I have the following documents under the puppies collection: + | title | date | content | + | Rover | 2009-03-27 | content for Rover. | + And I have a _posts directory + And I have the following post: + | title | date | layout | category | content | + | Rover | 2009-03-27 | none | puppies | Luke, I am your father. | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Conflict: The following destination is shared by multiple files." in the build output + And I should see "_site/amazing.html" in the build output + And I should see "awesome.md" in the build output + And I should see "cool.md" in the build output + And I should see "amazing.html" in the build output + And I should see "_site/puppies/2009/03/27/rover.html" in the build output + And I should see "_posts/2009-03-27-rover.markdown" in the build output + And I should see "_puppies/rover.md" in the build output + + Scenario: Redirecting from an existing permalink + Given I have a configuration file with "plugins" set to "[jekyll-redirect-from]" + And I have a "deals.html" file with content: + """ + --- + permalink: /deals/ + redirect_from: + - /offers/ + --- + """ + And I have a "offers.html" page with permalink "/offers/" that contains "Hurry! Limited time only!" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Conflict: The following destination is shared by multiple files." in the build output + And I should not see "_site/offers/index.html" in the build output + And I should not see "offers.html" in the build output + And I should not see "redirect.html" in the build output diff --git a/features/plugins.feature b/features/plugins.feature index a36c6c82d1a..e903783b18d 100644 --- a/features/plugins.feature +++ b/features/plugins.feature @@ -4,9 +4,10 @@ Feature: Configuring and using plugins Scenario: Add a gem-based plugin Given I have an "index.html" file that contains "Whatever" - And I have a configuration file with "gems" set to "[jekyll_test_plugin]" + And I have a configuration file with "plugins" set to "[jekyll_test_plugin]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Whatever" in "_site/index.html" And I should see "this is a test" in "_site/test.txt" @@ -14,10 +15,11 @@ Feature: Configuring and using plugins Given I have an "index.html" file that contains "Whatever" And I have a configuration file with: | key | value | - | gems | [jekyll_test_plugin] | + | plugins | [jekyll_test_plugin] | | whitelist | [] | When I run jekyll build --safe - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Whatever" in "_site/index.html" And the "_site/test.txt" file should not exist @@ -25,10 +27,11 @@ Feature: Configuring and using plugins Given I have an "index.html" file that contains "Whatever" And I have a configuration file with: | key | value | - | gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] | + | plugins | [jekyll_test_plugin, jekyll_test_plugin_malicious] | | whitelist | [jekyll_test_plugin] | When I run jekyll build --safe - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Whatever" in "_site/index.html" And the "_site/test.txt" file should exist And I should see "this is a test" in "_site/test.txt" diff --git a/features/post_data.feature b/features/post_data.feature index 6ebfb27d2e6..e807f9bc19d 100644 --- a/features/post_data.feature +++ b/features/post_data.feature @@ -11,7 +11,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post title: {{ page.title }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post title: Star Wars" in "_site/2009/03/27/star-wars.html" Scenario: Use post.url variable @@ -22,9 +23,22 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post url: {{ page.url }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post url: /2009/03/27/star-wars.html" in "_site/2009/03/27/star-wars.html" + Scenario: Use page.name variable + Given I have a _posts directory + And I have a _layouts directory + And I have the following post: + | title | date | layout | content | + | Star Wars | 2009-03-27 | simple | Luke, I am your father. | + And I have a simple layout that contains "Page name: {{ page.name }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Page name: 2009-03-27-star-wars.markdown" in "_site/2009/03/27/star-wars.html" + Scenario: Use post.date variable Given I have a _posts directory And I have a _layouts directory @@ -33,9 +47,24 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post date: {{ page.date | date_to_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post date: 27 Mar 2009" in "_site/2009/03/27/star-wars.html" + Scenario: Use post.date variable with invalid + Given I have a _posts directory + And I have a "_posts/2016-01-01-test.md" page with date "tuesday" that contains "I have a bad date." + When I run jekyll build + Then the _site directory should not exist + And I should see "Document '_posts/2016-01-01-test.md' does not have a valid date in the YAML front matter." in the build output + + Scenario: Invalid date in filename + Given I have a _posts directory + And I have a "_posts/2016-22-01-test.md" page that contains "I have a bad date." + When I run jekyll build + Then the _site directory should not exist + And I should see "Document '_posts/2016-22-01-test.md' does not have a valid date in the filename." in the build output + Scenario: Use post.id variable Given I have a _posts directory And I have a _layouts directory @@ -44,7 +73,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post id: {{ page.id }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post id: /2009/03/27/star-wars" in "_site/2009/03/27/star-wars.html" Scenario: Use post.content variable @@ -55,7 +85,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post content: {{ content }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post content:

    Luke, I am your father.

    " in "_site/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in a folder @@ -67,7 +98,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in a folder and has category in YAML @@ -79,7 +111,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | film | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/film/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in a folder and has categories in YAML @@ -91,7 +124,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | [film, scifi] | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/film/scifi/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in a folder and duplicated category is in YAML @@ -103,9 +137,52 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | movies | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" + Scenario: Use post.categories when category is a composite of multiple words + Given I have a Sci-Fi Movi3s directory + And I have a Sci-Fi Movi3s/_posts directory + And I have a _layouts directory + And I have the following post in "Sci-Fi Movi3s": + | title | date | layout | category | content | + | Star Wars | 2020-04-03 | simple | vintage | Luke, I am your father. | + And I have a "_layouts/simple.html" file with content: + """ + Post categories: {{ page.categories | join: ', ' }} + Post URL: {{ page.url }} + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Post categories: Sci-Fi Movi3s, vintage" in "_site/sci-fi movi3s/vintage/2020/04/03/star-wars.html" + And I should see "Post URL: /sci-fi%20movi3s/vintage/2020/04/03/star-wars.html" in "_site/sci-fi movi3s/vintage/2020/04/03/star-wars.html" + + Scenario: Use post.slugified_categories to generate URL when category is a composite of multiple words + Given I have a Sci-Fi Movi3s directory + And I have a Sci-Fi Movi3s/_posts directory + And I have a _layouts directory + And I have the following post in "Sci-Fi Movi3s": + | title | date | layout | category | content | + | Star Wars | 2020-04-03 | simple | vintage | Luke, I am your father. | + And I have a "_layouts/simple.html" file with content: + """ + Post categories: {{ page.categories | join: ', ' }} + Post URL: {{ page.url }} + """ + And I have a "_config.yml" file with content: + """ + collections: + posts: + permalink: "/:slugified_categories/:year/:month/:day/:title:output_ext" + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Post categories: Sci-Fi Movi3s, vintage" in "_site/sci-fi-movi3s/vintage/2020/04/03/star-wars.html" + And I should see "Post URL: /sci-fi-movi3s/vintage/2020/04/03/star-wars.html" in "_site/sci-fi-movi3s/vintage/2020/04/03/star-wars.html" + Scenario: Use post.tags variable Given I have a _posts directory And I have a _layouts directory @@ -114,7 +191,8 @@ Feature: Post data | Star Wars | 2009-05-18 | simple | twist | Luke, I am your father. | And I have a simple layout that contains "Post tags: {{ page.tags }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post tags: twist" in "_site/2009/05/18/star-wars.html" Scenario: Use post.categories variable when categories are in folders @@ -127,7 +205,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when categories are in folders with mixed case @@ -140,7 +219,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Luke, I am your father. | And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post categories: scifi and Movies" in "_site/scifi/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in YAML @@ -151,7 +231,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | movies | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when category is in YAML and is mixed-case @@ -162,7 +243,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Movies | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: Movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when categories are in YAML @@ -173,7 +255,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | ['scifi', 'movies'] | Luke, I am your father. | And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when categories are in YAML and are duplicated @@ -184,7 +267,8 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | ['movies', 'movies'] | Luke, I am your father. | And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Superdirectories of _posts applied to post.categories @@ -193,7 +277,8 @@ Feature: Post data And I have a _layouts directory And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Subdirectories of _posts not applied to post.categories @@ -202,7 +287,8 @@ Feature: Post data And I have a _layouts directory And I have a simple layout that contains "Post category: {{ page.categories }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" Scenario: Use post.categories variable when categories are in YAML with mixed case @@ -214,17 +300,32 @@ Feature: Post data | Star Trek | 2013-03-17 | simple | ['SciFi', 'movies'] | Jean Luc, I am your father. | And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post categories: scifi and Movies" in "_site/scifi/movies/2009/03/27/star-wars.html" And I should see "Post categories: SciFi and movies" in "_site/scifi/movies/2013/03/17/star-trek.html" +Scenario: Use page.render_with_liquid variable + Given I have a _posts directory + And I have the following posts: + | title | render_with_liquid | date | content | + | Unrendered Post | false | 2017-07-06 | Hello {{ page.title }} | + | Rendered Post | true | 2017-07-06 | Hello {{ page.title }} | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Hello Unrendered Post" in "_site/2017/07/06/unrendered-post.html" + But I should see "Hello {{ page.title }}" in "_site/2017/07/06/unrendered-post.html" + And I should see "Hello Rendered Post" in "_site/2017/07/06/rendered-post.html" + Scenario Outline: Use page.path variable Given I have a /_posts directory And I have the following post in "": | title | type | date | content | | my-post | html | 2013-04-12 | Source path: {{ page.path }} | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Source path: _posts/2013-04-12-my-post.html" in "_site//2013/04/12/my-post.html" Examples: @@ -233,14 +334,15 @@ Feature: Post data | dir | dir/ | | dir/nested | dir/nested/ | - Scenario: Override page.path variable + Scenario: Cannot override page.path variable Given I have a _posts directory And I have the following post: | title | date | path | content | - | override | 2013-04-12 | override-path.html | Custom path: {{ page.path }} | + | override | 2013-04-12 | override-path.html | Non-custom path: {{ page.path }} | When I run jekyll build - Then the _site directory should exist - And I should see "Custom path: override-path.html" in "_site/2013/04/12/override.html" + Then I should get a zero exit status + And the _site directory should exist + And I should see "Non-custom path: _posts/2013-04-12-override.markdown" in "_site/2013/04/12/override.html" Scenario: Disable a post from being published Given I have a _posts directory @@ -249,7 +351,8 @@ Feature: Post data | title | date | layout | published | content | | Star Wars | 2009-03-27 | simple | false | Luke, I am your father. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/2009/03/27/star-wars.html" file should not exist And I should see "Published!" in "_site/index.html" @@ -261,9 +364,22 @@ Feature: Post data | Star Wars | 2009-03-27 | simple | Darth Vader | Luke, I am your father. | And I have a simple layout that contains "Post author: {{ page.author }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Post author: Darth Vader" in "_site/2009/03/27/star-wars.html" + Scenario: Use a variable which is a reserved keyword in Ruby + Given I have a _posts directory + And I have a _layouts directory + And I have the following post: + | title | date | layout | class | content | + | My post | 2016-01-21 | simple | kewl-post | Luke, I am your father. | + And I have a simple layout that contains "{{page.title}} has class {{page.class}}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "My post has class kewl-post" in "_site/2016/01/21/my-post.html" + Scenario: Previous and next posts title Given I have a _posts directory And I have a _layouts directory @@ -274,6 +390,39 @@ Feature: Post data | Terminator | 2009-05-27 | ordered | Arnold | Sayonara, baby | And I have a ordered layout that contains "Previous post: {{ page.previous.title }} and next post: {{ page.next.title }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "next post: Some like it hot" in "_site/2009/03/27/star-wars.html" And I should see "Previous post: Some like it hot" in "_site/2009/05/27/terminator.html" + + Scenario: Deprecate calling data keys directly via Ruby + Given I have a _posts directory + And I have a _plugins directory + And I have the following post: + | title | date | content | + | My post | 2016-01-21 | Luke, I am your father. | + And I have a "_plugins/foo.rb" file with content: + """ + Jekyll::Hooks.register :documents, :pre_render do |doc| + doc.title + end + """ + And I have a "_plugins/bar.rb" file with content: + """ + module FooBar + def self.dummy?(doc) + doc.title == "Dummy Document" + end + end + + Jekyll::Hooks.register :documents, :post_render do |doc| + FooBar.dummy?(doc) + end + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Deprecation: Document#title" in the build output + And I should see "_plugins/foo.rb:2" in the build output + And I should see "_plugins/bar.rb:3" in the build output + But I should not see "lib/jekyll/document.rb" in the build output diff --git a/features/post_excerpts.feature b/features/post_excerpts.feature index c66c527bb6c..a32694fe7d6 100644 --- a/features/post_excerpts.feature +++ b/features/post_excerpts.feature @@ -12,7 +12,8 @@ Feature: Post excerpts | title | date | layout | content | | entry1 | 2007-12-31 | post | content for entry1. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see exactly "

    content for entry1.

    " in "_site/index.html" Scenario: An excerpt from a post with a layout @@ -24,7 +25,8 @@ Feature: Post excerpts | title | date | layout | content | | entry1 | 2007-12-31 | post | content for entry1. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the _site/2007 directory should exist And the _site/2007/12 directory should exist And the _site/2007/12/31 directory should exist @@ -32,6 +34,25 @@ Feature: Post excerpts And I should see exactly "

    content for entry1.

    " in "_site/2007/12/31/entry1.html" And I should see exactly "

    content for entry1.

    " in "_site/index.html" + Scenario: An excerpt with Liquid constructs from a post with a layout + Given I have an "index.html" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" + And I have a configuration file with "baseurl" set to "/blog" + And I have a _posts directory + And I have a _layouts directory + And I have a post layout that contains "{{ page.excerpt }}" + And I have the following posts: + | title | date | layout | content | + | entry1 | 2007-12-31 | post | {{ 'assets/style.css' \| relative_url }} | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the _site/2007 directory should exist + And the _site/2007/12 directory should exist + And the _site/2007/12/31 directory should exist + And the "_site/2007/12/31/entry1.html" file should exist + And I should see exactly "

    /blog/assets/style.css

    " in "_site/2007/12/31/entry1.html" + And I should see exactly "

    /blog/assets/style.css

    " in "_site/index.html" + Scenario: An excerpt from a post with a layout which has context Given I have an "index.html" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" And I have a _posts directory @@ -41,10 +62,53 @@ Feature: Post excerpts | title | date | layout | content | | entry1 | 2007-12-31 | post | content for entry1. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the _site/2007 directory should exist And the _site/2007/12 directory should exist And the _site/2007/12/31 directory should exist And the "_site/2007/12/31/entry1.html" file should exist And I should see "

    content for entry1.

    " in "_site/index.html" And I should see "

    content for entry1.

    \n" in "_site/2007/12/31/entry1.html" + + Scenario: Excerpts from posts having 'render_with_liquid' in their front matter + Given I have an "index.html" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" + And I have a _posts directory + And I have a _layouts directory + And I have a post layout that contains "{{ page.excerpt }}" + And I have the following posts: + | title | layout | render_with_liquid | date | content | + | Unrendered Post | post | false | 2017-07-06 | Liquid is not rendered at {{ page.url }} | + | Rendered Post | post | true | 2017-07-06 | Liquid is rendered at {{ page.url }} | + When I run jekyll build + Then I should get a zero exit status + And the _site/2017/07/06 directory should exist + And the "_site/2017/07/06/unrendered-post.html" file should exist + And the "_site/2017/07/06/rendered-post.html" file should exist + And I should see "Liquid is not rendered at {{ page.url }}" in "_site/2017/07/06/unrendered-post.html" + But I should see "

    Liquid is rendered at /2017/07/06/rendered-post.html

    " in "_site/2017/07/06/rendered-post.html" + And I should see "

    Liquid is not rendered at {{ page.url }}

    \n

    Liquid is rendered at /2017/07/06/rendered-post.html

    " in "_site/index.html" + + Scenario: Excerpts from posts with reference-style Markdown links + Given I have a configuration file with: + | key | value | + | permalink | "/:title:output_ext" | + | kramdown | { show_warnings: true } | + And I have an "index.html" page that contains "{% for post in site.posts %}{{ post.excerpt }}{% endfor %}" + And I have a _layouts directory + And I have a post layout that contains "{{ page.excerpt }}" + And I have a _posts directory + And I have the following posts: + | title | layout | date | content | + | Just Text Excerpt | post | 2019-03-06 | Install Jekyll\n\nNext Para [^1]\n\n[^1]: Lorem ipsum | + | Text and Footnote | post | 2019-03-07 | Alpha [^1]\n\nNext Para\n\n[^1]: Omega sigma | + | Text and Reference Link | post | 2019-03-08 | Read [docs][link]\n\nNext Para\n\n[link]: docs.jekyll.com | + | Text and Self-referencing Link | post | 2019-03-09 | Check out [jekyll]\n\nNext Para\n\n[jekyll]: jekyllrb.com | + When I run jekyll build + Then I should get a zero exit status + And I should not see "Kramdown warning" in the build output + But I should see exactly "

    Install Jekyll

    " in "_site/just-text-excerpt.html" + And I should see "

    Alpha 1

    " in "_site/text-and-footnote.html" + And I should see "

    Omega sigma 

    " in "_site/text-and-footnote.html" + And I should see "

    Read docs

    " in "_site/text-and-reference-link.html" + And I should see "

    Check out jekyll

    " in "_site/text-and-self-referencing-link.html" diff --git a/features/post_url_tag.feature b/features/post_url_tag.feature new file mode 100644 index 00000000000..395e9d173b5 --- /dev/null +++ b/features/post_url_tag.feature @@ -0,0 +1,193 @@ +Feature: PostUrl Tag + As a blogger who likes to write a variety of content + I want to be able to link to posts easily + And render them without much hassle + + Scenario: A site that is using the defaults for permalink + Given I have a _posts directory + And I have the following post: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have an "index.md" page that contains "[Welcome]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + + Scenario: Site with site-wide custom permalink setting + Given I have a _posts directory + And I have the following posts: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + | We Meet Again | 2019-02-05 | Alpha beta gamma | + And I have a configuration file with "permalink" set to "/:title:output_ext" + And I have an "index.md" page that contains "[Welcome]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + + Scenario: Site with custom permalink settings on each post + Given I have a _posts directory + And I have the following posts: + | title | date | permalink | content | + | Hello World | 2019-02-04 | "/2019/hello-world/" | Lorem ipsum dolor | + | We Meet Again | 2019-02-05 | "/2019/second-meeting/" | Alpha beta gamma | + And I have a configuration file with "permalink" set to "/:title:output_ext" + And I have an "index.md" page that contains "[Welcome]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + + Scenario: Site with no posts + Given I have an "index.md" page that contains "[Welcome]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a non-zero exit status + And the _site directory should not exist + But I should see "Could not find post \"2019-02-04-hello-world\" in tag 'post_url'." in the build output + + Scenario: Site with a future-dated post + Given I have a _posts directory + And I have the following posts: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + | We Meet Again | 2119-02-04 | Alpha beta gamma | + And I have a configuration file with "permalink" set to "/:title:output_ext" + And I have an "index.md" page that contains "[Welcome Again]({% post_url 2119-02-04-we-meet-again %})" + When I run jekyll build --future + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome Again

    " in "_site/index.html" + + Scenario: Site with configured baseurl + Given I have a _posts directory + And I have the following posts: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + | We Meet Again | 2019-02-05 | Alpha beta gamma | + And I have a configuration file with "baseurl" set to "blog" + And I have an "index.md" page that contains "[Welcome]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + + Scenario: Posts with categories + Given I have a _posts directory + And I have the following post: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have a movies/_posts directory + And I have the following post in "movies": + | title | date | content | + | Hello Movies | 2019-02-05 | Lorem ipsum dolor | + And I have the following post in "movies": + | title | date | category | content | + | Star Wars | 2019-02-06 | film | Luke, I am your father | + And I have an "index.md" page with content: + """ + [Welcome]({% post_url 2019-02-04-hello-world %}) + + [Movies]({% post_url movies/2019-02-05-hello-movies %}) + + [Film]({% post_url movies/2019-02-06-star-wars %}) + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + And I should see "

    Movies

    " in "_site/index.html" + And I should see "

    Film

    " in "_site/index.html" + + Scenario: Duplicate posts with categories + Given I have a _posts directory + And I have the following post: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have a movies/_posts directory + And I have the following post in "movies": + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have an "index.md" page with content: + """ + [Welcome]({% post_url 2019-02-04-hello-world %}) + + [Movies]({% post_url movies/2019-02-04-hello-world %}) + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + And I should see "

    Movies

    " in "_site/index.html" + + Scenario: Deprecated usage to link nested post + Given I have a movies/_posts directory + And I have the following post in "movies": + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have an "index.md" page that contains "[Movies]({% post_url 2019-02-04-hello-world %})" + When I run jekyll build + Then I should get a zero exit status + And I should see "Deprecation: A call to '{% post_url 2019-02-04-hello-world %}' did not match a post" in the build output + But the _site directory should exist + And I should see "

    Movies

    " in "_site/index.html" + + Scenario: Nested posts in a directory with name containing spaces + Given I have a Cats and Dogs/_posts directory + And I have the following post in "Cats and Dogs": + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have a _posts/Salt and Pepper directory + And I have the following post under "Salt and Pepper": + | title | date | content | + | Hello Again | 2019-02-05 | Lorem ipsum dolor | + And I have an "index.md" file with content: + """ + --- + --- + + [Post 1]({% post_url Cats and Dogs/2019-02-04-hello-world %}) + + [Post 2]({% post_url Salt and Pepper/2019-02-05-hello-again %}) + """ + When I run jekyll build + Then I should get a zero exit status + And I should not see "Deprecation: A call to '{% post_url" in the build output + But the _site directory should exist + And I should see "

    Post 1

    " in "_site/index.html" + And I should see "

    Post 2

    " in "_site/index.html" + + Scenario: Calling for a post via a liquid variable + Given I have a _posts directory + And I have the following post: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + And I have an "index.md" page with content: + """ + {% assign value='2019-02-04-hello-world' %} + [Welcome]({% post_url {{ value }} %}) + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "

    Welcome

    " in "_site/index.html" + + Scenario: Calling for posts via a liquid variable in a for tag + Given I have a _posts directory + And I have the following post: + | title | date | content | + | Hello World | 2019-02-04 | Lorem ipsum dolor | + | We Meet Again | 2019-02-05 | Alpha beta gamma | + And I have an "index.md" page with content: + """ + {% assign posts = '2019-02-04-hello-world;2019-02-05-we-meet-again' | split: ';' %} + {%- for slug in posts -%} + [{{ slug }}]({% post_url {{ slug }} %}) + {%- endfor %} + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "2019-02-04-hello-world" in "_site/index.html" + And I should see "2019-02-05-we-meet-again" in "_site/index.html" diff --git a/features/rendering.feature b/features/rendering.feature index 01507cb0b1c..c06e06524f5 100644 --- a/features/rendering.feature +++ b/features/rendering.feature @@ -5,6 +5,19 @@ Feature: Rendering But I want to make it as simply as possible So render with Liquid and place in Layouts + Scenario: Rendering a site with parentheses in its path name + Given I have a blank site in "omega(beta)" + And I have an "omega(beta)/test.md" page with layout "simple" that contains "Hello World" + And I have an omega(beta)/_includes directory + And I have an "omega(beta)/_includes/head.html" file that contains "Snippet" + And I have a configuration file with "source" set to "omega(beta)" + And I have an omega(beta)/_layouts directory + And I have an "omega(beta)/_layouts/simple.html" file that contains "{% include head.html %}: {{ content }}" + When I run jekyll build --profile + Then I should get a zero exit status + And I should see "Snippet:

    Hello World

    " in "_site/test.html" + And I should see "_layouts/simple.html" in the build output + Scenario: When receiving bad Liquid Given I have a "index.html" page with layout "simple" that contains "{% include invalid.html %}" And I have a simple layout that contains "{{ content }}" @@ -12,39 +25,217 @@ Feature: Rendering Then I should get a non-zero exit-status And I should see "Liquid Exception" in the build output + Scenario: When receiving a liquid syntax error in included file + Given I have a _includes directory + And I have a "_includes/invalid.html" file that contains "{% INVALID %}" + And I have a "index.html" page with layout "simple" that contains "{% include invalid.html %}" + And I have a simple layout that contains "{{ content }}" + When I run jekyll build + Then I should get a non-zero exit-status + And I should see "Liquid Exception: Liquid syntax error \(.+/invalid\.html line 1\): Unknown tag 'INVALID' included in index\.html" in the build output + + Scenario: When receiving a generic liquid error in included file + Given I have a _includes directory + And I have a "_includes/invalid.html" file that contains "{{ site.title | prepend 'Prepended Text' }}" + And I have a "index.html" page with layout "simple" that contains "{% include invalid.html %}" + And I have a simple layout that contains "{{ content }}" + When I run jekyll build + Then I should get a non-zero exit-status + And I should see "Liquid Exception: Liquid error \(.+/_includes/invalid\.html line 1\): wrong number of arguments (\(given 1, expected 2\)|\(1 for 2\)) included in index\.html" in the build output + + Scenario: Rendering a default site containing a file with rogue Liquid constructs + Given I have a "index.html" page with title "Simple Test" that contains "{{ page.title | foobar }}\n\n{{ page.author }}" + When I run jekyll build + Then I should get a zero exit-status + And I should not see "Liquid Exception:" in the build output + + Scenario: Rendering a default site containing a file with a non-existent Liquid variable + Given I have a "index.html" file with content: + """ + --- + title: Simple Test + --- + {{ site.lorem.ipsum }} + {{ site.title }} + """ + And I have a configuration file with "title" set to "Hello World" + When I run jekyll build + Then I should get a zero exit-status + And the _site directory should exist + + Scenario: Rendering a custom site containing a file with a non-existent Liquid variable + Given I have a "index.html" file with content: + """ + --- + title: Simple Test + --- + {{ page.title }} + + {{ page.author }} + """ + And I have a "_config.yml" file with content: + """ + liquid: + strict_variables: true + """ + When I run jekyll build + Then I should get a non-zero exit-status + And I should see "Liquid error \(line 3\): undefined variable author in index.html" in the build output + + Scenario: Rendering a custom site containing a file with a non-existent Liquid filter + Given I have a "index.html" file with content: + """ + --- + author: John Doe + --- + {{ page.title }} + + {{ page.author | foobar }} + """ + And I have a "_config.yml" file with content: + """ + liquid: + strict_filters: true + """ + When I run jekyll build + Then I should get a non-zero exit-status + And I should see "Liquid error \(line 3\): undefined filter foobar in index.html" in the build output + Scenario: Render Liquid and place in layout Given I have a "index.html" page with layout "simple" that contains "Hi there, Jekyll {{ jekyll.environment }}!" And I have a simple layout that contains "{{ content }}Ahoy, indeed!" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Hi there, Jekyll development!\nAhoy, indeed" in "_site/index.html" Scenario: Don't place asset files in layout Given I have an "index.scss" page with layout "simple" that contains ".foo-bar { color:black; }" And I have an "index.coffee" page with layout "simple" that contains "whatever()" - And I have a configuration file with "gems" set to "[jekyll-coffeescript]" + And I have a configuration file with "plugins" set to "[jekyll-coffeescript]" And I have a simple layout that contains "{{ content }}Ahoy, indeed!" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should not see "Ahoy, indeed!" in "_site/index.css" And I should not see "Ahoy, indeed!" in "_site/index.js" + Scenario: Ignore defaults and don't place pages and documents with layout set to 'none' + Given I have a "index.md" page with layout "none" that contains "Hi there, {{ site.author }}!" + And I have a _trials directory + And I have a "_trials/no-layout.md" page with layout "none" that contains "Hi there, {{ site.author }}!" + And I have a "_trials/test.md" page with layout "null" that contains "Hi there, {{ site.author }}!" + And I have a none layout that contains "{{ content }}Welcome!" + And I have a page layout that contains "{{ content }}Check this out!" + And I have a configuration file with: + | key | value | + | author | John Doe | + | collections | {trials: {output: true}} | + | defaults | [{scope: {path: ""}, values: {layout: page}}] | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Welcome!" in "_site/trials/no-layout.html" + And I should not see "Check this out!" in "_site/trials/no-layout.html" + But I should see "Check this out!" in "_site/trials/test.html" + And I should see "Hi there, John Doe!" in "_site/index.html" + And I should not see "Welcome!" in "_site/index.html" + And I should not see "Build Warning:" in the build output + + Scenario: Don't place pages and documents with layout set to 'none' + Given I have a "index.md" page with layout "none" that contains "Hi there, {{ site.author }}!" + And I have a _trials directory + And I have a "_trials/no-layout.md" page with layout "none" that contains "Hi there, {{ site.author }}!" + And I have a "_trials/test.md" page with layout "page" that contains "Hi there, {{ site.author }}!" + And I have a none layout that contains "{{ content }}Welcome!" + And I have a page layout that contains "{{ content }}Check this out!" + And I have a configuration file with: + | key | value | + | author | John Doe | + | collections | {trials: {output: true}} | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Welcome!" in "_site/trials/no-layout.html" + And I should not see "Welcome!" in "_site/index.html" + But I should see "Check this out!" in "_site/trials/test.html" + And I should see "Hi there, John Doe!" in "_site/index.html" + And I should not see "Build Warning:" in the build output + Scenario: Render liquid in Sass Given I have an "index.scss" page that contains ".foo-bar { color:{{site.color}}; }" And I have a configuration file with "color" set to "red" When I run jekyll build - Then the _site directory should exist - And I should see ".foo-bar {\n color: red; }" in "_site/index.css" + Then I should get a zero exit status + And the _site directory should exist + And I should see ".foo-bar {\n color: red;\n}\n\n\/\*# sourceMappingURL=index.css.map \*\/" in "_site/index.css" Scenario: Not render liquid in CoffeeScript without explicitly including jekyll-coffeescript Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/index.js" file should not exist Scenario: Render liquid in CoffeeScript with jekyll-coffeescript enabled Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'" - And I have a configuration file with "gems" set to "[jekyll-coffeescript]" + And I have a configuration file with "plugins" set to "[jekyll-coffeescript]" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "hey = 'for cicada';" in "_site/index.js" + + Scenario: Rendering Liquid expressions that return strings containing Liquid expressions + Given I have an "index.md" file with content: + """ + --- + prequel: "{% link series/first-part.md %}" + sequel: "{% link series/last-part.md %}" + --- + + This is the second-part of the series named {{ site.novel }}. + The first part is at {{ page.prequel }}. + + Lorem ipsum + + {% capture sequel_link %}{{ page.sequel }}{% endcapture %} + The last part of the series can be read at {{ sequel_link }} + """ + And I have a configuration file with "novel" set to "'{{ site.title }}'" + When I run jekyll build + Then I should get a zero exit status + And I should see "series named {{ site.title }}" in "_site/index.html" + And I should see "{% link series/first-part.md %}" in "_site/index.html" + And I should see "{% link series/last-part.md %}" in "_site/index.html" + + Scenario: Render content of another page + Given I have an "index.md" page that contains "__Hello World__" + And I have an "about.md" page that contains "{{ page.name }}" + And I have a "test.json" file with content: + """ + --- + --- + + { + "hpages": [ + {%- for page in site.html_pages %} + { + "url" : {{ page.url | jsonify }}, + "name" : {{ page.name | jsonify }}, + "path" : {{ page.path | jsonify }}, + "title" : {{ page.title | jsonify }}, + "layout" : {{ page.layout | jsonify }}, + "content": {{ page.content | jsonify }}, + "excerpt": {{ page.excerpt | jsonify }} + }{% unless forloop.last %},{% endunless -%} + {% endfor %} + ] + } + """ + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + But I should not see "content\": \"{{ page.name }}" in "_site/test.json" + And I should not see "content\": \"__Hello World__" in "_site/test.json" + But I should see "content\": \"

    about.md

    " in "_site/test.json" + And I should see "content\": \"

    Hello World

    " in "_site/test.json" diff --git a/features/site_configuration.feature b/features/site_configuration.feature index 379cea4f214..53d5b21fa4a 100644 --- a/features/site_configuration.feature +++ b/features/site_configuration.feature @@ -8,7 +8,8 @@ Feature: Site configuration And I have an "_sourcedir/index.html" file that contains "Changing source directory" And I have a configuration file with "source" set to "_sourcedir" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Changing source directory" in "_site/index.html" Scenario: Change destination directory @@ -43,9 +44,11 @@ Feature: Site configuration Given I have an "Rakefile" file that contains "I want to be excluded" And I have an "README" file that contains "I want to be excluded" And I have an "index.html" file that contains "I want to be included" + And I have a "Gemfile" file that contains "gem 'include-me'" And I have a configuration file with "exclude" set to "['Rakefile', 'README']" When I run jekyll build Then I should see "I want to be included" in "_site/index.html" + And the "_site/Gemfile" file should not exist And the "_site/Rakefile" file should not exist And the "_site/README" file should not exist @@ -53,6 +56,7 @@ Feature: Site configuration Given I have an "Rakefile" file that contains "I want to be excluded" And I have an "README" file that contains "I want to be excluded" And I have an "index.html" file that contains "I want to be included" + And I have a "Gemfile" file that contains "gem 'include-me'" And I have a configuration file with "exclude" set to: | value | | README | @@ -61,40 +65,132 @@ Feature: Site configuration Then I should see "I want to be included" in "_site/index.html" And the "_site/Rakefile" file should not exist And the "_site/README" file should not exist + And the "_site/Gemfile" file should not exist - Scenario: Use RDiscount for markup - Given I have an "index.markdown" page that contains "[Google](http://google.com)" - And I have a configuration file with "markdown" set to "rdiscount" + Scenario: Copy over excluded files when their directory is explicitly included + Given I have a ".gitignore" file that contains ".DS_Store" + And I have an ".htaccess" file that contains "SomeDirective" + And I have a "Gemfile" file that contains "gem 'include-me'" + And I have a node_modules directory + And I have a "node_modules/bazinga.js" file that contains "var c = 'Bazinga!';" + And I have a "node_modules/warning.js" file that contains "var w = 'Winter is coming!';" + And I have a configuration file with "include" set to: + | value | + | .gitignore | + | .foo | + | Gemfile | + | node_modules | When I run jekyll build - Then the _site directory should exist - And I should see "Google" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And the "_site/.htaccess" file should not exist + But I should see ".DS_Store" in "_site/.gitignore" + And I should see "gem 'include-me'" in "_site/Gemfile" + And I should see "var c = 'Bazinga!';" in "_site/node_modules/bazinga.js" + And I should see "var w = 'Winter is coming!';" in "_site/node_modules/warning.js" - Scenario: Use Kramdown for markup - Given I have an "index.markdown" page that contains "[Google](http://google.com)" - And I have a configuration file with "markdown" set to "kramdown" + Scenario: Copy over excluded files only when they are explicitly included + Given I have a ".gitignore" file that contains ".DS_Store" + And I have an ".htaccess" file that contains "SomeDirective" + And I have a node_modules directory + And I have a "node_modules/bazinga.js" file that contains "var c = 'Bazinga!';" + And I have a "node_modules/warning.js" file that contains "var w = 'Winter is coming!';" + And I have a configuration file with "include" set to: + | value | + | .gitignore | + | .foo | + | node_modules/bazinga.js | When I run jekyll build - Then the _site directory should exist - And I should see "Google" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And the "_site/.htaccess" file should not exist + But I should see ".DS_Store" in "_site/.gitignore" + And I should see "var c = 'Bazinga!';" in "_site/node_modules/bazinga.js" + But the "_site/node_modules/warning.js" file should not exist - Scenario: Use Redcarpet for markup - Given I have an "index.markdown" page that contains "[Google](http://google.com)" - And I have a configuration file with "markdown" set to "redcarpet" + Scenario: Copy over excluded wild-card files only when they are explicitly included + Given I have a ".gitignore" file that contains ".DS_Store" + And I have an ".htaccess" file that contains "SomeDirective" + And I have an "foo.txt" file that contains "Lorem Ipsum" + And I have an "index.md" page that contains "{{ site.title }}" + And I have an "about.md" page that contains "{{ site.author }}" + And I have a configuration file with: + | key | value | + | title | Barren Site | + | author | John Doe | + | exclude | ["**"] | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/.gitignore" file should not exist + And the "_site/foo.txt" file should not exist + And the "_site/index.html" file should not exist + And the "_site/about.html" file should not exist + But the "_site/.htaccess" file should exist + Given I have a configuration file with: + | key | value | + | title | Barren Site | + | author | John Doe | + | exclude | ["**"] | + | include | ["about.md"] | When I run jekyll build - Then the _site directory should exist - And I should see "Google" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + And the "_site/.gitignore" file should not exist + And the "_site/foo.txt" file should not exist + And the "_site/index.html" file should not exist + And the "_site/.htaccess" file should not exist + But the "_site/about.html" file should exist + And I should see "John Doe" in "_site/about.html" - Scenario: Highlight code with pygments - Given I have an "index.html" page that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}" + Scenario: Process included files only once + Given I have a ".foobar" page that contains "dotfile with front matter" + And I have an ".htaccess" file that contains "SomeDirective" + And I have a "_redirects" file that contains "/foo/* /bar/* 301!" + And I have an "index.md" file with content: + """ + --- + --- + + Dotpages: {{ site.pages | where: 'path', '.foobar' | size }} + Dotstatics: {{ site.static_files | where: 'path', '/_redirects' | size }} + """ + And I have a configuration file with "title" set to "Hello World" When I run jekyll build - Then the _site directory should exist - And I should see "Hello world!" in "_site/index.html" - And I should see "class=\"highlight\"" in "_site/index.html" + Then I should get a zero exit status + And the _site directory should exist + But the "_site/.foobar" file should not exist + And the "_site/_redirects" file should not exist + And I should see "Dotpages: 0" in "_site/index.html" + And I should see "Dotstatics: 0" in "_site/index.html" + + When I have a configuration file with: + | key | value | + | title | Hello World | + | include | [.foobar, _redirects] | + When I run jekyll build + Then I should get a zero exit status + And I should not see "Conflict:" in the build output + And the _site directory should exist + And the "_site/.foobar" file should exist + And the "_site/_redirects" file should exist + And I should see "Dotpages: 1" in "_site/index.html" + And I should see "Dotstatics: 1" in "_site/index.html" + + Scenario: Use Kramdown for markup + Given I have an "index.markdown" page that contains "[Google](https://www.google.com)" + And I have a configuration file with "markdown" set to "kramdown" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Google" in "_site/index.html" Scenario: Highlight code with rouge Given I have an "index.html" page that contains "{% highlight ruby %} puts 'Hello world!' {% endhighlight %}" And I have a configuration file with "highlighter" set to "rouge" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Hello world!" in "_site/index.html" And I should see "class=\"highlight\"" in "_site/index.html" @@ -122,7 +218,8 @@ Feature: Site configuration | entry1 | 2007-12-31 | post | content for entry1. | | entry2 | 2020-01-31 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: 1 on 2010-01-01" in "_site/index.html" And I should see "Post Layout:

    content for entry1.

    " in "_site/2007/12/31/entry1.html" And the "_site/2020/01/31/entry2.html" file should not exist @@ -142,7 +239,8 @@ Feature: Site configuration | entry1 | 2007-12-31 | post | content for entry1. | | entry2 | 2020-01-31 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: 2 on 2010-01-01" in "_site/index.html" And I should see "Post Layout:

    content for entry1.

    " in "_site/2007/12/31/entry1.html" And I should see "Post Layout:

    content for entry2.

    " in "_site/2020/01/31/entry2.html" @@ -161,10 +259,15 @@ Feature: Site configuration | entry1 | 2013-04-09 23:22 -0400 | post | content for entry1. | | entry2 | 2013-04-10 03:14 -0400 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: 2" in "_site/index.html" - And I should see "Post Layout:

    content for entry1.

    \n built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html" - And I should see "Post Layout:

    content for entry2.

    \n built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html" + And I should see "Post Layout:

    content for entry1.

    \n built at" in "_site/2013/04/09/entry1.html" + And I should see "Post Layout:

    content for entry2.

    \n built at" in "_site/2013/04/10/entry2.html" + And I should see date "2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html" unless Windows + And I should see date "2013-04-09T22:22:00-05:00" in "_site/2013/04/09/entry1.html" if on Windows + And I should see date "2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html" unless Windows + And I should see date "2013-04-10T02:14:00-05:00" in "_site/2013/04/10/entry2.html" if on Windows Scenario: Generate proper dates with explicitly set timezone (different than posts' time) Given I have a _layouts directory @@ -172,21 +275,44 @@ Feature: Site configuration And I have a post layout that contains "Post Layout: {{ content }} built at {{ page.date | date_to_xmlschema }}" And I have an "index.html" page with layout "page" that contains "site index page" And I have a configuration file with: - | key | value | - | timezone | Pacific/Honolulu | + | key | value | + | timezone | Pacific/Honolulu | And I have a _posts directory And I have the following posts: | title | date | layout | content | | entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. | | entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: 2" in "_site/index.html" And the "_site/2013/04/09/entry1.html" file should exist And the "_site/2013/04/09/entry2.html" file should exist And I should see "Post Layout:

    content for entry1.

    \n built at 2013-04-09T09:22:00-10:00" in "_site/2013/04/09/entry1.html" And I should see "Post Layout:

    content for entry2.

    \n built at 2013-04-09T13:14:00-10:00" in "_site/2013/04/09/entry2.html" + Scenario: Generate proper dates with explicitly set timezone (using non-half hour offset ) + Given I have a _layouts directory + And I have a page layout that contains "Page Layout: {{ site.posts.size }}" + And I have a post layout that contains "Post Layout: {{ content }} built at {{ page.date | date_to_xmlschema }}" + And I have an "index.html" page with layout "page" that contains "site index page" + And I have a configuration file with: + | key | value | + | timezone | Australia/Eucla | + And I have a _posts directory + And I have the following posts: + | title | date | layout | content | + | entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. | + | entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. | + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Page Layout: 2" in "_site/index.html" + And the "_site/2013/04/10/entry1.html" file should exist + And the "_site/2013/04/10/entry2.html" file should exist + And I should see "Post Layout:

    content for entry1.

    \n built at 2013-04-10T04:07:00\+08:45" in "_site/2013/04/10/entry1.html" + And I should see "Post Layout:

    content for entry2.

    \n built at 2013-04-10T07:59:00\+08:45" in "_site/2013/04/10/entry2.html" + Scenario: Limit the number of posts generated by most recent date Given I have a _posts directory And I have a configuration file with: @@ -198,23 +324,12 @@ Feature: Site configuration | Oranges | 2009-04-01 | An article about oranges | | Bananas | 2009-04-05 | An article about bananas | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And the "_site/2009/04/05/bananas.html" file should exist And the "_site/2009/04/01/oranges.html" file should exist And the "_site/2009/03/27/apples.html" file should not exist - Scenario: Copy over normally excluded files when they are explicitly included - Given I have a ".gitignore" file that contains ".DS_Store" - And I have an ".htaccess" file that contains "SomeDirective" - And I have a configuration file with "include" set to: - | value | - | .gitignore | - | .foo | - When I run jekyll build - Then the _site directory should exist - And I should see ".DS_Store" in "_site/.gitignore" - And the "_site/.htaccess" file should not exist - Scenario: Using a different layouts directory Given I have a _theme directory And I have a page theme that contains "Page Layout: {{ site.posts.size }} on {{ site.time | date: "%Y-%m-%d" }}" @@ -231,7 +346,8 @@ Feature: Site configuration | entry1 | 2007-12-31 | post | content for entry1. | | entry2 | 2020-01-31 | post | content for entry2. | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Page Layout: 2 on 2010-01-01" in "_site/index.html" And I should see "Post Layout:

    content for entry1.

    " in "_site/2007/12/31/entry1.html" And I should see "Post Layout:

    content for entry2.

    " in "_site/2020/01/31/entry2.html" @@ -240,6 +356,7 @@ Feature: Site configuration Given I have an "index.html" page with layout "page" that contains "FOO" And I have a "_config.yml" file that contains "layouts: '../../../../../../../../../../../../../../usr/include'" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "FOO" in "_site/index.html" And I should not see " " in "_site/index.html" diff --git a/features/site_data.feature b/features/site_data.feature index a7fadf34d17..e3c99a64154 100644 --- a/features/site_data.feature +++ b/features/site_data.feature @@ -6,14 +6,16 @@ Feature: Site data Scenario: Use page variable in a page Given I have an "contact.html" page with title "Contact" that contains "{{ page.title }}: email@example.com" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Contact: email@example.com" in "_site/contact.html" Scenario Outline: Use page.path variable in a page Given I have a directory And I have a "" page that contains "Source path: {{ page.path }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Source path: " in "_site/" Examples: @@ -25,13 +27,15 @@ Feature: Site data Scenario: Override page.path Given I have an "override.html" page with path "custom-override.html" that contains "Custom path: {{ page.path }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Custom path: custom-override.html" in "_site/override.html" Scenario: Use site.time variable Given I have an "index.html" page that contains "{{ site.time }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see today's time in "_site/index.html" Scenario: Use site.posts variable for latest post @@ -43,7 +47,8 @@ Feature: Site data | Second Post | 2009-03-26 | My Second Post | | Third Post | 2009-03-27 | My Third Post | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Third Post: /2009/03/27/third-post.html" in "_site/index.html" Scenario: Use site.posts variable in a loop @@ -55,7 +60,8 @@ Feature: Site data | Second Post | 2009-03-26 | My Second Post | | Third Post | 2009-03-27 | My Third Post | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Third Post Second Post First Post" in "_site/index.html" Scenario: Use site.categories.code variable @@ -66,7 +72,8 @@ Feature: Site data | Awesome Hack | 2009-03-26 | code | puts 'Hello World' | | Delicious Beer | 2009-03-26 | food | 1) Yuengling | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Awesome Hack" in "_site/index.html" Scenario: Use site.tags variable @@ -76,7 +83,8 @@ Feature: Site data | title | date | tag | content | | Delicious Beer | 2009-03-26 | beer | 1) Yuengling | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "Yuengling" in "_site/index.html" Scenario: Order Posts by name when on the same date @@ -90,18 +98,21 @@ Feature: Site data | C | 2009-03-26 | C | | last | 2009-04-26 | last | When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "last:C, C:B,last B:A,C A:first,B first:,A" in "_site/index.html" Scenario: Use configuration date in site payload Given I have an "index.html" page that contains "{{ site.url }}" And I have a configuration file with "url" set to "http://example.com" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "http://example.com" in "_site/index.html" Scenario: Access Jekyll version via jekyll.version Given I have an "index.html" page that contains "{{ jekyll.version }}" When I run jekyll build - Then the _site directory should exist + Then I should get a zero exit status + And the _site directory should exist And I should see "\d+\.\d+\.\d+" in "_site/index.html" diff --git a/features/step_definitions.rb b/features/step_definitions.rb new file mode 100644 index 00000000000..7530de9c1dd --- /dev/null +++ b/features/step_definitions.rb @@ -0,0 +1,431 @@ +# frozen_string_literal: true + +Before do + FileUtils.rm_rf(Paths.test_dir) if Paths.test_dir.exist? + FileUtils.mkdir_p(Paths.test_dir) unless Paths.test_dir.directory? + Dir.chdir(Paths.test_dir) + @timezone_before_scenario = ENV["TZ"] +end + +# + +After do + FileUtils.rm_rf(Paths.test_dir) if Paths.test_dir.exist? + Paths.output_file.delete if Paths.output_file.exist? + Paths.status_file.delete if Paths.status_file.exist? + Dir.chdir(Paths.test_dir.parent) + ENV["TZ"] = @timezone_before_scenario +end + +# + +Given(%r!^I have a blank site in "(.*)"$!) do |path| + unless File.exist?(path) + then FileUtils.mkdir_p(path) + end +end + +# + +Given(%r!^I do not have a "(.*)" directory$!) do |path| + Paths.test_dir.join(path).directory? +end + +# + +Given(%r!^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$!) do |file, key, value, text| + File.write(file, <<~DATA) + --- + #{key || "layout"}: #{value || "none"} + --- + + #{text} + DATA +end + +# + +Given(%r!^I have an? "(.*)" file that contains "(.*)"$!) do |file, text| + File.write(file, text) +end + +# + +Given(%r!^I have an? (.*) (layout|theme) that contains "(.*)"$!) do |name, type, text| + folder = type == "layout" ? "_layouts" : "_theme" + + destination_file = Pathname.new(File.join(folder, "#{name}.html")) + FileUtils.mkdir_p(destination_file.parent) unless destination_file.parent.directory? + File.write(destination_file, text) +end + +# + +Given(%r!^I have an? "(.*)" file with content:$!) do |file, text| + File.write(file, text) +end + +# + +Given(%r!^I have an? "(.*)" page with content:$!) do |file, text| + File.write(file, <<~DATA) + --- + --- + + #{text} + DATA +end + +# + +Given(%r!^I have an? (.*) directory$!) do |dir| + unless File.directory?(dir) + then FileUtils.mkdir_p(dir) + end +end + +# + +Given(%r!^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$!) do |status, direction, folder, table| + table.hashes.each do |input_hash| + title = slug(input_hash["title"]) + ext = input_hash["type"] || "markdown" + filename = "#{title}.#{ext}" if %w(draft page).include?(status) + before, after = location(folder, direction) + dest_folder = "_drafts" if status == "draft" + dest_folder = "_posts" if status == "post" + dest_folder = "" if status == "page" + + if status == "post" + parsed_date = Time.xmlschema(input_hash["date"]) rescue Time.parse(input_hash["date"]) + input_hash["date"] = parsed_date + filename = "#{parsed_date.strftime("%Y-%m-%d")}-#{title}.#{ext}" + end + + path = File.join(before, dest_folder, after, filename) + File.write(path, file_content_from_hash(input_hash)) + end +end + +# + +Given(%r!^I have the following (draft|post)s? within the "(.*)" directory:$!) do |type, folder, table| + table.hashes.each do |input_hash| + title = slug(input_hash["title"]) + parsed_date = Time.xmlschema(input_hash["date"]) rescue Time.parse(input_hash["date"]) + + filename = type == "draft" ? "#{title}.markdown" : "#{parsed_date.strftime("%Y-%m-%d")}-#{title}.markdown" + + path = File.join(folder, "_#{type}s", filename) + File.write(path, file_content_from_hash(input_hash)) + end +end + +# + +Given(%r!^I have the following documents? under the (.*) collection:$!) do |folder, table| + table.hashes.each do |input_hash| + title = slug(input_hash["title"]) + filename = "#{title}.md" + dest_folder = "_#{folder}" + + path = File.join(dest_folder, filename) + File.write(path, file_content_from_hash(input_hash)) + end +end + +# + +Given(%r!^I have the following documents? under the "(.*)" collection within the "(.*)" directory:$!) do |label, dir, table| + table.hashes.each do |input_hash| + title = slug(input_hash["title"]) + path = File.join(dir, "_#{label}", "#{title}.md") + File.write(path, file_content_from_hash(input_hash)) + end +end + +# + +Given(%r!^I have the following documents? nested inside "(.*)" directory under the "(.*)" collection within the "(.*)" directory:$!) do |subdir, label, dir, table| + table.hashes.each do |input_hash| + title = slug(input_hash["title"]) + path = File.join(dir, "_#{label}", subdir, "#{title}.md") + File.write(path, file_content_from_hash(input_hash)) + end +end + +# + +Given(%r!^I have a configuration file with "(.*)" set to "(.*)"$!) do |key, value| + config = \ + if source_dir.join("_config.yml").exist? + SafeYAML.load_file(source_dir.join("_config.yml")) + else + {} + end + config[key] = SafeYAML.load(value) + Jekyll.set_timezone(value) if key == "timezone" + File.write("_config.yml", YAML.dump(config)) +end + +# + +Given(%r!^I have a configuration file with:$!) do |table| + table.hashes.each do |row| + step %(I have a configuration file with "#{row["key"]}" set to "#{row["value"]}") + end +end + +# + +Given(%r!^I have a configuration file with "([^\"]*)" set to:$!) do |key, table| + File.open("_config.yml", "w") do |f| + f.write("#{key}:\n") + table.hashes.each do |row| + f.write("- #{row["value"]}\n") + end + end +end + +# + +Given(%r!^I have fixture collections(?: in "(.*)" directory)?$!) do |directory| + collections_dir = File.join(source_dir, directory.to_s) + FileUtils.cp_r Paths.source_dir.join("test", "source", "_methods"), collections_dir + FileUtils.cp_r Paths.source_dir.join("test", "source", "_thanksgiving"), collections_dir + FileUtils.cp_r Paths.source_dir.join("test", "source", "_tutorials"), collections_dir +end + +# + +Given(%r!^I wait (\d+) second(s?)$!) do |time, _| + sleep(time.to_f) +end + +# + +When(%r!^I run jekyll(.*)$!) do |args| + run_jekyll(args) + if args.include?("--verbose") || ENV["DEBUG"] + warn "\n#{jekyll_run_output}\n" + end +end + +# + +When(%r!^I run bundle(.*)$!) do |args| + run_bundle(args) + if args.include?("--verbose") || ENV["DEBUG"] + warn "\n#{jekyll_run_output}\n" + end +end + +# + +When(%r!^I run gem(.*)$!) do |args| + run_rubygem(args) + if args.include?("--verbose") || ENV["DEBUG"] + warn "\n#{jekyll_run_output}\n" + end +end + +# + +When(%r!^I run git add .$!) do + run_in_shell("git", "add", ".", "--verbose") +end + +# + +When(%r!^I decide to build the theme gem$!) do + Dir.chdir(Paths.theme_gem_dir) + [ + "_includes/blank.html", + "_sass/blank.scss", + "assets/blank.scss", + "_config.yml" + ].each do |filename| + File.new(filename, "w") + end +end + +# + +When(%r!^I change "(.*)" to contain "(.*)"$!) do |file, text| + File.open(file, "a") do |f| + f.write(text) + end +end + +# + +When(%r!^I delete the file "(.*)"$!) do |file| + File.delete(file) +end + +# + +Then(%r!^the (.*) directory should +(not )?exist$!) do |dir, negative| + if negative.nil? + expect(Pathname.new(dir)).to exist + else + expect(Pathname.new(dir)).to_not exist + end +end + +# + +Then(%r!^I should (not )?see "(.*)" in "(.*)"$!) do |negative, text, file| + step %(the "#{file}" file should exist) + regexp = Regexp.new(text, Regexp::MULTILINE) + if negative.nil? || negative.empty? + expect(file_contents(file)).to match regexp + else + expect(file_contents(file)).not_to match regexp + end +end + +# + +Then(%r!^I should (not )?see "(.*)" in "(.*)" if platform does not support symlinks$!) do |negative, text, file| + step %(the "#{file}" file should exist) + regexp = Regexp.new(text, Regexp::MULTILINE) + if negative.nil? || negative.empty? + if Platform.supports_symlink? + expect(file_contents(file)).not_to match regexp + else + expect(file_contents(file)).to match regexp + end + end +end + +# + +Then(%r!^I should (not )?see "(.*)" in "(.*)" if platform supports symlinks$!) do |negative, text, file| + step %(the "#{file}" file should exist) + regexp = Regexp.new(text, Regexp::MULTILINE) + if negative.nil? || negative.empty? + if Platform.supports_symlink? + expect(file_contents(file)).to match regexp + else + expect(file_contents(file)).not_to match regexp + end + end +end + +# + +Then(%r!^I should see date "(.*)" in "(.*)" unless Windows$!) do |text, file| + step %(the "#{file}" file should exist) + regexp = Regexp.new(text) + if Jekyll::Utils::Platforms.really_windows? && !dst_active? + expect(file_contents(file)).not_to match regexp + else + expect(file_contents(file)).to match regexp + end +end + +# + +Then(%r!^I should see date "(.*)" in "(.*)" if on Windows$!) do |text, file| + step %(the "#{file}" file should exist) + regexp = Regexp.new(text) + if Jekyll::Utils::Platforms.really_windows? && !dst_active? + expect(file_contents(file)).to match regexp + else + expect(file_contents(file)).not_to match regexp + end +end + +# + +Then(%r!^I should see exactly "(.*)" in "(.*)"$!) do |text, file| + step %(the "#{file}" file should exist) + expect(file_contents(file).strip).to eq text +end + +# + +Then(%r!^I should see escaped "(.*)" in "(.*)"$!) do |text, file| + step %(I should see "#{Regexp.escape(text)}" in "#{file}") +end + +# + +Then(%r!^the "(.*)" file should +(not )?exist$!) do |file, negative| + if negative.nil? + expect(Pathname.new(file)).to exist + else + expect(Pathname.new(file)).to_not exist + end +end + +# + +Then(%r!^I should see today's time in "(.*)"$!) do |file| + seconds = 3 + build_time = Time.now + content = file_contents(file) + date_time_pattern = /(\d{4}-\d{2}-\d{2}\s\d+:\d{2}:\d{2})/ + match_data = content.match(date_time_pattern) + expect(match_data).not_to be_nil, "No date-time pattern found in #{file}" + date_time_str = match_data.captures + file_time = Time.parse("#{date_time_str}") + time_difference = (build_time - file_time).abs + expect(time_difference).to be <= seconds, <<~MSG + Expected time in #{file} to be within #{seconds} seconds of build time. + Build time: #{build_time} + File time: #{file_time} + Difference: #{time_difference} seconds + MSG +end + +# + +Then(%r!^I should see today's date in "(.*)"$!) do |file| + step %(I should see "#{Date.today}" in "#{file}") +end + +# + +Then(%r!^I should (not )?see "(.*)" in the build output$!) do |negative, text| + if negative.nil? || negative.empty? + expect(jekyll_run_output).to match Regexp.new(text) + else + expect(jekyll_run_output).not_to match Regexp.new(text) + end +end + +# + +Then(%r!^I should get an updated git index$!) do + index = %w( + .gitignore + Gemfile + LICENSE.txt + README.md + _config.yml + _includes/blank.html + _layouts/default.html + _layouts/page.html + _layouts/post.html + _sass/blank.scss + assets/blank.scss + my-cool-theme.gemspec + ) + index.each do |file| + expect(jekyll_run_output).to match file + end +end + +# + +Then(%r!^I should get a zero exit(?:\-| )status$!) do + step %(I should see "EXIT STATUS: 0" in the build output) +end + +# + +Then(%r!^I should get a non-zero exit(?:\-| )status$!) do + step %(I should not see "EXIT STATUS: 0" in the build output) +end diff --git a/features/step_definitions/jekyll_steps.rb b/features/step_definitions/jekyll_steps.rb deleted file mode 100644 index 9164d549b28..00000000000 --- a/features/step_definitions/jekyll_steps.rb +++ /dev/null @@ -1,234 +0,0 @@ -def file_content_from_hash(input_hash) - matter_hash = input_hash.reject { |k, v| k == "content" } - matter = matter_hash.map { |k, v| "#{k}: #{v}\n" }.join.chomp - - content = if input_hash['input'] && input_hash['filter'] - "{{ #{input_hash['input']} | #{input_hash['filter']} }}" - else - input_hash['content'] - end - - <<-EOF ---- -#{matter} ---- -#{content} -EOF -end - -Before do - FileUtils.mkdir_p(TEST_DIR) unless File.exist?(TEST_DIR) - Dir.chdir(TEST_DIR) -end - -After do - FileUtils.rm_rf(TEST_DIR) if File.exist?(TEST_DIR) - FileUtils.rm(JEKYLL_COMMAND_OUTPUT_FILE) if File.exist?(JEKYLL_COMMAND_OUTPUT_FILE) - FileUtils.rm(JEKYLL_COMMAND_STATUS_FILE) if File.exist?(JEKYLL_COMMAND_STATUS_FILE) - Dir.chdir(File.dirname(TEST_DIR)) -end - -World do - MinitestWorld.new -end - -Given /^I have a blank site in "(.*)"$/ do |path| - FileUtils.mkdir_p(path) unless File.exist?(path) -end - -Given /^I do not have a "(.*)" directory$/ do |path| - File.directory?("#{TEST_DIR}/#{path}") -end - -# Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it -Given /^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text| - File.open(file, 'w') do |f| - f.write <<-EOF ---- -#{key || 'layout'}: #{value || 'nil'} ---- -#{text} -EOF - end -end - -Given /^I have an? "(.*)" file that contains "(.*)"$/ do |file, text| - File.open(file, 'w') do |f| - f.write(text) - end -end - -Given /^I have an? (.*) (layout|theme) that contains "(.*)"$/ do |name, type, text| - folder = if type == 'layout' - '_layouts' - else - '_theme' - end - destination_file = File.join(folder, name + '.html') - destination_path = File.dirname(destination_file) - unless File.exist?(destination_path) - FileUtils.mkdir_p(destination_path) - end - File.open(destination_file, 'w') do |f| - f.write(text) - end -end - -Given /^I have an? "(.*)" file with content:$/ do |file, text| - File.open(file, 'w') do |f| - f.write(text) - end -end - -Given /^I have an? (.*) directory$/ do |dir| - FileUtils.mkdir_p(dir) -end - -Given /^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$/ do |status, direction, folder, table| - table.hashes.each do |input_hash| - title = slug(input_hash['title']) - ext = input_hash['type'] || 'markdown' - before, after = location(folder, direction) - - case status - when "draft" - dest_folder = '_drafts' - filename = "#{title}.#{ext}" - when "page" - dest_folder = '' - filename = "#{title}.#{ext}" - when "post" - parsed_date = Time.xmlschema(input_hash['date']) rescue Time.parse(input_hash['date']) - dest_folder = '_posts' - filename = "#{parsed_date.strftime('%Y-%m-%d')}-#{title}.#{ext}" - end - - path = File.join(before, dest_folder, after, filename) - File.open(path, 'w') do |f| - f.write file_content_from_hash(input_hash) - end - end -end - -Given /^I have a configuration file with "(.*)" set to "(.*)"$/ do |key, value| - File.open('_config.yml', 'w') do |f| - f.write("#{key}: #{value}\n") - end -end - -Given /^I have a configuration file with:$/ do |table| - File.open('_config.yml', 'w') do |f| - table.hashes.each do |row| - f.write("#{row["key"]}: #{row["value"]}\n") - end - end -end - -Given /^I have a configuration file with "([^\"]*)" set to:$/ do |key, table| - File.open('_config.yml', 'w') do |f| - f.write("#{key}:\n") - table.hashes.each do |row| - f.write("- #{row["value"]}\n") - end - end -end - -Given /^I have fixture collections$/ do - FileUtils.cp_r File.join(JEKYLL_SOURCE_DIR, "test", "source", "_methods"), source_dir -end - -Given /^I wait (\d+) second(s?)$/ do |time, plural| - sleep(time.to_f) -end - -################## -# -# Changing stuff -# -################## - -When /^I run jekyll(.*)$/ do |args| - status = run_jekyll(args) - if args.include?("--verbose") || ENV['DEBUG'] - puts jekyll_run_output - end -end - -When /^I run bundle(.*)$/ do |args| - status = run_bundle(args) - if args.include?("--verbose") || ENV['DEBUG'] - puts jekyll_run_output - end -end - -When /^I change "(.*)" to contain "(.*)"$/ do |file, text| - File.open(file, 'a') do |f| - f.write(text) - end -end - -When /^I delete the file "(.*)"$/ do |file| - File.delete(file) -end - -################## -# -# Checking stuff -# -################## - -Then /^the (.*) directory should +exist$/ do |dir| - assert File.directory?(dir), "The directory \"#{dir}\" does not exist" -end - -Then /^the (.*) directory should not exist$/ do |dir| - assert !File.directory?(dir), "The directory \"#{dir}\" exists" -end - -Then /^I should see "(.*)" in "(.*)"$/ do |text, file| - assert_match Regexp.new(text, Regexp::MULTILINE), file_contents(file) -end - -Then /^I should see exactly "(.*)" in "(.*)"$/ do |text, file| - assert_equal text, file_contents(file).strip -end - -Then /^I should not see "(.*)" in "(.*)"$/ do |text, file| - refute_match Regexp.new(text, Regexp::MULTILINE), file_contents(file) -end - -Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file| - assert_match Regexp.new(Regexp.escape(text)), file_contents(file) -end - -Then /^the "(.*)" file should +exist$/ do |file| - file_does_exist = File.file?(file) - unless file_does_exist - all_steps_to_path(file).each do |dir| - STDERR.puts "" - STDERR.puts "Dir #{dir}:" - STDERR.puts Dir["#{dir}/**/*"] - end - end - assert file_does_exist, "The file \"#{file}\" does not exist.\n" -end - -Then /^the "(.*)" file should not exist$/ do |file| - assert !File.exist?(file), "The file \"#{file}\" exists" -end - -Then /^I should see today's time in "(.*)"$/ do |file| - assert_match Regexp.new(seconds_agnostic_time(Time.now)), file_contents(file) -end - -Then /^I should see today's date in "(.*)"$/ do |file| - assert_match Regexp.new(Date.today.to_s), file_contents(file) -end - -Then /^I should see "(.*)" in the build output$/ do |text| - assert_match Regexp.new(text), jekyll_run_output -end - -Then /^I should get a non-zero exit(?:\-| )status$/ do - assert jekyll_run_status > 0 -end diff --git a/features/support/env.rb b/features/support/env.rb deleted file mode 100644 index 76a3e70702e..00000000000 --- a/features/support/env.rb +++ /dev/null @@ -1,116 +0,0 @@ -require 'fileutils' -require 'posix-spawn' -require 'minitest/spec' -require 'time' - -class MinitestWorld - extend Minitest::Assertions - attr_accessor :assertions - - def initialize - self.assertions = 0 - end -end - -JEKYLL_SOURCE_DIR = File.dirname(File.dirname(File.dirname(__FILE__))) -TEST_DIR = File.expand_path(File.join('..', '..', 'tmp', 'jekyll'), File.dirname(__FILE__)) -JEKYLL_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'bin', 'jekyll')) -JEKYLL_COMMAND_OUTPUT_FILE = File.join(File.dirname(TEST_DIR), 'jekyll_output.txt') -JEKYLL_COMMAND_STATUS_FILE = File.join(File.dirname(TEST_DIR), 'jekyll_status.txt') - -def source_dir(*files) - File.join(TEST_DIR, *files) -end - -def all_steps_to_path(path) - source = Pathname.new(source_dir('_site')).expand_path - dest = Pathname.new(path).expand_path - paths = [] - dest.ascend do |f| - break if f.eql? source - paths.unshift f.to_s - end - paths -end - -def jekyll_output_file - JEKYLL_COMMAND_OUTPUT_FILE -end - -def jekyll_status_file - JEKYLL_COMMAND_STATUS_FILE -end - -def jekyll_run_output - File.read(jekyll_output_file) if File.file?(jekyll_output_file) -end - -def jekyll_run_status - (File.read(jekyll_status_file) rescue 0).to_i -end - -def run_bundle(args) - run_in_shell('bundle', *args.strip.split(' ')) -end - -def run_jekyll(args) - child = run_in_shell(JEKYLL_PATH, *args.strip.split(' '), "--trace") - child.status.exitstatus == 0 -end - -# ----------------------------------------------------------------------------- -# XXX: POSIX::Spawn::Child does not write output when the exit status is > 0 -# for example when doing [:out, :err] => [file, "w"] it will skip -# writing the file entirely, we sould switch to Open. -# ----------------------------------------------------------------------------- - -def run_in_shell(*args) - spawned = POSIX::Spawn::Child.new(*args) - status = spawned.status.exitstatus - File.write(JEKYLL_COMMAND_STATUS_FILE, status) - File.open(JEKYLL_COMMAND_OUTPUT_FILE, "w+") do |file| - status == 0 ? file.write(spawned.out) : file.write(spawned.err) - end - - spawned -end - -def slug(title) - if title - title.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') - else - Time.now.strftime("%s%9N") # nanoseconds since the Epoch - end -end - -def location(folder, direction) - if folder - before = folder if direction == "in" - after = folder if direction == "under" - end - [before || '.', after || '.'] -end - -def file_contents(path) - File.open(path) do |file| - file.readlines.join # avoid differences with \n and \r\n line endings - end -end - -def seconds_agnostic_datetime(datetime = Time.now) - date, time, zone = datetime.to_s.split(" ") - time = seconds_agnostic_time(time) - [ - Regexp.escape(date), - "#{time}:\\d{2}", - Regexp.escape(zone) - ].join("\\ ") -end - -def seconds_agnostic_time(time) - if time.is_a? Time - time = time.strftime("%H:%M:%S") - end - hour, minutes, _ = time.split(":") - "#{hour}:#{minutes}" -end diff --git a/features/support/formatter.rb b/features/support/formatter.rb new file mode 100644 index 00000000000..3a2f0e87a77 --- /dev/null +++ b/features/support/formatter.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require "cucumber/formatter/io" + +module Jekyll + module Cucumber + class Formatter + include ::Cucumber::Formatter::Io + + def initialize(path_or_io, error_stream) + @io = ensure_io(path_or_io, error_stream) + @timings = {} + end + + def before_test_case(test_case) + @timings[timing_key(test_case)] = Time.now + end + + def after_test_case(test_case) + @timings[timing_key(test_case)] = Time.now - @timings[timing_key(test_case)] + end + + def print_test_case_info(test_case) + @io.print "\n#{test_case.location} #{truncate(test_case.name).inspect} " + @io.flush + end + + def print_test_case_duration(test_case) + @io.print format(" (%.3fs)", @timings[timing_key(test_case)]) + end + + def print_worst_offenders + @io.puts "\n\nWorst offenders:" + + rows = @timings.sort_by { |_f, t| -t }.take(10).map! { |r| r[0].split(" \t ", 2).push(r[1]) } + padding = rows.max_by { |r| r[0].length }.first.length + 2 + rows.each { |row| @io.puts format_row_data(row, padding) } + end + + private + + def format_row_data(row, padding) + [ + row[0].ljust(padding).rjust(padding + 2), + row[1].ljust(45), + format("(%.3fs)", row[2]), + ].join + end + + def timing_key(test_case) + "#{test_case.location} \t #{truncate(test_case.name).inspect}" + end + + def truncate(input, max_len: 40) + str = input.to_s + str.length > max_len ? "#{str[0..(max_len - 2)]}..." : str + end + end + end +end + +InstallPlugin do |config| + progress_fmt = config.to_hash[:formats][0][0] == "progress" + f = Jekyll::Cucumber::Formatter.new($stdout, $stderr) + + config.on_event :test_case_started do |event| + test_case = event.test_case + + f.print_test_case_info(test_case) if progress_fmt + f.before_test_case(test_case) + end + + config.on_event :test_case_finished do |event| + test_case = event.test_case + + f.after_test_case(test_case) + f.print_test_case_duration(test_case) if progress_fmt + end + + config.on_event :test_run_finished do + f.print_worst_offenders + end +end diff --git a/features/support/helpers.rb b/features/support/helpers.rb new file mode 100644 index 00000000000..e7724f4c36e --- /dev/null +++ b/features/support/helpers.rb @@ -0,0 +1,157 @@ +# frozen_string_literal: true + +require "jekyll" + +class Paths + SOURCE_DIR = Pathname.new(File.expand_path("../..", __dir__)) + + def self.test_dir; source_dir.join("tmp", "jekyll"); end + + def self.theme_gem_dir; source_dir.join("tmp", "jekyll", "my-cool-theme"); end + + def self.output_file; test_dir.join("jekyll_output.txt"); end + + def self.status_file; test_dir.join("jekyll_status.txt"); end + + def self.jekyll_bin; source_dir.join("exe", "jekyll"); end + + def self.source_dir; SOURCE_DIR; end +end + +class Platform + REF_FILE = File.expand_path("../../test/source/symlink-test/symlinked-file", __dir__) + + def self.supports_symlink?; File.symlink?(REF_FILE); end +end + + +# + +def file_content_from_hash(input_hash) + matter_hash = input_hash.reject { |k, _v| k == "content" } + matter = matter_hash.map { |k, v| "#{k}: #{v}\n" }.join + matter.chomp! + content = if input_hash["input"] && input_hash["filter"] + "{{ #{input_hash["input"]} | #{input_hash["filter"]} }}" + else + input_hash["content"] + end + + <<~EOF + --- + #{matter} + --- + + #{content} + EOF +end + +# + +def source_dir(*files) + Paths.test_dir(*files) +end + +# + +def all_steps_to_path(path) + source = source_dir + dest = Pathname.new(path).expand_path + paths = [] + + dest.ascend do |f| + break if f == source + paths.unshift f.to_s + end + + paths +end + +# + +def jekyll_run_output + Paths.output_file.read if Paths.output_file.file? +end + +# + +def jekyll_run_status + Paths.status_file.read if Paths.status_file.file? +end + +# + +def run_bundle(args) + run_in_shell("bundle", *args.strip.split(" ")) +end + +# + +def run_rubygem(args) + run_in_shell("gem", *args.strip.split(" ")) +end + +# + +def run_jekyll(args) + args = args.strip.split(" ") # Shellwords? + process = run_in_shell("ruby", Paths.jekyll_bin.to_s, *args, "--trace") + process.exitstatus.zero? +end + +# + +def run_in_shell(*args) + p, output = Jekyll::Utils::Exec.run(*args) + + File.write(Paths.status_file, p.exitstatus) + File.open(Paths.output_file, "wb") do |f| + f.print "$ " + f.puts args.join(" ") + f.puts output + f.puts "EXIT STATUS: #{p.exitstatus}" + end + + p +end + +# + +def slug(title = nil) + if title + title.downcase.gsub(%r![^\w]!, " ").strip.gsub(%r!\s+!, "-") + else + Time.now.strftime("%s%9N") # nanoseconds since the Epoch + end +end + +# + +def location(folder, direction) + if folder + before = folder if direction == "in" + after = folder if direction == "under" + end + + [before || ".", + after || "",] +end + +# + +def file_contents(path) + Pathname.new(path).read +end + +# + +# Helper method for Windows +def dst_active? + config = Jekyll.configuration("quiet" => true) + ENV["TZ"] = config["timezone"] + dst = Time.now.isdst + + # reset variable to default state on Windows + ENV["TZ"] = nil + dst +end diff --git a/features/support/overview.rb b/features/support/overview.rb deleted file mode 100644 index 8d414be7f54..00000000000 --- a/features/support/overview.rb +++ /dev/null @@ -1,147 +0,0 @@ -require 'fileutils' -require 'colorator' -require 'cucumber/formatter/console' -require 'cucumber/formatter/io' -require 'gherkin/formatter/escaping' - -module Features - module Support - # The formatter used for --format pretty (the default formatter). - # - # This formatter prints features to plain text - exactly how they were parsed, - # just prettier. That means with proper indentation and alignment of table columns. - # - # If the output is STDOUT (and not a file), there are bright colours to watch too. - # - class Overview - include FileUtils - include Cucumber::Formatter::Console - include Cucumber::Formatter::Io - include Gherkin::Formatter::Escaping - attr_writer :indent - attr_reader :runtime - - def initialize(runtime, path_or_io, options) - @runtime, @io, @options = runtime, ensure_io(path_or_io, "pretty"), options - @exceptions = [] - @indent = 0 - @prefixes = options[:prefixes] || {} - @delayed_messages = [] - end - - def before_features(features) - print_profile_information - end - - def after_features(features) - @io.puts - print_summary(features) - end - - def before_feature(feature) - @exceptions = [] - @indent = 0 - end - - def comment_line(comment_line) - end - - def after_tags(tags) - end - - def tag_name(tag_name) - end - - def before_feature_element(feature_element) - @indent = 2 - @scenario_indent = 2 - end - - def after_feature_element(feature_element) - end - - def before_background(background) - @indent = 2 - @scenario_indent = 2 - @in_background = true - end - - def after_background(background) - @in_background = nil - end - - def background_name(keyword, name, file_colon_line, source_indent) - print_feature_element_name(keyword, name, file_colon_line, source_indent) - end - - def scenario_name(keyword, name, file_colon_line, source_indent) - print_feature_element_name(keyword, name, file_colon_line, source_indent) - end - - def before_step(step) - @current_step = step - end - - def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background, file_colon_line) - @hide_this_step = false - if exception - if @exceptions.include?(exception) - @hide_this_step = true - return - end - @exceptions << exception - end - if status != :failed && @in_background ^ background - @hide_this_step = true - return - end - @status = status - end - - CHARS = { - :failed => "x".red, - :pending => "?".yellow, - :undefined => "x".red, - :passed => ".".green, - :skipped => "-".blue - } - - def step_name(keyword, step_match, status, source_indent, background, file_colon_line) - @io.print CHARS[status] - end - - def exception(exception, status) - return if @hide_this_step - @io.puts - print_exception(exception, status, @indent) - @io.flush - end - - private - - def print_feature_element_name(keyword, name, file_colon_line, source_indent) - @io.puts - names = name.empty? ? [name] : name.split("\n") - line = " #{keyword}: #{names[0]}" - if @options[:source] - line_comment = "#{file_colon_line}" - @io.print(line_comment) - end - @io.print(line) - @io.print " " - @io.flush - end - - def cell_prefix(status) - @prefixes[status] - end - - def print_summary(features) - @io.puts - print_stats(features, @options) - print_snippets(@options) - print_passing_wip(@options) - end - end - end -end diff --git a/features/theme.feature b/features/theme.feature new file mode 100644 index 00000000000..ec63b21271d --- /dev/null +++ b/features/theme.feature @@ -0,0 +1,151 @@ +Feature: Writing themes + As a hacker who likes to share my expertise + I want to be able to make a gemified theme + In order to share my awesome style skillz with other Jekyllites + + Scenario: Generating a new theme scaffold + When I run jekyll new-theme my-cool-theme + Then I should get a zero exit status + And the my-cool-theme directory should exist + + Scenario: Generating a new theme scaffold with a code of conduct + When I run jekyll new-theme my-cool-theme --code-of-conduct + Then I should get a zero exit status + And the my-cool-theme directory should exist + And the "my-cool-theme/CODE_OF_CONDUCT.md" file should exist + + Scenario: A theme with SCSS + Given I have a configuration file with "theme" set to "test-theme" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see ".sample {\n color: red;\n}\n\n\/\*# sourceMappingURL=style.css.map \*\/" in "_site/assets/style.css" + + Scenario: Overriding a theme with SCSS + Given I have a configuration file with "theme" set to "test-theme" + And I have an assets directory + And I have an "assets/style.scss" page that contains "@import 'test-theme-black';" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see ".sample {\n color: black;\n}\n\n\/\*# sourceMappingURL=style.css.map \*\/" in "_site/assets/style.css" + + Scenario: A theme with an include + Given I have a configuration file with "theme" set to "test-theme" + And I have an _includes directory + And I have an "_includes/in_project.html" file that contains "I'm in the project." + And I have an "index.html" page that contains "{% include in_project.html %} {% include include.html %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I'm in the project." in "_site/index.html" + And I should see "include.html from test-theme" in "_site/index.html" + + Scenario: A theme without data + Given I have a configuration file with "theme" set to "test-theme-skinny" + And I have a _data directory + And I have a "_data/greetings.yml" file with content: + """ + foo: "Hello! I’m foo. And who are you?" + """ + And I have an "index.html" page that contains "{{ site.data.greetings.foo }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Hello! I’m foo. And who are you?" in "_site/index.html" + + Scenario: A theme with data overridden by data in source directory + Given I have a configuration file with "theme" set to "test-theme" + And I have a _data directory + And I have a "_data/greetings.yml" file with content: + """ + foo: "Hello! I’m foo. And who are you?" + """ + And I have an "index.html" page that contains "{{ site.data.greetings.foo }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Hello! I’m foo. And who are you?" in "_site/index.html" + And I should not see "Hello! I’m bar. What’s up so far?" in "_site/index.html" + + Scenario: A theme with a layout + Given I have a configuration file with "theme" set to "test-theme" + And I have an _layouts directory + And I have an "_layouts/post.html" file that contains "post.html from the project: {{ content }}" + And I have an "index.html" page with layout "default" that contains "I'm content." + And I have a "post.html" page with layout "post" that contains "I'm more content." + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "default.html from test-theme: I'm content." in "_site/index.html" + And I should see "post.html from the project: I'm more content." in "_site/post.html" + + Scenario: A theme with assets + Given I have a configuration file with "theme" set to "test-theme" + And I have an assets directory + And I have an "assets/application.coffee" file that contains "From your site." + And I have an "assets/base.js" file that contains "From your site." + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "From your site." in "_site/assets/application.coffee" + And I should see "From your site." in "_site/assets/base.js" + + Scenario: A theme with *just* layouts + Given I have a configuration file with "theme" set to "test-theme-skinny" + And I have an "index.html" page with layout "home" that contains "The quick brown fox." + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "Message: The quick brown fox." in "_site/index.html" + But I should not see "_includes" in the build output + And I should not see "_sass" in the build output + And I should not see "assets" in the build output + + Scenario: Requiring dependencies of a theme + Given I have a configuration file with "theme" set to "test-dependency-theme" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/test.txt" file should exist + + Scenario: Complicated site that puts it all together + Given I have a configuration file with "theme" set to "test-theme" + And I have a _posts directory + And I have the following posts: + | title | date | layout | content | + | entry1 | 2016-04-21 | post | I am using a local layout. {% include include.html %} | + | entry2 | 2016-04-21 | default | I am using a themed layout. {% include include.html %} {% include in_project.html %} | + And I have a _layouts directory + And I have a "_layouts/post.html" page with layout "default" that contains "I am a post layout! {{ content }}" + And I have an _includes directory + And I have an "_includes/in_project.html" file that contains "I am in the project, not the theme." + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "I am in the project, not the theme." in "_site/2016/04/21/entry2.html" + And I should see "include.html from test-theme" in "_site/2016/04/21/entry2.html" + And I should see "default.html from test-theme:" in "_site/2016/04/21/entry2.html" + And I should see "I am using a themed layout." in "_site/2016/04/21/entry2.html" + And I should not see "I am a post layout!" in "_site/2016/04/21/entry2.html" + And I should not see "I am in the project, not the theme." in "_site/2016/04/21/entry1.html" + And I should see "include.html from test-theme" in "_site/2016/04/21/entry1.html" + And I should see "default.html from test-theme:" in "_site/2016/04/21/entry1.html" + And I should see "I am using a local layout." in "_site/2016/04/21/entry1.html" + And I should see "I am a post layout!" in "_site/2016/04/21/entry1.html" + + Scenario: Complicated site that puts it all together in respect to data folders + Given I have a configuration file with "theme" set to "test-theme" + And I have a _data directory + And I have a "_data/i18n.yml" file with content: + """ + testimonials: + header: Kundenstimmen + """ + And I have an "index.html" page that contains "{% include testimonials.html %}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "Testimonials" in "_site/index.html" + And I should see "Kundenstimmen" in "_site/index.html" + And I should see "Design by FTC" in "_site/index.html" diff --git a/features/theme_configuration.feature b/features/theme_configuration.feature new file mode 100644 index 00000000000..00ed81ae4cc --- /dev/null +++ b/features/theme_configuration.feature @@ -0,0 +1,36 @@ +Feature: Bundling Config file with Theme gems + As a web developer who likes to share my expertise + I want to be able to pre-configure my gemified theme + In order to make it easier for other Jekyllites to use my theme + + Scenario: Easy onboarding with a pre-configured theme + Given I have a configuration file with "theme" set to "test-theme" + And I have an "index.md" page that contains "{{ site.test_theme.skin }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should see "aero" in "_site/index.html" + + Scenario: Disabling import of theme configuration entirely + Given I have a configuration file with: + | key | value | + | theme | test-theme | + | ignore_theme_config | true | + And I have an "index.md" page that contains "{{ site.test_theme.skin }}" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And I should not see "aero" in "_site/index.html" + + Scenario: A pre-configured theme with valid config file overriding Jekyll defaults + Given I have a configuration file with "theme" set to "test-theme" + And I have an "index.md" page that contains "{{ site.baseurl }}" + And I have a node_modules directory + And I have a "node_modules/alert.js" file that contains "alert('foo');" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/index.html" file should exist + But the "_site/node_modules/alert.js" file should not exist + And the "_site/extras/banner.html" file should not exist + And I should not see "/test-theme" in "_site/index.html" diff --git a/features/theme_gem.feature b/features/theme_gem.feature new file mode 100644 index 00000000000..ef849741158 --- /dev/null +++ b/features/theme_gem.feature @@ -0,0 +1,32 @@ +Feature: Building Theme Gems + As a hacker who likes to share my expertise + I want to be able to make a bonafide rubygem off my theme + In order to share my awesome style skillz with other Jekyllites + + Scenario: Generating a new Jekyll Theme + When I run jekyll new-theme my-cool-theme + Then I should get a zero exit status + And the my-cool-theme directory should exist + + Scenario: Checking if a bonafide Theme gem will be built from generated scaffolding + When I run jekyll new-theme my-cool-theme + Then the my-cool-theme directory should exist + When I decide to build the theme gem + Then the "_includes/blank.html" file should exist + Then the "_sass/blank.scss" file should exist + Then the "assets/blank.scss" file should exist + When I run git add . + Then I should get an updated git index + When I run gem build --force my-cool-theme.gemspec + Then the "./my-cool-theme-0.1.0.gem" file should exist + When I run gem unpack my-cool-theme-0.1.0.gem + Then the my-cool-theme-0.1.0 directory should exist + And the "my-cool-theme-0.1.0/_layouts/default.html" file should exist + And the "my-cool-theme-0.1.0/_includes/blank.html" file should exist + And the "my-cool-theme-0.1.0/_sass/blank.scss" file should exist + And the "my-cool-theme-0.1.0/assets/blank.scss" file should exist + And the "my-cool-theme-0.1.0/_config.yml" file should exist + And the my-cool-theme-0.1.0/.git directory should not exist + And the "my-cool-theme-0.1.0/.gitignore" file should not exist + And the "my-cool-theme-0.1.0/Gemfile" file should not exist + And the "my-cool-theme-0.1.0/my-cool-theme.gemspec" file should not exist diff --git a/jekyll-docs.gemspec b/jekyll-docs.gemspec deleted file mode 100644 index 0a7975a351b..00000000000 --- a/jekyll-docs.gemspec +++ /dev/null @@ -1,22 +0,0 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'jekyll/version' - -Gem::Specification.new do |spec| - spec.name = 'jekyll-docs' - spec.version = Jekyll::VERSION - spec.authors = ['Parker Moore'] - spec.email = ['parkrmoore@gmail.com'] - spec.summary = %q{Offline usage documentation for Jekyll.} - spec.homepage = 'http://jekyllrb.com' - spec.license = 'MIT' - - spec.files = `git ls-files -z`.split("\x0").grep(%r{^site/}) - spec.require_paths = ['lib'] - - spec.add_dependency 'jekyll', Jekyll::VERSION - - spec.add_development_dependency 'bundler', '~> 1.7' - spec.add_development_dependency 'rake', '~> 10.0' -end diff --git a/jekyll.gemspec b/jekyll.gemspec index 470781c7834..cb67a1d213b 100644 --- a/jekyll.gemspec +++ b/jekyll.gemspec @@ -1,39 +1,54 @@ -# coding: utf-8 -lib = File.expand_path('../lib', __FILE__) -$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) -require 'jekyll/version' +# frozen_string_literal: true -Gem::Specification.new do |s| - s.specification_version = 2 if s.respond_to? :specification_version= - s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version= - s.rubygems_version = '2.2.2' - s.required_ruby_version = '>= 2.0.0' +require "English" +require_relative "lib/jekyll/version" - s.name = 'jekyll' +Gem::Specification.new do |s| + s.name = "jekyll" s.version = Jekyll::VERSION - s.license = 'MIT' + s.license = "MIT" + s.authors = ["Tom Preston-Werner", "Parker Moore", "Matt Rogers"] + s.email = ["maintainers@jekyllrb.com"] + s.homepage = "https://jekyllrb.com" + s.summary = "A simple, blog aware, static site generator." + s.description = "Jekyll is a simple, blog aware, static site generator." - s.summary = 'A simple, blog aware, static site generator.' - s.description = 'Jekyll is a simple, blog aware, static site generator.' + all_files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) + s.files = all_files.grep(%r!^(exe|lib|rubocop)/|^.rubocop.yml$!) + s.executables = all_files.grep(%r!^exe/!) { |f| File.basename(f) } + s.bindir = "exe" + s.require_paths = ["lib"] - s.authors = ['Tom Preston-Werner'] - s.email = 'tom@mojombo.com' - s.homepage = 'https://github.com/jekyll/jekyll' + s.metadata = { + "source_code_uri" => "https://github.com/jekyll/jekyll", + "bug_tracker_uri" => "https://github.com/jekyll/jekyll/issues", + "changelog_uri" => "https://github.com/jekyll/jekyll/releases", + "homepage_uri" => s.homepage, + } - all_files = `git ls-files -z`.split("\x0") - s.files = all_files.grep(%r{^(bin|lib)/}) - s.executables = all_files.grep(%r{^bin/}) { |f| File.basename(f) } - s.require_paths = ['lib'] + s.rdoc_options = ["--charset=UTF-8"] + s.extra_rdoc_files = %w(README.markdown LICENSE) - s.rdoc_options = ['--charset=UTF-8'] - s.extra_rdoc_files = %w[README.markdown LICENSE] + s.required_ruby_version = ">= 2.7.0" + s.required_rubygems_version = ">= 2.7.0" - s.add_runtime_dependency('liquid', '~> 3.0') - s.add_runtime_dependency('kramdown', '~> 1.3') - s.add_runtime_dependency('mercenary', '~> 0.3.3') - s.add_runtime_dependency('safe_yaml', '~> 1.0') - s.add_runtime_dependency('colorator', '~> 0.1') - s.add_runtime_dependency('rouge', '~> 1.7') - s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0') - s.add_runtime_dependency('jekyll-watch', '~> 1.1') + s.add_runtime_dependency("addressable", "~> 2.4") + s.add_runtime_dependency("base64", "~> 0.2") + s.add_runtime_dependency("colorator", "~> 1.0") + s.add_runtime_dependency("csv", "~> 3.0") + s.add_runtime_dependency("em-websocket", "~> 0.5") + s.add_runtime_dependency("i18n", "~> 1.0") + s.add_runtime_dependency("jekyll-sass-converter", ">= 2.0", "< 4.0") + s.add_runtime_dependency("jekyll-watch", "~> 2.0") + s.add_runtime_dependency("json", "~> 2.6") + s.add_runtime_dependency("kramdown", "~> 2.3", ">= 2.3.1") + s.add_runtime_dependency("kramdown-parser-gfm", "~> 1.0") + s.add_runtime_dependency("liquid", "~> 4.0") + s.add_runtime_dependency("logger", "~> 1.3") + s.add_runtime_dependency("mercenary", "~> 0.3", ">= 0.3.6") + s.add_runtime_dependency("pathutil", "~> 0.9") + s.add_runtime_dependency("rouge", ">= 3.0", "< 5.0") + s.add_runtime_dependency("safe_yaml", "~> 1.0") + s.add_runtime_dependency("terminal-table", ">= 1.8", "< 4.0") + s.add_runtime_dependency("webrick", "~> 1.7") end diff --git a/lib/blank_template/_config.yml b/lib/blank_template/_config.yml new file mode 100644 index 00000000000..a0cd66a217a --- /dev/null +++ b/lib/blank_template/_config.yml @@ -0,0 +1,3 @@ +url: "" # the base hostname & protocol for your site, e.g. http://example.com +baseurl: "" # the subpath of your site, e.g. /blog +title: "" # the name of your site, e.g. ACME Corp. diff --git a/lib/blank_template/_layouts/default.html b/lib/blank_template/_layouts/default.html new file mode 100644 index 00000000000..fa0b00a4037 --- /dev/null +++ b/lib/blank_template/_layouts/default.html @@ -0,0 +1,12 @@ + + + + + + {{ page.title }} - {{ site.title }} + + + + {{ content }} + + diff --git a/lib/blank_template/_sass/base.scss b/lib/blank_template/_sass/base.scss new file mode 100644 index 00000000000..126160d3aa1 --- /dev/null +++ b/lib/blank_template/_sass/base.scss @@ -0,0 +1,9 @@ +$backgroundColor: #ffffff; +$bodyColor: #000000; +$bodyFont: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; + +body { + background: $backgroundColor; + color: $bodyColor; + font-family: $bodyFont; +} diff --git a/lib/blank_template/assets/css/main.scss b/lib/blank_template/assets/css/main.scss new file mode 100644 index 00000000000..9c288c5ce5a --- /dev/null +++ b/lib/blank_template/assets/css/main.scss @@ -0,0 +1,4 @@ +--- +--- + +@import "base"; diff --git a/lib/blank_template/index.md b/lib/blank_template/index.md new file mode 100644 index 00000000000..82eaafb0d16 --- /dev/null +++ b/lib/blank_template/index.md @@ -0,0 +1,8 @@ +--- +layout: default +title: "Happy Jekylling!" +--- + +## You're ready to go! + +Start developing your Jekyll website. diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 3e8e639def0..231f8fd89c9 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -1,4 +1,6 @@ -$:.unshift File.dirname(__FILE__) # For use/testing when no gem is installed +# frozen_string_literal: true + +$LOAD_PATH.unshift __dir__ # For use/testing when no gem is installed # Require all of the Ruby files in the given directory. # @@ -6,77 +8,90 @@ # # Returns nothing. def require_all(path) - glob = File.join(File.dirname(__FILE__), path, '*.rb') - Dir[glob].each do |f| + glob = File.join(__dir__, path, "*.rb") + Dir[glob].sort.each do |f| require f end end # rubygems -require 'rubygems' +require "rubygems" # stdlib -require 'fileutils' -require 'time' -require 'English' -require 'pathname' -require 'logger' -require 'set' +require "forwardable" +require "fileutils" +require "time" +require "English" +require "pathname" +require "logger" +require "set" +require "csv" +require "json" # 3rd party -require 'safe_yaml/load' -require 'liquid' -require 'kramdown' -require 'colorator' +require "pathutil" +require "addressable/uri" +require "safe_yaml/load" +require "liquid" +require "kramdown" +require "colorator" +require "i18n" SafeYAML::OPTIONS[:suppress_warnings] = true module Jekyll - # internal requires - autoload :Cleaner, 'jekyll/cleaner' - autoload :Collection, 'jekyll/collection' - autoload :Configuration, 'jekyll/configuration' - autoload :Convertible, 'jekyll/convertible' - autoload :Deprecator, 'jekyll/deprecator' - autoload :Document, 'jekyll/document' - autoload :Draft, 'jekyll/draft' - autoload :EntryFilter, 'jekyll/entry_filter' - autoload :Errors, 'jekyll/errors' - autoload :Excerpt, 'jekyll/excerpt' - autoload :External, 'jekyll/external' - autoload :Filters, 'jekyll/filters' - autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults' - autoload :Hooks, 'jekyll/hooks' - autoload :Layout, 'jekyll/layout' - autoload :CollectionReader, 'jekyll/readers/collection_reader' - autoload :DataReader, 'jekyll/readers/data_reader' - autoload :LayoutReader, 'jekyll/readers/layout_reader' - autoload :PostReader, 'jekyll/readers/post_reader' - autoload :PageReader, 'jekyll/readers/page_reader' - autoload :StaticFileReader, 'jekyll/readers/static_file_reader' - autoload :LogAdapter, 'jekyll/log_adapter' - autoload :Page, 'jekyll/page' - autoload :PluginManager, 'jekyll/plugin_manager' - autoload :Publisher, 'jekyll/publisher' - autoload :Reader, 'jekyll/reader' - autoload :Regenerator, 'jekyll/regenerator' - autoload :RelatedPosts, 'jekyll/related_posts' - autoload :Renderer, 'jekyll/renderer' - autoload :LiquidRenderer, 'jekyll/liquid_renderer' - autoload :Site, 'jekyll/site' - autoload :StaticFile, 'jekyll/static_file' - autoload :Stevenson, 'jekyll/stevenson' - autoload :URL, 'jekyll/url' - autoload :Utils, 'jekyll/utils' - autoload :VERSION, 'jekyll/version' + autoload :Cleaner, "jekyll/cleaner" + autoload :Collection, "jekyll/collection" + autoload :Configuration, "jekyll/configuration" + autoload :Convertible, "jekyll/convertible" + autoload :Deprecator, "jekyll/deprecator" + autoload :Document, "jekyll/document" + autoload :EntryFilter, "jekyll/entry_filter" + autoload :Errors, "jekyll/errors" + autoload :Excerpt, "jekyll/excerpt" + autoload :PageExcerpt, "jekyll/page_excerpt" + autoload :External, "jekyll/external" + autoload :FrontmatterDefaults, "jekyll/frontmatter_defaults" + autoload :Hooks, "jekyll/hooks" + autoload :Layout, "jekyll/layout" + autoload :Inclusion, "jekyll/inclusion" + autoload :Cache, "jekyll/cache" + autoload :CollectionReader, "jekyll/readers/collection_reader" + autoload :DataReader, "jekyll/readers/data_reader" + autoload :LayoutReader, "jekyll/readers/layout_reader" + autoload :PostReader, "jekyll/readers/post_reader" + autoload :PageReader, "jekyll/readers/page_reader" + autoload :StaticFileReader, "jekyll/readers/static_file_reader" + autoload :ThemeAssetsReader, "jekyll/readers/theme_assets_reader" + autoload :LogAdapter, "jekyll/log_adapter" + autoload :Page, "jekyll/page" + autoload :PageWithoutAFile, "jekyll/page_without_a_file" + autoload :PathManager, "jekyll/path_manager" + autoload :PluginManager, "jekyll/plugin_manager" + autoload :Publisher, "jekyll/publisher" + autoload :Profiler, "jekyll/profiler" + autoload :Reader, "jekyll/reader" + autoload :Regenerator, "jekyll/regenerator" + autoload :RelatedPosts, "jekyll/related_posts" + autoload :Renderer, "jekyll/renderer" + autoload :LiquidRenderer, "jekyll/liquid_renderer" + autoload :Site, "jekyll/site" + autoload :StaticFile, "jekyll/static_file" + autoload :Stevenson, "jekyll/stevenson" + autoload :Theme, "jekyll/theme" + autoload :ThemeBuilder, "jekyll/theme_builder" + autoload :URL, "jekyll/url" + autoload :Utils, "jekyll/utils" + autoload :VERSION, "jekyll/version" # extensions - require 'jekyll/plugin' - require 'jekyll/converter' - require 'jekyll/generator' - require 'jekyll/command' - require 'jekyll/liquid_extensions' + require "jekyll/plugin" + require "jekyll/converter" + require "jekyll/generator" + require "jekyll/command" + require "jekyll/liquid_extensions" + require "jekyll/filters" class << self # Public: Tells you which Jekyll environment you are building in so you can skip tasks @@ -91,22 +106,22 @@ def env # options with anything in _config.yml, and adding the given options on top. # # override - A Hash of config directives that override any options in both - # the defaults and the config file. See Jekyll::Configuration::DEFAULTS for a + # the defaults and the config file. + # See Jekyll::Configuration::DEFAULTS for a # list of option names and their defaults. # # Returns the final configuration Hash. - def configuration(override = Hash.new) - config = Configuration[Configuration::DEFAULTS] + def configuration(override = {}) + config = Configuration.new override = Configuration[override].stringify_keys - unless override.delete('skip_config_files') + unless override.delete("skip_config_files") config = config.read_config_files(config.config_files(override)) end # Merge DEFAULTS < _config.yml < override - config = Utils.deep_merge_hashes(config, override).stringify_keys - set_timezone(config['timezone']) if config['timezone'] - - config + Configuration.from(Utils.deep_merge_hashes(config, override)).tap do |obj| + set_timezone(obj["timezone"]) if obj["timezone"] + end end # Public: Set the TZ environment variable to use the timezone specified @@ -114,9 +129,15 @@ def configuration(override = Hash.new) # timezone - the IANA Time Zone # # Returns nothing + # rubocop:disable Naming/AccessorMethodName def set_timezone(timezone) - ENV['TZ'] = timezone + ENV["TZ"] = if Utils::Platforms.really_windows? + Utils::WinTZ.calculate(timezone) + else + timezone + end end + # rubocop:enable Naming/AccessorMethodName # Public: Fetch the logger instance for this Jekyll process. # @@ -127,7 +148,7 @@ def logger # Public: Set the log writer. # New log writer must respond to the same methods - # as Ruby's interal Logger. + # as Ruby's internal Logger. # # writer - the new Logger-compatible log transport # @@ -152,27 +173,23 @@ def sites # Returns the sanitized path. def sanitized_path(base_directory, questionable_path) return base_directory if base_directory.eql?(questionable_path) + return base_directory if questionable_path.nil? - clean_path = File.expand_path(questionable_path, "/") - clean_path = clean_path.sub(/\A\w\:\//, '/') - - unless clean_path.start_with?(base_directory.sub(/\A\w\:\//, '/')) - File.join(base_directory, clean_path) - else - clean_path - end + +Jekyll::PathManager.sanitized_path(base_directory, questionable_path) end # Conditional optimizations - Jekyll::External.require_if_present('liquid-c') - + Jekyll::External.require_if_present("liquid/c") end end -require_all 'jekyll/commands' -require_all 'jekyll/converters' -require_all 'jekyll/converters/markdown' -require_all 'jekyll/generators' -require_all 'jekyll/tags' +require "jekyll/drops/drop" +require "jekyll/drops/document_drop" +require_all "jekyll/commands" +require_all "jekyll/converters" +require_all "jekyll/converters/markdown" +require_all "jekyll/drops" +require_all "jekyll/generators" +require_all "jekyll/tags" -require 'jekyll-sass-converter' +require "jekyll-sass-converter" diff --git a/lib/jekyll/cache.rb b/lib/jekyll/cache.rb new file mode 100644 index 00000000000..8bffd0d407d --- /dev/null +++ b/lib/jekyll/cache.rb @@ -0,0 +1,186 @@ +# frozen_string_literal: true + +require "digest" + +module Jekyll + class Cache + # class-wide base cache + @base_cache = {} + + # class-wide directive to write cache to disk is enabled by default + @disk_cache_enabled = true + + class << self + attr_accessor :cache_dir # class-wide cache location + + attr_reader :base_cache, # class-wide base cache reader + :disk_cache_enabled # class-wide directive to write cache to disk + + # Disable Marshaling cached items to disk + def disable_disk_cache! + @disk_cache_enabled = false + end + + # Clear all caches + def clear + delete_cache_files + base_cache.each_value(&:clear) + end + + # Compare the current config to the cached config + # If they are different, clear all caches + # + # Returns nothing. + def clear_if_config_changed(config) + config = config.inspect + cache = Jekyll::Cache.new "Jekyll::Cache" + return if cache.key?("config") && cache["config"] == config + + clear + cache = Jekyll::Cache.new "Jekyll::Cache" + cache["config"] = config + nil + end + + private + + # Delete all cached items from all caches + # + # Returns nothing. + def delete_cache_files + FileUtils.rm_rf(@cache_dir) if disk_cache_enabled + end + end + + # + + # Get an existing named cache, or create a new one if none exists + # + # name - name of the cache + # + # Returns nothing. + def initialize(name) + @cache = Jekyll::Cache.base_cache[name] ||= {} + @name = name.gsub(%r![^\w\s-]!, "-") + end + + # Clear this particular cache + def clear + delete_cache_files + @cache.clear + end + + # Retrieve a cached item + # Raises if key does not exist in cache + # + # Returns cached value + def [](key) + return @cache[key] if @cache.key?(key) + + path = path_to(hash(key)) + if disk_cache_enabled? && File.file?(path) && File.readable?(path) + @cache[key] = load(path) + else + raise + end + end + + # Add an item to cache + # + # Returns nothing. + def []=(key, value) + @cache[key] = value + return unless disk_cache_enabled? + + path = path_to(hash(key)) + value = new Hash(value) if value.is_a?(Hash) && !value.default.nil? + dump(path, value) + rescue TypeError + Jekyll.logger.debug "Cache:", "Cannot dump object #{key}" + end + + # If an item already exists in the cache, retrieve it. + # Else execute code block, and add the result to the cache, and return that result. + def getset(key) + self[key] + rescue StandardError + value = yield + self[key] = value + value + end + + # Remove one particular item from the cache + # + # Returns nothing. + def delete(key) + @cache.delete(key) + File.delete(path_to(hash(key))) if disk_cache_enabled? + end + + # Check if `key` already exists in this cache + # + # Returns true if key exists in the cache, false otherwise + def key?(key) + # First, check if item is already cached in memory + return true if @cache.key?(key) + # Otherwise, it might be cached on disk + # but we should not consider the disk cache if it is disabled + return false unless disk_cache_enabled? + + path = path_to(hash(key)) + File.file?(path) && File.readable?(path) + end + + def disk_cache_enabled? + !!Jekyll::Cache.disk_cache_enabled + end + + private + + # Given a hashed key, return the path to where this item would be saved on disk. + def path_to(hash = nil) + @base_dir ||= File.join(Jekyll::Cache.cache_dir, @name) + return @base_dir if hash.nil? + + File.join(@base_dir, hash[0..1], hash[2..-1]).freeze + end + + # Given a key, return a SHA2 hash that can be used for caching this item to disk. + def hash(key) + Digest::SHA2.hexdigest(key).freeze + end + + # Remove all this caches items from disk + # + # Returns nothing. + def delete_cache_files + FileUtils.rm_rf(path_to) if disk_cache_enabled? + end + + # Load `path` from disk and return the result. + # This MUST NEVER be called in Safe Mode + # rubocop:disable Security/MarshalLoad + def load(path) + raise unless disk_cache_enabled? + + cached_file = File.open(path, "rb") + value = Marshal.load(cached_file) + cached_file.close + value + end + # rubocop:enable Security/MarshalLoad + + # Given a path and a value, save value to disk at path. + # This should NEVER be called in Safe Mode + # + # Returns nothing. + def dump(path, value) + return unless disk_cache_enabled? + + FileUtils.mkdir_p(File.dirname(path)) + File.open(path, "wb") do |cached_file| + Marshal.dump(value, cached_file) + end + end + end +end diff --git a/lib/jekyll/cleaner.rb b/lib/jekyll/cleaner.rb index d23da78fc4f..59e7c22ae47 100644 --- a/lib/jekyll/cleaner.rb +++ b/lib/jekyll/cleaner.rb @@ -1,9 +1,9 @@ -require 'set' +# frozen_string_literal: true module Jekyll # Handles the cleanup of a site's destination before it is built. class Cleaner - HIDDEN_FILE_REGEX = /\/\.{1,2}$/ + HIDDEN_FILE_REGEX = %r!/\.{1,2}$!.freeze attr_reader :site def initialize(site) @@ -13,7 +13,7 @@ def initialize(site) # Cleans up the site's destination directory def cleanup! FileUtils.rm_rf(obsolete_files) - FileUtils.rm_rf(metadata_file) if !@site.incremental? + FileUtils.rm_rf(metadata_file) unless @site.incremental? end private @@ -22,17 +22,20 @@ def cleanup! # # Returns an Array of the file and directory paths def obsolete_files - (existing_files - new_files - new_dirs + replaced_files).to_a + out = (existing_files - new_files - new_dirs + replaced_files).to_a + Jekyll::Hooks.trigger :clean, :on_obsolete, out + out end # Private: The metadata file storing dependency tree and build history # - # Returns an Array with the metdata file as the only item + # Returns an Array with the metadata file as the only item def metadata_file [site.regenerator.metadata_file] end - # Private: The list of existing files, apart from those included in keep_files and hidden files. + # Private: The list of existing files, apart from those included in + # keep_files and hidden files. # # Returns a Set with the file paths def existing_files @@ -40,8 +43,9 @@ def existing_files regex = keep_file_regex dirs = keep_dirs - Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file| - next if file =~ HIDDEN_FILE_REGEX || file =~ regex || dirs.include?(file) + Utils.safe_glob(site.in_dest_dir, ["**", "*"], File::FNM_DOTMATCH).each do |file| + next if HIDDEN_FILE_REGEX.match?(file) || regex.match?(file) || dirs.include?(file) + files << file end @@ -52,9 +56,9 @@ def existing_files # # Returns a Set with the file paths def new_files - files = Set.new - site.each_site_file { |item| files << item.destination(site.dest) } - files + @new_files ||= Set.new.tap do |files| + site.each_site_file { |item| files << item.destination(site.dest) } + end end # Private: The list of directories to be created when site is built. @@ -62,7 +66,7 @@ def new_files # # Returns a Set with the directory paths def new_dirs - new_files.map { |file| parent_dirs(file) }.flatten.to_set + @new_dirs ||= new_files.flat_map { |file| parent_dirs(file) }.to_set end # Private: The list of parent directories of a given file @@ -73,33 +77,35 @@ def parent_dirs(file) if parent_dir == site.dest [] else - [parent_dir] + parent_dirs(parent_dir) + parent_dirs(parent_dir).unshift(parent_dir) end end - # Private: The list of existing files that will be replaced by a directory during build + # Private: The list of existing files that will be replaced by a directory + # during build # # Returns a Set with the file paths def replaced_files new_dirs.select { |dir| File.file?(dir) }.to_set end - # Private: The list of directories that need to be kept because they are parent directories - # of files specified in keep_files + # Private: The list of directories that need to be kept because they are + # parent directories of files specified in keep_files # # Returns a Set with the directory paths def keep_dirs - site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set + site.keep_files.flat_map { |file| parent_dirs(site.in_dest_dir(file)) }.to_set end # Private: Creates a regular expression from the config's keep_files array # # Examples - # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ + # ['.git','.svn'] with site.dest "/myblog/_site" creates + # the following regex: /\A\/myblog\/_site\/(\.git|\/.svn)/ # # Returns the regular expression def keep_file_regex - Regexp.union(site.keep_files) + %r!\A#{Regexp.quote(site.dest)}/(#{Regexp.union(site.keep_files).source})! end end end diff --git a/lib/jekyll/collection.rb b/lib/jekyll/collection.rb index 4363aee195b..1ce33bf23c0 100644 --- a/lib/jekyll/collection.rb +++ b/lib/jekyll/collection.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll class Collection attr_reader :site, :label, :metadata @@ -25,15 +27,16 @@ def docs # Override of normal respond_to? to match method_missing's logic for # looking in @data. - def respond_to?(method, include_private = false) + def respond_to_missing?(method, include_private = false) docs.respond_to?(method.to_sym, include_private) || super end # Override of method_missing to check in @data for the key. def method_missing(method, *args, &blck) if docs.respond_to?(method.to_sym) - Jekyll.logger.warn "Deprecation:", "Collection##{method} should be called on the #docs array directly." - Jekyll.logger.warn "", "Called by #{caller.first}." + Jekyll.logger.warn "Deprecation:", + "#{label}.#{method} should be changed to #{label}.docs.#{method}." + Jekyll.logger.warn "", "Called by #{caller(0..0)}." docs.public_send(method.to_sym, *args, &blck) else super @@ -55,16 +58,15 @@ def read filtered_entries.each do |file_path| full_path = collection_dir(file_path) next if File.directory?(full_path) + if Utils.has_yaml_header? full_path - doc = Jekyll::Document.new(full_path, { site: site, collection: self }) - doc.read - docs << doc if site.publisher.publish?(doc) || !write? + read_document(full_path) else - relative_dir = Jekyll.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.") - files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self) + read_static_file(file_path, full_path) end end - docs.sort! + site.static_files.concat(files) unless files.empty? + sort_docs! end # All the entries in this collection. @@ -72,11 +74,15 @@ def read # Returns an Array of file paths to the documents in this collection # relative to the collection's directory def entries - return Array.new unless exists? - @entries ||= - Dir.glob(collection_dir("**", "*.*")).map do |entry| - entry["#{collection_dir}/"] = ''; entry + return [] unless exists? + + @entries ||= begin + collection_dir_slash = "#{collection_dir}/" + Utils.safe_glob(collection_dir, ["**", "*"], File::FNM_DOTMATCH).map do |entry| + entry[collection_dir_slash] = "" + entry end + end end # Filtered version of the entries in this collection. @@ -84,17 +90,19 @@ def entries # # Returns a list of filtered entry paths. def filtered_entries - return Array.new unless exists? + return [] unless exists? + @filtered_entries ||= Dir.chdir(directory) do entry_filter.filter(entries).reject do |f| path = collection_dir(f) - File.directory?(path) || (File.symlink?(f) && site.safe) + File.directory?(path) || entry_filter.symlink?(f) end end end - # The directory for this Collection, relative to the site source. + # The directory for this Collection, relative to the site source or the directory + # containing the collection. # # Returns a String containing the directory name where the collection # is stored on the filesystem. @@ -107,7 +115,9 @@ def relative_directory # Returns a String containing th directory name where the collection # is stored on the filesystem. def directory - @directory ||= site.in_source_dir(relative_directory) + @directory ||= site.in_source_dir( + File.join(container, relative_directory) + ) end # The full path to the directory containing the collection, with @@ -120,7 +130,8 @@ def directory # is stored on the filesystem. def collection_dir(*files) return directory if files.empty? - site.in_source_dir(relative_directory, *files) + + site.in_source_dir(container, relative_directory, *files) end # Checks whether the directory "exists" for this collection. @@ -130,7 +141,7 @@ def collection_dir(*files) # Returns false if the directory doesn't exist or if it's a symlink # and we're in safe mode. def exists? - File.directory?(directory) && !(File.symlink?(directory) && site.safe) + File.directory?(directory) && !entry_filter.symlink?(directory) end # The entry filter for this collection. @@ -145,7 +156,7 @@ def entry_filter # # Returns the inspect string def inspect - "#" + "#<#{self.class} @label=#{label} docs=#{docs}>" end # Produce a sanitized label name @@ -156,7 +167,7 @@ def inspect # # Returns a sanitized version of the label. def sanitize_label(label) - label.gsub(/[^a-z0-9_\-\.]/i, '') + label.gsub(%r![^a-z0-9_\-.]!i, "") end # Produce a representation of this Collection for use in Liquid. @@ -166,14 +177,7 @@ def sanitize_label(label) # # Returns a representation of this collection for use in Liquid. def to_liquid - metadata.merge({ - "label" => label, - "docs" => docs, - "files" => files, - "directory" => directory, - "output" => write?, - "relative_directory" => relative_directory - }) + Drops::CollectionDrop.new self end # Whether the collection's documents ought to be written as individual @@ -181,15 +185,15 @@ def to_liquid # # Returns true if the 'write' metadata is true, false otherwise. def write? - !!metadata.fetch('output', false) + !!metadata.fetch("output", false) end # The URL template to render collection's documents at. # # Returns the URL template to render collection's documents at. def url_template - metadata.fetch('permalink') do - Utils.add_permalink_suffix("/:collection/:path", site.permalink_style) + @url_template ||= metadata.fetch("permalink") do + Utils.add_permalink_suffix("/:collection/:path", site.permalink_style) end end @@ -197,11 +201,110 @@ def url_template # # Returns the metadata for this collection def extract_metadata - if site.config['collections'].is_a?(Hash) - site.config['collections'][label] || Hash.new + if site.config["collections"].is_a?(Hash) + site.config["collections"][label] || {} else {} end end + + private + + def container + @container ||= site.config["collections_dir"] + end + + def read_document(full_path) + doc = Document.new(full_path, :site => site, :collection => self) + doc.read + docs << doc if site.unpublished || doc.published? + end + + def sort_docs! + if metadata["order"].is_a?(Array) + rearrange_docs! + elsif metadata["sort_by"].is_a?(String) + sort_docs_by_key! + else + docs.sort! + end + end + + # A custom sort function based on Schwartzian transform + # Refer https://byparker.com/blog/2017/schwartzian-transform-faster-sorting/ for details + def sort_docs_by_key! + meta_key = metadata["sort_by"] + # Modify `docs` array to cache document's property along with the Document instance + docs.map! { |doc| [doc.data[meta_key], doc] }.sort! do |apples, olives| + order = determine_sort_order(meta_key, apples, olives) + + # Fall back to `Document#<=>` if the properties were equal or were non-sortable + # Otherwise continue with current sort-order + if order.nil? || order.zero? + apples[-1] <=> olives[-1] + else + order + end + + # Finally restore the `docs` array with just the Document objects themselves + end.map!(&:last) + end + + def determine_sort_order(sort_key, apples, olives) + apple_property, apple_document = apples + olive_property, olive_document = olives + + if apple_property.nil? && !olive_property.nil? + order_with_warning(sort_key, apple_document, 1) + elsif !apple_property.nil? && olive_property.nil? + order_with_warning(sort_key, olive_document, -1) + else + apple_property <=> olive_property + end + end + + def order_with_warning(sort_key, document, order) + Jekyll.logger.warn "Sort warning:", "'#{sort_key}' not defined in #{document.relative_path}" + order + end + + # Rearrange documents within the `docs` array as listed in the `metadata["order"]` array. + # + # Involves converting the two arrays into hashes based on relative_paths as keys first, then + # merging them to remove duplicates and finally retrieving the Document instances from the + # merged array. + def rearrange_docs! + docs_table = {} + custom_order = {} + + # pre-sort to normalize default array across platforms and then proceed to create a Hash + # from that sorted array. + docs.sort.each do |doc| + docs_table[doc.relative_path] = doc + end + + metadata["order"].each do |entry| + custom_order[File.join(relative_directory, entry)] = nil + end + + result = Jekyll::Utils.deep_merge_hashes(custom_order, docs_table).values + result.compact! + self.docs = result + end + + def read_static_file(file_path, full_path) + relative_dir = Jekyll.sanitized_path( + relative_directory, + File.dirname(file_path) + ).chomp("/.") + + files << StaticFile.new( + site, + site.source, + relative_dir, + File.basename(full_path), + self + ) + end end end diff --git a/lib/jekyll/command.rb b/lib/jekyll/command.rb index f3c89dfd2e3..be8890e72de 100644 --- a/lib/jekyll/command.rb +++ b/lib/jekyll/command.rb @@ -1,8 +1,8 @@ +# frozen_string_literal: true + module Jekyll class Command - class << self - # A list of subclasses of Jekyll::Command def subclasses @subclasses ||= [] @@ -39,31 +39,67 @@ def process_site(site) # # Returns a full Jekyll configuration def configuration_from_options(options) + return options if options.is_a?(Jekyll::Configuration) + Jekyll.configuration(options) end # Add common options to a command for building configuration # - # c - the Jekyll::Command to add these options to + # cmd - the Jekyll::Command to add these options to # # Returns nothing - def add_build_options(c) - c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file' - c.option 'destination', '-d', '--destination DESTINATION', 'The current folder will be generated into DESTINATION' - c.option 'source', '-s', '--source SOURCE', 'Custom source directory' - c.option 'future', '--future', 'Publishes posts with a future date' - c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish' - c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild' - c.option 'force_polling', '--force_polling', 'Force watch to use polling' - c.option 'lsi', '--lsi', 'Use LSI for improved related posts' - c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder' - c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished' - c.option 'quiet', '-q', '--quiet', 'Silence output.' - c.option 'verbose', '-V', '--verbose', 'Print verbose output.' - c.option 'incremental', '-I', '--incremental', 'Enable incremental rebuild.' + # rubocop:disable Metrics/MethodLength + def add_build_options(cmd) + cmd.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", + Array, "Custom configuration file" + cmd.option "destination", "-d", "--destination DESTINATION", + "The current folder will be generated into DESTINATION" + cmd.option "source", "-s", "--source SOURCE", "Custom source directory" + cmd.option "future", "--future", "Publishes posts with a future date" + cmd.option "limit_posts", "--limit_posts MAX_POSTS", Integer, + "Limits the number of posts to parse and publish" + cmd.option "watch", "-w", "--[no-]watch", "Watch for changes and rebuild" + cmd.option "baseurl", "-b", "--baseurl URL", + "Serve the website from the given base URL" + cmd.option "force_polling", "--force_polling", "Force watch to use polling" + cmd.option "lsi", "--lsi", "Use LSI for improved related posts" + cmd.option "show_drafts", "-D", "--drafts", "Render posts in the _drafts folder" + cmd.option "unpublished", "--unpublished", + "Render posts that were marked as unpublished" + cmd.option "disable_disk_cache", "--disable-disk-cache", + "Disable caching to disk in non-safe mode" + cmd.option "quiet", "-q", "--quiet", "Silence output." + cmd.option "verbose", "-V", "--verbose", "Print verbose output." + cmd.option "incremental", "-I", "--incremental", "Enable incremental rebuild." + cmd.option "strict_front_matter", "--strict_front_matter", + "Fail if errors are present in front matter" end + # rubocop:enable Metrics/MethodLength - end + # Run ::process method in a given set of Jekyll::Command subclasses and suggest + # re-running the associated command with --trace switch to obtain any additional + # information or backtrace regarding the encountered Exception. + # + # cmd - the Jekyll::Command to be handled + # options - configuration overrides + # klass - an array of Jekyll::Command subclasses associated with the command + # + # Note that all exceptions are rescued.. + # rubocop: disable Lint/RescueException + def process_with_graceful_fail(cmd, options, *klass) + klass.each { |k| k.process(options) if k.respond_to?(:process) } + rescue Exception => e + raise e if cmd.trace + msg = " Please append `--trace` to the `#{cmd.name}` command " + dashes = "-" * msg.length + Jekyll.logger.error "", dashes + Jekyll.logger.error "Jekyll #{Jekyll::VERSION} ", msg + Jekyll.logger.error "", " for any additional information or backtrace. " + Jekyll.logger.abort_with "", dashes + end + # rubocop: enable Lint/RescueException + end end end diff --git a/lib/jekyll/commands/build.rb b/lib/jekyll/commands/build.rb index de0cc8bcab8..204b2a12632 100644 --- a/lib/jekyll/commands/build.rb +++ b/lib/jekyll/commands/build.rb @@ -1,21 +1,21 @@ +# frozen_string_literal: true + module Jekyll module Commands class Build < Command - class << self - # Create the Mercenary command for the Jekyll CLI for this Command def init_with_program(prog) prog.command(:build) do |c| - c.syntax 'build [options]' - c.description 'Build your site' + c.syntax "build [options]" + c.description "Build your site" c.alias :b add_build_options(c) - c.action do |args, options| + c.action do |_, options| options["serving"] = false - Jekyll::Commands::Build.process(options) + process_with_graceful_fail(c, options, self) end end end @@ -29,13 +29,17 @@ def process(options) options = configuration_from_options(options) site = Jekyll::Site.new(options) - if options.fetch('skip_initial_build', false) - Jekyll.logger.warn "Build Warning:", "Skipping the initial build. This may result in an out-of-date site." + if options.fetch("skip_initial_build", false) + Jekyll.logger.warn "Build Warning:", + "Skipping the initial build. This may result in an out-of-date site." else build(site, options) end - if options.fetch('watch', false) + if options.fetch("detach", false) + Jekyll.logger.info "Auto-regeneration:", + "disabled when running server detached." + elsif options.fetch("watch", false) watch(site, options) else Jekyll.logger.info "Auto-regeneration:", "disabled. Use --watch to enable." @@ -50,12 +54,13 @@ def process(options) # Returns nothing. def build(site, options) t = Time.now - source = options['source'] - destination = options['destination'] - incremental = options['incremental'] + source = File.expand_path(options["source"]) + destination = File.expand_path(options["destination"]) + incremental = options["incremental"] Jekyll.logger.info "Source:", source Jekyll.logger.info "Destination:", destination - Jekyll.logger.info "Incremental build:", (incremental ? "enabled" : "disabled. Enable with --incremental") + Jekyll.logger.info "Incremental build:", + (incremental ? "enabled" : "disabled. Enable with --incremental") Jekyll.logger.info "Generating..." process_site(site) Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds." @@ -68,12 +73,10 @@ def build(site, options) # # Returns nothing. def watch(site, options) - External.require_with_graceful_fail 'jekyll-watch' - Jekyll::Watcher.watch(options) + External.require_with_graceful_fail "jekyll-watch" + Jekyll::Watcher.watch(options, site) end - - end # end of class << self - + end end end end diff --git a/lib/jekyll/commands/clean.rb b/lib/jekyll/commands/clean.rb index bf05dbe0bf9..9b657a49a07 100644 --- a/lib/jekyll/commands/clean.rb +++ b/lib/jekyll/commands/clean.rb @@ -1,43 +1,43 @@ +# frozen_string_literal: true + module Jekyll module Commands class Clean < Command class << self - def init_with_program(prog) prog.command(:clean) do |c| - c.syntax 'clean [subcommand]' - c.description 'Clean the site (removes site output and metadata file) without building.' + c.syntax "clean [subcommand]" + c.description "Clean the site (removes site output and metadata file) without building." add_build_options(c) - c.action do |args, _| - Jekyll::Commands::Clean.process({}) + c.action do |_, options| + Jekyll::Commands::Clean.process(options) end end end def process(options) options = configuration_from_options(options) - destination = options['destination'] - metadata_file = File.join(options['source'], '.jekyll-metadata') + destination = options["destination"] + metadata_file = File.join(options["source"], ".jekyll-metadata") + cache_dir = File.join(options["source"], options["cache_dir"]) + sass_cache = ".sass-cache" - if File.directory? destination - Jekyll.logger.info "Cleaning #{destination}..." - FileUtils.rm_rf(destination) - Jekyll.logger.info "", "done." - else - Jekyll.logger.info "Nothing to do for #{destination}." - end + remove(destination, :checker_func => :directory?) + remove(metadata_file, :checker_func => :file?) + remove(cache_dir, :checker_func => :directory?) + remove(sass_cache, :checker_func => :directory?) + end - if File.file? metadata_file - Jekyll.logger.info "Removing #{metadata_file}..." - FileUtils.rm_rf(metadata_file) - Jekyll.logger.info "", "done." + def remove(filename, checker_func: :file?) + if File.public_send(checker_func, filename) + Jekyll.logger.info "Cleaner:", "Removing #{filename}..." + FileUtils.rm_rf(filename) else - Jekyll.logger.info "Nothing to do for #{metadata_file}." + Jekyll.logger.info "Cleaner:", "Nothing to do for #{filename}." end end - end end end diff --git a/lib/jekyll/commands/doctor.rb b/lib/jekyll/commands/doctor.rb index 6d7429eb150..eec7133cbbe 100644 --- a/lib/jekyll/commands/doctor.rb +++ b/lib/jekyll/commands/doctor.rb @@ -1,17 +1,19 @@ +# frozen_string_literal: true + module Jekyll module Commands class Doctor < Command class << self - def init_with_program(prog) prog.command(:doctor) do |c| - c.syntax 'doctor' - c.description 'Search site and print specific deprecation warnings' + c.syntax "doctor" + c.description "Search site and print specific deprecation warnings" c.alias(:hyde) - c.option '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file' + c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", Array, + "Custom configuration file" - c.action do |args, options| + c.action do |_, options| Jekyll::Commands::Doctor.process(options) end end @@ -19,7 +21,9 @@ def init_with_program(prog) def process(options) site = Jekyll::Site.new(configuration_from_options(options)) + site.reset site.read + site.generate if healthy?(site) Jekyll.logger.info "Your test results", "are in. Everything looks fine." @@ -32,41 +36,59 @@ def healthy?(site) [ fsnotify_buggy?(site), !deprecated_relative_permalinks(site), - !conflicting_urls(site) + !conflicting_urls(site), + !urls_only_differ_by_case(site), + proper_site_url?(site), + properly_gathered_posts?(site), ].all? end + def properly_gathered_posts?(site) + return true if site.config["collections_dir"].empty? + + posts_at_root = site.in_source_dir("_posts") + return true unless File.directory?(posts_at_root) + + Jekyll.logger.warn "Warning:", + "Detected '_posts' directory outside custom `collections_dir`!" + Jekyll.logger.warn "", + "Please move '#{posts_at_root}' into the custom directory at " \ + "'#{site.in_source_dir(site.config["collections_dir"])}'" + false + end + def deprecated_relative_permalinks(site) - if site.config['relative_permalinks'] - Jekyll::Deprecator.deprecation_message "Your site still uses relative" + - " permalinks, which was removed in" + - " Jekyll v3.0.0." - return true + if site.config["relative_permalinks"] + Jekyll::Deprecator.deprecation_message "Your site still uses relative permalinks, " \ + "which was removed in Jekyll v3.0.0." + true end end def conflicting_urls(site) conflicting_urls = false - urls = {} - urls = collect_urls(urls, site.pages, site.dest) - urls = collect_urls(urls, site.posts.docs, site.dest) - urls.each do |url, paths| - if paths.size > 1 - conflicting_urls = true - Jekyll.logger.warn "Conflict:", "The URL '#{url}' is the destination" + - " for the following pages: #{paths.join(", ")}" - end + destination_map(site).each do |dest, paths| + next unless paths.size > 1 + + conflicting_urls = true + Jekyll.logger.warn "Conflict:", + "The following destination is shared by multiple files." + Jekyll.logger.warn "", "The written file may end up with unexpected contents." + Jekyll.logger.warn "", dest.to_s.cyan + paths.each { |path| Jekyll.logger.warn "", " - #{path}" } + Jekyll.logger.warn "" end conflicting_urls end - def fsnotify_buggy?(site) - return true if !Utils::Platforms.osx? + def fsnotify_buggy?(_site) + return true unless Utils::Platforms.osx? + if Dir.pwd != `pwd`.strip - Jekyll.logger.error " " + <<-STR.strip.gsub(/\n\s+/, "\n ") + Jekyll.logger.error <<~STR We have detected that there might be trouble using fsevent on your operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug) - for possible work arounds or you can work around it immediately + for possible workarounds or you can work around it immediately with `--force-polling`. STR @@ -76,21 +98,80 @@ def fsnotify_buggy?(site) true end + def urls_only_differ_by_case(site) + urls_only_differ_by_case = false + urls = case_insensitive_urls(site.pages + site.docs_to_write, site.dest) + urls.each_value do |real_urls| + next unless real_urls.uniq.size > 1 + + urls_only_differ_by_case = true + Jekyll.logger.warn "Warning:", "The following URLs only differ by case. On a " \ + "case-insensitive file system one of the URLs will be " \ + "overwritten by the other: #{real_urls.join(", ")}" + end + urls_only_differ_by_case + end + + def proper_site_url?(site) + url = site.config["url"] + [ + url_exists?(url), + url_valid?(url), + url_absolute(url), + ].all? + end + private - def collect_urls(urls, things, destination) - things.each do |thing| - dest = thing.destination(destination) - if urls[dest] - urls[dest] << thing.path - else - urls[dest] = [thing.path] + + def destination_map(site) + {}.tap do |result| + site.each_site_file do |thing| + next if allow_used_permalink?(thing) + + dest_path = thing.destination(site.dest) + (result[dest_path] ||= []) << thing.path end end - urls end - end + def allow_used_permalink?(item) + defined?(JekyllRedirectFrom) && item.is_a?(JekyllRedirectFrom::RedirectPage) + end + + def case_insensitive_urls(things, destination) + things.each_with_object({}) do |thing, memo| + dest = thing.destination(destination) + (memo[dest.downcase] ||= []) << dest + end + end + + def url_exists?(url) + return true unless url.nil? || url.empty? + Jekyll.logger.warn "Warning:", "You didn't set an URL in the config file, you may " \ + "encounter problems with some plugins." + false + end + + def url_valid?(url) + Addressable::URI.parse(url) + true + # Addressable::URI#parse only raises a TypeError + # https://github.com/sporkmonger/addressable/blob/0a0e96acb17225f9b1c9cab0bad332b448934c9a/lib/addressable/uri.rb#L103 + rescue TypeError + Jekyll.logger.warn "Warning:", "The site URL does not seem to be valid, " \ + "check the value of `url` in your config file." + false + end + + def url_absolute(url) + return true if url.is_a?(String) && Addressable::URI.parse(url).absolute? + + Jekyll.logger.warn "Warning:", "Your site URL does not seem to be absolute, " \ + "check the value of `url` in your config file." + false + end + end end end end diff --git a/lib/jekyll/commands/help.rb b/lib/jekyll/commands/help.rb index 421d87e580a..90403dfd06c 100644 --- a/lib/jekyll/commands/help.rb +++ b/lib/jekyll/commands/help.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true + module Jekyll module Commands class Help < Command class << self - def init_with_program(prog) prog.command(:help) do |c| - c.syntax 'help [subcommand]' - c.description 'Show the help message, optionally for a given subcommand.' + c.syntax "help [subcommand]" + c.description "Show the help message, optionally for a given subcommand." c.action do |args, _| cmd = (args.first || "").to_sym if args.empty? - puts prog + Jekyll.logger.info prog.to_s elsif prog.has_command? cmd - puts prog.commands[cmd] + Jekyll.logger.info prog.commands[cmd].to_s else invalid_command(prog, cmd) abort @@ -23,10 +24,10 @@ def init_with_program(prog) end def invalid_command(prog, cmd) - Jekyll.logger.error "Error:", "Hmm... we don't know what the '#{cmd}' command is." + Jekyll.logger.error "Error:", + "Hmm... we don't know what the '#{cmd}' command is." Jekyll.logger.info "Valid commands:", prog.commands.keys.join(", ") end - end end end diff --git a/lib/jekyll/commands/new.rb b/lib/jekyll/commands/new.rb index 433d33b79f2..161a3dd378d 100644 --- a/lib/jekyll/commands/new.rb +++ b/lib/jekyll/commands/new.rb @@ -1,4 +1,6 @@ -require 'erb' +# frozen_string_literal: true + +require "erb" module Jekyll module Commands @@ -6,11 +8,12 @@ class New < Command class << self def init_with_program(prog) prog.command(:new) do |c| - c.syntax 'new PATH' - c.description 'Creates a new Jekyll site scaffold in PATH' + c.syntax "new PATH" + c.description "Creates a new Jekyll site scaffold in PATH" - c.option 'force', '--force', 'Force creation even if PATH already exists' - c.option 'blank', '--blank', 'Creates scaffolding but with empty files' + c.option "force", "--force", "Force creation even if PATH already exists" + c.option "blank", "--blank", "Creates scaffolding but with empty files" + c.option "skip-bundle", "--skip-bundle", "Skip 'bundle install'" c.action do |args, options| Jekyll::Commands::New.process(args, options) @@ -19,31 +22,35 @@ def init_with_program(prog) end def process(args, options = {}) - raise ArgumentError.new('You must specify a path.') if args.empty? + raise ArgumentError, "You must specify a path." if args.empty? new_blog_path = File.expand_path(args.join(" "), Dir.pwd) FileUtils.mkdir_p new_blog_path if preserve_source_location?(new_blog_path, options) - Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty." + Jekyll.logger.error "Conflict:", "#{new_blog_path} exists and is not empty." + Jekyll.logger.abort_with "", "Ensure #{new_blog_path} is empty or else try again " \ + "with `--force` to proceed and overwrite any files." end if options["blank"] create_blank_site new_blog_path else - create_sample_files new_blog_path - - File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f| - f.write(scaffold_post_content) - end + create_site new_blog_path end - Jekyll.logger.info "New jekyll site installed in #{new_blog_path}." + after_install(new_blog_path, options) + end + + def blank_template + File.expand_path("../../blank_template", __dir__) end def create_blank_site(path) + FileUtils.cp_r blank_template + "/.", path + FileUtils.chmod_R "u+w", path + Dir.chdir(path) do - FileUtils.mkdir(%w(_layouts _posts _drafts)) - FileUtils.touch("index.html") + FileUtils.mkdir(%w(_data _drafts _includes _posts)) end end @@ -55,27 +62,106 @@ def scaffold_post_content # # Returns the filename of the sample post, as a String def initialized_post_name - "_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown" + "_posts/#{Time.now.strftime("%Y-%m-%d")}-welcome-to-jekyll.markdown" end private + def gemfile_contents + <<~RUBY + source "https://rubygems.org" + # Hello! This is where you manage which Jekyll version is used to run. + # When you want to use a different version, change it below, save the + # file and run `bundle install`. Run Jekyll with `bundle exec`, like so: + # + # bundle exec jekyll serve + # + # This will help ensure the proper Jekyll version is running. + # Happy Jekylling! + gem "jekyll", "~> #{Jekyll::VERSION}" + # This is the default theme for new Jekyll sites. You may change this to anything you like. + gem "minima", "~> 2.5" + # If you want to use GitHub Pages, remove the "gem "jekyll"" above and + # uncomment the line below. To upgrade, run `bundle update github-pages`. + # gem "github-pages", group: :jekyll_plugins + # If you have any plugins, put them here! + group :jekyll_plugins do + gem "jekyll-feed", "~> 0.12" + end + + # Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem + # and associated library. + platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" + end + + # Performance-booster for watching directories on Windows + gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin] + + # Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem + # do not have a Java counterpart. + gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby] + RUBY + end + + def create_site(new_blog_path) + create_sample_files new_blog_path + + File.write(File.expand_path(initialized_post_name, new_blog_path), scaffold_post_content) + + File.write(File.expand_path("Gemfile", new_blog_path), gemfile_contents) + end + def preserve_source_location?(path, options) !options["force"] && !Dir["#{path}/**/*"].empty? end def create_sample_files(path) - FileUtils.cp_r site_template + '/.', path + FileUtils.cp_r site_template + "/.", path + FileUtils.chmod_R "u+w", path FileUtils.rm File.expand_path(scaffold_path, path) end def site_template - File.expand_path("../../site_template", File.dirname(__FILE__)) + File.expand_path("../../site_template", __dir__) end def scaffold_path "_posts/0000-00-00-welcome-to-jekyll.markdown.erb" end + + # After a new blog has been created, print a success notification and + # then automatically execute bundle install from within the new blog dir + # unless the user opts to generate a blank blog or skip 'bundle install'. + + def after_install(path, options = {}) + unless options["blank"] || options["skip-bundle"] + begin + require "bundler" + bundle_install path + rescue LoadError + Jekyll.logger.info "Could not load Bundler. Bundle install skipped." + end + end + + Jekyll.logger.info "New jekyll site installed in #{path.cyan}." + Jekyll.logger.info "Bundle install skipped." if options["skip-bundle"] + end + + def bundle_install(path) + Jekyll.logger.info "Running bundle install in #{path.cyan}..." + Dir.chdir(path) do + exe = Gem.bin_path("bundler", "bundle") + process, output = Jekyll::Utils::Exec.run("ruby", exe, "install") + + output.to_s.each_line do |line| + Jekyll.logger.info("Bundler:".green, line.strip) unless line.to_s.empty? + end + + raise SystemExit unless process.success? + end + end end end end diff --git a/lib/jekyll/commands/new_theme.rb b/lib/jekyll/commands/new_theme.rb new file mode 100644 index 00000000000..3419d175b0c --- /dev/null +++ b/lib/jekyll/commands/new_theme.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require "erb" + +module Jekyll + module Commands + class NewTheme < Jekyll::Command + class << self + def init_with_program(prog) + prog.command(:"new-theme") do |c| + c.syntax "new-theme NAME" + c.description "Creates a new Jekyll theme scaffold" + c.option "code_of_conduct", "-c", "--code-of-conduct", + "Include a Code of Conduct. (defaults to false)" + + c.action do |args, opts| + Jekyll::Commands::NewTheme.process(args, opts) + end + end + end + + def process(args, opts) + if !args || args.empty? + raise Jekyll::Errors::InvalidThemeName, "You must specify a theme name." + end + + new_theme_name = args.join("_") + theme = Jekyll::ThemeBuilder.new(new_theme_name, opts) + Jekyll.logger.abort_with "Conflict:", "#{theme.path} already exists." if theme.path.exist? + + theme.create! + Jekyll.logger.info "Your new Jekyll theme, #{theme.name.cyan}, " \ + "is ready for you in #{theme.path.to_s.cyan}!" + Jekyll.logger.info "For help getting started, read #{theme.path}/README.md." + end + end + end + end +end diff --git a/lib/jekyll/commands/serve.rb b/lib/jekyll/commands/serve.rb index 111d6709f7f..21bfa4d67b4 100644 --- a/lib/jekyll/commands/serve.rb +++ b/lib/jekyll/commands/serve.rb @@ -1,151 +1,372 @@ -# -*- encoding: utf-8 -*- +# frozen_string_literal: true + module Jekyll module Commands class Serve < Command + # Similar to the pattern in Utils::ThreadEvent except we are maintaining the + # state of @running instead of just signaling an event. We have to maintain this + # state since Serve is just called via class methods instead of an instance + # being created each time. + @mutex = Mutex.new + @run_cond = ConditionVariable.new + @running = false class << self + COMMAND_OPTIONS = { + "ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."], + "host" => ["host", "-H", "--host [HOST]", "Host to bind to"], + "open_url" => ["-o", "--open-url", "Launch your site in a browser"], + "detach" => ["-B", "--detach", + "Run the server in the background",], + "ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."], + "port" => ["-P", "--port [PORT]", "Port to listen on"], + "show_dir_listing" => ["--show-dir-listing", + "Show a directory listing instead of loading " \ + "your index file.",], + "skip_initial_build" => ["skip_initial_build", "--skip-initial-build", + "Skips the initial site build which occurs before " \ + "the server is started.",], + "livereload" => ["-l", "--livereload", + "Use LiveReload to automatically refresh browsers",], + "livereload_ignore" => ["--livereload-ignore GLOB1[,GLOB2[,...]]", + Array, + "Files for LiveReload to ignore. " \ + "Remember to quote the values so your shell " \ + "won't expand them",], + "livereload_min_delay" => ["--livereload-min-delay [SECONDS]", + "Minimum reload delay",], + "livereload_max_delay" => ["--livereload-max-delay [SECONDS]", + "Maximum reload delay",], + "livereload_port" => ["--livereload-port [PORT]", Integer, + "Port for LiveReload to listen on",], + }.freeze + + DIRECTORY_INDEX = %w( + index.htm + index.html + index.rhtml + index.xht + index.xhtml + index.cgi + index.xml + index.json + ).freeze + + LIVERELOAD_PORT = 35_729 + LIVERELOAD_DIR = File.join(__dir__, "serve", "livereload_assets") + + attr_reader :mutex, :run_cond, :running + alias_method :running?, :running def init_with_program(prog) - prog.command(:serve) do |c| - c.syntax 'serve [options]' - c.description 'Serve your site locally' - c.alias :server - c.alias :s - - add_build_options(c) - - c.option 'detach', '-B', '--detach', 'Run the server in the background (detach)' - c.option 'port', '-P', '--port [PORT]', 'Port to listen on' - c.option 'host', '-H', '--host [HOST]', 'Host to bind to' - c.option 'baseurl', '-b', '--baseurl [URL]', 'Base URL' - c.option 'skip_initial_build', '--skip-initial-build', 'Skips the initial site build which occurs before the server is started.' - - c.action do |args, options| - options["serving"] = true - options["watch"] = true unless options.key?("watch") - Jekyll::Commands::Build.process(options) - Jekyll::Commands::Serve.process(options) + prog.command(:serve) do |cmd| + cmd.description "Serve your site locally" + cmd.syntax "serve [options]" + cmd.alias :server + cmd.alias :s + + add_build_options(cmd) + COMMAND_OPTIONS.each do |key, val| + cmd.option key, *val + end + + cmd.action do |_, opts| + opts["serving"] = true + opts["watch"] = true unless opts.key?("watch") + + # Set the reactor to nil so any old reactor will be GCed. + # We can't unregister a hook so while running tests we don't want to + # inadvertently keep using a reactor created by a previous test. + @reload_reactor = nil + + config = configuration_from_options(opts) + config["url"] = default_url(config) if Jekyll.env == "development" + + process_with_graceful_fail(cmd, config, Build, Serve) end end end - # Boot up a WEBrick server which points to the compiled site's root. - def process(options) - options = configuration_from_options(options) - destination = options['destination'] + # + + def process(opts) + opts = configuration_from_options(opts) + destination = opts["destination"] + if opts["livereload"] + opts["livereload_port"] ||= LIVERELOAD_PORT + validate_options(opts) + register_reload_hooks(opts) + end setup(destination) - s = WEBrick::HTTPServer.new(webrick_options(options)) - s.unmount("") + start_up_webrick(opts, destination) + end - s.mount( - options['baseurl'], - custom_file_handler, - destination, - file_handler_options - ) + def shutdown + @server.shutdown if running? + end - Jekyll.logger.info "Server address:", server_address(s, options) + # Perform logical validation of CLI options - if options['detach'] # detach the server - pid = Process.fork { s.start } - Process.detach(pid) - Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server." - else # create a new server thread, then join it with current terminal - t = Thread.new { s.start } - trap("INT") { s.shutdown } - t.join + private + + def validate_options(opts) + if opts["livereload"] + if opts["detach"] + Jekyll.logger.warn "Warning:", "--detach and --livereload are mutually exclusive. " \ + "Choosing --livereload" + opts["detach"] = false + end + if opts["ssl_cert"] || opts["ssl_key"] + # This is not technically true. LiveReload works fine over SSL, but + # EventMachine's SSL support in Windows requires building the gem's + # native extensions against OpenSSL and that proved to be a process + # so tedious that expecting users to do it is a non-starter. + Jekyll.logger.abort_with "Error:", "LiveReload does not support SSL" + end + unless opts["watch"] + # Using livereload logically implies you want to watch the files + opts["watch"] = true + end + elsif %w(livereload_min_delay + livereload_max_delay + livereload_ignore + livereload_port).any? { |o| opts[o] } + Jekyll.logger.abort_with "--livereload-min-delay, --livereload-max-delay, " \ + "--livereload-ignore, and --livereload-port require " \ + "the --livereload option." + end + end + + def register_reload_hooks(opts) + require_relative "serve/live_reload_reactor" + @reload_reactor = LiveReloadReactor.new + + Jekyll::Hooks.register(:site, :post_render) do |site| + @changed_pages = [] + site.each_site_file do |item| + @changed_pages << item if site.regenerator.regenerate?(item) + end + end + + # A note on ignoring files: LiveReload errs on the side of reloading when it + # comes to the message it gets. If, for example, a page is ignored but a CSS + # file linked in the page isn't, the page will still be reloaded if the CSS + # file is contained in the message sent to LiveReload. Additionally, the + # path matching is very loose so that a message to reload "/" will always + # lead the page to reload since every page starts with "/". + Jekyll::Hooks.register(:site, :post_write) do + if @changed_pages && @reload_reactor && @reload_reactor.running? + ignore, @changed_pages = @changed_pages.partition do |p| + Array(opts["livereload_ignore"]).any? do |filter| + File.fnmatch(filter, p.relative_path) + end + end + Jekyll.logger.debug "LiveReload:", "Ignoring #{ignore.map(&:relative_path)}" + @reload_reactor.reload(@changed_pages) + end + @changed_pages = nil end end + # Do a base pre-setup of WEBRick so that everything is in place + # when we get ready to party, checking for an setting up an error page + # and making sure our destination exists. + # + # rubocop:disable Security/IoMethods def setup(destination) - require 'webrick' + require_relative "serve/servlet" FileUtils.mkdir_p(destination) - - # monkey patch WEBrick using custom 404 page (/404.html) - if File.exist?(File.join(destination, '404.html')) + if File.exist?(File.join(destination, "404.html")) WEBrick::HTTPResponse.class_eval do def create_error_page - @header['content-type'] = "text/html; charset=UTF-8" - @body = IO.read(File.join(@config[:DocumentRoot], '404.html')) + @header["Content-Type"] = "text/html; charset=UTF-8" + @body = IO.read(File.join(@config[:DocumentRoot], "404.html")) end end end end + # rubocop:enable Security/IoMethods - def webrick_options(config) + def webrick_opts(opts) opts = { - :BindAddress => config['host'], - :DirectoryIndex => %w(index.html index.htm index.cgi index.rhtml index.xml), - :DocumentRoot => config['destination'], + :JekyllOptions => opts, :DoNotReverseLookup => true, :MimeTypes => mime_types, - :Port => config['port'], - :StartCallback => start_callback(config['detach']) + :MimeTypesCharset => mime_types_charset, + :DocumentRoot => opts["destination"], + :StartCallback => start_callback(opts["detach"]), + :StopCallback => stop_callback(opts["detach"]), + :BindAddress => opts["host"], + :Port => opts["port"], + :DirectoryIndex => DIRECTORY_INDEX, } - if config['verbose'] - opts.merge!({ - :Logger => WEBrick::Log.new($stdout, WEBrick::Log::DEBUG) - }) + opts[:DirectoryIndex] = [] if opts[:JekyllOptions]["show_dir_listing"] + + enable_ssl(opts) + enable_logging(opts) + opts + end + + def start_up_webrick(opts, destination) + @reload_reactor.start(opts) if opts["livereload"] + + @server = WEBrick::HTTPServer.new(webrick_opts(opts)).tap { |o| o.unmount("") } + @server.mount(opts["baseurl"].to_s, Servlet, destination, file_handler_opts) + + Jekyll.logger.info "Server address:", server_address(@server, opts) + launch_browser @server, opts if opts["open_url"] + boot_or_detach @server, opts + end + + # Recreate NondisclosureName under utf-8 circumstance + def file_handler_opts + WEBrick::Config::FileHandler.merge( + :FancyIndexing => true, + :NondisclosureName => [ + ".ht*", "~*", + ] + ) + end + + def server_address(server, options = {}) + format_url( + server.config[:SSLEnable], + server.config[:BindAddress], + server.config[:Port], + options["baseurl"] + ) + end + + def format_url(ssl_enabled, address, port, baseurl = nil) + format("%s://%
    s:%i%s", + :prefix => ssl_enabled ? "https" : "http", + :address => address.include?(":") ? "[#{address}]" : address, + :port => port, + :baseurl => baseurl ? "#{baseurl}/" : "") + end + + def default_url(opts) + config = configuration_from_options(opts) + format_url( + config["ssl_cert"] && config["ssl_key"], + config["host"] == "127.0.0.1" ? "localhost" : config["host"], + config["port"] + ) + end + + def launch_browser(server, opts) + address = server_address(server, opts) + return system "start", address if Utils::Platforms.windows? + return system "xdg-open", address if Utils::Platforms.linux? + return system "open", address if Utils::Platforms.osx? + + Jekyll.logger.error "Refusing to launch browser. Platform launcher unknown." + end + + # Keep in our area with a thread or detach the server as requested + # by the user. This method determines what we do based on what you + # ask us to do. + def boot_or_detach(server, opts) + if opts["detach"] + pid = Process.fork do + # Detach the process from controlling terminal + $stdin.reopen("/dev/null", "r") + $stdout.reopen("/dev/null", "w") + $stderr.reopen("/dev/null", "w") + server.start + end + + Process.detach(pid) + Jekyll.logger.info "Server detached with pid '#{pid}'.", + "Run `pkill -f jekyll' or `kill -9 #{pid}' to stop the server." + + # Exit without running `at_exit` inherited by the forked process. + Process.exit! 0 else - opts.merge!({ - :AccessLog => [], - :Logger => WEBrick::Log.new([], WEBrick::Log::WARN) - }) + t = Thread.new { server.start } + trap("INT") { server.shutdown } + t.join end + end - opts + # Make the stack verbose if the user requests it. + def enable_logging(opts) + opts[:AccessLog] = [] + level = WEBrick::Log.const_get(opts[:JekyllOptions]["verbose"] ? :DEBUG : :WARN) + opts[:Logger] = WEBrick::Log.new($stdout, level) end - # Custom WEBrick FileHandler servlet for serving "/file.html" at "/file" - # when no exact match is found. This mirrors the behavior of GitHub - # Pages and many static web server configs. - def custom_file_handler - Class.new WEBrick::HTTPServlet::FileHandler do - def search_file(req, res, basename) - if file = super - file - else - super(req, res, "#{basename}.html") - end + # Add SSL to the stack if the user triggers --enable-ssl and they + # provide both types of certificates commonly needed. Raise if they + # forget to add one of the certificates. + def enable_ssl(opts) + cert, key, src = + opts[:JekyllOptions].values_at("ssl_cert", "ssl_key", "source") + + return if cert.nil? && key.nil? + raise "Missing --ssl_cert or --ssl_key. Both are required." unless cert && key + + require "openssl" + require "webrick/https" + + opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(read_file(src, cert)) + begin + opts[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(read_file(src, key)) + rescue StandardError + if defined?(OpenSSL::PKey::EC) + opts[:SSLPrivateKey] = OpenSSL::PKey::EC.new(read_file(src, key)) + else + raise end end + opts[:SSLEnable] = true end def start_callback(detached) unless detached - Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." } + proc do + mutex.synchronize do + # Block until EventMachine reactor starts + @reload_reactor&.started_event&.wait + @running = true + Jekyll.logger.info("Server running...", "press ctrl-c to stop.") + @run_cond.broadcast + end + end end end - def mime_types - mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__)) - WEBrick::HTTPUtils::load_mime_types(mime_types_file) + def stop_callback(detached) + unless detached + proc do + mutex.synchronize do + unless @reload_reactor.nil? + @reload_reactor.stop + @reload_reactor.stopped_event.wait + end + @running = false + @run_cond.broadcast + end + end + end end - def server_address(server, options) - baseurl = "#{options['baseurl']}/" if options['baseurl'] - [ - "http://", - server.config[:BindAddress], - ":", - server.config[:Port], - baseurl || "" - ].map(&:to_s).join("") + def mime_types + file = File.expand_path("../mime.types", __dir__) + WEBrick::HTTPUtils.load_mime_types(file) end - # recreate NondisclosureName under utf-8 circumstance - def file_handler_options - WEBrick::Config::FileHandler.merge({ - :FancyIndexing => true, - :NondisclosureName => ['.ht*','~*'] - }) + def mime_types_charset + SafeYAML.load_file(File.expand_path("serve/mime_types_charset.json", __dir__)) end + def read_file(source_dir, file_path) + File.read(Jekyll.sanitized_path(source_dir, file_path)) + end end - end end end diff --git a/lib/jekyll/commands/serve/live_reload_reactor.rb b/lib/jekyll/commands/serve/live_reload_reactor.rb new file mode 100644 index 00000000000..30e88812638 --- /dev/null +++ b/lib/jekyll/commands/serve/live_reload_reactor.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true + +require "em-websocket" + +require_relative "websockets" + +module Jekyll + module Commands + class Serve + class LiveReloadReactor + attr_reader :started_event, :stopped_event, :thread + + def initialize + @websockets = [] + @connections_count = 0 + @started_event = Utils::ThreadEvent.new + @stopped_event = Utils::ThreadEvent.new + end + + def stop + # There is only one EventMachine instance per Ruby process so stopping + # it here will stop the reactor thread we have running. + EM.stop if EM.reactor_running? + Jekyll.logger.debug "LiveReload Server:", "halted" + end + + def running? + EM.reactor_running? + end + + def handle_websockets_event(websocket) + websocket.onopen { |handshake| connect(websocket, handshake) } + websocket.onclose { disconnect(websocket) } + websocket.onmessage { |msg| print_message(msg) } + websocket.onerror { |error| log_error(error) } + end + + def start(opts) + @thread = Thread.new do + # Use epoll if the kernel supports it + EM.epoll + EM.run do + EM.error_handler { |e| log_error(e) } + + EM.start_server( + opts["host"], + opts["livereload_port"], + HttpAwareConnection, + opts + ) do |ws| + handle_websockets_event(ws) + end + + # Notify blocked threads that EventMachine has started or shutdown + EM.schedule { @started_event.set } + EM.add_shutdown_hook { @stopped_event.set } + + host = opts["host"].include?(":") ? "[#{opts["host"]}]" : opts["host"] + Jekyll.logger.info "LiveReload address:", + "http://#{host}:#{opts["livereload_port"]}" + end + end + @thread.abort_on_exception = true + end + + # For a description of the protocol see + # http://feedback.livereload.com/knowledgebase/articles/86174-livereload-protocol + def reload(pages) + pages.each do |p| + json_message = JSON.dump( + :command => "reload", + :path => p.url, + :liveCSS => true + ) + + Jekyll.logger.debug "LiveReload:", "Reloading URL #{p.url.inspect}" + @websockets.each { |ws| ws.send(json_message) } + end + end + + private + + def connect(websocket, handshake) + @connections_count += 1 + if @connections_count == 1 + message = "Browser connected" + message += " over SSL/TLS" if handshake.secure? + Jekyll.logger.info "LiveReload:", message + end + websocket.send( + JSON.dump( + :command => "hello", + :protocols => ["http://livereload.com/protocols/official-7"], + :serverName => "jekyll" + ) + ) + + @websockets << websocket + end + + def disconnect(websocket) + @websockets.delete(websocket) + end + + def print_message(json_message) + msg = JSON.parse(json_message) + # Not sure what the 'url' command even does in LiveReload. The spec is silent + # on its purpose. + Jekyll.logger.info "LiveReload:", "Browser URL: #{msg["url"]}" if msg["command"] == "url" + end + + def log_error(error) + Jekyll.logger.error "LiveReload experienced an error. " \ + "Run with --trace for more information." + raise error + end + end + end + end +end diff --git a/lib/jekyll/commands/serve/livereload_assets/livereload.js b/lib/jekyll/commands/serve/livereload_assets/livereload.js new file mode 100644 index 00000000000..eee60ec8b1d --- /dev/null +++ b/lib/jekyll/commands/serve/livereload_assets/livereload.js @@ -0,0 +1,1183 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o tag"); + return; + } + } + this.reloader = new Reloader(this.window, this.console, Timer); + this.connector = new Connector(this.options, this.WebSocket, Timer, { + connecting: (function(_this) { + return function() {}; + })(this), + socketConnected: (function(_this) { + return function() {}; + })(this), + connected: (function(_this) { + return function(protocol) { + var _base; + if (typeof (_base = _this.listeners).connect === "function") { + _base.connect(); + } + _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ")."); + return _this.analyze(); + }; + })(this), + error: (function(_this) { + return function(e) { + if (e instanceof ProtocolError) { + if (typeof console !== "undefined" && console !== null) { + return console.log("" + e.message + "."); + } + } else { + if (typeof console !== "undefined" && console !== null) { + return console.log("LiveReload internal error: " + e.message); + } + } + }; + })(this), + disconnected: (function(_this) { + return function(reason, nextDelay) { + var _base; + if (typeof (_base = _this.listeners).disconnect === "function") { + _base.disconnect(); + } + switch (reason) { + case 'cannot-connect': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec."); + case 'broken': + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec."); + case 'handshake-timeout': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec."); + case 'handshake-failed': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec."); + case 'manual': + break; + case 'error': + break; + default: + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec."); + } + }; + })(this), + message: (function(_this) { + return function(message) { + switch (message.command) { + case 'reload': + return _this.performReload(message); + case 'alert': + return _this.performAlert(message); + } + }; + })(this) + }); + this.initialized = true; + } + + LiveReload.prototype.on = function(eventName, handler) { + return this.listeners[eventName] = handler; + }; + + LiveReload.prototype.log = function(message) { + return this.console.log("" + message); + }; + + LiveReload.prototype.performReload = function(message) { + var _ref, _ref1; + this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2))); + return this.reloader.reload(message.path, { + liveCSS: (_ref = message.liveCSS) != null ? _ref : true, + liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true, + originalPath: message.originalPath || '', + overrideURL: message.overrideURL || '', + serverURL: "http://" + this.options.host + ":" + this.options.port + }); + }; + + LiveReload.prototype.performAlert = function(message) { + return alert(message.message); + }; + + LiveReload.prototype.shutDown = function() { + var _base; + if (!this.initialized) { + return; + } + this.connector.disconnect(); + this.log("LiveReload disconnected."); + return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0; + }; + + LiveReload.prototype.hasPlugin = function(identifier) { + return !!this.pluginIdentifiers[identifier]; + }; + + LiveReload.prototype.addPlugin = function(pluginClass) { + var plugin; + if (!this.initialized) { + return; + } + if (this.hasPlugin(pluginClass.identifier)) { + return; + } + this.pluginIdentifiers[pluginClass.identifier] = true; + plugin = new pluginClass(this.window, { + _livereload: this, + _reloader: this.reloader, + _connector: this.connector, + console: this.console, + Timer: Timer, + generateCacheBustUrl: (function(_this) { + return function(url) { + return _this.reloader.generateCacheBustUrl(url); + }; + })(this) + }); + this.plugins.push(plugin); + this.reloader.addPlugin(plugin); + }; + + LiveReload.prototype.analyze = function() { + var plugin, pluginData, pluginsData, _i, _len, _ref; + if (!this.initialized) { + return; + } + if (!(this.connector.protocol >= 7)) { + return; + } + pluginsData = {}; + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {}; + pluginData.version = plugin.constructor.version; + } + this.connector.sendCommand({ + command: 'info', + plugins: pluginsData, + url: this.window.location.href + }); + }; + + return LiveReload; + + })(); + +}).call(this); + +},{"./connector":1,"./options":5,"./reloader":7,"./timer":9}],5:[function(require,module,exports){ +(function() { + var Options; + + exports.Options = Options = (function() { + function Options() { + this.https = false; + this.host = null; + this.port = 35729; + this.snipver = null; + this.ext = null; + this.extver = null; + this.mindelay = 1000; + this.maxdelay = 60000; + this.handshake_timeout = 5000; + } + + Options.prototype.set = function(name, value) { + if (typeof value === 'undefined') { + return; + } + if (!isNaN(+value)) { + value = +value; + } + return this[name] = value; + }; + + return Options; + + })(); + + Options.extract = function(document) { + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1; + _ref = document.getElementsByTagName('script'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { + options = new Options(); + options.https = src.indexOf("https") === 0; + if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { + options.host = mm[1]; + if (mm[2]) { + options.port = parseInt(mm[2], 10); + } + } + if (m[2]) { + _ref1 = m[2].split('&'); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + pair = _ref1[_j]; + if ((keyAndValue = pair.split('=')).length > 1) { + options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); + } + } + } + return options; + } + } + return null; + }; + +}).call(this); + +},{}],6:[function(require,module,exports){ +(function() { + var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + exports.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; + + exports.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; + + exports.ProtocolError = ProtocolError = (function() { + function ProtocolError(reason, data) { + this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; + } + + return ProtocolError; + + })(); + + exports.Parser = Parser = (function() { + function Parser(handlers) { + this.handlers = handlers; + this.reset(); + } + + Parser.prototype.reset = function() { + return this.protocol = null; + }; + + Parser.prototype.process = function(data) { + var command, e, message, options, _ref; + try { + if (this.protocol == null) { + if (data.match(/^!!ver:([\d.]+)$/)) { + this.protocol = 6; + } else if (message = this._parseMessage(data, ['hello'])) { + if (!message.protocols.length) { + throw new ProtocolError("no protocols specified in handshake message"); + } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { + this.protocol = 7; + } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { + this.protocol = 6; + } else { + throw new ProtocolError("no supported protocols found"); + } + } + return this.handlers.connected(this.protocol); + } else if (this.protocol === 6) { + message = JSON.parse(data); + if (!message.length) { + throw new ProtocolError("protocol 6 messages must be arrays"); + } + command = message[0], options = message[1]; + if (command !== 'refresh') { + throw new ProtocolError("unknown protocol 6 command"); + } + return this.handlers.message({ + command: 'reload', + path: options.path, + liveCSS: (_ref = options.apply_css_live) != null ? _ref : true + }); + } else { + message = this._parseMessage(data, ['reload', 'alert']); + return this.handlers.message(message); + } + } catch (_error) { + e = _error; + if (e instanceof ProtocolError) { + return this.handlers.error(e); + } else { + throw e; + } + } + }; + + Parser.prototype._parseMessage = function(data, validCommands) { + var e, message, _ref; + try { + message = JSON.parse(data); + } catch (_error) { + e = _error; + throw new ProtocolError('unparsable JSON', data); + } + if (!message.command) { + throw new ProtocolError('missing "command" key', data); + } + if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { + throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); + } + return message; + }; + + return Parser; + + })(); + +}).call(this); + +},{}],7:[function(require,module,exports){ +(function() { + var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + + splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash + }; + }; + + pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); + }; + + pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 + }; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; + } + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } + }; + + numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; + }; + + pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; + }; + + IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } + ]; + + exports.Reloader = Reloader = (function() { + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } + + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; + + Reloader.prototype.analyze = function(callback) { + return results; + }; + + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; + } + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { + return; + } + } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; + } + } + return this.reloadPage(); + }; + + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; + + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); + } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); + } + } + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); + } + return _results; + } + }; + + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var e, rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); + } + } + }; + + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, (function(_this) { + return function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; + } + }; + })(this)); + if (newValue !== value) { + style[styleName] = newValue; + } + } + } + }; + + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.rel.match(/^stylesheet$/i) && !link.__LiveReload_pendingRemoval) { + _results.push(link); + } + } + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); + } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); + } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), (function(_this) { + return function(l) { + return pathFromUrl(_this.linkHref(l)); + }; + })(this)); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); + } else { + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); + } + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); + } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var e, index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; + } + } + } + }; + + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll; + callbackExecuted = false; + executeCallback = (function(_this) { + return function() { + if (callbackExecuted) { + return; + } + callbackExecuted = true; + return func(); + }; + })(this); + clone.onload = (function(_this) { + return function() { + _this.console.log("LiveReload: the new stylesheet has finished loading"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); + }; + })(this); + if (!this.knownToSupportCssOnLoad) { + (poll = (function(_this) { + return function() { + if (clone.sheet) { + _this.console.log("LiveReload is polling until the new CSS finishes loading..."); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + }; + })(this))(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; + + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, (function(_this) { + return function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; + } else { + additionalWaitingTime = 200; + } + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; + } + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; + }); + }; + })(this)); + }; + + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, (function(_this) { + return function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); + } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + return parent.deleteRule(index + 1); + }); + }; + })(this)); + }; + + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; + + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, originalUrl, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + originalUrl = url; + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); + this.console.log("LiveReload is overriding source URL " + originalUrl + " with " + url); + } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; + } + } + return url + params + hash; + }; + + return Reloader; + + })(); + +}).call(this); + +},{}],8:[function(require,module,exports){ +(function() { + var CustomEvents, LiveReload, k; + + CustomEvents = require('./customevents'); + + LiveReload = window.LiveReload = new (require('./livereload').LiveReload)(window); + + for (k in window) { + if (k.match(/^LiveReloadPlugin/)) { + LiveReload.addPlugin(window[k]); + } + } + + LiveReload.addPlugin(require('./less')); + + LiveReload.on('shutdown', function() { + return delete window.LiveReload; + }); + + LiveReload.on('connect', function() { + return CustomEvents.fire(document, 'LiveReloadConnect'); + }); + + LiveReload.on('disconnect', function() { + return CustomEvents.fire(document, 'LiveReloadDisconnect'); + }); + + CustomEvents.bind(document, 'LiveReloadShutDown', function() { + return LiveReload.shutDown(); + }); + +}).call(this); + +},{"./customevents":2,"./less":3,"./livereload":4}],9:[function(require,module,exports){ +(function() { + var Timer; + + exports.Timer = Timer = (function() { + function Timer(func) { + this.func = func; + this.running = false; + this.id = null; + this._handler = (function(_this) { + return function() { + _this.running = false; + _this.id = null; + return _this.func(); + }; + })(this); + } + + Timer.prototype.start = function(timeout) { + if (this.running) { + clearTimeout(this.id); + } + this.id = setTimeout(this._handler, timeout); + return this.running = true; + }; + + Timer.prototype.stop = function() { + if (this.running) { + clearTimeout(this.id); + this.running = false; + return this.id = null; + } + }; + + return Timer; + + })(); + + Timer.start = function(timeout, func) { + return setTimeout(func, timeout); + }; + +}).call(this); + +},{}]},{},[8]); diff --git a/lib/jekyll/commands/serve/mime_types_charset.json b/lib/jekyll/commands/serve/mime_types_charset.json new file mode 100644 index 00000000000..017469b9ccd --- /dev/null +++ b/lib/jekyll/commands/serve/mime_types_charset.json @@ -0,0 +1,71 @@ +{ + "application/javascript": "UTF-8", + "application/json": "UTF-8", + "application/manifest+json": "UTF-8", + "application/vnd.syncml+xml": "UTF-8", + "application/vnd.syncml.dm+wbxml": "UTF-8", + "application/vnd.syncml.dm+xml": "UTF-8", + "application/vnd.syncml.dmddf+xml": "UTF-8", + "application/vnd.wap.wbxml": "UTF-8", + "text/cache-manifest": "UTF-8", + "text/calendar": "UTF-8", + "text/coffeescript": "UTF-8", + "text/css": "UTF-8", + "text/csv": "UTF-8", + "text/html": "UTF-8", + "text/jade": "UTF-8", + "text/jsx": "UTF-8", + "text/less": "UTF-8", + "text/markdown": "UTF-8", + "text/mathml": "UTF-8", + "text/mdx": "UTF-8", + "text/n3": "UTF-8", + "text/plain": "UTF-8", + "text/prs.lines.tag": "UTF-8", + "text/richtext": "UTF-8", + "text/sgml": "UTF-8", + "text/shex": "UTF-8", + "text/slim": "UTF-8", + "text/spdx": "UTF-8", + "text/stylus": "UTF-8", + "text/tab-separated-values": "UTF-8", + "text/troff": "UTF-8", + "text/turtle": "UTF-8", + "text/uri-list": "UTF-8", + "text/vcard": "UTF-8", + "text/vnd.curl": "UTF-8", + "text/vnd.curl.dcurl": "UTF-8", + "text/vnd.curl.mcurl": "UTF-8", + "text/vnd.curl.scurl": "UTF-8", + "text/vnd.familysearch.gedcom": "UTF-8", + "text/vnd.fly": "UTF-8", + "text/vnd.fmi.flexstor": "UTF-8", + "text/vnd.graphviz": "UTF-8", + "text/vnd.in3d.3dml": "UTF-8", + "text/vnd.in3d.spot": "UTF-8", + "text/vnd.sun.j2me.app-descriptor": "UTF-8", + "text/vnd.wap.wml": "UTF-8", + "text/vnd.wap.wmlscript": "UTF-8", + "text/vtt": "UTF-8", + "text/x-asm": "UTF-8", + "text/x-c": "UTF-8", + "text/x-component": "UTF-8", + "text/x-fortran": "UTF-8", + "text/x-handlebars-template": "UTF-8", + "text/x-java-source": "UTF-8", + "text/x-lua": "UTF-8", + "text/x-markdown": "UTF-8", + "text/x-nfo": "UTF-8", + "text/x-opml": "UTF-8", + "text/x-pascal": "UTF-8", + "text/x-processing": "UTF-8", + "text/x-sass": "UTF-8", + "text/x-scss": "UTF-8", + "text/x-setext": "UTF-8", + "text/x-sfv": "UTF-8", + "text/x-suse-ymp": "UTF-8", + "text/x-uuencode": "UTF-8", + "text/x-vcalendar": "UTF-8", + "text/x-vcard": "UTF-8", + "text/yaml": "UTF-8" +} diff --git a/lib/jekyll/commands/serve/servlet.rb b/lib/jekyll/commands/serve/servlet.rb new file mode 100644 index 00000000000..8ef84d149d7 --- /dev/null +++ b/lib/jekyll/commands/serve/servlet.rb @@ -0,0 +1,204 @@ +# frozen_string_literal: true + +require "webrick" + +module Jekyll + module Commands + class Serve + # This class is used to determine if the Servlet should modify a served file + # to insert the LiveReload script tags + class SkipAnalyzer + BAD_USER_AGENTS = [%r!MSIE!].freeze + + def self.skip_processing?(request, response, options) + new(request, response, options).skip_processing? + end + + def initialize(request, response, options) + @options = options + @request = request + @response = response + end + + def skip_processing? + !html? || chunked? || inline? || bad_browser? + end + + def chunked? + @response["Transfer-Encoding"] == "chunked" + end + + def inline? + @response["Content-Disposition"].to_s.start_with?("inline") + end + + def bad_browser? + BAD_USER_AGENTS.any? { |pattern| pattern.match?(@request["User-Agent"]) } + end + + def html? + @response["Content-Type"].to_s.include?("text/html") + end + end + + # This class inserts the LiveReload script tags into HTML as it is served + class BodyProcessor + HEAD_TAG_REGEX = %r!|!.freeze + + attr_reader :content_length, :new_body, :livereload_added + + def initialize(body, options) + @body = body + @options = options + @processed = false + end + + def processed? + @processed + end + + # rubocop:disable Metrics/MethodLength + def process! + @new_body = [] + # @body will usually be a File object but Strings occur in rare cases + if @body.respond_to?(:each) + begin + @body.each { |line| @new_body << line.to_s } + ensure + @body.close + end + else + @new_body = @body.lines + end + + @content_length = 0 + @livereload_added = false + + @new_body.each do |line| + if !@livereload_added && line[" + document.write( + ' + TEMPLATE + end + + def livereload_args + # XHTML standard requires ampersands to be encoded as entities when in + # attributes. See http://stackoverflow.com/a/2190292 + src = "" + if @options["livereload_min_delay"] + src += "&mindelay=#{@options["livereload_min_delay"]}" + end + if @options["livereload_max_delay"] + src += "&maxdelay=#{@options["livereload_max_delay"]}" + end + src += "&port=#{@options["livereload_port"]}" if @options["livereload_port"] + src + end + end + + class Servlet < WEBrick::HTTPServlet::FileHandler + DEFAULTS = { + "Cache-Control" => "private, max-age=0, proxy-revalidate, " \ + "no-store, no-cache, must-revalidate", + }.freeze + + def initialize(server, root, callbacks) + # So we can access them easily. + @jekyll_opts = server.config[:JekyllOptions] + @mime_types_charset = server.config[:MimeTypesCharset] + set_defaults + super + end + + def search_index_file(req, res) + super || + search_file(req, res, ".html") || + search_file(req, res, ".xhtml") + end + + # Add the ability to tap file.html the same way that Nginx does on our + # Docker images (or on GitHub Pages.) The difference is that we might end + # up with a different preference on which comes first. + + def search_file(req, res, basename) + # /file.* > /file/index.html > /file.html + super || + super(req, res, "#{basename}.html") || + super(req, res, "#{basename}.xhtml") + end + + # rubocop:disable Naming/MethodName + def do_GET(req, res) + rtn = super + + if @jekyll_opts["livereload"] && !SkipAnalyzer.skip_processing?(req, res, @jekyll_opts) + processor = BodyProcessor.new(res.body, @jekyll_opts) + processor.process! + res.body = processor.new_body + res.content_length = processor.content_length.to_s + + if processor.livereload_added + # Add a header to indicate that the page content has been modified + res["X-Rack-LiveReload"] = "1" + end + end + + conditionally_inject_charset(res) + res.header.merge!(@headers) + rtn + end + # rubocop:enable Naming/MethodName + + private + + # Inject charset based on Jekyll config only if our mime-types database contains + # the charset metadata. + # + # Refer `script/vendor-mimes` in the repository for further details. + def conditionally_inject_charset(res) + typ = res.header["content-type"] + return unless @mime_types_charset.key?(typ) + return if %r!;\s*charset=!.match?(typ) + + res.header["content-type"] = "#{typ}; charset=#{@jekyll_opts["encoding"]}" + end + + def set_defaults + hash_ = @jekyll_opts.fetch("webrick", {}).fetch("headers", {}) + DEFAULTS.each_with_object(@headers = hash_) do |(key, val), hash| + hash[key] = val unless hash.key?(key) + end + end + end + end + end +end diff --git a/lib/jekyll/commands/serve/websockets.rb b/lib/jekyll/commands/serve/websockets.rb new file mode 100644 index 00000000000..6aa522cc96b --- /dev/null +++ b/lib/jekyll/commands/serve/websockets.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +require "http/parser" + +module Jekyll + module Commands + class Serve + # The LiveReload protocol requires the server to serve livereload.js over HTTP + # despite the fact that the protocol itself uses WebSockets. This custom connection + # class addresses the dual protocols that the server needs to understand. + class HttpAwareConnection < EventMachine::WebSocket::Connection + attr_reader :reload_body, :reload_size + + def initialize(_opts) + # If EventMachine SSL support on Windows ever gets better, the code below will + # set up the reactor to handle SSL + # + # @ssl_enabled = opts["ssl_cert"] && opts["ssl_key"] + # if @ssl_enabled + # em_opts[:tls_options] = { + # :private_key_file => Jekyll.sanitized_path(opts["source"], opts["ssl_key"]), + # :cert_chain_file => Jekyll.sanitized_path(opts["source"], opts["ssl_cert"]) + # } + # em_opts[:secure] = true + # end + + # This is too noisy even for --verbose, but uncomment if you need it for + # a specific WebSockets issue. Adding ?LR-verbose=true onto the URL will + # enable logging on the client side. + # em_opts[:debug] = true + + em_opts = {} + super(em_opts) + + reload_file = File.join(Serve.singleton_class::LIVERELOAD_DIR, "livereload.js") + + @reload_body = File.read(reload_file) + @reload_size = @reload_body.bytesize + end + + # rubocop:disable Metrics/MethodLength + def dispatch(data) + parser = Http::Parser.new + parser << data + + # WebSockets requests will have a Connection: Upgrade header + if parser.http_method != "GET" || parser.upgrade? + super + elsif parser.request_url.start_with?("/livereload.js") + headers = [ + "HTTP/1.1 200 OK", + "Content-Type: application/javascript", + "Content-Length: #{reload_size}", + "", + "", + ].join("\r\n") + send_data(headers) + + # stream_file_data would free us from keeping livereload.js in memory + # but JRuby blocks on that call and never returns + send_data(reload_body) + close_connection_after_writing + else + body = "This port only serves livereload.js over HTTP.\n" + headers = [ + "HTTP/1.1 400 Bad Request", + "Content-Type: text/plain", + "Content-Length: #{body.bytesize}", + "", + "", + ].join("\r\n") + send_data(headers) + send_data(body) + close_connection_after_writing + end + end + # rubocop:enable Metrics/MethodLength + end + end + end +end diff --git a/lib/jekyll/configuration.rb b/lib/jekyll/configuration.rb index f57b3ae4853..9f3d2fa730b 100644 --- a/lib/jekyll/configuration.rb +++ b/lib/jekyll/configuration.rb @@ -1,92 +1,100 @@ -# encoding: UTF-8 +# frozen_string_literal: true module Jekyll class Configuration < Hash - # Default options. Overridden by values in _config.yml. # Strings rather than symbols are used for compatibility with YAML. - DEFAULTS = Configuration[{ + DEFAULTS = { # Where things are - 'source' => Dir.pwd, - 'destination' => File.join(Dir.pwd, '_site'), - 'plugins_dir' => '_plugins', - 'layouts_dir' => '_layouts', - 'data_dir' => '_data', - 'includes_dir' => '_includes', - 'collections' => {}, + "source" => Dir.pwd, + "destination" => File.join(Dir.pwd, "_site"), + "collections_dir" => "", + "cache_dir" => ".jekyll-cache", + "plugins_dir" => "_plugins", + "layouts_dir" => "_layouts", + "data_dir" => "_data", + "includes_dir" => "_includes", + "collections" => {}, # Handling Reading - 'safe' => false, - 'include' => ['.htaccess'], - 'exclude' => [], - 'keep_files' => ['.git','.svn'], - 'encoding' => 'utf-8', - 'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md', + "safe" => false, + "include" => [".htaccess"], + "exclude" => [], + "keep_files" => [".git", ".svn"], + "encoding" => "utf-8", + "markdown_ext" => "markdown,mkdown,mkdn,mkd,md", + "strict_front_matter" => false, # Filtering Content - 'show_drafts' => nil, - 'limit_posts' => 0, - 'future' => false, - 'unpublished' => false, + "show_drafts" => nil, + "limit_posts" => 0, + "future" => false, + "unpublished" => false, # Plugins - 'whitelist' => [], - 'gems' => [], + "whitelist" => [], + "plugins" => [], # Conversion - 'markdown' => 'kramdown', - 'highlighter' => 'rouge', - 'lsi' => false, - 'excerpt_separator' => "\n\n", - 'incremental' => false, + "markdown" => "kramdown", + "highlighter" => "rouge", + "lsi" => false, + "excerpt_separator" => "\n\n", + "incremental" => false, # Serving - 'detach' => false, # default to not detaching the server - 'port' => '4000', - 'host' => '127.0.0.1', - 'baseurl' => '', + "detach" => false, # default to not detaching the server + "port" => "4000", + "host" => "127.0.0.1", + "baseurl" => nil, # this mounts at /, i.e. no subdirectory + "show_dir_listing" => false, # Output Configuration - 'permalink' => 'date', - 'paginate_path' => '/page:num', - 'timezone' => nil, # use the local timezone - - 'quiet' => false, - 'verbose' => false, - 'defaults' => [], - - 'rdiscount' => { - 'extensions' => [] + "permalink" => "date", + "paginate_path" => "/page:num", + "timezone" => nil, # use the local timezone + + "quiet" => false, + "verbose" => false, + "defaults" => [], + + "liquid" => { + "error_mode" => "warn", + "strict_filters" => false, + "strict_variables" => false, }, - 'redcarpet' => { - 'extensions' => [] + "kramdown" => { + "auto_ids" => true, + "toc_levels" => (1..6).to_a, + "entity_output" => "as_char", + "smart_quotes" => "lsquo,rsquo,ldquo,rdquo", + "input" => "GFM", + "hard_wrap" => false, + "guess_lang" => true, + "footnote_nr" => 1, + "show_warnings" => false, }, - - 'kramdown' => { - 'auto_ids' => true, - 'footnote_nr' => 1, - 'entity_output' => 'as_char', - 'toc_levels' => '1..6', - 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo', - 'enable_coderay' => false, - - 'coderay' => { - 'coderay_wrap' => 'div', - 'coderay_line_numbers' => 'inline', - 'coderay_line_number_start' => 1, - 'coderay_tab_width' => 4, - 'coderay_bold_every' => 10, - 'coderay_css' => 'style' - } - } - }] + }.each_with_object(Configuration.new) { |(k, v), hsh| hsh[k] = v.freeze }.freeze + + class << self + # Static: Produce a Configuration ready for use in a Site. + # It takes the input, fills in the defaults where values do not exist. + # + # user_config - a Hash or Configuration of overrides. + # + # Returns a Configuration filled with defaults. + def from(user_config) + Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys) + .add_default_collections.add_default_excludes + end + end # Public: Turn all keys into string # # Return a copy of the hash where all its keys are strings def stringify_keys - reduce({}) { |hsh,(k,v)| hsh.merge(k.to_s => v) } + each_with_object({}) { |(k, v), hsh| hsh[k.to_s] = v } end def get_config_value_with_override(config_key, override) @@ -99,28 +107,29 @@ def get_config_value_with_override(config_key, override) # # Returns the path to the Jekyll source directory def source(override) - get_config_value_with_override('source', override) + get_config_value_with_override("source", override) end def quiet(override = {}) - get_config_value_with_override('quiet', override) + get_config_value_with_override("quiet", override) end alias_method :quiet?, :quiet def verbose(override = {}) - get_config_value_with_override('verbose', override) + get_config_value_with_override("verbose", override) end alias_method :verbose?, :verbose def safe_load_file(filename) case File.extname(filename) - when /\.toml/i - Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML) - TOML.load_file(filename) - when /\.ya?ml/i - SafeYAML.load_file(filename) + when %r!\.toml!i + Jekyll::External.require_with_graceful_fail("tomlrb") unless defined?(Tomlrb) + Tomlrb.load_file(filename) + when %r!\.ya?ml!i + SafeYAML.load_file(filename) || {} else - raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead." + raise ArgumentError, + "No parser for '#{filename}' is available. Use a .y(a)ml or .toml file instead." end end @@ -131,19 +140,21 @@ def safe_load_file(filename) # Returns an Array of config files def config_files(override) # Adjust verbosity quickly - Jekyll.logger.adjust_verbosity(:quiet => quiet?(override), :verbose => verbose?(override)) + Jekyll.logger.adjust_verbosity( + :quiet => quiet?(override), + :verbose => verbose?(override) + ) # Get configuration from /_config.yml or / - config_files = override.delete('config') + config_files = override["config"] if config_files.to_s.empty? - default = %w[yml yaml].find(Proc.new { 'yml' }) do |ext| + default = %w(yml yaml toml).find(-> { "yml" }) do |ext| File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}")) end config_files = Jekyll.sanitized_path(source(override), "_config.#{default}") @default_config_file = true end - config_files = [config_files] unless config_files.is_a? Array - config_files + Array(config_files) end # Public: Read configuration and return merged Hash @@ -152,12 +163,17 @@ def config_files(override) # # Returns this configuration, overridden by the values in the file def read_config_file(file) + file = File.expand_path(file) next_config = safe_load_file(file) - raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow) unless next_config.is_a?(Hash) + + unless next_config.is_a?(Hash) + raise ArgumentError, "Configuration file: (INVALID) #{file}".yellow + end + Jekyll.logger.info "Configuration file:", file next_config rescue SystemCallError - if @default_config_file + if @default_config_file ||= nil Jekyll.logger.warn "Configuration file:", "none" {} else @@ -177,16 +193,17 @@ def read_config_files(files) begin files.each do |config_file| + next if config_file.nil? || config_file.empty? + new_config = read_config_file(config_file) configuration = Utils.deep_merge_hashes(configuration, new_config) end - rescue ArgumentError => err - Jekyll.logger.warn "WARNING:", "Error reading configuration. " + - "Using defaults (and options)." - $stderr.puts "#{err}" + rescue ArgumentError => e + Jekyll.logger.warn "WARNING:", "Error reading configuration. Using defaults (and options)." + warn e end - configuration.fix_common_issues.backwards_compatibilize.add_default_collections + configuration.validate.add_default_collections end # Public: Split a CSV string into an array containing its values @@ -198,121 +215,99 @@ def csv_to_array(csv) csv.split(",").map(&:strip) end - # Public: Ensure the proper options are set in the configuration to allow for - # backwards-compatibility with Jekyll pre-1.0 + # Public: Ensure the proper options are set in the configuration # - # Returns the backwards-compatible configuration - def backwards_compatibilize + # Returns the configuration Hash + def validate config = clone - # Provide backwards-compatibility - if config.key?('auto') || config.key?('watch') - Jekyll::Deprecator.deprecation_message "Auto-regeneration can no longer" + - " be set from your configuration file(s). Use the"+ - " --[no-]watch/-w command-line option instead." - config.delete('auto') - config.delete('watch') - end - if config.key? 'server' - Jekyll::Deprecator.deprecation_message "The 'server' configuration option" + - " is no longer accepted. Use the 'jekyll serve'" + - " subcommand to serve your site with WEBrick." - config.delete('server') - end + check_plugins(config) + check_include_exclude(config) - renamed_key 'server_port', 'port', config - renamed_key 'plugins', 'plugins_dir', config - renamed_key 'layouts', 'layouts_dir', config - renamed_key 'data_source', 'data_dir', config + config + end - if config.key? 'pygments' - Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" + - " has been renamed to 'highlighter'. Please update your" + - " config file accordingly. The allowed values are 'rouge', " + - "'pygments' or null." + def add_default_collections + config = clone - config['highlighter'] = 'pygments' if config['pygments'] - config.delete('pygments') - end + # It defaults to `{}`, so this is only if someone sets it to null manually. + return config if config["collections"].nil? - %w[include exclude].each do |option| - if config.fetch(option, []).is_a?(String) - Jekyll::Deprecator.deprecation_message "The '#{option}' configuration option" + - " must now be specified as an array, but you specified" + - " a string. For now, we've treated the string you provided" + - " as a list of comma-separated values." - config[option] = csv_to_array(config[option]) + # Ensure we have a hash. + if config["collections"].is_a?(Array) + config["collections"] = config["collections"].each_with_object({}) do |collection, hash| + hash[collection] = {} end - config[option].map!(&:to_s) - end - - if (config['kramdown'] || {}).key?('use_coderay') - Jekyll::Deprecator.deprecation_message "Please change 'use_coderay'" + - " to 'enable_coderay' in your configuration file." - config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay') end - if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku") - Jekyll.logger.abort_with "Error:", "You're using the 'maruku' " + - "Markdown processor, which has been removed as of 3.0.0. " + - "We recommend you switch to Kramdown. To do this, replace " + - "`markdown: maruku` with `markdown: kramdown` in your " + - "`_config.yml` file." + config["collections"] = Utils.deep_merge_hashes( + { "posts" => {} }, config["collections"] + ).tap do |collections| + collections["posts"]["output"] = true + if config["permalink"] + collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"]) + end end config end - def fix_common_issues - config = clone + DEFAULT_EXCLUDES = %w( + .sass-cache .jekyll-cache .ruby-lsp + gemfiles Gemfile Gemfile.lock + node_modules + vendor/bundle/ vendor/cache/ vendor/gems/ vendor/ruby/ + ).freeze - if config.key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1) - Jekyll.logger.warn "Config Warning:", "The `paginate` key must be a" + - " positive integer or nil. It's currently set to '#{config['paginate'].inspect}'." - config['paginate'] = nil - end + def add_default_excludes + config = clone + return config if config["exclude"].nil? + config["exclude"].concat(DEFAULT_EXCLUDES).uniq! config end - def add_default_collections - config = clone + private - return config if config['collections'].nil? + STYLE_TO_PERMALINK = { + :none => "/:categories/:title:output_ext", + :date => "/:categories/:year/:month/:day/:title:output_ext", + :ordinal => "/:categories/:year/:y_day/:title:output_ext", + :pretty => "/:categories/:year/:month/:day/:title/", + :weekdate => "/:categories/:year/W:week/:short_day/:title:output_ext", + }.freeze - if config['collections'].is_a?(Array) - config['collections'] = Hash[config['collections'].map{|c| [c, {}]}] - end - config['collections']['posts'] ||= {} - config['collections']['posts']['output'] = true - config['collections']['posts']['permalink'] = style_to_permalink(config['permalink']) + private_constant :STYLE_TO_PERMALINK - config + def style_to_permalink(permalink_style) + STYLE_TO_PERMALINK[permalink_style.to_sym] || permalink_style.to_s end - def renamed_key(old, new, config, allowed_values = nil) - if config.key?(old) - Jekyll::Deprecator.deprecation_message "The '#{old}' configuration" + - "option has been renamed to '#{new}'. Please update your config " + - "file accordingly." - config[new] = config.delete(old) + def check_include_exclude(config) + %w(include exclude).each do |option| + next unless config.key?(option) + next if config[option].is_a?(Array) + + raise Jekyll::Errors::InvalidConfigurationError, + "'#{option}' should be set as an array, but was: #{config[option].inspect}." end end - private - def style_to_permalink(permalink_style) - case permalink_style.to_sym - when :pretty - "/:categories/:year/:month/:day/:title/" - when :none - "/:categories/:title.html" - when :date - "/:categories/:year/:month/:day/:title.html" - when :ordinal - "/:categories/:year/:y_day/:title.html" - else - permalink_style.to_s - end + # Private: Checks if the `plugins` config is a String + # + # config - the config hash + # + # Raises a Jekyll::Errors::InvalidConfigurationError if the config `plugins` + # is not an Array. + def check_plugins(config) + return unless config.key?("plugins") + return if config["plugins"].is_a?(Array) + + Jekyll.logger.error "'plugins' should be set as an array of gem-names, but was: " \ + "#{config["plugins"].inspect}. Use 'plugins_dir' instead to set " \ + "the directory for your non-gemified Ruby plugins." + raise Jekyll::Errors::InvalidConfigurationError, + "'plugins' should be set as an array, but was: #{config["plugins"].inspect}." end end end diff --git a/lib/jekyll/converter.rb b/lib/jekyll/converter.rb index c30f49445f5..3cb74de2123 100644 --- a/lib/jekyll/converter.rb +++ b/lib/jekyll/converter.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll class Converter < Plugin # Public: Get or set the highlighter prefix. When an argument is specified, @@ -8,7 +10,9 @@ class Converter < Plugin # # Returns the String prefix. def self.highlighter_prefix(highlighter_prefix = nil) - @highlighter_prefix = highlighter_prefix if highlighter_prefix + unless defined?(@highlighter_prefix) && highlighter_prefix.nil? + @highlighter_prefix = highlighter_prefix + end @highlighter_prefix end @@ -20,7 +24,9 @@ def self.highlighter_prefix(highlighter_prefix = nil) # # Returns the String suffix. def self.highlighter_suffix(highlighter_suffix = nil) - @highlighter_suffix = highlighter_suffix if highlighter_suffix + unless defined?(@highlighter_suffix) && highlighter_suffix.nil? + @highlighter_suffix = highlighter_suffix + end @highlighter_suffix end diff --git a/lib/jekyll/converters/identity.rb b/lib/jekyll/converters/identity.rb index 69171b008ab..7579b330a06 100644 --- a/lib/jekyll/converters/identity.rb +++ b/lib/jekyll/converters/identity.rb @@ -1,18 +1,38 @@ +# frozen_string_literal: true + module Jekyll module Converters + # Identity converter. Returns same content as given. + # For more info on converters see https://jekyllrb.com/docs/plugins/converters/ class Identity < Converter safe true priority :lowest - def matches(ext) + # Public: Does the given extension match this converter's list of acceptable extensions? + # Takes one argument: the file's extension (including the dot). + # + # _ext - The String extension to check (not relevant here) + # + # Returns true since it always matches. + def matches(_ext) true end + # Public: The extension to be given to the output file (including the dot). + # + # ext - The String extension or original file. + # + # Returns The String output file extension. def output_ext(ext) ext end + # Logic to do the content conversion. + # + # content - String content of file (without front matter). + # + # Returns a String of the converted content. def convert(content) content end diff --git a/lib/jekyll/converters/markdown.rb b/lib/jekyll/converters/markdown.rb index 30c7ef36682..da1f1ce605f 100644 --- a/lib/jekyll/converters/markdown.rb +++ b/lib/jekyll/converters/markdown.rb @@ -1,76 +1,112 @@ +# frozen_string_literal: true + module Jekyll module Converters + # Markdown converter. + # For more info on converters see https://jekyllrb.com/docs/plugins/converters/ class Markdown < Converter - safe true - highlighter_prefix "\n" highlighter_suffix "\n" + safe true def setup - return if @setup - @parser = - case @config['markdown'].downcase - when 'redcarpet' then RedcarpetParser.new(@config) - when 'kramdown' then KramdownParser.new(@config) - when 'rdiscount' then RDiscountParser.new(@config) - else - # So they can't try some tricky bullshit or go down the ancestor chain, I hope. - if allowed_custom_class?(@config['markdown']) - self.class.const_get(@config['markdown']).new(@config) - else - Jekyll.logger.error "Invalid Markdown Processor:", "#{@config['markdown']}" - Jekyll.logger.error "", "Valid options are [ #{valid_processors.join(" | ")} ]" - raise Errors::FatalException, "Invalid Markdown Processor: #{@config['markdown']}" - end + return if @setup ||= false + + unless (@parser = get_processor) + if @config["safe"] + Jekyll.logger.warn "Build Warning:", "Custom processors are not loaded in safe mode" end + + Jekyll.logger.error "Markdown processor:", + "#{@config["markdown"].inspect} is not a valid Markdown processor." + Jekyll.logger.error "", "Available processors are: #{valid_processors.join(", ")}" + Jekyll.logger.error "" + raise Errors::FatalException, "Invalid Markdown processor given: #{@config["markdown"]}" + end + + @cache = Jekyll::Cache.new("Jekyll::Converters::Markdown") @setup = true end - def valid_processors - %w[ - rdiscount - kramdown - redcarpet - ] + third_party_processors + # RuboCop does not allow reader methods to have names starting with `get_` + # To ensure compatibility, this check has been disabled on this method + # + # rubocop:disable Naming/AccessorMethodName + def get_processor + case @config["markdown"].downcase + when "kramdown" then KramdownParser.new(@config) + else + custom_processor + end end + # rubocop:enable Naming/AccessorMethodName - def third_party_processors - self.class.constants - %w[ - KramdownParser - RDiscountParser - RedcarpetParser - PRIORITIES - ].map(&:to_sym) + # Public: Provides you with a list of processors comprised of the ones we support internally + # and the ones that you have provided to us (if they're whitelisted for use in safe mode). + # + # Returns an array of symbols. + def valid_processors + [:kramdown] + third_party_processors end - def extname_list - @extname_list ||= @config['markdown_ext'].split(',').map { |e| ".#{e.downcase}" } + # Public: A list of processors that you provide via plugins. + # + # Returns an array of symbols + def third_party_processors + self.class.constants - [:KramdownParser, :PRIORITIES] end + # Does the given extension match this converter's list of acceptable extensions? + # Takes one argument: the file's extension (including the dot). + # + # ext - The String extension to check. + # + # Returns true if it matches, false otherwise. def matches(ext) - extname_list.include? ext.downcase + extname_list.include?(ext.downcase) end - def output_ext(ext) + # Public: The extension to be given to the output file (including the dot). + # + # ext - The String extension or original file. + # + # Returns The String output file extension. + def output_ext(_ext) ".html" end + # Logic to do the content conversion. + # + # content - String content of file (without front matter). + # + # Returns a String of the converted content. def convert(content) setup - @parser.convert(content) + @cache.getset(content) do + @parser.convert(content) + end + end + + def extname_list + @extname_list ||= @config["markdown_ext"].split(",").map! { |e| ".#{e.downcase}" } end private - # Private: Determine whether a class name is an allowed custom markdown - # class name + def custom_processor + converter_name = @config["markdown"] + self.class.const_get(converter_name).new(@config) if custom_class_allowed?(converter_name) + end + + # Private: Determine whether a class name is an allowed custom + # markdown class name. # # parser_name - the name of the parser class # - # Returns true if the parser name contains only alphanumeric characters - # and is defined within Jekyll::Converters::Markdown - def allowed_custom_class?(parser_name) - parser_name !~ /[^A-Za-z0-9]/ && self.class.constants.include?(parser_name.to_sym) + # Returns true if the parser name contains only alphanumeric characters and is defined + # within Jekyll::Converters::Markdown + def custom_class_allowed?(parser_name) + parser_name !~ %r![^A-Za-z0-9_]! && self.class.constants.include?(parser_name.to_sym) end end end diff --git a/lib/jekyll/converters/markdown/kramdown_parser.rb b/lib/jekyll/converters/markdown/kramdown_parser.rb index 40dfa87eaea..1e6a1dedecd 100644 --- a/lib/jekyll/converters/markdown/kramdown_parser.rb +++ b/lib/jekyll/converters/markdown/kramdown_parser.rb @@ -1,33 +1,196 @@ +# frozen_string_literal: true + +module Kramdown + # A Kramdown::Document subclass meant to optimize memory usage from initializing + # a kramdown document for parsing. + # + # The optimization is by using the same options Hash (and its derivatives) for + # converting all Markdown documents in a Jekyll site. + class JekyllDocument < Document + class << self + attr_reader :options, :parser + + # The implementation is basically the core logic in +Kramdown::Document#initialize+ + # + # rubocop:disable Naming/MemoizedInstanceVariableName + def setup(options) + @cache ||= {} + + # reset variables on a subsequent set up with a different options Hash + unless @cache[:id] == options.hash + @options = @parser = nil + @cache[:id] = options.hash + end + + @options ||= Options.merge(options).freeze + @parser ||= begin + parser_name = (@options[:input] || "kramdown").to_s + parser_name = parser_name[0..0].upcase + parser_name[1..-1] + try_require("parser", parser_name) + + if Parser.const_defined?(parser_name) + Parser.const_get(parser_name) + else + raise Kramdown::Error, "kramdown has no parser to handle the specified " \ + "input format: #{@options[:input]}" + end + end + end + # rubocop:enable Naming/MemoizedInstanceVariableName + + private + + def try_require(type, name) + require "kramdown/#{type}/#{Utils.snake_case(name)}" + rescue LoadError + false + end + end + + def initialize(source, options = {}) + JekyllDocument.setup(options) + + @options = JekyllDocument.options + @root, @warnings = JekyllDocument.parser.parse(source, @options) + end + + # Use Kramdown::Converter::Html class to convert this document into HTML. + # + # The implementation is basically an optimized version of core logic in + # +Kramdown::Document#method_missing+ from kramdown-2.1.0. + def to_html + output, warnings = Kramdown::Converter::Html.convert(@root, @options) + @warnings.concat(warnings) + output + end + end +end + +# + module Jekyll module Converters class Markdown class KramdownParser + CODERAY_DEFAULTS = { + "css" => "style", + "bold_every" => 10, + "line_numbers" => "inline", + "line_number_start" => 1, + "tab_width" => 4, + "wrap" => "div", + }.freeze + def initialize(config) - require 'kramdown' - @config = config - # If kramdown supported highlighter enabled, use that - highlighter = @config['highlighter'] - if highlighter == 'rouge' || highlighter == 'coderay' - @config['kramdown']['syntax_highlighter'] ||= highlighter - end - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install kramdown' - raise Errors::FatalException.new("Missing dependency: kramdown") + @main_fallback_highlighter = config["highlighter"] || "rouge" + @config = config["kramdown"] || {} + @highlighter = nil + setup + load_dependencies + end + + # Setup and normalize the configuration: + # * Create Kramdown if it doesn't exist. + # * Set syntax_highlighter, detecting enable_coderay and merging + # highlighter if none. + # * Merge kramdown[coderay] into syntax_highlighter_opts stripping coderay_. + # * Make sure `syntax_highlighter_opts` exists. + + def setup + @config["syntax_highlighter"] ||= highlighter + @config["syntax_highlighter_opts"] ||= {} + @config["syntax_highlighter_opts"]["default_lang"] ||= "plaintext" + @config["syntax_highlighter_opts"]["guess_lang"] = @config["guess_lang"] + @config["coderay"] ||= {} # XXX: Legacy. + modernize_coderay_config end def convert(content) - # Check for use of coderay - if @config['kramdown']['enable_coderay'] - %w[wrap line_numbers line_numbers_start tab_width bold_every css default_lang].each do |opt| - key = "coderay_#{opt}" - @config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].key?(key) + document = Kramdown::JekyllDocument.new(content, @config) + html_output = document.to_html + if @config["show_warnings"] + document.warnings.each do |warning| + Jekyll.logger.warn "Kramdown warning:", warning end end + html_output + end + + private + + def load_dependencies + require "kramdown-parser-gfm" if @config["input"] == "GFM" + + if highlighter == "coderay" + Jekyll::External.require_with_graceful_fail("kramdown-syntax-coderay") + end + + # `mathjax` engine is bundled within kramdown-2.x and will be handled by + # kramdown itself. + if (math_engine = @config["math_engine"]) && math_engine != "mathjax" + Jekyll::External.require_with_graceful_fail("kramdown-math-#{math_engine}") + end + end + + # config[kramdown][syntax_highlighter] > + # config[kramdown][enable_coderay] > + # config[highlighter] + # Where `enable_coderay` is now deprecated because Kramdown + # supports Rouge now too. + def highlighter + return @highlighter if @highlighter + + if @config["syntax_highlighter"] + return @highlighter = @config[ + "syntax_highlighter" + ] + end + + @highlighter = if @config.key?("enable_coderay") && @config["enable_coderay"] + Jekyll::Deprecator.deprecation_message( + "You are using 'enable_coderay', " \ + "use syntax_highlighter: coderay in your configuration file." + ) + + "coderay" + else + @main_fallback_highlighter + end + end + + def strip_coderay_prefix(hash) + hash.each_with_object({}) do |(key, val), hsh| + cleaned_key = key.to_s.delete_prefix("coderay_") + + if key != cleaned_key + Jekyll::Deprecator.deprecation_message( + "You are using '#{key}'. Normalizing to #{cleaned_key}." + ) + end - Kramdown::Document.new(content, Utils.symbolize_hash_keys(@config['kramdown'])).to_html + hsh[cleaned_key] = val + end end + # If our highlighter is CodeRay we go in to merge the CodeRay defaults + # with your "coderay" key if it's there, deprecating it in the + # process of you using it. + def modernize_coderay_config + unless @config["coderay"].empty? + Jekyll::Deprecator.deprecation_message( + "You are using 'kramdown.coderay' in your configuration, " \ + "please use 'syntax_highlighter_opts' instead." + ) + + @config["syntax_highlighter_opts"] = begin + strip_coderay_prefix( + @config["syntax_highlighter_opts"] \ + .merge(CODERAY_DEFAULTS) \ + .merge(@config["coderay"]) + ) + end + end + end end end end diff --git a/lib/jekyll/converters/markdown/rdiscount_parser.rb b/lib/jekyll/converters/markdown/rdiscount_parser.rb deleted file mode 100644 index fb5172e7a5e..00000000000 --- a/lib/jekyll/converters/markdown/rdiscount_parser.rb +++ /dev/null @@ -1,33 +0,0 @@ -module Jekyll - module Converters - class Markdown - class RDiscountParser - def initialize(config) - Jekyll::External.require_with_graceful_fail "rdiscount" - @config = config - @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym } - end - - def convert(content) - rd = RDiscount.new(content, *@rdiscount_extensions) - html = rd.to_html - if @config['rdiscount']['toc_token'] - html = replace_generated_toc(rd, html, @config['rdiscount']['toc_token']) - end - html - end - - private - def replace_generated_toc(rd, html, toc_token) - if rd.generate_toc && html.include?(toc_token) - utf8_toc = rd.toc_content - utf8_toc.force_encoding('utf-8') if utf8_toc.respond_to?(:force_encoding) - html.gsub(toc_token, utf8_toc) - else - html - end - end - end - end - end -end diff --git a/lib/jekyll/converters/markdown/redcarpet_parser.rb b/lib/jekyll/converters/markdown/redcarpet_parser.rb deleted file mode 100644 index 6788d96e0e8..00000000000 --- a/lib/jekyll/converters/markdown/redcarpet_parser.rb +++ /dev/null @@ -1,103 +0,0 @@ -module Jekyll - module Converters - class Markdown - class RedcarpetParser - - module CommonMethods - def add_code_tags(code, lang) - code = code.to_s - code = code.sub(/
    /, "
    ")
    -            code = code.sub(/<\/pre>/,"
    ") - end - end - - module WithPygments - include CommonMethods - def block_code(code, lang) - Jekyll::External.require_with_graceful_fail("pygments") - lang = lang && lang.split.first || "text" - add_code_tags( - Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }), - lang - ) - end - end - - module WithoutHighlighting - require 'cgi' - - include CommonMethods - - def code_wrap(code) - "
    #{CGI::escapeHTML(code)}
    " - end - - def block_code(code, lang) - lang = lang && lang.split.first || "text" - add_code_tags(code_wrap(code), lang) - end - end - - module WithRouge - def block_code(code, lang) - code = "
    #{super}
    " - - output = "
    " - output << add_code_tags(code, lang) - output << "
    " - end - - protected - def rouge_formatter(lexer) - Rouge::Formatters::HTML.new(:wrap => false) - end - end - - - def initialize(config) - External.require_with_graceful_fail("redcarpet") - @config = config - @redcarpet_extensions = {} - @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true } - - @renderer ||= class_with_proper_highlighter(@config['highlighter']) - end - - def class_with_proper_highlighter(highlighter) - case highlighter - when "pygments" - Class.new(Redcarpet::Render::HTML) do - include WithPygments - end - when "rouge" - Class.new(Redcarpet::Render::HTML) do - Jekyll::External.require_with_graceful_fail(%w[ - rouge - rouge/plugins/redcarpet - ]) - - unless Gem::Version.new(Rouge.version) > Gem::Version.new("1.3.0") - abort "Please install Rouge 1.3.0 or greater and try running Jekyll again." - end - - include Rouge::Plugins::Redcarpet - include CommonMethods - include WithRouge - end - else - Class.new(Redcarpet::Render::HTML) do - include WithoutHighlighting - end - end - end - - def convert(content) - @redcarpet_extensions[:fenced_code_blocks] = !@redcarpet_extensions[:no_fenced_code_blocks] - @renderer.send :include, Redcarpet::Render::SmartyPants if @redcarpet_extensions[:smart] - markdown = Redcarpet::Markdown.new(@renderer.new(@redcarpet_extensions), @redcarpet_extensions) - markdown.render(content) - end - end - end - end -end diff --git a/lib/jekyll/converters/smartypants.rb b/lib/jekyll/converters/smartypants.rb new file mode 100644 index 00000000000..606afdc803b --- /dev/null +++ b/lib/jekyll/converters/smartypants.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module Kramdown + module Parser + class SmartyPants < Kramdown::Parser::Kramdown + def initialize(source, options) + super + @block_parsers = [:block_html, :content] + @span_parsers = [:smart_quotes, :html_entity, :typographic_syms, :span_html] + end + + def parse_content + add_text @src.scan(%r!\A.*\n!) + end + define_parser(:content, %r!\A!) + end + end +end + +module Jekyll + module Converters + # SmartyPants converter. + # For more info on converters see https://jekyllrb.com/docs/plugins/converters/ + class SmartyPants < Converter + safe true + priority :low + + def initialize(config) + Jekyll::External.require_with_graceful_fail "kramdown" unless defined?(Kramdown) + @config = config["kramdown"].dup || {} + @config[:input] = :SmartyPants + end + + # Does the given extension match this converter's list of acceptable extensions? + # Takes one argument: the file's extension (including the dot). + # + # ext - The String extension to check. + # + # Returns true if it matches, false otherwise. + def matches(_ext) + false + end + + # Public: The extension to be given to the output file (including the dot). + # + # ext - The String extension or original file. + # + # Returns The String output file extension. + def output_ext(_ext) + nil + end + + # Logic to do the content conversion. + # + # content - String content of file (without front matter). + # + # Returns a String of the converted content. + def convert(content) + document = Kramdown::Document.new(content, @config) + html_output = document.to_html.chomp + if @config["show_warnings"] + document.warnings.each do |warning| + Jekyll.logger.warn "Kramdown warning:", warning.sub(%r!^Warning:\s+!, "") + end + end + html_output + end + end + end +end diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 121513955ba..b9f7a93fbd7 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -1,6 +1,4 @@ -# encoding: UTF-8 - -require 'set' +# frozen_string_literal: true # Convertible provides methods for converting a pagelike item # from a certain type of markup into actual content @@ -20,18 +18,12 @@ module Jekyll module Convertible # Returns the contents as a String. def to_s - content || '' + content || "" end # Whether the file is published or not, as indicated in YAML front-matter def published? - !(data.key?('published') && data['published'] == false) - end - - # Returns merged option hash for File.read of self.site (if exists) - # and a given param - def merged_file_read_opts(opts) - (site ? site.file_read_opts : {}).merge(opts) + !(data.key?("published") && data["published"] == false) end # Read the YAML frontmatter. @@ -41,42 +33,52 @@ def merged_file_read_opts(opts) # opts - optional parameter to File.read, default at site configs # # Returns nothing. + # rubocop:disable Metrics/AbcSize def read_yaml(base, name, opts = {}) + filename = @path || site.in_source_dir(base, name) + Jekyll.logger.debug "Reading:", relative_path + begin - self.content = File.read(site.in_source_dir(base, name), - merged_file_read_opts(opts)) - if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m - self.content = $POSTMATCH - self.data = SafeYAML.load($1) + self.content = File.read(filename, **Utils.merged_file_read_opts(site, opts)) + if content =~ Document::YAML_FRONT_MATTER_REGEXP + self.content = Regexp.last_match.post_match + self.data = SafeYAML.load(Regexp.last_match(1)) end - rescue SyntaxError => e - Jekyll.logger.warn "YAML Exception reading #{File.join(base, name)}: #{e.message}" - rescue Exception => e - Jekyll.logger.warn "Error reading file #{File.join(base, name)}: #{e.message}" + rescue Psych::SyntaxError => e + Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}" + raise e if site.config["strict_front_matter"] + rescue StandardError => e + Jekyll.logger.warn "Error reading file #{filename}: #{e.message}" + raise e if site.config["strict_front_matter"] end self.data ||= {} + validate_data! filename + validate_permalink! filename + + self.data + end + # rubocop:enable Metrics/AbcSize + + def validate_data!(filename) unless self.data.is_a?(Hash) - Jekyll.logger.abort_with "Fatal:", "Invalid YAML front matter in #{File.join(base, name)}" + raise Errors::InvalidYAMLFrontMatterError, + "Invalid YAML front matter in #{filename}" end + end - self.data + def validate_permalink!(filename) + if self.data["permalink"] == "" + raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}" + end end # Transform the contents based on the content type. # # Returns the transformed contents. def transform - converters.reduce(content) do |output, converter| - begin - converter.convert output - rescue => e - Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{path}':" - Jekyll.logger.error("", e.to_s) - raise e - end - end + renderer.convert(content) end # Determine the extension depending on content_type. @@ -84,13 +86,7 @@ def transform # Returns the String extension for the output file. # e.g. ".html" for an HTML output file. def output_ext - if converters.all? { |c| c.is_a?(Jekyll::Converters::Identity) } - ext - else - converters.map { |c| - c.output_ext(ext) unless c.is_a?(Jekyll::Converters::Identity) - }.compact.last - end + renderer.output_ext end # Determine which converter to use based on this convertible's @@ -98,7 +94,7 @@ def output_ext # # Returns the Converter instance. def converters - @converters ||= site.converters.select { |c| c.matches(ext) }.sort + renderer.converters end # Render Liquid in the content @@ -109,24 +105,18 @@ def converters # # Returns the converted content def render_liquid(content, payload, info, path) - site.liquid_renderer.file(path).parse(content).render!(payload, info) - rescue Tags::IncludeTagError => e - Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || self.path}" - raise e - rescue Exception => e - Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}" - raise e + renderer.render_liquid(content, payload, info, path) end # Convert this Convertible's data to a Hash suitable for use by Liquid. # # Returns the Hash representation of this Convertible. def to_liquid(attrs = nil) - further_data = Hash[(attrs || self.class::ATTRIBUTES_FOR_LIQUID).map { |attribute| - [attribute, send(attribute)] - }] + further_data = \ + (attrs || self.class::ATTRIBUTES_FOR_LIQUID).each_with_object({}) do |attribute, hsh| + hsh[attribute] = send(attribute) + end - defaults = site.frontmatter_defaults.all(relative_path, type) Utils.deep_merge_hashes defaults, Utils.deep_merge_hashes(data, further_data) end @@ -135,16 +125,12 @@ def to_liquid(attrs = nil) # # Returns the type of self. def type - if is_a?(Page) - :pages - end + :pages if is_a?(Page) end # returns the owner symbol for hook triggering def hook_owner - if is_a?(Page) - :pages - end + :pages if is_a?(Page) end # Determine whether the document is an asset file. @@ -160,28 +146,31 @@ def asset_file? # # Returns true if extname == .sass or .scss, false otherwise. def sass_file? - %w[.sass .scss].include?(ext) + Jekyll::Document::SASS_FILE_EXTS.include?(ext) end # Determine whether the document is a CoffeeScript file. # # Returns true if extname == .coffee, false otherwise. def coffeescript_file? - '.coffee'.eql?(ext) + ext == ".coffee" end # Determine whether the file should be rendered with Liquid. # - # Always returns true. + # Returns true if the file has Liquid Tags or Variables, false otherwise. def render_with_liquid? - true + return false if data["render_with_liquid"] == false + + Jekyll::Utils.has_liquid_construct?(content) end # Determine whether the file should be placed into layouts. # - # Returns false if the document is an asset file. + # Returns false if the document is an asset file or if the front matter + # specifies `layout: none` def place_in_layout? - !asset_file? + !(asset_file? || no_layout?) end # Checks if the layout specified in the document actually exists @@ -190,7 +179,7 @@ def place_in_layout? # # Returns true if the layout is invalid, false if otherwise def invalid_layout?(layout) - !data["layout"].nil? && layout.nil? && !(self.is_a? Jekyll::Excerpt) + !data["layout"].nil? && layout.nil? && !(is_a? Jekyll::Excerpt) end # Recursively render layouts @@ -201,68 +190,28 @@ def invalid_layout?(layout) # # Returns nothing def render_all_layouts(layouts, payload, info) - # recursively render layouts - layout = layouts[data["layout"]] - - Jekyll.logger.warn("Build Warning:", "Layout '#{data["layout"]}' requested in #{path} does not exist.") if invalid_layout? layout - - used = Set.new([layout]) - - while layout - Jekyll.logger.debug "Rendering Layout:", path - payload = Utils.deep_merge_hashes(payload, {"content" => output, "page" => layout.data}) - - self.output = render_liquid(layout.content, - payload, - info, - File.join(site.config['layouts_dir'], layout.name)) - - # Add layout to dependency tree - site.regenerator.add_dependency( - site.in_source_dir(path), - site.in_source_dir(layout.path) - ) - - if layout = layouts[layout.data["layout"]] - if used.include?(layout) - layout = nil # avoid recursive chain - else - used << layout - end - end - end + renderer.layouts = layouts + self.output = renderer.place_in_layouts(output, payload, info) + ensure + @renderer = nil # this will allow the modifications above to disappear end # Add any necessary layouts to this convertible document. # - # payload - The site payload Hash. + # payload - The site payload Drop or Hash. # layouts - A Hash of {"name" => "layout"}. # # Returns nothing. def do_layout(payload, layouts) - Jekyll.logger.debug "Rendering:", self.relative_path - - Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path - Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload - info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload['page'] } } - - # render and transform content (this becomes the final content of the object) - payload["highlighter_prefix"] = converters.first.highlighter_prefix - payload["highlighter_suffix"] = converters.first.highlighter_suffix - - if render_with_liquid? - Jekyll.logger.debug "Rendering Liquid:", self.relative_path - self.content = render_liquid(content, payload, info, path) - end - Jekyll.logger.debug "Rendering Markup:", self.relative_path - self.content = transform - - # output keeps track of what will finally be written - self.output = content + self.output = renderer.tap do |doc_renderer| + doc_renderer.layouts = layouts + doc_renderer.payload = payload + end.run - render_all_layouts(layouts, payload, info) if place_in_layout? - Jekyll.logger.debug "Post-Render Hooks:", self.relative_path + Jekyll.logger.debug "Post-Render Hooks:", relative_path Jekyll::Hooks.trigger hook_owner, :post_render, self + ensure + @renderer = nil # this will allow the modifications above to disappear end # Write the generated page file to the destination directory. @@ -273,9 +222,8 @@ def do_layout(payload, layouts) def write(dest) path = destination(dest) FileUtils.mkdir_p(File.dirname(path)) - File.open(path, 'wb') do |f| - f.write(output) - end + Jekyll.logger.debug "Writing:", path + File.write(path, output, :mode => "wb") Jekyll::Hooks.trigger hook_owner, :post_write, self end @@ -291,5 +239,19 @@ def [](property) data[property] end end + + def renderer + @renderer ||= Jekyll::Renderer.new(site, self) + end + + private + + def defaults + @defaults ||= site.frontmatter_defaults.all(relative_path, type) + end + + def no_layout? + data["layout"] == "none" + end end end diff --git a/lib/jekyll/deprecator.rb b/lib/jekyll/deprecator.rb index 8fda510bb3a..4ecb6563921 100644 --- a/lib/jekyll/deprecator.rb +++ b/lib/jekyll/deprecator.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll module Deprecator extend self @@ -5,42 +7,44 @@ module Deprecator def process(args) arg_is_present? args, "--server", "The --server command has been replaced by the \ 'serve' subcommand." - arg_is_present? args, "--serve", "The --server command has been replaced by the \ + arg_is_present? args, "--serve", "The --serve command has been replaced by the \ 'serve' subcommand." arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \ use the 'build' subcommand." - arg_is_present? args, "--auto", "The switch '--auto' has been replaced with '--watch'." + arg_is_present? args, "--auto", "The switch '--auto' has been replaced with \ + '--watch'." arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \ the '--watch' switch." - arg_is_present? args, "--pygments", "The 'pygments'settings has been removed in \ + arg_is_present? args, "--pygments", "The 'pygments' settings has been removed in \ favour of 'highlighter'." - arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in your \ + arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in \ + your config files." + arg_is_present? args, "--url", "The 'url' setting can only be set in your \ config files." - arg_is_present? args, "--url", "The 'url' setting can only be set in your config files." no_subcommand(args) end def no_subcommand(args) - if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first) - deprecation_message "Jekyll now uses subcommands instead of just switches. Run `jekyll --help` to find out more." + unless args.empty? || + args.first !~ %r(!/^--/!) || %w(--help --version).include?(args.first) + deprecation_message "Jekyll now uses subcommands instead of just switches. \ + Run `jekyll help` to find out more." abort end end def arg_is_present?(args, deprecated_argument, message) - if args.include?(deprecated_argument) - deprecation_message(message) - end + deprecation_message(message) if args.include?(deprecated_argument) end def deprecation_message(message) - Jekyll.logger.error "Deprecation:", message + Jekyll.logger.warn "Deprecation:", message end def defaults_deprecate_type(old, current) Jekyll.logger.warn "Defaults:", "The '#{old}' type has become '#{current}'." - Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'." + Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use \ + 'type: #{current}'." end - end end diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 528fed6845f..2e39024e74b 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -1,27 +1,51 @@ -# encoding: UTF-8 +# frozen_string_literal: true module Jekyll class Document include Comparable + extend Forwardable - attr_reader :path, :site, :extname, :output_ext, :content, :output, :collection + attr_reader :path, :site, :extname, :collection, :type + attr_accessor :content, :output - YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m - DATELESS_FILENAME_MATCHER = /^(.*)(\.[^.]+)$/ - DATE_FILENAME_MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/ + def_delegator :self, :read_post_data, :post_read + + YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m.freeze + DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!.freeze + DATE_FILENAME_MATCHER = %r!^(?>.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)(\.[^.]+)$!.freeze + + SASS_FILE_EXTS = %w(.sass .scss).freeze + YAML_FILE_EXTS = %w(.yaml .yml).freeze + + # + + # Class-wide cache to stash and retrieve regexp to detect "super-directories" + # of a particular Jekyll::Document object. + # + # dirname - The *special directory* for the Document. + # e.g. "_posts" or "_drafts" for Documents from the `site.posts` collection. + def self.superdirs_regex(dirname) + @superdirs_regex ||= {} + @superdirs_regex[dirname] ||= %r!#{dirname}.*! + end + + # # Create a new Document. # - # site - the Jekyll::Site instance to which this Document belongs # path - the path to the file + # relations - a hash with keys :site and :collection, the values of which + # are the Jekyll::Site and Jekyll::Collection to which this + # Document belong. # # Returns nothing. - def initialize(path, relations) + def initialize(path, relations = {}) @site = relations[:site] @path = path @extname = File.extname(path) - @output_ext = Jekyll::Renderer.new(site, self).output_ext @collection = relations[:collection] + @type = @collection.label.to_sym + @has_yaml_header = nil if draft? @@ -30,50 +54,44 @@ def initialize(path, relations) categories_from_path(collection.relative_directory) end - data.default_proc = proc do |hash, key| - site.frontmatter_defaults.find(relative_path, collection.label, key) + data.default_proc = proc do |_, key| + site.frontmatter_defaults.find(relative_path, type, key) end trigger_hooks(:post_init) end - def output=(output) - @to_liquid = nil - @output = output - end - - def content=(content) - @to_liquid = nil - @content = content - end - # Fetch the Document's data. # # Returns a Hash containing the data. An empty hash is returned if # no data was read. def data - @data ||= Hash.new + @data ||= {} end # Merge some data in with this document's data. # # Returns the merged data. - def merge_data!(other) - if other.key?('categories') && !other['categories'].nil? - if other['categories'].is_a?(String) - other['categories'] = other['categories'].split(" ").map(&:strip) - end - other['categories'] = (data['categories'] || []) | other['categories'] - end + def merge_data!(other, source: "YAML front matter") + merge_categories!(other) Utils.deep_merge_hashes!(data, other) - if data.key?('date') && !data['date'].is_a?(Time) - data['date'] = Utils.parse_date(data['date'].to_s, "Document '#{relative_path}' does not have a valid date in the YAML front matter.") - end + merge_date!(source) data end + # Returns the document date. If metadata is not present then calculates it + # based on Jekyll::Site#time or the document file modification time. + # + # Return document date string. def date - data['date'] ||= site.time + data["date"] ||= (draft? ? source_file_mtime : site.time) + end + + # Return document file modification time in the form of a Time object. + # + # Return document file modification Time object. + def source_file_mtime + File.mtime(path) end # Returns whether the document is a draft. This is only the case if @@ -82,22 +100,30 @@ def date # # Returns whether the document is a draft. def draft? - data['draft'] ||= relative_path.index(collection.relative_directory).nil? && collection.label == "posts" + data["draft"] ||= relative_path.index(collection.relative_directory).nil? && + collection.label == "posts" end - # The path to the document, relative to the site source. + # The path to the document, relative to the collections_dir. # - # Returns a String path which represents the relative path - # from the site source to this document + # Returns a String path which represents the relative path from the collections_dir + # to this document. def relative_path - @relative_path ||= Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s + @relative_path ||= path.sub("#{site.collections_path}/", "") + end + + # The output extension of the document. + # + # Returns the output extension + def output_ext + renderer.output_ext end # The base filename of the document, without the file extname. # # Returns the basename without the file extname. def basename_without_ext - @basename_without_ext ||= File.basename(path, '.*') + @basename_without_ext ||= File.basename(path, ".*") end # The base filename of the document. @@ -107,27 +133,35 @@ def basename @basename ||= File.basename(path) end + def renderer + @renderer ||= Jekyll::Renderer.new(site, self) + end + # Produces a "cleaned" relative path. # The "cleaned" relative path is the relative path without the extname # and with the collection's directory removed as well. # This method is useful when building the URL of the document. # + # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`) + # # Examples: - # When relative_path is "_methods/site/generate.md": + # When relative_path is "_methods/site/generate...md": # cleaned_relative_path # # => "/site/generate" # # Returns the cleaned relative path of the document. def cleaned_relative_path @cleaned_relative_path ||= - relative_path[0 .. -extname.length - 1].sub(collection.relative_directory, "") + relative_path[0..-extname.length - 1] + .sub(collection.relative_directory, "") + .gsub(%r!\.*\z!, "") end # Determine whether the document is a YAML file. # # Returns true if the extname is either .yml or .yaml, false otherwise. def yaml_file? - %w[.yaml .yml].include?(extname) + YAML_FILE_EXTS.include?(extname) end # Determine whether the document is an asset file. @@ -143,30 +177,40 @@ def asset_file? # # Returns true if extname == .sass or .scss, false otherwise. def sass_file? - %w[.sass .scss].include?(extname) + SASS_FILE_EXTS.include?(extname) end # Determine whether the document is a CoffeeScript file. # # Returns true if extname == .coffee, false otherwise. def coffeescript_file? - '.coffee'.eql?(extname) + extname == ".coffee" end # Determine whether the file should be rendered with Liquid. # # Returns false if the document is either an asset file or a yaml file, + # or if the document doesn't contain any Liquid Tags or Variables, # true otherwise. def render_with_liquid? - !(coffeescript_file? || yaml_file?) + return false if data["render_with_liquid"] == false + + !(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content)) + end + + # Determine whether the file should be rendered with a layout. + # + # Returns true if the Front Matter specifies that `layout` is set to `none`. + def no_layout? + data["layout"] == "none" end # Determine whether the file should be placed into layouts. # - # Returns false if the document is either an asset file or a yaml file, - # true otherwise. + # Returns false if the document is set to `layouts: none`, or is either an + # asset file or a yaml file. Returns true otherwise. def place_in_layout? - !(asset_file? || yaml_file?) + !(asset_file? || yaml_file? || no_layout?) end # The URL template where the document would be accessible. @@ -181,27 +225,7 @@ def url_template # # Returns the Hash of key-value pairs for replacement in the URL. def url_placeholders - { - collection: collection.label, - path: cleaned_relative_path, - output_ext: output_ext, - name: Utils.slugify(basename_without_ext), - title: Utils.slugify(data['slug'], mode: "pretty", cased: true) || Utils - .slugify(basename_without_ext, mode: "pretty", cased: true), - slug: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext), - year: date.strftime("%Y"), - month: date.strftime("%m"), - day: date.strftime("%d"), - hour: date.strftime("%H"), - minute: date.strftime("%M"), - second: date.strftime("%S"), - i_day: date.strftime("%-d"), - i_month: date.strftime("%-m"), - categories: (data['categories'] || []).map { |c| c.to_s.downcase }.uniq.join('/'), - short_month: date.strftime("%b"), - short_year: date.strftime("%y"), - y_day: date.strftime("%j"), - } + @url_placeholders ||= Drops::UrlDrop.new(self) end # The permalink for this Document. @@ -209,18 +233,18 @@ def url_placeholders # # Returns the permalink or nil if no permalink was set in the data. def permalink - data && data.is_a?(Hash) && data['permalink'] + data && data.is_a?(Hash) && data["permalink"] end # The computed URL for the document. See `Jekyll::URL#to_s` for more details. # # Returns the computed URL for the document. def url - @url = URL.new({ - template: url_template, - placeholders: url_placeholders, - permalink: permalink - }).to_s + @url ||= URL.new( + :template => url_template, + :placeholders => url_placeholders, + :permalink => permalink + ).to_s end def [](key) @@ -233,11 +257,16 @@ def [](key) # # Returns the full path to the output file of this document. def destination(base_directory) - dest = site.in_dest_dir(base_directory) - path = site.in_dest_dir(dest, URL.unescape_path(url)) - path = File.join(path, "index.html") if url.end_with?("/") - path << output_ext unless path.end_with?(output_ext) - path + @destination ||= {} + @destination[base_directory] ||= begin + path = site.in_dest_dir(base_directory, URL.unescape_path(url)) + if url.end_with? "/" + path = File.join(path, "index.html") + else + path << output_ext unless path.end_with? output_ext + end + path + end end # Write the generated Document file to the destination directory. @@ -248,28 +277,18 @@ def destination(base_directory) def write(dest) path = destination(dest) FileUtils.mkdir_p(File.dirname(path)) - File.open(path, 'wb') do |f| - f.write(output) - end + Jekyll.logger.debug "Writing:", path + File.write(path, output, :mode => "wb") trigger_hooks(:post_write) end - # Returns merged option hash for File.read of self.site (if exists) - # and a given param - # - # opts - override options - # - # Return the file read options hash. - def merged_file_read_opts(opts) - site ? site.file_read_opts.merge(opts) : opts - end - # Whether the file is published or not, as indicated in YAML front-matter # - # Returns true if the 'published' key is specified in the YAML front-matter and not `false`. + # Returns 'false' if the 'published' key is specified in the + # YAML front-matter and is 'false'. Otherwise returns 'true'. def published? - !(data.key?('published') && data['published'] == false) + !(data.key?("published") && data["published"] == false) end # Read in the file and assign the content and data based on the file contents. @@ -278,96 +297,26 @@ def published? # # Returns nothing. def read(opts = {}) - @to_liquid = nil - Jekyll.logger.debug "Reading:", relative_path if yaml_file? @data = SafeYAML.load_file(path) else begin - defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym) - merge_data!(defaults) unless defaults.empty? - - self.content = File.read(path, merged_file_read_opts(opts)) - if content =~ YAML_FRONT_MATTER_REGEXP - self.content = $POSTMATCH - data_file = SafeYAML.load($1) - merge_data!(data_file) if data_file - end - - post_read - rescue SyntaxError => e - puts "YAML Exception reading #{path}: #{e.message}" - rescue Exception => e - puts "Error reading file #{path}: #{e.message}" + merge_defaults + read_content(**opts) + read_post_data + rescue StandardError => e + handle_read_error(e) end end end - def post_read - if DATE_FILENAME_MATCHER =~ relative_path - m, cats, date, slug, ext = *relative_path.match(DATE_FILENAME_MATCHER) - merge_data!({ - "slug" => slug, - "ext" => ext - }) - merge_data!({"date" => date}) if data['date'].nil? || data['date'].to_i == site.time.to_i - data['title'] ||= slug.split('-').select {|w| w.capitalize! || w }.join(' ') - end - populate_categories - populate_tags - - if generate_excerpt? - data['excerpt'] ||= Jekyll::Excerpt.new(self) - end - end - - # Add superdirectories of the special_dir to categories. - # In the case of es/_posts, 'es' is added as a category. - # In the case of _posts/es, 'es' is NOT added as a category. - # - # Returns nothing. - def categories_from_path(special_dir) - superdirs = relative_path.sub(/#{special_dir}(.*)/, '').split(File::SEPARATOR).reject do |c| - c.empty? || c.eql?(special_dir) || c.eql?(basename) - end - merge_data!({ 'categories' => superdirs }) - end - - def populate_categories - merge_data!({ - 'categories' => ( - Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories') - ).map { |c| c.to_s }.flatten.uniq - }) - end - - def populate_tags - merge_data!({ - "tags" => Utils.pluralized_array_from_hash(data, "tag", "tags").flatten - }) - end - # Create a Liquid-understandable version of this Document. # # Returns a Hash representing this Document's data. def to_liquid - @to_liquid ||= if data.is_a?(Hash) - Utils.deep_merge_hashes Utils.deep_merge_hashes({ - "output" => output, - "content" => content, - "relative_path" => relative_path, - "path" => relative_path, - "url" => url, - "collection" => collection.label, - "next" => next_doc, - "previous" => previous_doc, - "id" => id, - }, data), { 'excerpt' => data['excerpt'].to_s } - else - data - end + @to_liquid ||= Drops::DocumentDrop.new(self) end # The inspect string for this document. @@ -375,14 +324,14 @@ def to_liquid # # Returns the inspect string for this document. def inspect - "#" + "#<#{self.class} #{relative_path} collection=#{collection.label}>" end # The string representation for this document. # # Returns the content of the document def to_s - output || content || 'NO CONTENT' + output || content || "NO CONTENT" end # Compare this document against another document. @@ -391,9 +340,10 @@ def to_s # Returns -1, 0, +1 or nil depending on whether this doc's path is less than, # equal or greater than the other doc's path. See String#<=> for more details. def <=>(other) - return nil if !other.respond_to?(:data) - cmp = data['date'] <=> other.data['date'] - cmp = path <=> other.path if cmp == 0 + return nil unless other.respond_to?(:data) + + cmp = data["date"] <=> other.data["date"] + cmp = path <=> other.path if cmp.nil? || cmp.zero? cmp end @@ -401,17 +351,23 @@ def <=>(other) # Based on the Collection to which it belongs. # # True if the document has a collection and if that collection's #write? - # method returns true, otherwise false. + # method returns true, and if the site's Publisher will publish the document. + # False otherwise. + # + # rubocop:disable Naming/MemoizedInstanceVariableName def write? - collection && collection.write? + return @write_p if defined?(@write_p) + + @write_p = collection&.write? && site.publisher.publish?(self) end + # rubocop:enable Naming/MemoizedInstanceVariableName # The Document excerpt_separator, from the YAML Front-Matter or site # default excerpt_separator value # # Returns the document excerpt_separator def excerpt_separator - (data['excerpt_separator'] || site.config['excerpt_separator']).to_s + @excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s end # Whether to generate an excerpt @@ -422,21 +378,13 @@ def generate_excerpt? end def next_doc - pos = collection.docs.index {|post| post.equal?(self) } - if pos && pos < collection.docs.length - 1 - collection.docs[pos + 1] - else - nil - end + pos = collection.docs.index { |post| post.equal?(self) } + collection.docs[pos + 1] if pos && pos < collection.docs.length - 1 end def previous_doc - pos = collection.docs.index {|post| post.equal?(self) } - if pos && pos > 0 - collection.docs[pos - 1] - else - nil - end + pos = collection.docs.index { |post| post.equal?(self) } + collection.docs[pos - 1] if pos && pos.positive? end def trigger_hooks(hook_name, *args) @@ -445,31 +393,151 @@ def trigger_hooks(hook_name, *args) end def id - @id ||= File.join(File.dirname(url), (data['slug'] || basename_without_ext).to_s) + @id ||= File.join(File.dirname(url), (data["slug"] || basename_without_ext).to_s) end # Calculate related posts. # # Returns an Array of related Posts. def related_posts - Jekyll::RelatedPosts.new(self).build - end - - # Override of normal respond_to? to match method_missing's logic for - # looking in @data. - def respond_to?(method, include_private = false) - data.key?(method.to_s) || super + @related_posts ||= Jekyll::RelatedPosts.new(self).build end # Override of method_missing to check in @data for the key. def method_missing(method, *args, &blck) if data.key?(method.to_s) - Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash." - Jekyll.logger.warn "", "Called by #{caller.first}." + Jekyll::Deprecator.deprecation_message "Document##{method} is now a key in the #data hash." + Jekyll.logger.warn "", "Called by #{caller(1..1)[0]}." data[method.to_s] else super end end + + def respond_to_missing?(method, *) + data.key?(method.to_s) || super + end + + # Add superdirectories of the special_dir to categories. + # In the case of es/_posts, 'es' is added as a category. + # In the case of _posts/es, 'es' is NOT added as a category. + # + # Returns nothing. + def categories_from_path(special_dir) + if relative_path.start_with?(special_dir) + superdirs = [] + else + superdirs = relative_path.sub(Document.superdirs_regex(special_dir), "") + superdirs = superdirs.split(File::SEPARATOR) + superdirs.reject! { |c| c.empty? || c == special_dir || c == basename } + end + + merge_data!({ "categories" => superdirs }, :source => "file path") + end + + def populate_categories + categories = Array(data["categories"]) + Utils.pluralized_array_from_hash( + data, "category", "categories" + ) + categories.map!(&:to_s) + categories.flatten! + categories.uniq! + + merge_data!({ "categories" => categories }) + end + + def populate_tags + tags = Utils.pluralized_array_from_hash(data, "tag", "tags") + tags.flatten! + + merge_data!({ "tags" => tags }) + end + + private + + def merge_categories!(other) + if other.key?("categories") && !other["categories"].nil? + other["categories"] = other["categories"].split if other["categories"].is_a?(String) + + if data["categories"].is_a?(Array) + other["categories"] = data["categories"] | other["categories"] + end + end + end + + def merge_date!(source) + if data.key?("date") + data["date"] = Utils.parse_date( + data["date"].to_s, + "Document '#{relative_path}' does not have a valid date in the #{source}." + ) + end + end + + def merge_defaults + defaults = @site.frontmatter_defaults.all(relative_path, type) + merge_data!(defaults, :source => "front matter defaults") unless defaults.empty? + end + + def read_content(**opts) + self.content = File.read(path, **Utils.merged_file_read_opts(site, opts)) + if content =~ YAML_FRONT_MATTER_REGEXP + self.content = Regexp.last_match.post_match + data_file = SafeYAML.load(Regexp.last_match(1)) + merge_data!(data_file, :source => "YAML front matter") if data_file + end + end + + def read_post_data + populate_title + populate_categories + populate_tags + generate_excerpt + end + + def handle_read_error(error) + if error.is_a? Psych::SyntaxError + Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{error.message}" + else + Jekyll.logger.error "Error:", "could not read file #{path}: #{error.message}" + end + + if site.config["strict_front_matter"] || error.is_a?(Jekyll::Errors::FatalException) + raise error + end + end + + def populate_title + if relative_path =~ DATE_FILENAME_MATCHER + date, slug, ext = Regexp.last_match.captures + modify_date(date) + elsif relative_path =~ DATELESS_FILENAME_MATCHER + slug, ext = Regexp.last_match.captures + end + # `slug` will be nil for documents without an extension since the regex patterns + # above tests for an extension as well. + # In such cases, assign `basename_without_ext` as the slug. + slug ||= basename_without_ext + + # slugs shouldn't end with a period + # `String#gsub!` removes all trailing periods (in comparison to `String#chomp!`) + slug.gsub!(%r!\.*\z!, "") + + # Try to ensure the user gets a title. + data["title"] ||= Utils.titleize_slug(slug) + # Only overwrite slug & ext if they aren't specified. + data["slug"] ||= slug + data["ext"] ||= ext + end + + def modify_date(date) + if !data["date"] || data["date"].to_i == site.time.to_i + merge_data!({ "date" => date }, :source => "filename") + end + end + + def generate_excerpt + data["excerpt"] ||= Jekyll::Excerpt.new(self) if generate_excerpt? + end end end diff --git a/lib/jekyll/drops/collection_drop.rb b/lib/jekyll/drops/collection_drop.rb new file mode 100644 index 00000000000..4fe95a554df --- /dev/null +++ b/lib/jekyll/drops/collection_drop.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class CollectionDrop < Drop + extend Forwardable + + mutable false + + delegate_method_as :write?, :output + delegate_methods :label, :docs, :files, :directory, :relative_directory + + private delegate_method_as :metadata, :fallback_data + + def to_s + docs.to_s + end + end + end +end diff --git a/lib/jekyll/drops/document_drop.rb b/lib/jekyll/drops/document_drop.rb new file mode 100644 index 00000000000..0cff3741074 --- /dev/null +++ b/lib/jekyll/drops/document_drop.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class DocumentDrop < Drop + extend Forwardable + + NESTED_OBJECT_FIELD_BLACKLIST = %w( + content output excerpt next previous + ).freeze + + mutable false + + delegate_method_as :relative_path, :path + private delegate_method_as :data, :fallback_data + + delegate_methods :id, :output, :content, :to_s, :relative_path, :url, :date + data_delegators "title", "categories", "tags" + + def collection + @obj.collection.label + end + + def excerpt + fallback_data["excerpt"].to_s + end + + def name + fallback_data["name"] || @obj.basename + end + + def <=>(other) + return nil unless other.is_a? DocumentDrop + + cmp = self["date"] <=> other["date"] + cmp = self["path"] <=> other["path"] if cmp.nil? || cmp.zero? + cmp + end + + def previous + @obj.previous_doc.to_liquid + end + + def next + @obj.next_doc.to_liquid + end + + # Generate a Hash for use in generating JSON. + # This is useful if fields need to be cleared before the JSON can generate. + # + # state - the JSON::State object which determines the state of current processing. + # + # Returns a Hash ready for JSON generation. + def hash_for_json(state = nil) + to_h.tap do |hash| + if state && state.depth >= 2 + hash["previous"] = collapse_document(hash["previous"]) if hash["previous"] + hash["next"] = collapse_document(hash["next"]) if hash["next"] + end + end + end + + # Generate a Hash which breaks the recursive chain. + # Certain fields which are normally available are omitted. + # + # Returns a Hash with only non-recursive fields present. + def collapse_document(doc) + doc.keys.each_with_object({}) do |(key, _), result| + result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key) + end + end + end + end +end diff --git a/lib/jekyll/drops/drop.rb b/lib/jekyll/drops/drop.rb new file mode 100644 index 00000000000..b82c7b4873e --- /dev/null +++ b/lib/jekyll/drops/drop.rb @@ -0,0 +1,294 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class Drop < Liquid::Drop + include Enumerable + + NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze + NON_CONTENT_METHOD_NAMES = NON_CONTENT_METHODS.map(&:to_s).freeze + private_constant :NON_CONTENT_METHOD_NAMES + + # A private stash to avoid repeatedly generating the setter method name string for + # a call to `Drops::Drop#[]=`. + # The keys of the stash below have a very high probability of being called upon during + # the course of various `Jekyll::Renderer#run` calls. + SETTER_KEYS_STASH = { + "content" => "content=", + "layout" => "layout=", + "page" => "page=", + "paginator" => "paginator=", + "highlighter_prefix" => "highlighter_prefix=", + "highlighter_suffix" => "highlighter_suffix=", + }.freeze + private_constant :SETTER_KEYS_STASH + + class << self + # Get or set whether the drop class is mutable. + # Mutability determines whether or not pre-defined fields may be + # overwritten. + # + # is_mutable - Boolean set mutability of the class (default: nil) + # + # Returns the mutability of the class + def mutable(is_mutable = nil) + @is_mutable = is_mutable || false + end + + def mutable? + @is_mutable + end + + # public delegation helper methods that calls onto Drop's instance + # variable `@obj`. + + # Generate private Drop instance_methods for each symbol in the given list. + # + # Returns nothing. + def private_delegate_methods(*symbols) + symbols.each { |symbol| private delegate_method(symbol) } + nil + end + + # Generate public Drop instance_methods for each symbol in the given list. + # + # Returns nothing. + def delegate_methods(*symbols) + symbols.each { |symbol| delegate_method(symbol) } + nil + end + + # Generate public Drop instance_method for given symbol that calls `@obj.`. + # + # Returns delegated method symbol. + def delegate_method(symbol) + define_method(symbol) { @obj.send(symbol) } + end + + # Generate public Drop instance_method named `delegate` that calls `@obj.`. + # + # Returns delegated method symbol. + def delegate_method_as(original, delegate) + define_method(delegate) { @obj.send(original) } + end + + # Generate public Drop instance_methods for each string entry in the given list. + # The generated method(s) access(es) `@obj`'s data hash. + # + # Returns nothing. + def data_delegators(*strings) + strings.each do |key| + data_delegator(key) if key.is_a?(String) + end + nil + end + + # Generate public Drop instance_methods for given string `key`. + # The generated method access(es) `@obj`'s data hash. + # + # Returns method symbol. + def data_delegator(key) + define_method(key.to_sym) { @obj.data[key] } + end + + # Array of stringified instance methods that do not end with the assignment operator. + # + # (.instance_methods always generates a new Array object so it can be mutated) + # + # Returns array of strings. + def getter_method_names + @getter_method_names ||= instance_methods.map!(&:to_s).tap do |list| + list.reject! { |item| item.end_with?("=") } + end + end + end + + # Create a new Drop + # + # obj - the Jekyll Site, Collection, or Document required by the + # drop. + # + # Returns nothing + def initialize(obj) + @obj = obj + end + + # Access a method in the Drop or a field in the underlying hash data. + # If mutable, checks the mutations first. Then checks the methods, + # and finally check the underlying hash (e.g. document front matter) + # if all the previous places didn't match. + # + # key - the string key whose value to fetch + # + # Returns the value for the given key, or nil if none exists + def [](key) + if self.class.mutable? && mutations.key?(key) + mutations[key] + elsif self.class.invokable? key + public_send key + else + fallback_data[key] + end + end + alias_method :invoke_drop, :[] + + # Set a field in the Drop. If mutable, sets in the mutations and + # returns. If not mutable, checks first if it's trying to override a + # Drop method and raises a DropMutationException if so. If not + # mutable and the key is not a method on the Drop, then it sets the + # key to the value in the underlying hash (e.g. document front + # matter) + # + # key - the String key whose value to set + # val - the Object to set the key's value to + # + # Returns the value the key was set to unless the Drop is not mutable + # and the key matches a method in which case it raises a + # DropMutationException. + def []=(key, val) + setter = SETTER_KEYS_STASH[key] || "#{key}=" + if respond_to?(setter) + public_send(setter, val) + elsif respond_to?(key.to_s) + if self.class.mutable? + mutations[key] = val + else + raise Errors::DropMutationException, "Key #{key} cannot be set in the drop." + end + else + fallback_data[key] = val + end + end + + # Generates a list of strings which correspond to content getter + # methods. + # + # Returns an Array of strings which represent method-specific keys. + def content_methods + @content_methods ||= \ + self.class.getter_method_names \ + - Jekyll::Drops::Drop.getter_method_names \ + - NON_CONTENT_METHOD_NAMES + end + + # Check if key exists in Drop + # + # key - the string key whose value to fetch + # + # Returns true if the given key is present + def key?(key) + return false if key.nil? + return true if self.class.mutable? && mutations.key?(key) + + respond_to?(key) || fallback_data.key?(key) + end + + # Generates a list of keys with user content as their values. + # This gathers up the Drop methods and keys of the mutations and + # underlying data hashes and performs a set union to ensure a list + # of unique keys for the Drop. + # + # Returns an Array of unique keys for content for the Drop. + def keys + (content_methods | + mutations.keys | + fallback_data.keys).flatten + end + + # Generate a Hash representation of the Drop by resolving each key's + # value. It includes Drop methods, mutations, and the underlying object's + # data. See the documentation for Drop#keys for more. + # + # Returns a Hash with all the keys and values resolved. + def to_h + keys.each_with_object({}) do |(key, _), result| + result[key] = self[key] + end + end + alias_method :to_hash, :to_h + + # Inspect the drop's keys and values through a JSON representation + # of its keys and values. + # + # Returns a pretty generation of the hash representation of the Drop. + def inspect + JSON.pretty_generate to_h + end + + # Generate a Hash for use in generating JSON. + # This is useful if fields need to be cleared before the JSON can generate. + # + # Returns a Hash ready for JSON generation. + def hash_for_json(*) + to_h + end + + # Generate a JSON representation of the Drop. + # + # state - the JSON::State object which determines the state of current processing. + # + # Returns a JSON representation of the Drop in a String. + def to_json(state = nil) + JSON.generate(hash_for_json(state), state) + end + + # Collects all the keys and passes each to the block in turn. + # + # block - a block which accepts one argument, the key + # + # Returns nothing. + def each_key(&block) + keys.each(&block) + end + + def each + each_key.each do |key| + yield key, self[key] + end + end + + def merge(other, &block) + dup.tap do |me| + if block.nil? + me.merge!(other) + else + me.merge!(other, block) + end + end + end + + def merge!(other) + other.each_key do |key| + if block_given? + self[key] = yield key, self[key], other[key] + else + if Utils.mergable?(self[key]) && Utils.mergable?(other[key]) + self[key] = Utils.deep_merge_hashes(self[key], other[key]) + next + end + + self[key] = other[key] unless other[key].nil? + end + end + end + + # Imitate Hash.fetch method in Drop + # + # Returns value if key is present in Drop, otherwise returns default value + # KeyError is raised if key is not present and no default value given + def fetch(key, default = nil, &block) + return self[key] if key?(key) + raise KeyError, %(key not found: "#{key}") if default.nil? && block.nil? + return yield(key) unless block.nil? + + default unless default.nil? + end + + private + + def mutations + @mutations ||= {} + end + end + end +end diff --git a/lib/jekyll/drops/excerpt_drop.rb b/lib/jekyll/drops/excerpt_drop.rb new file mode 100644 index 00000000000..82d3cdf827b --- /dev/null +++ b/lib/jekyll/drops/excerpt_drop.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class ExcerptDrop < DocumentDrop + def layout + @obj.doc.data["layout"] + end + + def date + @obj.doc.date + end + + def excerpt + nil + end + + def name + @obj.doc.data["name"] || @obj.doc.basename + end + end + end +end diff --git a/lib/jekyll/drops/jekyll_drop.rb b/lib/jekyll/drops/jekyll_drop.rb new file mode 100644 index 00000000000..63187cc4dcb --- /dev/null +++ b/lib/jekyll/drops/jekyll_drop.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class JekyllDrop < Liquid::Drop + class << self + def global + @global ||= JekyllDrop.new + end + end + + def version + Jekyll::VERSION + end + + def environment + Jekyll.env + end + + def to_h + @to_h ||= { + "version" => version, + "environment" => environment, + } + end + + def to_json(state = nil) + JSON.generate(to_h, state) + end + end + end +end diff --git a/lib/jekyll/drops/site_drop.rb b/lib/jekyll/drops/site_drop.rb new file mode 100644 index 00000000000..cc3c60fb619 --- /dev/null +++ b/lib/jekyll/drops/site_drop.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class SiteDrop < Drop + extend Forwardable + + mutable false + + delegate_method_as :site_data, :data + delegate_methods :time, :pages, :static_files, :tags, :categories + + private delegate_method_as :config, :fallback_data + + def [](key) + if key != "posts" && @obj.collections.key?(key) + @obj.collections[key].docs + else + super(key) + end + end + + def key?(key) + (key != "posts" && @obj.collections.key?(key)) || super + end + + def posts + @site_posts ||= @obj.posts.docs.sort { |a, b| b <=> a } + end + + def html_pages + @site_html_pages ||= @obj.pages.select do |page| + page.html? || page.url.end_with?("/") + end + end + + def collections + @site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid) + end + + # `Site#documents` cannot be memoized so that `Site#docs_to_write` can access the + # latest state of the attribute. + # + # Since this method will be called after `Site#pre_render` hook, the `Site#documents` + # array shouldn't thereafter change and can therefore be safely memoized to prevent + # additional computation of `Site#documents`. + def documents + @documents ||= @obj.documents + end + + # `{{ site.related_posts }}` is how posts can get posts related to + # them, either through LSI if it's enabled, or through the most + # recent posts. + # We should remove this in 4.0 and switch to `{{ post.related_posts }}`. + def related_posts + return nil unless @current_document.is_a?(Jekyll::Document) + + @current_document.related_posts + end + attr_writer :current_document + + # return nil for `{{ site.config }}` even if --config was passed via CLI + def config; end + end + end +end diff --git a/lib/jekyll/drops/static_file_drop.rb b/lib/jekyll/drops/static_file_drop.rb new file mode 100644 index 00000000000..d00973b0a0b --- /dev/null +++ b/lib/jekyll/drops/static_file_drop.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class StaticFileDrop < Drop + extend Forwardable + delegate_methods :name, :extname, :modified_time, :basename + delegate_method_as :relative_path, :path + delegate_method_as :type, :collection + + private delegate_method_as :data, :fallback_data + end + end +end diff --git a/lib/jekyll/drops/theme_drop.rb b/lib/jekyll/drops/theme_drop.rb new file mode 100644 index 00000000000..dd5b281a2d0 --- /dev/null +++ b/lib/jekyll/drops/theme_drop.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class ThemeDrop < Drop + delegate_method_as :runtime_dependencies, :dependencies + + def root + @root ||= ENV["JEKYLL_ENV"] == "development" ? @obj.root : "" + end + + def authors + @authors ||= gemspec.authors.join(", ") + end + + def version + @version ||= gemspec.version.to_s + end + + def description + @description ||= gemspec.description || gemspec.summary + end + + def metadata + @metadata ||= gemspec.metadata + end + + private + + def gemspec + @gemspec ||= @obj.send(:gemspec) + end + + def fallback_data + @fallback_data ||= {} + end + end + end +end diff --git a/lib/jekyll/drops/unified_payload_drop.rb b/lib/jekyll/drops/unified_payload_drop.rb new file mode 100644 index 00000000000..709ad712da0 --- /dev/null +++ b/lib/jekyll/drops/unified_payload_drop.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class UnifiedPayloadDrop < Drop + mutable true + + attr_accessor :content, :page, :layout, :paginator, + :highlighter_prefix, :highlighter_suffix + + def jekyll + JekyllDrop.global + end + + def site + @site_drop ||= SiteDrop.new(@obj) + end + + def theme + @theme_drop ||= ThemeDrop.new(@obj.theme) if @obj.theme + end + + private + + def fallback_data + @fallback_data ||= {} + end + end + end +end diff --git a/lib/jekyll/drops/url_drop.rb b/lib/jekyll/drops/url_drop.rb new file mode 100644 index 00000000000..de58c95fef6 --- /dev/null +++ b/lib/jekyll/drops/url_drop.rb @@ -0,0 +1,140 @@ +# frozen_string_literal: true + +module Jekyll + module Drops + class UrlDrop < Drop + extend Forwardable + + mutable false + + delegate_method :output_ext + delegate_method_as :cleaned_relative_path, :path + + def collection + @obj.collection.label + end + + def name + Utils.slugify(@obj.basename_without_ext) + end + + def title + Utils.slugify(@obj.data["slug"], :mode => "pretty", :cased => true) || + Utils.slugify(@obj.basename_without_ext, :mode => "pretty", :cased => true) + end + + def slug + Utils.slugify(@obj.data["slug"]) || Utils.slugify(@obj.basename_without_ext) + end + + def categories + category_set = Set.new + Array(@obj.data["categories"]).each do |category| + category_set << category.to_s.downcase + end + category_set.to_a.join("/") + end + + # Similar to output from #categories, but each category will be downcased and + # all non-alphanumeric characters of the category replaced with a hyphen. + def slugified_categories + Array(@obj.data["categories"]).each_with_object(Set.new) do |category, set| + set << Utils.slugify(category.to_s) + end.to_a.join("/") + end + + # CCYY + def year + @obj.date.strftime("%Y") + end + + # MM: 01..12 + def month + @obj.date.strftime("%m") + end + + # DD: 01..31 + def day + @obj.date.strftime("%d") + end + + # hh: 00..23 + def hour + @obj.date.strftime("%H") + end + + # mm: 00..59 + def minute + @obj.date.strftime("%M") + end + + # ss: 00..59 + def second + @obj.date.strftime("%S") + end + + # D: 1..31 + def i_day + @obj.date.strftime("%-d") + end + + # M: 1..12 + def i_month + @obj.date.strftime("%-m") + end + + # MMM: Jan..Dec + def short_month + @obj.date.strftime("%b") + end + + # MMMM: January..December + def long_month + @obj.date.strftime("%B") + end + + # YY: 00..99 + def short_year + @obj.date.strftime("%y") + end + + # CCYYw, ISO week year + # may differ from CCYY for the first days of January and last days of December + def w_year + @obj.date.strftime("%G") + end + + # WW: 01..53 + # %W and %U do not comply with ISO 8601-1 + def week + @obj.date.strftime("%V") + end + + # d: 1..7 (Monday..Sunday) + def w_day + @obj.date.strftime("%u") + end + + # dd: Mon..Sun + def short_day + @obj.date.strftime("%a") + end + + # ddd: Monday..Sunday + def long_day + @obj.date.strftime("%A") + end + + # DDD: 001..366 + def y_day + @obj.date.strftime("%j") + end + + private + + def fallback_data + @fallback_data ||= {} + end + end + end +end diff --git a/lib/jekyll/entry_filter.rb b/lib/jekyll/entry_filter.rb index e42701875df..4e70a5d9c7b 100644 --- a/lib/jekyll/entry_filter.rb +++ b/lib/jekyll/entry_filter.rb @@ -1,12 +1,16 @@ +# frozen_string_literal: true + module Jekyll class EntryFilter - SPECIAL_LEADING_CHARACTERS = ['.', '_', '#'].freeze - attr_reader :site + SPECIAL_LEADING_CHAR_REGEX = %r!\A#{Regexp.union([".", "_", "#", "~"])}!o.freeze + def initialize(site, base_directory = nil) @site = site - @base_directory = derive_base_directory(@site, base_directory.to_s.dup) + @base_directory = derive_base_directory( + @site, base_directory.to_s.dup + ) end def base_directory @@ -14,58 +18,99 @@ def base_directory end def derive_base_directory(site, base_dir) - if base_dir.start_with?(site.source) - base_dir[site.source] = "" - end + base_dir[site.source] = "" if base_dir.start_with?(site.source) base_dir end def relative_to_source(entry) - File.join(base_directory, entry) + File.join( + base_directory, entry + ) end def filter(entries) entries.reject do |e| - unless included?(e) - special?(e) || backup?(e) || excluded?(e) || symlink?(e) - end + # Reject this entry if it is just a "dot" representation. + # e.g.: '.', '..', '_movies/.', 'music/..', etc + next true if e.end_with?(".") + + # Check if the current entry is explicitly included and cache the result + included = included?(e) + + # Reject current entry if it is excluded but not explicitly included as well. + next true if excluded?(e) && !included + + # Reject current entry if it is a symlink. + next true if symlink?(e) + + # Do not reject current entry if it is explicitly included. + next false if included + + # Reject current entry if it is special or a backup file. + special?(e) || backup?(e) end end def included?(entry) - glob_include?(site.include, entry) + glob_include?(site.include, entry) || + glob_include?(site.include, File.basename(entry)) end def special?(entry) - SPECIAL_LEADING_CHARACTERS.include?(entry[0..0]) || - SPECIAL_LEADING_CHARACTERS.include?(File.basename(entry)[0..0]) + SPECIAL_LEADING_CHAR_REGEX.match?(entry) || + SPECIAL_LEADING_CHAR_REGEX.match?(File.basename(entry)) end def backup?(entry) - entry[-1..-1] == '~' + entry.end_with?("~") end def excluded?(entry) - excluded = glob_include?(site.exclude, relative_to_source(entry)) - Jekyll.logger.debug "EntryFilter:", "excluded?(#{relative_to_source(entry)}) ==> #{excluded}" - excluded + glob_include?(site.exclude - site.include, relative_to_source(entry)).tap do |excluded| + if excluded + Jekyll.logger.debug( + "EntryFilter:", + "excluded #{relative_to_source(entry)}" + ) + end + end end + # -- + # Check if a file is a symlink. + # NOTE: This can be converted to allowing even in safe, + # since we use Pathutil#in_path? now. + # -- def symlink?(entry) - File.symlink?(entry) && site.safe + site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry) end - def ensure_leading_slash(path) - path[0..0] == "/" ? path : "/#{path}" + # -- + # Check if given path is outside of current site's configured source directory. + # -- + def symlink_outside_site_source?(entry) + !File.realpath(entry).start_with?(site.in_source_dir) end - # Returns true if path matches against any glob pattern. - # Look for more detail about glob pattern in method File::fnmatch. - def glob_include?(enum, e) - entry = ensure_leading_slash(e) - enum.any? do |exp| - item = ensure_leading_slash(exp) - File.fnmatch?(item, entry) || entry.start_with?(item) + # Check if an entry matches a specific pattern. + # Returns true if path matches against any glob pattern, else false. + def glob_include?(enumerator, entry) + entry_with_source = PathManager.join(site.source, entry) + entry_is_directory = File.directory?(entry_with_source) + + enumerator.any? do |pattern| + case pattern + when String + pattern_with_source = PathManager.join(site.source, pattern) + + File.fnmatch?(pattern_with_source, entry_with_source) || + entry_with_source.start_with?(pattern_with_source) || + (pattern_with_source == "#{entry_with_source}/" if entry_is_directory) + when Regexp + pattern.match?(entry_with_source) + else + false + end end end end diff --git a/lib/jekyll/errors.rb b/lib/jekyll/errors.rb index dc5238a05ee..8d659e8d285 100644 --- a/lib/jekyll/errors.rb +++ b/lib/jekyll/errors.rb @@ -1,9 +1,20 @@ +# frozen_string_literal: true + module Jekyll module Errors - class FatalException < RuntimeError - end + FatalException = Class.new(::RuntimeError) + + InvalidThemeName = Class.new(FatalException) + + DropMutationException = Class.new(FatalException) + InvalidPermalinkError = Class.new(FatalException) + InvalidYAMLFrontMatterError = Class.new(FatalException) + MissingDependencyException = Class.new(FatalException) - class MissingDependencyException < FatalException - end + InvalidDateError = Class.new(FatalException) + InvalidPostNameError = Class.new(FatalException) + PostURLError = Class.new(FatalException) + InvalidURLError = Class.new(FatalException) + InvalidConfigurationError = Class.new(FatalException) end end diff --git a/lib/jekyll/excerpt.rb b/lib/jekyll/excerpt.rb index 36fcd11b4c5..63185203a13 100644 --- a/lib/jekyll/excerpt.rb +++ b/lib/jekyll/excerpt.rb @@ -1,15 +1,19 @@ -require 'forwardable' +# frozen_string_literal: true module Jekyll class Excerpt extend Forwardable - attr_accessor :doc - attr_accessor :content, :ext + attr_accessor :content, :doc, :ext attr_writer :output - def_delegators :@doc, :site, :name, :ext, :relative_path, :extname, - :render_with_liquid?, :collection, :related_posts + def_delegators :@doc, + :site, :name, :ext, :extname, + :collection, :related_posts, :type, + :coffeescript_file?, :yaml_file?, + :url, :next_doc, :previous_doc + + private :coffeescript_file?, :yaml_file? # Initialize this Excerpt instance. # @@ -31,8 +35,7 @@ def data @data end - def trigger_hooks(*) - end + def trigger_hooks(*); end # 'Path' of the excerpt. # @@ -41,11 +44,18 @@ def path File.join(doc.path, "#excerpt") end + # 'Relative Path' of the excerpt. + # + # Returns the relative_path for the doc this excerpt belongs to with #excerpt appended + def relative_path + @relative_path ||= File.join(doc.relative_path, "#excerpt") + end + # Check if excerpt includes a string # # Returns true if the string passed in def include?(something) - (output && output.include?(something)) || content.include?(something) + output&.include?(something) || content.include?(something) end # The UID for this doc (useful in feeds). @@ -61,15 +71,12 @@ def to_s end def to_liquid - doc.data['excerpt'] = nil - @to_liquid ||= doc.to_liquid - doc.data['excerpt'] = self - @to_liquid + Jekyll::Drops::ExcerptDrop.new(self) end # Returns the shorthand String identifier of this doc. def inspect - "" + "<#{self.class} id=#{id}>" end def output @@ -80,6 +87,12 @@ def place_in_layout? false end + def render_with_liquid? + return false if data["render_with_liquid"] == false + + !(coffeescript_file? || yaml_file? || !Utils.has_liquid_construct?(content)) + end + protected # Internal: Extract excerpt from the content @@ -116,14 +129,72 @@ def place_in_layout? # Excerpts are rendered same time as content is rendered. # # Returns excerpt String + + LIQUID_TAG_REGEX = %r!{%-?\s*(\w+)\s*.*?-?%}!m.freeze + MKDWN_LINK_REF_REGEX = %r!^ {0,3}(?:(\[[^\]]+\])(:.+))$!.freeze + def extract_excerpt(doc_content) head, _, tail = doc_content.to_s.partition(doc.excerpt_separator) + return head if tail.empty? + + head = sanctify_liquid_tags(head) if head.include?("{%") + definitions = extract_markdown_link_reference_definitions(head, tail) + return head if definitions.empty? + + head << "\n\n" << definitions.join("\n") + end - if tail.empty? - head - else - "" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n") + private + + # append appropriate closing tag(s) (for each Liquid block), to the `head` if the + # partitioning resulted in leaving the closing tag somewhere in the `tail` partition. + def sanctify_liquid_tags(head) + modified = false + tag_names = head.scan(LIQUID_TAG_REGEX) + tag_names.flatten! + tag_names.reverse_each do |tag_name| + next unless liquid_block?(tag_name) + next if endtag_regex_stash(tag_name).match?(head) + + modified = true + head << "\n{% end#{tag_name} %}" end + + print_build_warning if modified + head + end + + def extract_markdown_link_reference_definitions(head, tail) + [].tap do |definitions| + tail.scan(MKDWN_LINK_REF_REGEX).each do |segments| + definitions << segments.join if head.include?(segments[0]) + end + end + end + + def endtag_regex_stash(tag_name) + @endtag_regex_stash ||= {} + @endtag_regex_stash[tag_name] ||= %r!{%-?\s*end#{tag_name}.*?\s*-?%}!m + end + + def liquid_block?(tag_name) + return false unless tag_name.is_a?(String) + return false unless Liquid::Template.tags[tag_name] + + Liquid::Template.tags[tag_name].ancestors.include?(Liquid::Block) + rescue NoMethodError + Jekyll.logger.error "Error:", + "A Liquid tag in the excerpt of #{doc.relative_path} couldn't be parsed." + raise + end + + def print_build_warning + Jekyll.logger.warn "Warning:", "Excerpt modified in #{doc.relative_path}!" + Jekyll.logger.warn "", "Found a Liquid block containing the excerpt separator " \ + "#{doc.excerpt_separator.inspect}." + Jekyll.logger.warn "", "The block has been modified with the appropriate closing tag." + Jekyll.logger.warn "", "Feel free to define a custom excerpt or excerpt_separator in the" + Jekyll.logger.warn "", "document's Front Matter if the generated excerpt is unsatisfactory." end end end diff --git a/lib/jekyll/external.rb b/lib/jekyll/external.rb index e41bce27d17..b484160c8eb 100644 --- a/lib/jekyll/external.rb +++ b/lib/jekyll/external.rb @@ -1,16 +1,18 @@ +# frozen_string_literal: true + module Jekyll module External class << self - # # Gems that, if installed, should be loaded. # Usually contain subcommands. # def blessed_gems - %w{ + %w( + jekyll-compose jekyll-docs jekyll-import - } + ) end # @@ -20,15 +22,28 @@ def blessed_gems # def require_if_present(names) Array(names).each do |name| - begin - require name - rescue LoadError - Jekyll.logger.debug "Couldn't load #{name}. Skipping." - false - end + require name + rescue LoadError + Jekyll.logger.debug "Couldn't load #{name}. Skipping." + yield(name, version_constraint(name)) if block_given? + false end end + # + # The version constraint required to activate a given gem. + # Usually the gem version requirement is "> 0," because any version + # will do. In the case of jekyll-docs, however, we require the exact + # same version as Jekyll. + # + # Returns a String version constraint in a parseable form for + # RubyGems. + def version_constraint(gem_name) + return "= #{Jekyll::VERSION}" if gem_name.to_s.eql?("jekyll-docs") + + "> 0" + end + # # Require a gem or gems. If it's not present, show a very nice error # message that explains everything and is much more helpful than the @@ -38,22 +53,23 @@ def require_if_present(names) # def require_with_graceful_fail(names) Array(names).each do |name| - begin - require name - rescue LoadError => e - Jekyll.logger.error "Dependency Error:", <<-MSG -Yikes! It looks like you don't have #{name} or one of its dependencies installed. -In order to use Jekyll as currently configured, you'll need to install this gem. - -The full error message from Ruby is: '#{e.message}' - -If you run into trouble, you can find helpful resources at http://jekyllrb.com/help/! - MSG - raise Jekyll::Errors::MissingDependencyException.new(name) - end + Jekyll.logger.debug "Requiring:", name.to_s + require name + rescue LoadError => e + Jekyll.logger.error "Dependency Error:", <<~MSG + Yikes! It looks like you don't have #{name} or one of its dependencies installed. + In order to use Jekyll as currently configured, you'll need to install this gem. + + If you've run Jekyll with `bundle exec`, ensure that you have included the #{name} + gem in your Gemfile as well. + + The full error message from Ruby is: '#{e.message}' + + If you run into trouble, you can find helpful resources at https://jekyllrb.com/help/! + MSG + raise Jekyll::Errors::MissingDependencyException, name end end - end end end diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 7e2d30f3492..7a79eec9eb6 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -1,18 +1,33 @@ -require 'uri' -require 'json' -require 'date' +# frozen_string_literal: true + +require_all "jekyll/filters" module Jekyll module Filters + include URLFilters + include GroupingFilters + include DateFilters + # Convert a Markdown string into HTML output. # # input - The Markdown String to convert. # # Returns the HTML formatted String. def markdownify(input) - site = @context.registers[:site] - converter = site.find_converter_instance(Jekyll::Converters::Markdown) - converter.convert(input) + @context.registers[:site].find_converter_instance( + Jekyll::Converters::Markdown + ).convert(input.to_s) + end + + # Convert quotes into smart quotes. + # + # input - The String to convert. + # + # Returns the smart-quotified String. + def smartify(input) + @context.registers[:site].find_converter_instance( + Jekyll::Converters::SmartyPants + ).convert(input.to_s) end # Convert a Sass string into CSS output. @@ -21,9 +36,9 @@ def markdownify(input) # # Returns the CSS formatted String. def sassify(input) - site = @context.registers[:site] - converter = site.find_converter_instance(Jekyll::Converters::Sass) - converter.convert(input) + @context.registers[:site].find_converter_instance( + Jekyll::Converters::Sass + ).convert(input) end # Convert a Scss string into CSS output. @@ -32,9 +47,9 @@ def sassify(input) # # Returns the CSS formatted String. def scssify(input) - site = @context.registers[:site] - converter = site.find_converter_instance(Jekyll::Converters::Scss) - converter.convert(input) + @context.registers[:site].find_converter_instance( + Jekyll::Converters::Scss + ).convert(input) end # Slugify a filename or title. @@ -44,54 +59,8 @@ def scssify(input) # # Returns the given filename or title as a lowercase URL String. # See Utils.slugify for more detail. - def slugify(input, mode=nil) - Utils.slugify(input, mode: mode) - end - - # Format a date in short format e.g. "27 Jan 2011". - # - # date - the Time to format. - # - # Returns the formatting String. - def date_to_string(date) - time(date).strftime("%d %b %Y") - end - - # Format a date in long format e.g. "27 January 2011". - # - # date - The Time to format. - # - # Returns the formatted String. - def date_to_long_string(date) - time(date).strftime("%d %B %Y") - end - - # Format a date for use in XML. - # - # date - The Time to format. - # - # Examples - # - # date_to_xmlschema(Time.now) - # # => "2011-04-24T20:34:46+08:00" - # - # Returns the formatted String. - def date_to_xmlschema(date) - time(date).xmlschema - end - - # Format a date according to RFC-822 - # - # date - The Time to format. - # - # Examples - # - # date_to_rfc822(Time.now) - # # => "Sun, 24 Apr 2011 12:34:46 +0000" - # - # Returns the formatted String. - def date_to_rfc822(date) - time(date).rfc822 + def slugify(input, mode = nil) + Utils.slugify(input, :mode => mode) end # XML escape a string for use. Replaces any special characters with @@ -106,7 +75,7 @@ def date_to_rfc822(date) # # Returns the escaped String. def xml_escape(input) - CGI.escapeHTML(input.to_s) + input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "") end # CGI escape a string for use in a URL. Replaces any special characters @@ -121,7 +90,7 @@ def xml_escape(input) # # Returns the escaped String. def cgi_escape(input) - CGI::escape(input) + CGI.escape(input) end # URI escape a string. @@ -135,7 +104,16 @@ def cgi_escape(input) # # Returns the escaped String. def uri_escape(input) - URI.escape(input) + Addressable::URI.normalize_component(input) + end + + # Replace any whitespace in the input string with a single space + # + # input - The String on which to operate. + # + # Returns the formatted String + def normalize_whitespace(input) + input.to_s.gsub(%r!\s+!, " ").tap(&:strip!) end # Count the number of words in the input string. @@ -143,14 +121,27 @@ def uri_escape(input) # input - The String on which to operate. # # Returns the Integer word count. - def number_of_words(input) - input.split.length + def number_of_words(input, mode = nil) + cjk_charset = '\p{Han}\p{Katakana}\p{Hiragana}\p{Hangul}' + cjk_regex = %r![#{cjk_charset}]!o + word_regex = %r![^#{cjk_charset}\s]+!o + + case mode + when "cjk" + input.scan(cjk_regex).length + input.scan(word_regex).length + when "auto" + cjk_count = input.scan(cjk_regex).length + cjk_count.zero? ? input.split.length : cjk_count + input.scan(word_regex).length + else + input.split.length + end end # Join an array of things into a string by separating with commas and the # word "and" for the last one. # # array - The Array of Strings to join. + # connector - Word used to connect the last 2 items in the array # # Examples # @@ -158,8 +149,7 @@ def number_of_words(input) # # => "apples, oranges, and grapes" # # Returns the formatted String. - def array_to_sentence_string(array) - connector = "and" + def array_to_sentence_string(array, connector = "and") case array.length when 0 "" @@ -168,7 +158,7 @@ def array_to_sentence_string(array) when 2 "#{array[0]} #{connector} #{array[1]}" else - "#{array[0...-1].join(', ')}, #{connector} #{array[-1]}" + "#{array[0...-1].join(", ")}, #{connector} #{array[-1]}" end end @@ -181,37 +171,124 @@ def jsonify(input) as_liquid(input).to_json end - # Group an array of items by a property + # Filter an array of objects # - # input - the inputted Enumerable - # property - the property + # input - the object array. + # property - the property within each object to filter by. + # value - the desired value. + # Cannot be an instance of Array nor Hash since calling #to_s on them returns + # their `#inspect` string object. # - # Returns an array of Hashes, each looking something like this: - # {"name" => "larry" - # "items" => [...] } # all the items where `property` == "larry" - def group_by(input, property) - if groupable?(input) - input.group_by do |item| - item_property(item, property).to_s - end.inject([]) do |memo, i| - memo << {"name" => i.first, "items" => i.last} - end - else - input - end + # Returns the filtered array of objects + def where(input, property, value) + return input if !property || value.is_a?(Array) || value.is_a?(Hash) + return input unless input.respond_to?(:select) + + input = input.values if input.is_a?(Hash) + input_id = input.hash + + # implement a hash based on method parameters to cache the end-result + # for given parameters. + @where_filter_cache ||= {} + @where_filter_cache[input_id] ||= {} + @where_filter_cache[input_id][property] ||= {} + + # stash or retrieve results to return + @where_filter_cache[input_id][property][value] ||= input.select do |object| + compare_property_vs_target(item_property(object, property), value) + end.to_a end - # Filter an array of objects + # Filters an array of objects against an expression # # input - the object array - # property - property within each object to filter by - # value - desired value + # variable - the variable to assign each item to in the expression + # expression - a Liquid comparison expression passed in as a string # # Returns the filtered array of objects - def where(input, property, value) - return input unless input.is_a?(Enumerable) + def where_exp(input, variable, expression) + return input unless input.respond_to?(:select) + + input = input.values if input.is_a?(Hash) # FIXME + + condition = parse_condition(expression) + @context.stack do + input.select do |object| + @context[variable] = object + condition.evaluate(@context) + end + end || [] + end + + # Search an array of objects and returns the first object that has the queried attribute + # with the given value or returns nil otherwise. + # + # input - the object array. + # property - the property within each object to search by. + # value - the desired value. + # Cannot be an instance of Array nor Hash since calling #to_s on them returns + # their `#inspect` string object. + # + # Returns the found object or nil + # + # rubocop:disable Metrics/CyclomaticComplexity + def find(input, property, value) + return input if !property || value.is_a?(Array) || value.is_a?(Hash) + return input unless input.respond_to?(:find) + + input = input.values if input.is_a?(Hash) + input_id = input.hash + + # implement a hash based on method parameters to cache the end-result for given parameters. + @find_filter_cache ||= {} + @find_filter_cache[input_id] ||= {} + @find_filter_cache[input_id][property] ||= {} + + # stash or retrieve results to return + # Since `enum.find` can return nil or false, we use a placeholder string "<__NO MATCH__>" + # to validate caching. + result = @find_filter_cache[input_id][property][value] ||= input.find do |object| + compare_property_vs_target(item_property(object, property), value) + end || "<__NO MATCH__>" + + return nil if result == "<__NO MATCH__>" + + result + end + # rubocop:enable Metrics/CyclomaticComplexity + + # Searches an array of objects against an expression and returns the first object for which + # the expression evaluates to true, or returns nil otherwise. + # + # input - the object array + # variable - the variable to assign each item to in the expression + # expression - a Liquid comparison expression passed in as a string + # + # Returns the found object or nil + def find_exp(input, variable, expression) + return input unless input.respond_to?(:find) + input = input.values if input.is_a?(Hash) - input.select { |object| item_property(object, property).to_s == value.to_s } + + condition = parse_condition(expression) + @context.stack do + input.find do |object| + @context[variable] = object + condition.evaluate(@context) + end + end + end + + # Convert the input into integer + # + # input - the object string + # + # Returns the integer value + def to_integer(input) + return 1 if input == true + return 0 if input == false + + input.to_i end # Sort an array of objects @@ -222,112 +299,177 @@ def where(input, property, value) # # Returns the filtered array of objects def sort(input, property = nil, nils = "first") - if input.nil? - raise ArgumentError.new("Cannot sort a null object.") - end + raise ArgumentError, "Cannot sort a null object." if input.nil? + if property.nil? input.sort else - case - when nils == "first" + case nils + when "first" order = - 1 - when nils == "last" + when "last" order = + 1 else - raise ArgumentError.new("Invalid nils order: " + - "'#{nils}' is not a valid nils order. It must be 'first' or 'last'.") + raise ArgumentError, "Invalid nils order: " \ + "'#{nils}' is not a valid nils order. It must be 'first' or 'last'." end - input.sort { |apple, orange| - apple_property = item_property(apple, property) - orange_property = item_property(orange, property) - - if !apple_property.nil? && orange_property.nil? - - order - elsif apple_property.nil? && !orange_property.nil? - + order - else - apple_property <=> orange_property - end - } + sort_input(input, property, order) end end - def pop(array, input = 1) + def pop(array, num = 1) return array unless array.is_a?(Array) + + num = Liquid::Utils.to_integer(num) new_ary = array.dup - new_ary.pop(input.to_i || 1) + new_ary.pop(num) new_ary end def push(array, input) return array unless array.is_a?(Array) + new_ary = array.dup new_ary.push(input) new_ary end - def shift(array, input = 1) + def shift(array, num = 1) return array unless array.is_a?(Array) + + num = Liquid::Utils.to_integer(num) new_ary = array.dup - new_ary.shift(input.to_i || 1) + new_ary.shift(num) new_ary end def unshift(array, input) return array unless array.is_a?(Array) + new_ary = array.dup new_ary.unshift(input) new_ary end + def sample(input, num = 1) + return input unless input.respond_to?(:sample) + + num = Liquid::Utils.to_integer(num) rescue 1 + if num == 1 + input.sample + else + input.sample(num) + end + end + # Convert an object into its String representation for debugging # # input - The Object to be converted # # Returns a String representation of the object. def inspect(input) - CGI.escapeHTML(input.inspect) + xml_escape(input.inspect) end private - def time(input) - case input - when Time - input - when Date - input.to_time - when String - Time.parse(input) rescue Time.at(input.to_i) - when Numeric - Time.at(input) - else - Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime." - exit(1) - end.localtime + + # Sort the input Enumerable by the given property. + # If the property doesn't exist, return the sort order respective of + # which item doesn't have the property. + # We also utilize the Schwartzian transform to make this more efficient. + def sort_input(input, property, order) + input.map { |item| [item_property(item, property), item] } + .sort! do |a_info, b_info| + a_property = a_info.first + b_property = b_info.first + + if !a_property.nil? && b_property.nil? + - order + elsif a_property.nil? && !b_property.nil? + + order + else + a_property <=> b_property || a_property.to_s <=> b_property.to_s + end + end + .map!(&:last) end - def groupable?(element) - element.respond_to?(:group_by) + # `where` filter helper + # + def compare_property_vs_target(property, target) + case target + when NilClass + return true if property.nil? + when Liquid::Expression::MethodLiteral # `empty` or `blank` + target = target.to_s + return true if property == target || Array(property).join == target + else + target = target.to_s + if property.is_a? String + return true if property == target + else + Array(property).each do |prop| + return true if prop.to_s == target + end + end + end + + false end def item_property(item, property) - if item.respond_to?(:to_liquid) - item.to_liquid[property.to_s] - elsif item.respond_to?(:data) - item.data[property.to_s] - else - item[property.to_s] + @item_property_cache ||= @context.registers[:site].filter_cache[:item_property] ||= {} + @item_property_cache[property] ||= {} + @item_property_cache[property][item] ||= begin + property = property.to_s + property = if item.respond_to?(:to_liquid) + read_liquid_attribute(item.to_liquid, property) + elsif item.respond_to?(:data) + item.data[property] + else + item[property] + end + + parse_sort_input(property) + end + end + + def read_liquid_attribute(liquid_data, property) + return liquid_data[property] unless property.include?(".") + + property.split(".").reduce(liquid_data) do |data, key| + data.respond_to?(:[]) && data[key] end + rescue TypeError => e + msg = if liquid_data.is_a?(Array) + "Error accessing object (#{liquid_data.to_s[0...20]}) with given key. Expected an " \ + "integer but got #{property.inspect} instead." + else + e.message + end + raise e, msg + end + + FLOAT_LIKE = %r!\A\s*-?(?:\d+\.?\d*|\.\d+)\s*\Z!.freeze + INTEGER_LIKE = %r!\A\s*-?\d+\s*\Z!.freeze + private_constant :FLOAT_LIKE, :INTEGER_LIKE + + # return numeric values as numbers for proper sorting + def parse_sort_input(property) + stringified = property.to_s + return property.to_i if INTEGER_LIKE.match?(stringified) + return property.to_f if FLOAT_LIKE.match?(stringified) + + property end def as_liquid(item) case item when Hash - pairs = item.map { |k, v| as_liquid([k, v]) } - Hash[pairs] + item.each_with_object({}) { |(k, v), result| result[as_liquid(k)] = as_liquid(v) } when Array - item.map{ |i| as_liquid(i) } + item.map { |i| as_liquid(i) } else if item.respond_to?(:to_liquid) liquidated = item.to_liquid @@ -342,5 +484,57 @@ def as_liquid(item) end end end + + # ----------- The following set of code was *adapted* from Liquid::If + # ----------- ref: https://github.com/Shopify/liquid/blob/ffb0ace30315bbcf3548a0383fab531452060ae8/lib/liquid/tags/if.rb#L84-L107 + + # Parse a string to a Liquid Condition + def parse_condition(exp) + parser = Liquid::Parser.new(exp) + condition = parse_binary_comparison(parser) + + parser.consume(:end_of_string) + condition + end + + # Generate a Liquid::Condition object from a Liquid::Parser object additionally processing + # the parsed expression based on whether the expression consists of binary operations with + # Liquid operators `and` or `or` + # + # - parser: an instance of Liquid::Parser + # + # Returns an instance of Liquid::Condition + def parse_binary_comparison(parser) + condition = parse_comparison(parser) + first_condition = condition + while (binary_operator = parser.id?("and") || parser.id?("or")) + child_condition = parse_comparison(parser) + condition.send(binary_operator, child_condition) + condition = child_condition + end + first_condition + end + + # Generates a Liquid::Condition object from a Liquid::Parser object based on whether the parsed + # expression involves a "comparison" operator (e.g. <, ==, >, !=, etc) + # + # - parser: an instance of Liquid::Parser + # + # Returns an instance of Liquid::Condition + def parse_comparison(parser) + left_operand = Liquid::Expression.parse(parser.expression) + operator = parser.consume?(:comparison) + + # No comparison-operator detected. Initialize a Liquid::Condition using only left operand + return Liquid::Condition.new(left_operand) unless operator + + # Parse what remained after extracting the left operand and the `:comparison` operator + # and initialize a Liquid::Condition object using the operands and the comparison-operator + Liquid::Condition.new(left_operand, operator, Liquid::Expression.parse(parser.expression)) + end end end + +Liquid::Template.register_filter( + Jekyll::Filters +) diff --git a/lib/jekyll/filters/date_filters.rb b/lib/jekyll/filters/date_filters.rb new file mode 100644 index 00000000000..966b49b8a8f --- /dev/null +++ b/lib/jekyll/filters/date_filters.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +module Jekyll + module Filters + module DateFilters + # Format a date in short format e.g. "27 Jan 2011". + # Ordinal format is also supported, in both the UK + # (e.g. "27th Jan 2011") and US ("e.g. Jan 27th, 2011") formats. + # UK format is the default. + # + # date - the Time to format. + # type - if "ordinal" the returned String will be in ordinal format + # style - if "US" the returned String will be in US format. + # Otherwise it will be in UK format. + # + # Returns the formatting String. + def date_to_string(date, type = nil, style = nil) + stringify_date(date, "%b", type, style) + end + + # Format a date in long format e.g. "27 January 2011". + # Ordinal format is also supported, in both the UK + # (e.g. "27th January 2011") and US ("e.g. January 27th, 2011") formats. + # UK format is the default. + # + # date - the Time to format. + # type - if "ordinal" the returned String will be in ordinal format + # style - if "US" the returned String will be in US format. + # Otherwise it will be in UK format. + # + # Returns the formatted String. + def date_to_long_string(date, type = nil, style = nil) + stringify_date(date, "%B", type, style) + end + + # Format a date for use in XML. + # + # date - The Time to format. + # + # Examples + # + # date_to_xmlschema(Time.now) + # # => "2011-04-24T20:34:46+08:00" + # + # Returns the formatted String. + def date_to_xmlschema(date) + return date if date.to_s.empty? + + time(date).xmlschema + end + + # Format a date according to RFC-822 + # + # date - The Time to format. + # + # Examples + # + # date_to_rfc822(Time.now) + # # => "Sun, 24 Apr 2011 12:34:46 +0000" + # + # Returns the formatted String. + def date_to_rfc822(date) + return date if date.to_s.empty? + + time(date).rfc822 + end + + private + + # month_type: Notations that evaluate to 'Month' via `Time#strftime` ("%b", "%B") + # type: nil (default) or "ordinal" + # style: nil (default) or "US" + # + # Returns a stringified date or the empty input. + def stringify_date(date, month_type, type = nil, style = nil) + return date if date.to_s.empty? + + time = time(date) + if type == "ordinal" + day = time.day + ordinal_day = "#{day}#{ordinal(day)}" + return time.strftime("#{month_type} #{ordinal_day}, %Y") if style == "US" + + return time.strftime("#{ordinal_day} #{month_type} %Y") + end + time.strftime("%d #{month_type} %Y") + end + + def ordinal(number) + return "th" if (11..13).cover?(number) + + case number % 10 + when 1 then "st" + when 2 then "nd" + when 3 then "rd" + else "th" + end + end + + def time(input) + date = Liquid::Utils.to_date(input) + unless date.respond_to?(:to_time) + raise Errors::InvalidDateError, + "Invalid Date: '#{input.inspect}' is not a valid datetime." + end + date.to_time.dup.localtime + end + end + end +end diff --git a/lib/jekyll/filters/grouping_filters.rb b/lib/jekyll/filters/grouping_filters.rb new file mode 100644 index 00000000000..c9cdc6544cc --- /dev/null +++ b/lib/jekyll/filters/grouping_filters.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +module Jekyll + module Filters + module GroupingFilters + # Group an array of items by a property + # + # input - the inputted Enumerable + # property - the property + # + # Returns an array of Hashes, each looking something like this: + # {"name" => "larry" + # "items" => [...] } # all the items where `property` == "larry" + def group_by(input, property) + if groupable?(input) + groups = input.group_by { |item| item_property(item, property).to_s } + grouped_array(groups) + else + input + end + end + + # Group an array of items by an expression + # + # input - the object array + # variable - the variable to assign each item to in the expression + # expression -a Liquid comparison expression passed in as a string + # + # Returns the filtered array of objects + def group_by_exp(input, variable, expression) + return input unless groupable?(input) + + parsed_expr = parse_expression(expression) + @context.stack do + groups = input.group_by do |item| + @context[variable] = item + parsed_expr.render(@context) + end + grouped_array(groups) + end + end + + private + + def parse_expression(str) + Liquid::Variable.new(str, Liquid::ParseContext.new) + end + + def groupable?(element) + element.respond_to?(:group_by) + end + + def grouped_array(groups) + groups.each_with_object([]) do |item, array| + array << { + "name" => item.first, + "items" => item.last, + "size" => item.last.size, + } + end + end + end + end +end diff --git a/lib/jekyll/filters/url_filters.rb b/lib/jekyll/filters/url_filters.rb new file mode 100644 index 00000000000..aa28c5a5094 --- /dev/null +++ b/lib/jekyll/filters/url_filters.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +module Jekyll + module Filters + module URLFilters + # Produces an absolute URL based on site.url and site.baseurl. + # + # input - the URL to make absolute. + # + # Returns the absolute URL as a String. + def absolute_url(input) + return if input.nil? + + cache = if input.is_a?(String) + (@context.registers[:site].filter_cache[:absolute_url] ||= {}) + else + (@context.registers[:cached_absolute_url] ||= {}) + end + cache[input] ||= compute_absolute_url(input) + + # Duplicate cached string so that the cached value is never mutated by + # a subsequent filter. + cache[input].dup + end + + # Produces a URL relative to the domain root based on site.baseurl + # unless it is already an absolute url with an authority (host). + # + # input - the URL to make relative to the domain root + # + # Returns a URL relative to the domain root as a String. + def relative_url(input) + return if input.nil? + + cache = if input.is_a?(String) + (@context.registers[:site].filter_cache[:relative_url] ||= {}) + else + (@context.registers[:cached_relative_url] ||= {}) + end + cache[input] ||= compute_relative_url(input) + + # Duplicate cached string so that the cached value is never mutated by + # a subsequent filter. + cache[input].dup + end + + # Strips trailing `/index.html` from URLs to create pretty permalinks + # + # input - the URL with a possible `/index.html` + # + # Returns a URL with the trailing `/index.html` removed + def strip_index(input) + return if input.nil? || input.to_s.empty? + + input.sub(%r!/index\.html?$!, "/") + end + + private + + def compute_absolute_url(input) + input = input.url if input.respond_to?(:url) + return input if Addressable::URI.parse(input.to_s).absolute? + + site = @context.registers[:site] + site_url = site.config["url"] + return relative_url(input) if site_url.nil? || site_url == "" + + Addressable::URI.parse( + site_url.to_s + relative_url(input) + ).normalize.to_s + end + + def compute_relative_url(input) + input = input.url if input.respond_to?(:url) + return input if Addressable::URI.parse(input.to_s).absolute? + + parts = [sanitized_baseurl, input] + Addressable::URI.parse( + parts.map! { |part| ensure_leading_slash(part.to_s) }.join + ).normalize.to_s + end + + def sanitized_baseurl + site = @context.registers[:site] + baseurl = site.config["baseurl"] + return "" if baseurl.nil? + + baseurl.to_s.chomp("/") + end + + def ensure_leading_slash(input) + return input if input.nil? || input.empty? || input.start_with?("/") + + "/#{input}" + end + end + end +end diff --git a/lib/jekyll/frontmatter_defaults.rb b/lib/jekyll/frontmatter_defaults.rb index d6cb173f9c8..5ad896b287c 100644 --- a/lib/jekyll/frontmatter_defaults.rb +++ b/lib/jekyll/frontmatter_defaults.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll # This class handles custom defaults for YAML frontmatter settings. # These are set in _config.yml and apply both to internal use (e.g. layout) @@ -10,30 +12,48 @@ def initialize(site) @site = site end + def reset + @glob_cache = {} if @glob_cache + end + def update_deprecated_types(set) - return set unless set.key?('scope') && set['scope'].key?('type') - - set['scope']['type'] = case set['scope']['type'] - when 'page' - Deprecator.defaults_deprecate_type('page', 'pages') - 'pages' - when 'post' - Deprecator.defaults_deprecate_type('post', 'posts') - 'posts' - when 'draft' - Deprecator.defaults_deprecate_type('draft', 'drafts') - 'drafts' - else - set['scope']['type'] - end + return set unless set.key?("scope") && set["scope"].key?("type") + + set["scope"]["type"] = + case set["scope"]["type"] + when "page" + Deprecator.defaults_deprecate_type("page", "pages") + "pages" + when "post" + Deprecator.defaults_deprecate_type("post", "posts") + "posts" + when "draft" + Deprecator.defaults_deprecate_type("draft", "drafts") + "drafts" + else + set["scope"]["type"] + end set end + def ensure_time!(set) + return set unless set.key?("values") && set["values"].key?("date") + return set if set["values"]["date"].is_a?(Time) + + set["values"]["date"] = Utils.parse_date( + set["values"]["date"], + "An invalid date format was found in a front-matter default set: #{set}" + ) + set + end + # Finds a default value for a given setting, filtered by path and type # - # path - the path (relative to the source) of the page, post or :draft the default is used in - # type - a symbol indicating whether a :page, a :post or a :draft calls this method + # path - the path (relative to the source) of the page, + # post or :draft the default is used in + # type - a symbol indicating whether a :page, + # a :post or a :draft calls this method # # Returns the default value or nil if none was found def find(path, type, setting) @@ -41,9 +61,9 @@ def find(path, type, setting) old_scope = nil matching_sets(path, type).each do |set| - if set['values'].key?(setting) && has_precedence?(old_scope, set['scope']) - value = set['values'][setting] - old_scope = set['scope'] + if set["values"].key?(setting) && has_precedence?(old_scope, set["scope"]) + value = set["values"][setting] + old_scope = set["scope"] end end value @@ -59,11 +79,11 @@ def all(path, type) defaults = {} old_scope = nil matching_sets(path, type).each do |set| - if has_precedence?(old_scope, set['scope']) - defaults = Utils.deep_merge_hashes(defaults, set['values']) - old_scope = set['scope'] + if has_precedence?(old_scope, set["scope"]) + defaults = Utils.deep_merge_hashes(defaults, set["values"]) + old_scope = set["scope"] else - defaults = Utils.deep_merge_hashes(set['values'], defaults) + defaults = Utils.deep_merge_hashes(set["values"], defaults) end end defaults @@ -77,20 +97,52 @@ def all(path, type) # path - the path to check for # type - the type (:post, :page or :draft) to check for # - # Returns true if the scope applies to the given path and type + # Returns true if the scope applies to the given type and path def applies?(scope, path, type) - applies_path?(scope, path) && applies_type?(scope, type) + applies_type?(scope, type) && applies_path?(scope, path) end def applies_path?(scope, path) - return true if !scope.has_key?('path') || scope['path'].empty? + rel_scope_path = scope["path"] + return true if !rel_scope_path.is_a?(String) || rel_scope_path.empty? - scope_path = Pathname.new(scope['path']) - Pathname.new(sanitize_path(path)).ascend do |path| - if path.to_s == scope_path.to_s - return true - end + sanitized_path = sanitize_path(path) + + if rel_scope_path.include?("*") + glob_scope(sanitized_path, rel_scope_path) + else + path_is_subpath?(sanitized_path, strip_collections_dir(rel_scope_path)) + end + end + + def glob_scope(sanitized_path, rel_scope_path) + site_source = Pathname.new(@site.source) + abs_scope_path = site_source.join(rel_scope_path).to_s + + glob_cache(abs_scope_path).each do |scope_path| + scope_path = Pathname.new(scope_path).relative_path_from(site_source).to_s + scope_path = strip_collections_dir(scope_path) + Jekyll.logger.debug "Globbed Scope Path:", scope_path + return true if path_is_subpath?(sanitized_path, scope_path) end + false + end + + def glob_cache(path) + @glob_cache ||= {} + @glob_cache[path] ||= Dir.glob(path) + end + + def path_is_subpath?(path, parent_path) + path.start_with?(parent_path) + end + + def strip_collections_dir(path) + collections_dir = @site.config["collections_dir"] + slashed_coll_dir = collections_dir.empty? ? "/" : "#{collections_dir}/" + return path if collections_dir.empty? || !path.to_s.start_with?(slashed_coll_dir) + + path.sub(slashed_coll_dir, "") end # Determines whether the scope applies to type. @@ -105,7 +157,7 @@ def applies_path?(scope, path) # Returns true if either of the above conditions are satisfied, # otherwise returns false def applies_type?(scope, type) - !scope.key?('type') || scope['type'].eql?(type.to_s) + !scope.key?("type") || type&.to_sym.eql?(scope["type"].to_sym) end # Checks if a given set of default values is valid @@ -114,7 +166,7 @@ def applies_type?(scope, type) # # Returns true if the set is valid and can be used in this class def valid?(set) - set.is_a?(Hash) && set['values'].is_a?(Hash) + set.is_a?(Hash) && set["values"].is_a?(Hash) end # Determines if a new scope has precedence over an old one @@ -123,27 +175,31 @@ def valid?(set) # new_scope - the new scope hash # # Returns true if the new scope has precedence over the older + # rubocop: disable Naming/PredicateName def has_precedence?(old_scope, new_scope) return true if old_scope.nil? - new_path = sanitize_path(new_scope['path']) - old_path = sanitize_path(old_scope['path']) + new_path = sanitize_path(new_scope["path"]) + old_path = sanitize_path(old_scope["path"]) if new_path.length != old_path.length new_path.length >= old_path.length - elsif new_scope.key? 'type' + elsif new_scope.key?("type") true else - !old_scope.key? 'type' + !old_scope.key? "type" end end + # rubocop: enable Naming/PredicateName # Collects a list of sets that match the given path and type # # Returns an array of hashes def matching_sets(path, type) - valid_sets.select do |set| - !set.has_key?('scope') || applies?(set['scope'], path, type) + @matched_set_cache ||= {} + @matched_set_cache[path] ||= {} + @matched_set_cache[path][type] ||= valid_sets.select do |set| + !set.key?("scope") || applies?(set["scope"], path, type) end end @@ -154,26 +210,28 @@ def matching_sets(path, type) # # Returns an array of hashes def valid_sets - sets = @site.config['defaults'] + sets = @site.config["defaults"] return [] unless sets.is_a?(Array) sets.map do |set| if valid?(set) - update_deprecated_types(set) + ensure_time!(update_deprecated_types(set)) else Jekyll.logger.warn "Defaults:", "An invalid front-matter default set was found:" - Jekyll.logger.warn "#{set}" + Jekyll.logger.warn set.to_s nil end - end.compact + end.tap(&:compact!) end - # Sanitizes the given path by removing a leading and adding a trailing slash + # Sanitizes the given path by removing a leading slash def sanitize_path(path) if path.nil? || path.empty? "" + elsif path.start_with?("/") + path.gsub(%r!\A/|(?<=[^/])\z!, "") else - path.gsub(/\A\//, '').gsub(/([^\/])\z/, '\1') + path end end end diff --git a/lib/jekyll/generator.rb b/lib/jekyll/generator.rb index 57973a74eb9..649715f840c 100644 --- a/lib/jekyll/generator.rb +++ b/lib/jekyll/generator.rb @@ -1,4 +1,5 @@ +# frozen_string_literal: true + module Jekyll - class Generator < Plugin - end + Generator = Class.new(Plugin) end diff --git a/lib/jekyll/hooks.rb b/lib/jekyll/hooks.rb index a9a5e73529c..482d802614f 100644 --- a/lib/jekyll/hooks.rb +++ b/lib/jekyll/hooks.rb @@ -1,40 +1,49 @@ +# frozen_string_literal: true + module Jekyll module Hooks DEFAULT_PRIORITY = 20 # compatibility layer for octopress-hooks users PRIORITY_MAP = { - low: 10, - normal: 20, - high: 30, + :low => 10, + :normal => 20, + :high => 30, }.freeze # initial empty hooks @registry = { - :site => { - after_reset: [], - post_read: [], - pre_render: [], - post_render: [], - post_write: [], + :site => { + :after_init => [], + :after_reset => [], + :post_read => [], + :pre_render => [], + :post_render => [], + :post_write => [], }, - :pages => { - post_init: [], - pre_render: [], - post_render: [], - post_write: [], + :pages => { + :post_init => [], + :pre_render => [], + :post_convert => [], + :post_render => [], + :post_write => [], }, - :posts => { - post_init: [], - pre_render: [], - post_render: [], - post_write: [], + :posts => { + :post_init => [], + :pre_render => [], + :post_convert => [], + :post_render => [], + :post_write => [], }, :documents => { - post_init: [], - pre_render: [], - post_render: [], - post_write: [], + :post_init => [], + :pre_render => [], + :post_convert => [], + :post_render => [], + :post_write => [], + }, + :clean => { + :on_obsolete => [], }, } @@ -53,44 +62,41 @@ def self.register(owners, event, priority: DEFAULT_PRIORITY, &block) # Ensure the priority is a Fixnum def self.priority_value(priority) - return priority if priority.is_a?(Fixnum) + return priority if priority.is_a?(Integer) + PRIORITY_MAP[priority] || DEFAULT_PRIORITY end # register a single hook to be called later, internal API def self.register_one(owner, event, priority, &block) - @registry[owner] ||={ - post_init: [], - pre_render: [], - post_render: [], - post_write: [], + @registry[owner] ||= { + :post_init => [], + :pre_render => [], + :post_convert => [], + :post_render => [], + :post_write => [], } unless @registry[owner][event] - raise NotAvailable, "Invalid hook. #{owner} supports only the " << - "following hooks #{@registry[owner].keys.inspect}" + raise NotAvailable, "Invalid hook. #{owner} supports only the following hooks " \ + "#{@registry[owner].keys.inspect}" end - unless block.respond_to? :call - raise Uncallable, "Hooks must respond to :call" - end + raise Uncallable, "Hooks must respond to :call" unless block.respond_to? :call insert_hook owner, event, priority, &block end def self.insert_hook(owner, event, priority, &block) - @hook_priority[block] = "#{priority}.#{@hook_priority.size}".to_f + @hook_priority[block] = [-priority, @hook_priority.size] @registry[owner][event] << block end # interface for Jekyll core components to trigger hooks def self.trigger(owner, event, *args) # proceed only if there are hooks to call - return unless @registry[owner] - return unless @registry[owner][event] - - # hooks to call for this owner and event - hooks = @registry[owner][event] + hooks = @registry.dig(owner, event) + return if hooks.nil? || hooks.empty? # sort and call hooks according to priority and load order hooks.sort_by { |h| @hook_priority[h] }.each do |hook| diff --git a/lib/jekyll/inclusion.rb b/lib/jekyll/inclusion.rb new file mode 100644 index 00000000000..179ddb045cb --- /dev/null +++ b/lib/jekyll/inclusion.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Jekyll + class Inclusion + attr_reader :site, :name, :path + private :site + + def initialize(site, base, name) + @site = site + @name = name + @path = PathManager.join(base, name) + end + + def render(context) + @template ||= site.liquid_renderer.file(path).parse(content) + @template.render!(context) + rescue Liquid::Error => e + e.template_name = path + e.markup_context = "included " if e.markup_context.nil? + raise e + end + + def content + @content ||= File.read(path, **site.file_read_opts) + end + + def inspect + "#{self.class} #{path.inspect}" + end + alias_method :to_s, :inspect + end +end diff --git a/lib/jekyll/layout.rb b/lib/jekyll/layout.rb index c29f353fa3e..af3ea71a788 100644 --- a/lib/jekyll/layout.rb +++ b/lib/jekyll/layout.rb @@ -1,24 +1,17 @@ +# frozen_string_literal: true + module Jekyll class Layout include Convertible - # Gets the Site object. - attr_reader :site - - # Gets the name of this layout. - attr_reader :name - - # Gets the path to this layout. - attr_reader :path - - # Gets/Sets the extension of this layout. - attr_accessor :ext + attr_accessor :content, # content of layout + :data, # the Hash that holds the metadata for this layout + :ext # extension of layout - # Gets/Sets the Hash that holds the metadata for this layout. - attr_accessor :data - - # Gets/Sets the content of this layout. - attr_accessor :content + attr_reader :name, # name of layout + :path, # path to layout + :site, # the Site object + :relative_path # path to layout relative to its base # Initialize a new Layout. # @@ -29,7 +22,15 @@ def initialize(site, base, name) @site = site @base = base @name = name - @path = site.in_source_dir(base, name) + + if site.theme && site.theme.layouts_path.eql?(base) + @base_dir = site.theme.root + @path = site.in_theme_dir(base, name) + else + @base_dir = site.source + @path = site.in_source_dir(base, name) + end + @relative_path = @path.sub(@base_dir, "") self.data = {} @@ -45,5 +46,10 @@ def initialize(site, base, name) def process(name) self.ext = File.extname(name) end + + # Returns the object as a debug String. + def inspect + "#<#{self.class} @path=#{@path.inspect}>" + end end end diff --git a/lib/jekyll/liquid_extensions.rb b/lib/jekyll/liquid_extensions.rb index 5ba7dd8e79f..87e06ef7c7e 100644 --- a/lib/jekyll/liquid_extensions.rb +++ b/lib/jekyll/liquid_extensions.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + module Jekyll module LiquidExtensions - # Lookup a Liquid variable in the given context. # # context - the Liquid context in question. @@ -17,6 +18,5 @@ def lookup_variable(context, variable) lookup || variable end - end end diff --git a/lib/jekyll/liquid_renderer.rb b/lib/jekyll/liquid_renderer.rb index 0edeb44b367..7655e04da2e 100644 --- a/lib/jekyll/liquid_renderer.rb +++ b/lib/jekyll/liquid_renderer.rb @@ -1,39 +1,80 @@ -require 'jekyll/liquid_renderer/file' -require 'jekyll/liquid_renderer/table' +# frozen_string_literal: true + +require_relative "liquid_renderer/file" +require_relative "liquid_renderer/table" module Jekyll class LiquidRenderer def initialize(site) @site = site + Liquid::Template.error_mode = @site.config["liquid"]["error_mode"].to_sym reset end def reset @stats = {} + @cache = {} end def file(filename) - filename = @site.in_source_dir(filename).sub(/\A#{Regexp.escape(@site.source)}\//, '') - - LiquidRenderer::File.new(self, filename).tap do |file| - @stats[filename] ||= {} - @stats[filename][:count] ||= 0 - @stats[filename][:count] += 1 + filename = normalize_path(filename) + LiquidRenderer::File.new(self, filename).tap do + @stats[filename] ||= new_profile_hash end end def increment_bytes(filename, bytes) - @stats[filename][:bytes] ||= 0 @stats[filename][:bytes] += bytes end def increment_time(filename, time) - @stats[filename][:time] ||= 0.0 @stats[filename][:time] += time end - def stats_table(n = 50) - LiquidRenderer::Table.new(@stats).to_s(n) + def increment_count(filename) + @stats[filename][:count] += 1 + end + + def stats_table(num_of_rows = 50) + LiquidRenderer::Table.new(@stats).to_s(num_of_rows) + end + + def self.format_error(error, path) + "#{error.message} in #{path}" + end + + # A persistent cache to store and retrieve parsed templates based on the filename + # via `LiquidRenderer::File#parse` + # + # It is emptied when `self.reset` is called. + def cache + @cache ||= {} + end + + private + + def normalize_path(filename) + @normalize_path ||= {} + @normalize_path[filename] ||= begin + theme_dir = @site.theme&.root + case filename + when %r!\A(#{Regexp.escape(@site.source)}/)(?.*)!io + Regexp.last_match(:rest) + when %r!(/gems/.*)*/gems/(?[^/]+)(?.*)!, + %r!(?[^/]+/lib)(?.*)! + "#{Regexp.last_match(:dirname)}#{Regexp.last_match(:rest)}" + when theme_dir && %r!\A#{Regexp.escape(theme_dir)}/(?.*)!io + PathManager.join(@site.theme.basename, Regexp.last_match(:rest)) + when %r!\A/(.*)! + Regexp.last_match(1) + else + filename + end + end + end + + def new_profile_hash + Hash.new { |hash, key| hash[key] = 0 } end end end diff --git a/lib/jekyll/liquid_renderer/file.rb b/lib/jekyll/liquid_renderer/file.rb index f91a5a2c625..146c416d3ff 100644 --- a/lib/jekyll/liquid_renderer/file.rb +++ b/lib/jekyll/liquid_renderer/file.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll class LiquidRenderer class File @@ -8,30 +10,55 @@ def initialize(renderer, filename) def parse(content) measure_time do - @template = Liquid::Template.parse(content) + @renderer.cache[@filename] ||= Liquid::Template.parse(content, :line_numbers => true) end + @template = @renderer.cache[@filename] self end def render(*args) + reset_template_assigns + measure_time do measure_bytes do - @template.render(*args) + measure_counts do + @template.render(*args) + end end end end + # This method simply 'rethrows any error' before attempting to render the template. def render!(*args) + reset_template_assigns + measure_time do measure_bytes do - @template.render!(*args) + measure_counts do + @template.render!(*args) + end end end end + def warnings + @template.warnings + end + private + # clear assigns to `Liquid::Template` instance prior to rendering since + # `Liquid::Template` instances are cached in Jekyll 4. + def reset_template_assigns + @template.instance_assigns.clear + end + + def measure_counts + @renderer.increment_count(@filename) + yield + end + def measure_bytes yield.tap do |str| @renderer.increment_bytes(@filename, str.bytesize) diff --git a/lib/jekyll/liquid_renderer/table.rb b/lib/jekyll/liquid_renderer/table.rb index 32b09cb3f04..2d06a26a76a 100644 --- a/lib/jekyll/liquid_renderer/table.rb +++ b/lib/jekyll/liquid_renderer/table.rb @@ -1,94 +1,45 @@ -module Jekyll - class LiquidRenderer::Table - def initialize(stats) - @stats = stats - end - - def to_s(n = 50) - data = data_for_table(n) - widths = table_widths(data) - generate_table(data, widths) - end - - private - - def generate_table(data, widths) - str = "\n" +# frozen_string_literal: true - table_head = data.shift - str << generate_row(table_head, widths) - str << generate_table_head_border(table_head, widths) +module Jekyll + class LiquidRenderer + class Table + GAUGES = [:count, :bytes, :time].freeze - data.each do |row_data| - str << generate_row(row_data, widths) + def initialize(stats) + @stats = stats end - str << "\n" - str - end - - def generate_table_head_border(row_data, widths) - str = "" - - row_data.each_index do |cell_index| - str << '-' * widths[cell_index] - str << '-+-' unless cell_index == row_data.length-1 + def to_s(num_of_rows = 50) + Jekyll::Profiler.tabulate(data_for_table(num_of_rows)) end - str << "\n" - str - end + private - def generate_row(row_data, widths) - str = '' + def data_for_table(num_of_rows) + sorted = @stats.sort_by { |_, file_stats| -file_stats[:time] } + sorted = sorted.slice(0, num_of_rows) - row_data.each_with_index do |cell_data, cell_index| - if cell_index == 0 - str << cell_data.ljust(widths[cell_index], ' ') - else - str << cell_data.rjust(widths[cell_index], ' ') + table = [header_labels] + sorted.each do |filename, file_stats| + row = [] + row << filename + row << file_stats[:count].to_s + row << format_bytes(file_stats[:bytes]) + row << format("%.3f", file_stats[:time]) + table << row end - str << ' | ' unless cell_index == row_data.length-1 + table end - str << "\n" - str - end - - def table_widths(data) - widths = [] - - data.each do |row| - row.each_with_index do |cell, index| - widths[index] = [ cell.length, widths[index] ].compact.max - end + def header_labels + GAUGES.map { |gauge| gauge.to_s.capitalize }.unshift("Filename") end - widths - end - - def data_for_table(n) - sorted = @stats.sort_by{ |filename, file_stats| -file_stats[:time] } - sorted = sorted.slice(0, n) - - table = [[ 'Filename', 'Count', 'Bytes', 'Time' ]] - - sorted.each do |filename, file_stats| - row = [] - row << filename - row << file_stats[:count].to_s - row << format_bytes(file_stats[:bytes]) - row << "%.3f" % file_stats[:time] - table << row + def format_bytes(bytes) + bytes /= 1024.0 + format("%.2fK", bytes) end - - table - end - - def format_bytes(bytes) - bytes /= 1024.0 - "%.2fK" % bytes end end end diff --git a/lib/jekyll/log_adapter.rb b/lib/jekyll/log_adapter.rb index df0cfdc4b10..6ddfa4ad6d2 100644 --- a/lib/jekyll/log_adapter.rb +++ b/lib/jekyll/log_adapter.rb @@ -1,13 +1,15 @@ +# frozen_string_literal: true + module Jekyll class LogAdapter - attr_reader :writer, :messages + attr_reader :writer, :messages, :level LOG_LEVELS = { :debug => ::Logger::DEBUG, :info => ::Logger::INFO, :warn => ::Logger::WARN, - :error => ::Logger::ERROR - } + :error => ::Logger::ERROR, + }.freeze # Public: Create a new instance of a log writer # @@ -27,7 +29,10 @@ def initialize(writer, level = :info) # # Returns nothing def log_level=(level) - writer.level = LOG_LEVELS.fetch(level) + writer.level = level if level.is_a?(Integer) && level.between?(0, 3) + writer.level = LOG_LEVELS[level] || + raise(ArgumentError, "unknown log level") + @level = level end def adjust_verbosity(options = {}) @@ -38,6 +43,7 @@ def adjust_verbosity(options = {}) self.log_level = :debug end debug "Logging at level:", LOG_LEVELS.key(writer.level).to_s + debug "Jekyll Version:", Jekyll::VERSION end # Public: Print a debug message @@ -46,8 +52,8 @@ def adjust_verbosity(options = {}) # message - the message detail # # Returns nothing - def debug(topic, message = nil) - writer.debug(message(topic, message)) + def debug(topic, message = nil, &block) + write(:debug, topic, message, &block) end # Public: Print a message @@ -56,8 +62,8 @@ def debug(topic, message = nil) # message - the message detail # # Returns nothing - def info(topic, message = nil) - writer.info(message(topic, message)) + def info(topic, message = nil, &block) + write(:info, topic, message, &block) end # Public: Print a message @@ -66,8 +72,8 @@ def info(topic, message = nil) # message - the message detail # # Returns nothing - def warn(topic, message = nil) - writer.warn(message(topic, message)) + def warn(topic, message = nil, &block) + write(:warn, topic, message, &block) end # Public: Print an error message @@ -76,8 +82,8 @@ def warn(topic, message = nil) # message - the message detail # # Returns nothing - def error(topic, message = nil) - writer.error(message(topic, message)) + def error(topic, message = nil, &block) + write(:error, topic, message, &block) end # Public: Print an error message and immediately abort the process @@ -86,8 +92,8 @@ def error(topic, message = nil) # message - the message detail (can be omitted) # # Returns nothing - def abort_with(topic, message = nil) - error(topic, message) + def abort_with(topic, message = nil, &block) + error(topic, message, &block) abort end @@ -97,19 +103,49 @@ def abort_with(topic, message = nil) # message - the message detail # # Returns the formatted message - def message(topic, message) - msg = formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ') - messages << msg - msg + def message(topic, message = nil) + raise ArgumentError, "block or message, not both" if block_given? && message + + message = yield if block_given? + message = message.to_s.gsub(%r!\s+!, " ") + topic = formatted_topic(topic, block_given?) + out = topic + message + messages << out + out end # Internal: Format the topic # # topic - the topic of the message, e.g. "Configuration file", "Deprecation", etc. + # colon - # # Returns the formatted topic statement - def formatted_topic(topic) - "#{topic} ".rjust(20) + def formatted_topic(topic, colon = false) + "#{topic}#{colon ? ": " : " "}".rjust(20) + end + + # Internal: Check if the message should be written given the log level. + # + # level_of_message - the Symbol level of message, one of :debug, :info, :warn, :error + # + # Returns whether the message should be written. + def write_message?(level_of_message) + LOG_LEVELS.fetch(level) <= LOG_LEVELS.fetch(level_of_message) + end + + # Internal: Log a message. + # + # level_of_message - the Symbol level of message, one of :debug, :info, :warn, :error + # topic - the String topic or full message + # message - the String message (optional) + # block - a block containing the message (optional) + # + # Returns false if the message was not written, otherwise returns the value of calling + # the appropriate writer method, e.g. writer.info. + def write(level_of_message, topic, message = nil, &block) + return false unless write_message?(level_of_message) + + writer.public_send(level_of_message, message(topic, message, &block)) end end end diff --git a/lib/jekyll/mime.types b/lib/jekyll/mime.types index 15828b91c4c..10f713c6ed7 100644 --- a/lib/jekyll/mime.types +++ b/lib/jekyll/mime.types @@ -5,41 +5,55 @@ application/andrew-inset ez application/applixware aw application/atom+xml atom application/atomcat+xml atomcat +application/atomdeleted+xml atomdeleted application/atomsvc+xml atomsvc +application/atsc-dwd+xml dwd +application/atsc-held+xml held +application/atsc-rsat+xml rsat application/bdoc bdoc +application/calendar+xml xcs application/ccxml+xml ccxml +application/cdfx+xml cdfx application/cdmi-capability cdmia application/cdmi-container cdmic application/cdmi-domain cdmid application/cdmi-object cdmio application/cdmi-queue cdmiq +application/cpl+xml cpl application/cu-seeme cu -application/dash+xml mdp +application/dash+xml mpd +application/dash-patch+xml mpp application/davmount+xml davmount application/docbook+xml dbk application/dssc+der dssc application/dssc+xml xdssc -application/ecmascript ecma +application/ecmascript ecma es application/emma+xml emma +application/emotionml+xml emotionml application/epub+zip epub application/exi exi +application/express exp +application/fdt+xml fdt application/font-tdpfr pfr -application/font-woff woff -application/font-woff2 woff2 +application/geo+json geojson application/gml+xml gml application/gpx+xml gpx application/gxf gxf +application/gzip gz +application/hjson hjson application/hyperstudio stk application/inkml+xml ink inkml application/ipfix ipfix -application/java-archive jar war ear +application/its+xml its +application/java-archive ear jar war application/java-serialized-object ser application/java-vm class -application/javascript js +application/javascript js mjs application/json json map application/json5 json5 application/jsonml+json jsonml application/ld+json jsonld +application/lgr+xml lgr application/lost+xml lostxml application/mac-binhex40 hqx application/mac-compactpro cpt @@ -47,32 +61,40 @@ application/mads+xml mads application/manifest+json webmanifest application/marc mrc application/marcxml+xml mrcx -application/mathematica ma nb mb +application/mathematica ma mb nb application/mathml+xml mathml application/mbox mbox +application/media-policy-dataset+xml mpf application/mediaservercontrol+xml mscml application/metalink+xml metalink application/metalink4+xml meta4 application/mets+xml mets +application/mmt-aei+xml maei +application/mmt-usd+xml musd application/mods+xml mods application/mp21 m21 mp21 -application/mp4 mp4s m4p +application/mp4 m4p mp4s application/msword doc dot application/mxf mxf -application/octet-stream bin dms lrf mar so dist distz pkg bpk dump elc deploy exe dll deb dmg iso img msi msp msm buffer +application/n-quads nq +application/n-triples nt +application/node cjs +application/octet-stream bin bpk buffer deb deploy dist distz dll dmg dms dump elc exe img iso lrf mar msi msm msp pkg so application/oda oda application/oebps-package+xml opf application/ogg ogx application/omdoc+xml omdoc -application/onenote onetoc onetoc2 onetmp onepkg +application/onenote onepkg onetmp onetoc onetoc2 application/oxps oxps +application/p2p-overlay+xml relo application/patch-ops-error+xml xer application/pdf pdf application/pgp-encrypted pgp -application/pgp-signature asc sig +application/pgp-keys asc +application/pgp-signature sig application/pics-rules prf application/pkcs10 p10 -application/pkcs7-mime p7m p7c +application/pkcs7-mime p7c p7m application/pkcs7-signature p7s application/pkcs8 p8 application/pkix-attr-cert ac @@ -82,14 +104,19 @@ application/pkix-pkipath pkipat application/pkixcmp pki application/pls+xml pls application/postscript ai eps ps +application/provenance+xml provx application/prs.cww cww application/pskc+xml pskcxml -application/rdf+xml rdf +application/raml+yaml raml +application/rdf+xml owl rdf application/reginfo+xml rif application/relax-ng-compact-syntax rnc application/resource-lists+xml rl application/resource-lists-diff+xml rld application/rls-services+xml rs +application/route-apd+xml rapd +application/route-s-tsid+xml sls +application/route-usd+xml rusd application/rpki-ghostbusters gbr application/rpki-manifest mft application/rpki-roa roa @@ -102,9 +129,12 @@ application/scvp-cv-response scs application/scvp-vp-request spq application/scvp-vp-response spp application/sdp sdp +application/senml+xml senmlx +application/sensml+xml sensmlx application/set-payment-initiation setpay application/set-registration-initiation setreg application/shf+xml shf +application/sieve sieve siv application/smil+xml smi smil application/sparql-query rq application/sparql-results+xml srx @@ -113,9 +143,17 @@ application/srgs+xml grxml application/sru+xml sru application/ssdl+xml ssdl application/ssml+xml ssml +application/swid+xml swidtag application/tei+xml tei teicorpus application/thraud+xml tfi application/timestamped-data tsd +application/toml toml +application/trig trig +application/ttml+xml ttml +application/ubjson ubj +application/urc-ressheet+xml rsheet +application/urc-targetdesc+xml td +application/vnd.1000minds.decision-model+xml 1km application/vnd.3gpp.pic-bw-large plb application/vnd.3gpp.pic-bw-small psb application/vnd.3gpp.pic-bw-var pvb @@ -124,12 +162,13 @@ application/vnd.3m.post-it-notes pwn application/vnd.accpac.simply.aso aso application/vnd.accpac.simply.imp imp application/vnd.acucobol acu -application/vnd.acucorp atc acutc +application/vnd.acucorp acutc atc application/vnd.adobe.air-application-installer-package+zip air application/vnd.adobe.formscentral.fcdt fcdt application/vnd.adobe.fxp fxp fxpl application/vnd.adobe.xdp+xml xdp application/vnd.adobe.xfdf xfdf +application/vnd.age age application/vnd.ahead.space ahead application/vnd.airzip.filesecure.azf azf application/vnd.airzip.filesecure.azs azs @@ -141,19 +180,25 @@ application/vnd.anser-web-certificate-issue-initiation cii application/vnd.anser-web-funds-transfer-initiation fti application/vnd.antix.game-component atx application/vnd.apple.installer+xml mpkg +application/vnd.apple.keynote key application/vnd.apple.mpegurl m3u8 +application/vnd.apple.numbers numbers +application/vnd.apple.pages pages +application/vnd.apple.pkpass pkpass application/vnd.aristanetworks.swi swi application/vnd.astraea-software.iota iota application/vnd.audiograph aep +application/vnd.balsamiq.bmml+xml bmml application/vnd.blueice.multipass mpm application/vnd.bmi bmi application/vnd.businessobjects rep application/vnd.chemdraw+xml cdxml application/vnd.chipnuts.karaoke-mmd mmd application/vnd.cinderella cdy +application/vnd.citationstyles.style+xml csl application/vnd.claymore cla application/vnd.cloanto.rp9 rp9 -application/vnd.clonk.c4group c4g c4d c4f c4p c4u +application/vnd.clonk.c4group c4d c4f c4g c4p c4u application/vnd.cluetrust.cartomobile-config c11amc application/vnd.cluetrust.cartomobile-config-pkg c11amz application/vnd.commonspace csp @@ -171,10 +216,11 @@ application/vnd.curl.car car application/vnd.curl.pcurl pcurl application/vnd.dart dart application/vnd.data-vision.rdz rdz -application/vnd.dece.data uvf uvvf uvd uvvd +application/vnd.dbf dbf +application/vnd.dece.data uvd uvf uvvd uvvf application/vnd.dece.ttml+xml uvt uvvt -application/vnd.dece.unspecified uvx uvvx -application/vnd.dece.zip uvz uvvz +application/vnd.dece.unspecified uvvx uvx +application/vnd.dece.zip uvvz uvz application/vnd.denovo.fcselayout-link fe_launch application/vnd.dna dna application/vnd.dolby.mlp mlp @@ -196,10 +242,10 @@ application/vnd.ezpix-album ez2 application/vnd.ezpix-package ez3 application/vnd.fdf fdf application/vnd.fdsn.mseed mseed -application/vnd.fdsn.seed seed dataless +application/vnd.fdsn.seed dataless seed application/vnd.flographit gph application/vnd.fluxtime.clip ftc -application/vnd.framemaker fm frame maker book +application/vnd.framemaker book fm frame maker application/vnd.frogans.fnc fnc application/vnd.frogans.ltf ltf application/vnd.fsc.weblaunch fsc @@ -220,6 +266,9 @@ application/vnd.geonext gxt application/vnd.geoplan g2w application/vnd.geospace g3w application/vnd.gmx gmx +application/vnd.google-apps.document gdoc +application/vnd.google-apps.presentation gslides +application/vnd.google-apps.spreadsheet gsheet application/vnd.google-earth.kml+xml kml application/vnd.google-earth.kmz kmz application/vnd.grafeq gqf gqs @@ -242,7 +291,7 @@ application/vnd.hp-pcl pcl application/vnd.hp-pclxl pclxl application/vnd.hydrostatix.sof-data sfd-hdstx application/vnd.ibm.minipay mpy -application/vnd.ibm.modcap afp listafp list3820 +application/vnd.ibm.modcap afp list3820 listafp application/vnd.ibm.rights-management irm application/vnd.ibm.secure-container sc application/vnd.iccprofile icc icm @@ -262,7 +311,7 @@ application/vnd.jam jam application/vnd.jcp.javame.midlet-rms rms application/vnd.jisp jisp application/vnd.joost.joda-archive joda -application/vnd.kahootz ktz ktr +application/vnd.kahootz ktr ktz application/vnd.kde.karbon karbon application/vnd.kde.kchart chrt application/vnd.kde.kformula kfo @@ -274,7 +323,7 @@ application/vnd.kde.kword kwd kw application/vnd.kenameaapp htke application/vnd.kidspiration kia application/vnd.kinar kne knp -application/vnd.koan skp skd skt skm +application/vnd.koan skd skm skp skt application/vnd.kodak-descriptor sse application/vnd.las.las+xml lasxml application/vnd.llamagraphics.life-balance.desktop lbd @@ -287,6 +336,7 @@ application/vnd.lotus-organizer org application/vnd.lotus-screencam scm application/vnd.lotus-wordpro lwp application/vnd.macports.portpkg portpkg +application/vnd.mapbox-vector-tile mvt application/vnd.mcd mcd application/vnd.medcalcdata mc1 application/vnd.mediastation.cdkey cdkey @@ -307,7 +357,7 @@ application/vnd.mophun.certificate mpc application/vnd.mozilla.xul+xml xul application/vnd.ms-artgalry cil application/vnd.ms-cab-compressed cab -application/vnd.ms-excel xls xlm xla xlc xlt xlw +application/vnd.ms-excel xla xlc xlm xls xlt xlw application/vnd.ms-excel.addin.macroenabled.12 xlam application/vnd.ms-excel.sheet.binary.macroenabled.12 xlsb application/vnd.ms-excel.sheet.macroenabled.12 xlsm @@ -317,18 +367,19 @@ application/vnd.ms-htmlhelp chm application/vnd.ms-ims ims application/vnd.ms-lrm lrm application/vnd.ms-officetheme thmx +application/vnd.ms-outlook msg application/vnd.ms-pki.seccat cat application/vnd.ms-pki.stl stl -application/vnd.ms-powerpoint ppt pps pot +application/vnd.ms-powerpoint pot pps ppt application/vnd.ms-powerpoint.addin.macroenabled.12 ppam application/vnd.ms-powerpoint.presentation.macroenabled.12 pptm application/vnd.ms-powerpoint.slide.macroenabled.12 sldm application/vnd.ms-powerpoint.slideshow.macroenabled.12 ppsm application/vnd.ms-powerpoint.template.macroenabled.12 potm -application/vnd.ms-project mpp mpt +application/vnd.ms-project mpt application/vnd.ms-word.document.macroenabled.12 docm application/vnd.ms-word.template.macroenabled.12 dotm -application/vnd.ms-works wps wks wcm wdb +application/vnd.ms-works wcm wdb wks wps application/vnd.ms-wpl wpl application/vnd.ms-xpsdocument xps application/vnd.mseq mseq @@ -336,7 +387,7 @@ application/vnd.musician mus application/vnd.muvee.style msty application/vnd.mynfc taglet application/vnd.neurolanguage.nlu nlu -application/vnd.nitf ntf nitf +application/vnd.nitf nitf ntf application/vnd.noblenet-directory nnd application/vnd.noblenet-sealer nns application/vnd.noblenet-web nnw @@ -366,7 +417,9 @@ application/vnd.oasis.opendocument.text-template ott application/vnd.oasis.opendocument.text-web oth application/vnd.olpc-sugar xo application/vnd.oma.dd2+xml dd2 +application/vnd.openblox.game+xml obgx application/vnd.openofficeorg.extension oxt +application/vnd.openstreetmap.data+xml osm application/vnd.openxmlformats-officedocument.presentationml.presentation pptx application/vnd.openxmlformats-officedocument.presentationml.slide sldx application/vnd.openxmlformats-officedocument.presentationml.slideshow ppsx @@ -378,7 +431,7 @@ application/vnd.openxmlformats-officedocument.wordprocessingml.template dotx application/vnd.osgeo.mapguide.package mgp application/vnd.osgi.dp dp application/vnd.osgi.subsystem esa -application/vnd.palm pdb pqa oprc +application/vnd.palm oprc pdb pqa application/vnd.pawaafile paw application/vnd.pg.format str application/vnd.pg.osasli ei6 @@ -390,7 +443,8 @@ application/vnd.previewsystems.box box application/vnd.proteus.magazine mgz application/vnd.publishare-delta-tree qps application/vnd.pvi.ptid1 ptid -application/vnd.quark.quarkxpress qxd qxt qwd qwt qxl qxb +application/vnd.quark.quarkxpress qwd qwt qxb qxd qxl qxt +application/vnd.rar rar application/vnd.realvnc.bed bed application/vnd.recordare.musicxml mxl application/vnd.recordare.musicxml+xml musicxml @@ -411,7 +465,8 @@ application/vnd.shana.informed.package ipk application/vnd.simtech-mindmapper twd twds application/vnd.smaf mmf application/vnd.smart.teacher teacher -application/vnd.solent.sdkm+xml sdkm sdkd +application/vnd.software602.filler.form+xml fo +application/vnd.solent.sdkm+xml sdkd sdkm application/vnd.spotfire.dxp dxp application/vnd.spotfire.sfs sfs application/vnd.stardivision.calc sdc @@ -422,6 +477,7 @@ application/vnd.stardivision.writer sdw vo application/vnd.stardivision.writer-global sgl application/vnd.stepmania.package smzip application/vnd.stepmania.stepchart sm +application/vnd.sun.wadl+xml wadl application/vnd.sun.xml.calc sxc application/vnd.sun.xml.calc.template stc application/vnd.sun.xml.draw sxd @@ -438,8 +494,9 @@ application/vnd.symbian.install sis si application/vnd.syncml+xml xsm application/vnd.syncml.dm+wbxml bdm application/vnd.syncml.dm+xml xdm +application/vnd.syncml.dmddf+xml ddf application/vnd.tao.intent-module-archive tao -application/vnd.tcpdump.pcap pcap cap dmp +application/vnd.tcpdump.pcap cap dmp pcap application/vnd.tmobile-livetv tmo application/vnd.trid.tpt tpt application/vnd.triscape.mxs mxs @@ -450,7 +507,7 @@ application/vnd.umajin umj application/vnd.unity unityweb application/vnd.uoml+xml uoml application/vnd.vcx vcx -application/vnd.visio vsd vst vss vsw +application/vnd.visio vsd vss vst vsw application/vnd.visionary vis application/vnd.vsf vsf application/vnd.wap.wbxml wbxml @@ -474,6 +531,8 @@ application/vnd.yellowriver-custom-menu cmp application/vnd.zul zir zirz application/vnd.zzazz.deck+xml zaz application/voicexml+xml vxml +application/wasm wasm +application/watcherinfo+xml wif application/widget wgt application/winhlp hlp application/wsdl+xml wsdl @@ -481,15 +540,16 @@ application/wspolicy+xml wspoli application/x-7z-compressed 7z application/x-abiword abw application/x-ace-compressed ace -application/x-authorware-bin aab x32 u32 vox +application/x-arj arj +application/x-authorware-bin aab u32 vox x32 application/x-authorware-map aam application/x-authorware-seg aas application/x-bcpio bcpio application/x-bittorrent torrent application/x-blorb blb blorb application/x-bzip bz -application/x-bzip2 bz2 boz -application/x-cbr cbr cba cbt cbz cb7 +application/x-bzip2 boz bz2 +application/x-cbr cb7 cba cbr cbt cbz application/x-cdlink vcd application/x-cfs-compressed cfs application/x-chat chat @@ -501,7 +561,7 @@ application/x-cpio cpio application/x-csh csh application/x-debian-package udeb application/x-dgc-compressed dgc -application/x-director dir dcr dxr cst cct cxt w3d fgd swa +application/x-director cct cst cxt dcr dir dxr fgd swa w3d application/x-doom wad application/x-dtbncx+xml ncx application/x-dtbook+xml dtb @@ -512,11 +572,9 @@ application/x-eva eva application/x-font-bdf bdf application/x-font-ghostscript gsf application/x-font-linux-psf psf -application/x-font-otf otf application/x-font-pcf pcf application/x-font-snf snf -application/x-font-ttf ttf ttc -application/x-font-type1 pfa pfb pfm afm +application/x-font-type1 afm pfa pfb pfm application/x-freearc arc application/x-futuresplash spl application/x-gca-compressed gca @@ -529,12 +587,13 @@ application/x-httpd-php php application/x-install-instructions install application/x-java-archive-diff jardiff application/x-java-jnlp-file jnlp +application/x-keepass2 kdbx application/x-latex latex application/x-lua-bytecode luac -application/x-lzh-compressed lzh lha +application/x-lzh-compressed lha lzh application/x-makeself run application/x-mie mie -application/x-mobipocket-ebook prc mobi +application/x-mobipocket-ebook mobi prc application/x-ms-application application application/x-ms-shortcut lnk application/x-ms-wmd wmd @@ -544,22 +603,21 @@ application/x-msaccess mdb application/x-msbinder obd application/x-mscardfile crd application/x-msclip clp -application/x-msdownload com bat -application/x-msmediaview mvb m13 m14 -application/x-msmetafile wmf emf emz +application/x-msdownload bat com +application/x-msmediaview m13 m14 mvb +application/x-msmetafile emf emz wmf application/x-msmoney mny application/x-mspublisher pub application/x-msschedule scd application/x-msterminal trm application/x-mswrite wri -application/x-netcdf nc cdf +application/x-netcdf cdf nc application/x-ns-proxy-autoconfig pac application/x-nzb nzb application/x-perl pl pm application/x-pkcs12 p12 pfx application/x-pkcs7-certificates p7b spc application/x-pkcs7-certreqresp p7r -application/x-rar-compressed rar application/x-redhat-package-manager rpm application/x-research-info-systems ris application/x-sea sea @@ -579,37 +637,53 @@ application/x-tar tar application/x-tcl tcl tk application/x-tex tex application/x-tex-tfm tfm -application/x-texinfo texinfo texi +application/x-texinfo texi texinfo application/x-tgif obj application/x-ustar ustar +application/x-virtualbox-hdd hdd +application/x-virtualbox-ova ova +application/x-virtualbox-ovf ovf +application/x-virtualbox-vbox vbox +application/x-virtualbox-vbox-extpack vbox-extpack +application/x-virtualbox-vdi vdi +application/x-virtualbox-vhd vhd +application/x-virtualbox-vmdk vmdk application/x-wais-source src application/x-web-app-manifest+json webapp -application/x-x509-ca-cert der crt pem +application/x-x509-ca-cert crt der pem application/x-xfig fig application/x-xliff+xml xlf application/x-xpinstall xpi application/x-xz xz application/x-zmachine z1 z2 z3 z4 z5 z6 z7 z8 application/xaml+xml xaml +application/xcap-att+xml xav +application/xcap-caps+xml xca application/xcap-diff+xml xdf +application/xcap-el+xml xel +application/xcap-ns+xml xns application/xenc+xml xenc -application/xhtml+xml xhtml xht -application/xml xml xsl xsd +application/xhtml+xml xht xhtml +application/xml rng xml xsd xsl application/xml-dtd dtd application/xop+xml xop application/xproc+xml xpl application/xslt+xml xslt application/xspf+xml xspf -application/xv+xml mxml xhvml xvml xvm +application/xv+xml mxml xhvml xvm xvml application/yang yang application/yin+xml yin application/zip zip +audio/3gpp 3gpp audio/adpcm adp +audio/amr amr audio/basic au snd -audio/midi mid midi kar rmi -audio/mp4 mp4a m4a -audio/mpeg mpga mp2 mp2a mp3 m2a m3a -audio/ogg oga ogg spx +audio/midi kar mid midi rmi +audio/mobile-xmf mxmf +audio/mp3 mp3 +audio/mp4 m4a mp4a +audio/mpeg m2a m3a mp2 mp2a mpga +audio/ogg oga ogg opus spx audio/s3m s3m audio/silk sil audio/vnd.dece.audio uva uvva @@ -626,14 +700,14 @@ audio/vnd.rip rip audio/wav wav audio/webm weba audio/x-aac aac -audio/x-aiff aif aiff aifc +audio/x-aiff aif aifc aiff audio/x-caf caf audio/x-flac flac audio/x-matroska mka audio/x-mpegurl m3u audio/x-ms-wax wax audio/x-ms-wma wma -audio/x-pn-realaudio ram ra +audio/x-pn-realaudio ra ram audio/x-pn-realaudio-plugin rmp audio/xm xm chemical/x-cdx cdx @@ -642,21 +716,57 @@ chemical/x-cmdf cmdf chemical/x-cml cml chemical/x-csml csml chemical/x-xyz xyz +font/collection ttc +font/otf otf +font/ttf ttf +font/woff woff +font/woff2 woff2 +image/aces exr +image/apng apng +image/avci avci +image/avcs avcs +image/avif avif image/bmp bmp image/cgm cgm +image/dicom-rle drle +image/fits fits image/g3fax g3 image/gif gif +image/heic heic +image/heic-sequence heics +image/heif heif +image/heif-sequence heifs +image/hej2k hej2 +image/hsj2 hsj2 image/ief ief -image/jpeg jpeg jpg jpe +image/jls jls +image/jp2 jp2 jpg2 +image/jpeg jpe jpeg jpg +image/jph jph +image/jphc jhc +image/jpm jpm +image/jpx jpf jpx +image/jxr jxr +image/jxra jxra +image/jxrs jxrs +image/jxs jxs +image/jxsc jxsc +image/jxsi jxsi +image/jxss jxss image/ktx ktx +image/ktx2 ktx2 image/png png image/prs.btif btif +image/prs.pti pti image/sgi sgi image/svg+xml svg svgz -image/tiff tiff tif +image/t38 t38 +image/tiff tif tiff +image/tiff-fx tfx image/vnd.adobe.photoshop psd -image/vnd.dece.graphic uvi uvvi uvg uvvg -image/vnd.djvu djvu djv +image/vnd.airzip.accelerator.azv azv +image/vnd.dece.graphic uvg uvi uvvg uvvi +image/vnd.djvu djv djvu image/vnd.dvb.subtitle sub image/vnd.dwg dwg image/vnd.dxf dxf @@ -665,21 +775,25 @@ image/vnd.fpx fpx image/vnd.fst fst image/vnd.fujixerox.edmics-mmr mmr image/vnd.fujixerox.edmics-rlc rlc +image/vnd.microsoft.icon ico +image/vnd.ms-dds dds image/vnd.ms-modi mdi image/vnd.ms-photo wdp image/vnd.net-fpx npx +image/vnd.pco.b16 b16 +image/vnd.tencent.tap tap +image/vnd.valve.source.texture vtf image/vnd.wap.wbmp wbmp image/vnd.xiff xif +image/vnd.zbrush.pcx pcx image/webp webp image/x-3ds 3ds image/x-cmu-raster ras image/x-cmx cmx -image/x-freehand fh fhc fh4 fh5 fh7 -image/x-icon ico +image/x-freehand fh fh4 fh5 fh7 fhc image/x-jng jng image/x-mrsid-image sid -image/x-pcx pcx -image/x-pict pic pct +image/x-pict pct pic image/x-portable-anymap pnm image/x-portable-bitmap pbm image/x-portable-graymap pgm @@ -689,16 +803,35 @@ image/x-tga tga image/x-xbitmap xbm image/x-xpixmap xpm image/x-xwindowdump xwd +message/disposition-notification disposition-notification +message/global u8msg +message/global-delivery-status u8dsn +message/global-disposition-notification u8mdn +message/global-headers u8hdr message/rfc822 eml mime -model/iges igs iges -model/mesh msh mesh silo +message/vnd.wfa.wsc wsc +model/3mf 3mf +model/gltf+json gltf +model/gltf-binary glb +model/iges iges igs +model/mesh mesh msh silo +model/mtl mtl +model/step+xml stpx +model/step+zip stpz +model/step-xml+zip stpxz model/vnd.collada+xml dae model/vnd.dwf dwf model/vnd.gdl gdl model/vnd.gtw gtw model/vnd.mts mts +model/vnd.opengex ogex +model/vnd.parasolid.transmit.binary x_b +model/vnd.parasolid.transmit.text x_t +model/vnd.sap.vds vds +model/vnd.usdz+zip usdz +model/vnd.valve.source.compiled-map bsp model/vnd.vtu vtu -model/vrml wrl vrml +model/vrml vrml wrl model/x3d+binary x3db x3dbz model/x3d+vrml x3dv x3dvz model/x3d+xml x3d x3dz @@ -707,20 +840,24 @@ text/calendar ics if text/coffeescript coffee litcoffee text/css css text/csv csv -text/hjson hjson -text/html html htm shtml +text/html htm html shtml text/jade jade text/jsx jsx text/less less +text/markdown markdown md text/mathml mml +text/mdx mdx text/n3 n3 -text/plain txt text conf def list log in ini +text/plain conf def in ini list log text txt text/prs.lines.tag dsc text/richtext rtx -text/sgml sgml sgm -text/stylus stylus styl +text/sgml sgm sgml +text/shex shex +text/slim slim slm +text/spdx spdx +text/stylus styl stylus text/tab-separated-values tsv -text/troff t tr roff man me ms +text/troff man me ms roff t tr text/turtle ttl text/uri-list uri uris urls text/vcard vcard @@ -728,6 +865,7 @@ text/vnd.curl curl text/vnd.curl.dcurl dcurl text/vnd.curl.mcurl mcurl text/vnd.curl.scurl scurl +text/vnd.familysearch.gedcom ged text/vnd.fly fly text/vnd.fmi.flexstor flx text/vnd.graphviz gv @@ -737,14 +875,14 @@ text/vnd.sun.j2me.app-descriptor jad text/vnd.wap.wml wml text/vnd.wap.wmlscript wmls text/vtt vtt -text/x-asm s asm -text/x-c c cc cxx cpp h hh dic +text/x-asm asm s +text/x-c c cc cpp cxx dic h hh text/x-component htc -text/x-fortran f for f77 f90 +text/x-fortran f f77 f90 for text/x-handlebars-template hbs text/x-java-source java text/x-lua lua -text/x-markdown markdown md mkd +text/x-markdown mkd text/x-nfo nfo text/x-opml opml text/x-pascal p pas @@ -753,23 +891,25 @@ text/x-sass sass text/x-scss scss text/x-setext etx text/x-sfv sfv +text/x-suse-ymp ymp text/x-uuencode uu text/x-vcalendar vcs text/x-vcard vcf text/yaml yaml yml -video/3gpp 3gp 3gpp +video/3gpp 3gp video/3gpp2 3g2 video/h261 h261 video/h263 h263 video/h264 h264 +video/iso.segment m4s video/jpeg jpgv -video/jpm jpm jpgm +video/jpm jpgm video/mj2 mj2 mjp2 video/mp2t ts video/mp4 mp4 mp4v mpg4 -video/mpeg mpeg mpg mpe m1v m2v +video/mpeg m1v m2v mpe mpeg mpg video/ogg ogv -video/quicktime qt mov +video/quicktime mov qt video/vnd.dece.hd uvh uvvh video/vnd.dece.mobile uvm uvvm video/vnd.dece.pd uvp uvvp @@ -777,7 +917,7 @@ video/vnd.dece.sd uvs uv video/vnd.dece.video uvv uvvv video/vnd.dvb.file dvb video/vnd.fvt fvt -video/vnd.mpegurl mxu m4u +video/vnd.mpegurl m4u mxu video/vnd.ms-playready.media.pyv pyv video/vnd.uvvu.mp4 uvu uvvu video/vnd.vivo viv @@ -786,7 +926,7 @@ video/x-f4v f4v video/x-fli fli video/x-flv flv video/x-m4v m4v -video/x-matroska mkv mk3d mks +video/x-matroska mk3d mks mkv video/x-mng mng video/x-ms-asf asf asx video/x-ms-vob vob diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index ca5bb268131..64821a82d56 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -1,20 +1,32 @@ +# frozen_string_literal: true + module Jekyll class Page include Convertible attr_writer :dir - attr_accessor :site, :pager - attr_accessor :name, :ext, :basename - attr_accessor :data, :content, :output + attr_accessor :basename, :content, :data, :ext, :name, :output, :pager, :site + + alias_method :extname, :ext # Attributes for Liquid templates - ATTRIBUTES_FOR_LIQUID = %w[ + ATTRIBUTES_FOR_LIQUID = %w( content dir + excerpt name path url - ] + ).freeze + + # A set of extensions that are considered HTML or HTML-like so we + # should not alter them, this includes .xhtml through XHTM5. + + HTML_EXTENSIONS = %w( + .html + .xhtml + .htm + ).freeze # Initialize a new Page. # @@ -27,13 +39,18 @@ def initialize(site, base, dir, name) @base = base @dir = dir @name = name - + @path = if site.in_theme_dir(base) == base # we're in a theme + site.in_theme_dir(base, dir, name) + else + site.in_source_dir(base, dir, name) + end process(name) - read_yaml(File.join(base, dir), name) + read_yaml(PathManager.join(base, dir), name) + generate_excerpt if site.config["page_excerpts"] - data.default_proc = proc do |hash, key| - site.frontmatter_defaults.find(File.join(dir, name), type, key) + data.default_proc = proc do |_, key| + site.frontmatter_defaults.find(relative_path, type, key) end Jekyll::Hooks.trigger :pages, :post_init, self @@ -41,11 +58,11 @@ def initialize(site, base, dir, name) # The generated directory into which the page will be placed # upon generation. This is derived from the permalink or, if - # permalink is absent, we be '/' + # permalink is absent, will be '/' # # Returns the String destination directory. def dir - url[-1, 1] == '/' ? url : File.dirname(url) + url.end_with?("/") ? url : url_dir end # The full path and filename of the post. Defined in the YAML of the post @@ -53,8 +70,7 @@ def dir # # Returns the String permalink or nil if none has been set. def permalink - return nil if data.nil? || data['permalink'].nil? - data['permalink'] + data.nil? ? nil : data["permalink"] end # The template of the permalink. @@ -74,11 +90,11 @@ def template # # Returns the String url. def url - @url ||= URL.new({ - :template => template, + @url ||= URL.new( + :template => template, :placeholders => url_placeholders, - :permalink => permalink - }).to_s + :permalink => permalink + ).to_s end # Returns a hash of URL placeholder names (as symbols) mapping to the @@ -87,7 +103,7 @@ def url_placeholders { :path => @dir, :basename => basename, - :output_ext => output_ext + :output_ext => output_ext, } end @@ -95,10 +111,13 @@ def url_placeholders # # name - The String filename of the page file. # + # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`) # Returns nothing. def process(name) + return unless name + self.ext = File.extname(name) - self.basename = name[0 .. -ext.length - 1] + self.basename = name[0..-ext.length - 1].gsub(%r!\.*\z!, "") end # Add any necessary layouts to this post @@ -106,26 +125,24 @@ def process(name) # layouts - The Hash of {"name" => "layout"}. # site_payload - The site payload Hash. # - # Returns nothing. + # Returns String rendered page. def render(layouts, site_payload) - payload = Utils.deep_merge_hashes({ - "page" => to_liquid, - 'paginator' => pager.to_liquid - }, site_payload) + site_payload["page"] = to_liquid + site_payload["paginator"] = pager.to_liquid - do_layout(payload, layouts) + do_layout(site_payload, layouts) end # The path to the source file # # Returns the path to the source file def path - data.fetch('path') { relative_path.sub(/\A\//, '') } + data.fetch("path") { relative_path } end # The path to the page source file, relative to the site source def relative_path - File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)) + @relative_path ||= PathManager.join(@dir, @name).delete_prefix("/") end # Obtain destination path. @@ -134,25 +151,65 @@ def relative_path # # Returns the destination file path String. def destination(dest) - path = site.in_dest_dir(dest, URL.unescape_path(url)) - path = File.join(path, "index.html") if url.end_with?("/") - path << output_ext unless path.end_with?(output_ext) - path + @destination ||= {} + @destination[dest] ||= begin + path = site.in_dest_dir(dest, URL.unescape_path(url)) + path = File.join(path, "index") if url.end_with?("/") + path << output_ext unless path.end_with? output_ext + path + end end # Returns the object as a debug String. def inspect - "#" + "#<#{self.class} @relative_path=#{relative_path.inspect}>" end # Returns the Boolean of whether this Page is HTML or not. def html? - output_ext == '.html' + HTML_EXTENSIONS.include?(output_ext) end # Returns the Boolean of whether this Page is an index file or not. def index? - basename == 'index' + basename == "index" + end + + def trigger_hooks(hook_name, *args) + Jekyll::Hooks.trigger :pages, hook_name, self, *args + end + + def write? + true + end + + def excerpt_separator + @excerpt_separator ||= (data["excerpt_separator"] || site.config["excerpt_separator"]).to_s + end + + def excerpt + return @excerpt if defined?(@excerpt) + + @excerpt = data["excerpt"] ? data["excerpt"].to_s : nil + end + + def generate_excerpt? + !excerpt_separator.empty? && instance_of?(Jekyll::Page) && html? + end + + private + + def generate_excerpt + return unless generate_excerpt? + + data["excerpt"] ||= Jekyll::PageExcerpt.new(self) + end + + def url_dir + @url_dir ||= begin + value = File.dirname(url) + value.end_with?("/") ? value : "#{value}/" + end end end end diff --git a/lib/jekyll/page_excerpt.rb b/lib/jekyll/page_excerpt.rb new file mode 100644 index 00000000000..dd79fca8d78 --- /dev/null +++ b/lib/jekyll/page_excerpt.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Jekyll + class PageExcerpt < Excerpt + attr_reader :doc + alias_method :id, :relative_path + + EXCERPT_ATTRIBUTES = (Page::ATTRIBUTES_FOR_LIQUID - %w(excerpt)).freeze + private_constant :EXCERPT_ATTRIBUTES + + def to_liquid + @to_liquid ||= doc.to_liquid(EXCERPT_ATTRIBUTES) + end + + def render_with_liquid? + return false if data["render_with_liquid"] == false + + Jekyll::Utils.has_liquid_construct?(content) + end + + def inspect + "#<#{self.class} id=#{id.inspect}>" + end + end +end diff --git a/lib/jekyll/page_without_a_file.rb b/lib/jekyll/page_without_a_file.rb new file mode 100644 index 00000000000..e314f970a6d --- /dev/null +++ b/lib/jekyll/page_without_a_file.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module Jekyll + # A Jekyll::Page subclass to handle processing files without reading it to + # determine the page-data and page-content based on Front Matter delimiters. + # + # The class instance is basically just a bare-bones entity with just + # attributes "dir", "name", "path", "url" defined on it. + class PageWithoutAFile < Page + def read_yaml(*) + @data ||= {} + end + end +end diff --git a/lib/jekyll/path_manager.rb b/lib/jekyll/path_manager.rb new file mode 100644 index 00000000000..5d9752228ad --- /dev/null +++ b/lib/jekyll/path_manager.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +module Jekyll + # A singleton class that caches frozen instances of path strings returned from its methods. + # + # NOTE: + # This class exists because `File.join` allocates an Array and returns a new String on every + # call using **the same arguments**. Caching the result means reduced memory usage. + # However, the caches are never flushed so that they can be used even when a site is + # regenerating. The results are frozen to deter mutation of the cached string. + # + # Therefore, employ this class only for situations where caching the result is necessary + # for performance reasons. + # + class PathManager + # This class cannot be initialized from outside + private_class_method :new + + class << self + # Wraps `File.join` to cache the frozen result. + # Reassigns `nil`, empty strings and empty arrays to a frozen empty string beforehand. + # + # Returns a frozen string. + def join(base, item) + base = "" if base.nil? || base.empty? + item = "" if item.nil? || item.empty? + @join ||= {} + @join[base] ||= {} + @join[base][item] ||= File.join(base, item).freeze + end + + # Ensures the questionable path is prefixed with the base directory + # and prepends the questionable path with the base directory if false. + # + # Returns a frozen string. + def sanitized_path(base_directory, questionable_path) + @sanitized_path ||= {} + @sanitized_path[base_directory] ||= {} + @sanitized_path[base_directory][questionable_path] ||= if questionable_path.nil? + base_directory.freeze + else + sanitize_and_join( + base_directory, questionable_path + ).freeze + end + end + + private + + def sanitize_and_join(base_directory, questionable_path) + clean_path = if questionable_path.start_with?("~") + questionable_path.dup.insert(0, "/") + else + questionable_path + end + clean_path = File.expand_path(clean_path, "/") + return clean_path if clean_path.eql?(base_directory) + + # remove any remaining extra leading slashes not stripped away by calling + # `File.expand_path` above. + clean_path.squeeze!("/") + return clean_path if clean_path.start_with?(slashed_dir_cache(base_directory)) + + clean_path.sub!(%r!\A\w:/!, "/") + join(base_directory, clean_path) + end + + def slashed_dir_cache(base_directory) + @slashed_dir_cache ||= {} + @slashed_dir_cache[base_directory] ||= base_directory.sub(%r!\z!, "/") + end + end + end +end diff --git a/lib/jekyll/plugin.rb b/lib/jekyll/plugin.rb index 0207314c8af..1157e12a688 100644 --- a/lib/jekyll/plugin.rb +++ b/lib/jekyll/plugin.rb @@ -1,20 +1,39 @@ +# frozen_string_literal: true + module Jekyll class Plugin - PRIORITIES = { :lowest => -100, - :low => -10, - :normal => 0, - :high => 10, - :highest => 100 } + PRIORITIES = { + :low => -10, + :highest => 100, + :lowest => -100, + :normal => 0, + :high => 10, + }.freeze - # Fetch all the subclasses of this class and its subclasses' subclasses. # - # Returns an array of descendant classes. - def self.descendants - descendants = [] - ObjectSpace.each_object(singleton_class) do |k| - descendants.unshift k unless k == self + + def self.inherited(const) + catch_inheritance(const) do |const_| + catch_inheritance(const_) + end + end + + # + + def self.catch_inheritance(const) + const.define_singleton_method :inherited do |const_| + (@children ||= Set.new).add const_ + yield const_ if block_given? end - descendants + end + + # + + def self.descendants + @children ||= Set.new + out = @children.map(&:descendants) + out << self unless superclass == Plugin + Set.new(out).flatten end # Get or set the priority of this plugin. When called without an @@ -27,9 +46,7 @@ def self.descendants # Returns the Symbol priority. def self.priority(priority = nil) @priority ||= nil - if priority && PRIORITIES.key?(priority) - @priority = priority - end + @priority = priority if priority && PRIORITIES.key?(priority) @priority || :normal end @@ -41,9 +58,7 @@ def self.priority(priority = nil) # # Returns the safety Boolean. def self.safe(safe = nil) - if safe - @safe = safe - end + @safe = safe unless defined?(@safe) && safe.nil? @safe || false end @@ -53,7 +68,7 @@ def self.safe(safe = nil) # # Returns -1, 0, 1. def self.<=>(other) - PRIORITIES[other.priority] <=> PRIORITIES[self.priority] + PRIORITIES[other.priority] <=> PRIORITIES[priority] end # Spaceship is priority [higher -> lower] diff --git a/lib/jekyll/plugin_manager.rb b/lib/jekyll/plugin_manager.rb index bc541617255..810a2fa129f 100644 --- a/lib/jekyll/plugin_manager.rb +++ b/lib/jekyll/plugin_manager.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll class PluginManager attr_reader :site @@ -15,6 +17,7 @@ def initialize(site) # # Returns nothing def conscientious_require + require_theme_deps if site.theme require_plugin_files require_gems deprecation_checks @@ -24,37 +27,55 @@ def conscientious_require # # Returns nothing. def require_gems - site.gems.each do |gem| - if plugin_allowed?(gem) - Jekyll.logger.debug("PluginManager:", "Requiring #{gem}") - require gem - end + Jekyll::External.require_with_graceful_fail( + site.gems.select { |plugin| plugin_allowed?(plugin) } + ) + end + + # Require each of the runtime_dependencies specified by the theme's gemspec. + # + # Returns false only if no dependencies have been specified, otherwise nothing. + def require_theme_deps + return false unless site.theme.runtime_dependencies + + site.theme.runtime_dependencies.each do |dep| + next if dep.name == "jekyll" + + External.require_with_graceful_fail(dep.name) if plugin_allowed?(dep.name) end end def self.require_from_bundler - if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile") + if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && gemfile_exists? require "bundler" - Bundler.setup # puts all groups on the load path - required_gems = Bundler.require(:jekyll_plugins) # requires the gems in this group only - Jekyll.logger.debug("PluginManager:", "Required #{required_gems.map(&:name).join(', ')}") + + Bundler.setup + required_gems = Bundler.require(:jekyll_plugins) + message = "Required #{required_gems.map(&:name).join(", ")}" + Jekyll.logger.debug("PluginManager:", message) ENV["JEKYLL_NO_BUNDLER_REQUIRE"] = "true" + true else false end - rescue LoadError, Bundler::GemfileNotFound - false + end + + # Check for the existence of a Gemfile. + # + # Returns true if a Gemfile exists in the places bundler will look + def self.gemfile_exists? + File.file?("Gemfile") || (ENV["BUNDLE_GEMFILE"] && File.file?(ENV["BUNDLE_GEMFILE"])) end # Check whether a gem plugin is allowed to be used during this build. # - # gem_name - the name of the gem + # plugin_name - the name of the plugin # - # Returns true if the gem name is in the whitelist or if the site is not + # Returns true if the plugin name is in the whitelist or if the site is not # in safe mode. - def plugin_allowed?(gem_name) - !site.safe || whitelist.include?(gem_name) + def plugin_allowed?(plugin_name) + !site.safe || whitelist.include?(plugin_name) end # Build an array of allowed plugin gem names. @@ -62,7 +83,7 @@ def plugin_allowed?(gem_name) # Returns an array of strings, each string being the name of a gem name # that is allowed to be used. def whitelist - @whitelist ||= Array[site.config['whitelist']].flatten + @whitelist ||= [site.config["whitelist"]].flatten end # Require all .rb files if safe mode is off @@ -70,10 +91,9 @@ def whitelist # Returns nothing. def require_plugin_files unless site.safe - plugins_path.each do |plugins| - Dir[File.join(plugins, "**", "*.rb")].sort.each do |f| - require f - end + plugins_path.each do |plugin_search_path| + plugin_files = Utils.safe_glob(plugin_search_path, File.join("**", "*.rb")) + Jekyll::External.require_with_graceful_fail(plugin_files) end end end @@ -82,21 +102,22 @@ def require_plugin_files # # Returns an Array of plugin search paths def plugins_path - if (site.config['plugins_dir'] == Jekyll::Configuration::DEFAULTS['plugins_dir']) - [site.in_source_dir(site.config['plugins_dir'])] + if site.config["plugins_dir"].eql? Jekyll::Configuration::DEFAULTS["plugins_dir"] + [site.in_source_dir(site.config["plugins_dir"])] else - Array(site.config['plugins_dir']).map { |d| File.expand_path(d) } + Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) } end end def deprecation_checks - pagination_included = (site.config['gems'] || []).include?('jekyll-paginate') || defined?(Jekyll::Paginate) - if site.config['paginate'] && !pagination_included - Jekyll::Deprecator.deprecation_message "You appear to have pagination " + - "turned on, but you haven't included the `jekyll-paginate` gem. " + - "Ensure you have `gems: [jekyll-paginate]` in your configuration file." + pagination_included = (site.config["plugins"] || []).include?("jekyll-paginate") || + defined?(Jekyll::Paginate) + if site.config["paginate"] && !pagination_included + Jekyll::Deprecator.deprecation_message <<~MSG + You appear to have pagination turned on, but you haven't included the `jekyll-paginate` + gem. Ensure you have `plugins: [jekyll-paginate]` in your configuration file. + MSG end end - end end diff --git a/lib/jekyll/profiler.rb b/lib/jekyll/profiler.rb new file mode 100644 index 00000000000..f5dbfb18e7e --- /dev/null +++ b/lib/jekyll/profiler.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module Jekyll + class Profiler + TERMINAL_TABLE_STYLES = { + :alignment => :right, + :border_top => false, + :border_bottom => false, + }.freeze + private_constant :TERMINAL_TABLE_STYLES + + def self.tabulate(table_rows) + require "terminal-table" + + rows = table_rows.dup + header = rows.shift + output = +"\n" + + table = Terminal::Table.new do |t| + t << header + t << :separator + rows.each { |row| t << row } + t.style = TERMINAL_TABLE_STYLES + t.align_column(0, :left) + end + + output << table.to_s << "\n" + end + + def initialize(site) + @site = site + end + + def profile_process + profile_data = { "PHASE" => "TIME" } + + [:reset, :read, :generate, :render, :cleanup, :write].each do |method| + start_time = Time.now + @site.send(method) + end_time = (Time.now - start_time).round(4) + profile_data[method.to_s.upcase] = format("%.4f", end_time) + end + + Jekyll.logger.info "\nBuild Process Summary:" + Jekyll.logger.info Profiler.tabulate(Array(profile_data)) + + Jekyll.logger.info "\nSite Render Stats:" + @site.print_stats + end + end +end diff --git a/lib/jekyll/publisher.rb b/lib/jekyll/publisher.rb index 6bb8a882116..46df177c1c1 100644 --- a/lib/jekyll/publisher.rb +++ b/lib/jekyll/publisher.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll class Publisher def initialize(site) @@ -8,14 +10,21 @@ def publish?(thing) can_be_published?(thing) && !hidden_in_the_future?(thing) end + def hidden_in_the_future?(thing) + thing.respond_to?(:date) && + !@site.future && + !collection_allows_future?(thing) && + thing.date.to_i > @site.time.to_i + end + private def can_be_published?(thing) - thing.data.fetch('published', true) || @site.unpublished + thing.data.fetch("published", true) || @site.unpublished end - def hidden_in_the_future?(thing) - thing.respond_to?(:date) && !@site.future && thing.date.to_i > @site.time.to_i + def collection_allows_future?(thing) + thing.respond_to?(:collection) && !!thing.collection.metadata["future"] end end end diff --git a/lib/jekyll/reader.rb b/lib/jekyll/reader.rb index 45a204228bc..5d15177c914 100644 --- a/lib/jekyll/reader.rb +++ b/lib/jekyll/reader.rb @@ -1,5 +1,4 @@ -# encoding: UTF-8 -require 'csv' +# frozen_string_literal: true module Jekyll class Reader @@ -15,14 +14,33 @@ def initialize(site) def read @site.layouts = LayoutReader.new(site).read read_directories + read_included_excludes sort_files! - @site.data = DataReader.new(site).read(site.config['data_dir']) CollectionReader.new(site).read + ThemeAssetsReader.new(site).read + read_data + end + + # Read and merge the data files. + # If a theme is specified and it contains data, it will be read. + # Site data will overwrite theme data with the same key using the + # semantics of Utils.deep_merge_hashes. + # + # Returns nothing. + def read_data + @site.data = DataReader.new(site).read(site.config["data_dir"]) + return unless site.theme&.data_path + + theme_data = DataReader.new( + site, + :in_source_dir => site.method(:in_theme_dir) + ).read(site.theme.data_path) + @site.data = Jekyll::Utils.deep_merge_hashes(theme_data, @site.data) end # Sorts posts, pages, and static files. def sort_files! - site.collections.values.each{|c| c.docs.sort!} + site.collections.each_value { |c| c.docs.sort! } site.pages.sort_by!(&:name) site.static_files.sort_by!(&:relative_path) end @@ -34,14 +52,26 @@ def sort_files! # dir - The String relative path of the directory to read. Default: ''. # # Returns nothing. - def read_directories(dir = '') + def read_directories(dir = "") base = site.in_source_dir(dir) - dot = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) } - dot_dirs = dot.select{ |file| File.directory?(@site.in_source_dir(base,file)) } - dot_files = (dot - dot_dirs) - dot_pages = dot_files.select{ |file| Utils.has_yaml_header?(@site.in_source_dir(base,file)) } - dot_static_files = dot_files - dot_pages + return unless File.directory?(base) + + dot_dirs = [] + dot_pages = [] + dot_static_files = [] + + dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) } + dot.each do |entry| + file_path = @site.in_source_dir(base, entry) + if File.directory?(file_path) + dot_dirs << entry + elsif Utils.has_yaml_header?(file_path) + dot_pages << entry + else + dot_static_files << entry + end + end retrieve_posts(dir) retrieve_dirs(base, dir, dot_dirs) @@ -56,8 +86,10 @@ def read_directories(dir = '') # # Returns nothing. def retrieve_posts(dir) - site.posts.docs.concat(PostReader.new(site).read_posts(dir)) - site.posts.docs.concat(PostReader.new(site).read_drafts(dir)) if site.show_drafts + return if outside_configured_directory?(dir) + + site.posts.docs.concat(post_reader.read_posts(dir)) + site.posts.docs.concat(post_reader.read_drafts(dir)) if site.show_drafts end # Recursively traverse directories with the read_directories function. @@ -67,12 +99,12 @@ def retrieve_posts(dir) # dot_dirs - The Array of subdirectories in the dir. # # Returns nothing. - def retrieve_dirs(base, dir, dot_dirs) - dot_dirs.map { |file| - dir_path = site.in_source_dir(dir,file) - rel_path = File.join(dir, file) - @site.reader.read_directories(rel_path) unless @site.dest.sub(/\/$/, '') == dir_path - } + def retrieve_dirs(_base, dir, dot_dirs) + dot_dirs.each do |file| + dir_path = site.in_source_dir(dir, file) + rel_path = PathManager.join(dir, file) + @site.reader.read_directories(rel_path) unless @site.dest.chomp("/") == dir_path + end end # Retrieve all the pages from the current directory, @@ -119,8 +151,59 @@ def filter_entries(entries, base_directory = nil) def get_entries(dir, subfolder) base = site.in_source_dir(dir, subfolder) return [] unless File.exist?(base) - entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) } + + entries = Dir.chdir(base) { filter_entries(Dir["**/*"], base) } entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) } end + + private + + # Internal + # + # Determine if the directory is supposed to contain posts and drafts. + # If the user has defined a custom collections_dir, then attempt to read + # posts and drafts only from within that directory. + # + # Returns true if a custom collections_dir has been set but current directory lies + # outside that directory. + def outside_configured_directory?(dir) + collections_dir = site.config["collections_dir"] + !collections_dir.empty? && !dir.start_with?("/#{collections_dir}") + end + + # Create a single PostReader instance to retrieve drafts and posts from all valid + # directories in current site. + def post_reader + @post_reader ||= PostReader.new(site) + end + + def read_included_excludes + entry_filter = EntryFilter.new(site) + + site.include.each do |entry| + entry_path = site.in_source_dir(entry) + next if File.directory?(entry_path) + next if entry_filter.symlink?(entry_path) + + read_included_file(entry_path) if File.file?(entry_path) + end + end + + def read_included_file(entry_path) + if Utils.has_yaml_header?(entry_path) + conditionally_generate_entry(entry_path, site.pages, PageReader) + else + conditionally_generate_entry(entry_path, site.static_files, StaticFileReader) + end + end + + def conditionally_generate_entry(entry_path, container, reader) + return if container.find { |item| site.in_source_dir(item.relative_path) == entry_path } + + dir, files = File.split(entry_path) + dir.sub!(site.source, "") + files = Array(files) + container.concat(reader.new(site, dir).read(files)) + end end end diff --git a/lib/jekyll/readers/collection_reader.rb b/lib/jekyll/readers/collection_reader.rb index 6a54321d45d..6d1827504b8 100644 --- a/lib/jekyll/readers/collection_reader.rb +++ b/lib/jekyll/readers/collection_reader.rb @@ -1,8 +1,11 @@ +# frozen_string_literal: true + module Jekyll class CollectionReader - SPECIAL_COLLECTIONS = %w{posts data}.freeze + SPECIAL_COLLECTIONS = %w(posts data).freeze attr_reader :site, :content + def initialize(site) @site = site @content = {} @@ -12,10 +15,9 @@ def initialize(site) # # Returns nothing. def read - site.collections.each do |_, collection| + site.collections.each_value do |collection| collection.read unless SPECIAL_COLLECTIONS.include?(collection.label) end end - end end diff --git a/lib/jekyll/readers/data_reader.rb b/lib/jekyll/readers/data_reader.rb index cbb24be3053..80b57bd6bd7 100644 --- a/lib/jekyll/readers/data_reader.rb +++ b/lib/jekyll/readers/data_reader.rb @@ -1,45 +1,51 @@ +# frozen_string_literal: true + module Jekyll class DataReader attr_reader :site, :content - def initialize(site) + + def initialize(site, in_source_dir: nil) @site = site @content = {} + @entry_filter = EntryFilter.new(site) + @in_source_dir = in_source_dir || @site.method(:in_source_dir) + @source_dir = @in_source_dir.call("/") end - # Read all the files in //_drafts and create a new Draft - # object with each one. + # Read all the files in and adds them to @content # # dir - The String relative path of the directory to read. # - # Returns nothing. + # Returns @content, a Hash of the .yaml, .yml, + # .json, and .csv files in the base directory def read(dir) - base = site.in_source_dir(dir) + base = @in_source_dir.call(dir) read_data_to(base, @content) @content end - # Read and parse all yaml files under and add them to the - # variable. + # Read and parse all .yaml, .yml, .json, .csv and .tsv + # files under and add them to the variable. # # dir - The string absolute path of the directory to read. # data - The variable to which data will be added. # # Returns nothing def read_data_to(dir, data) - return unless File.directory?(dir) && (!site.safe || !File.symlink?(dir)) + return unless File.directory?(dir) && !@entry_filter.symlink?(dir) entries = Dir.chdir(dir) do - Dir['*.{yaml,yml,json,csv}'] + Dir['*'].select { |fn| File.directory?(fn) } + Dir["*.{yaml,yml,json,csv,tsv}"] + Dir["*"].select { |fn| File.directory?(fn) } end entries.each do |entry| - path = @site.in_source_dir(dir, entry) - next if File.symlink?(path) && site.safe + path = @in_source_dir.call(dir, entry) + next if @entry_filter.symlink?(path) - key = sanitize_filename(File.basename(entry, '.*')) if File.directory?(path) - read_data_to(path, data[key] = {}) + read_data_to(path, data[sanitize_filename(entry)] = {}) else + key = sanitize_filename(File.basename(entry, ".*")) data[key] = read_data_file(path) end end @@ -49,21 +55,59 @@ def read_data_to(dir, data) # # Returns the contents of the data file. def read_data_file(path) + Jekyll.logger.debug "Reading:", path.sub(@source_dir, "") + case File.extname(path).downcase - when '.csv' - CSV.read(path, { - :headers => true, - :encoding => site.config['encoding'] - }).map(&:to_hash) - else - SafeYAML.load_file(path) + when ".csv" + CSV.read(path, **csv_config).map { |row| convert_row(row) } + when ".tsv" + CSV.read(path, **tsv_config).map { |row| convert_row(row) } + else + SafeYAML.load_file(path) end end def sanitize_filename(name) - name.gsub!(/[^\w\s-]+/, '') - name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2') - name.gsub(/\s+/, '_') + name.gsub(%r![^\w\s-]+|(?<=^|\b\s)\s+(?=$|\s?\b)!, "") + .gsub(%r!\s+!, "_") + end + + private + + # @return [Hash] + def csv_config + @csv_config ||= read_config("csv_reader") + end + + # @return [Hash] + def tsv_config + @tsv_config ||= read_config("tsv_reader", { :col_sep => "\t" }) + end + + # @param config_key [String] + # @param overrides [Hash] + # @return [Hash] + # @see https://ruby-doc.org/stdlib-2.5.0/libdoc/csv/rdoc/CSV.html#Converters + def read_config(config_key, overrides = {}) + reader_config = config[config_key] || {} + + defaults = { + :converters => reader_config.fetch("csv_converters", []).map(&:to_sym), + :headers => reader_config.fetch("headers", true), + :encoding => reader_config.fetch("encoding", config["encoding"]), + } + + defaults.merge(overrides) + end + + def config + @config ||= site.config + end + + # @param row [Array, CSV::Row] + # @return [Array, Hash] + def convert_row(row) + row.instance_of?(CSV::Row) ? row.to_hash : row end end end diff --git a/lib/jekyll/readers/layout_reader.rb b/lib/jekyll/readers/layout_reader.rb index f062029488c..981867b3027 100644 --- a/lib/jekyll/readers/layout_reader.rb +++ b/lib/jekyll/readers/layout_reader.rb @@ -1,29 +1,50 @@ +# frozen_string_literal: true + module Jekyll class LayoutReader attr_reader :site + def initialize(site) @site = site @layouts = {} end def read - layout_entries.each do |f| - @layouts[layout_name(f)] = Layout.new(site, layout_directory, f) + layout_entries.each do |layout_file| + @layouts[layout_name(layout_file)] = \ + Layout.new(site, layout_directory, layout_file) + end + + theme_layout_entries.each do |layout_file| + @layouts[layout_name(layout_file)] ||= \ + Layout.new(site, theme_layout_directory, layout_file) end @layouts end def layout_directory - @layout_directory ||= (layout_directory_in_cwd || layout_directory_inside_source) + @layout_directory ||= site.in_source_dir(site.config["layouts_dir"]) + end + + def theme_layout_directory + @theme_layout_directory ||= site.theme.layouts_path if site.theme end private def layout_entries + entries_in layout_directory + end + + def theme_layout_entries + theme_layout_directory ? entries_in(theme_layout_directory) : [] + end + + def entries_in(dir) entries = [] - within(layout_directory) do - entries = EntryFilter.new(site).filter(Dir['**/*.*']) + within(dir) do + entries = EntryFilter.new(site).filter(Dir["**/*.*"]) end entries end @@ -34,20 +55,8 @@ def layout_name(file) def within(directory) return unless File.exist?(directory) - Dir.chdir(directory) { yield } - end - def layout_directory_inside_source - site.in_source_dir(site.config['layouts_dir']) - end - - def layout_directory_in_cwd - dir = Jekyll.sanitized_path(Dir.pwd, site.config['layouts_dir']) - if File.directory?(dir) && !site.safe - dir - else - nil - end + Dir.chdir(directory) { yield } end end end diff --git a/lib/jekyll/readers/page_reader.rb b/lib/jekyll/readers/page_reader.rb index 099ebf133ed..e72f76769ed 100644 --- a/lib/jekyll/readers/page_reader.rb +++ b/lib/jekyll/readers/page_reader.rb @@ -1,21 +1,25 @@ +# frozen_string_literal: true + module Jekyll class PageReader attr_reader :site, :dir, :unfiltered_content + def initialize(site, dir) @site = site @dir = dir - @unfiltered_content = Array.new + @unfiltered_content = [] end - # Read all the files in // for Yaml header and create a new Page - # object for each file. + # Create a new `Jekyll::Page` object for each entry in a given array. # - # dir - The String relative path of the directory to read. + # files - An array of file names inside `@dir` # - # Returns an array of static pages. + # Returns an array of publishable `Jekyll::Page` objects. def read(files) - files.map{ |page| @unfiltered_content << Page.new(@site, @site.source, @dir, page) } - @unfiltered_content.select{ |page| site.publisher.publish?(page) } + files.each do |page| + @unfiltered_content << Page.new(@site, @site.source, @dir, page) + end + @unfiltered_content.select { |page| site.publisher.publish?(page) } end end end diff --git a/lib/jekyll/readers/post_reader.rb b/lib/jekyll/readers/post_reader.rb index c41ef10aaaf..25c5f98fb07 100644 --- a/lib/jekyll/readers/post_reader.rb +++ b/lib/jekyll/readers/post_reader.rb @@ -1,6 +1,9 @@ +# frozen_string_literal: true + module Jekyll class PostReader attr_reader :site, :unfiltered_content + def initialize(site) @site = site end @@ -12,7 +15,7 @@ def initialize(site) # # Returns nothing. def read_drafts(dir) - read_publishable(dir, '_drafts', Document::DATELESS_FILENAME_MATCHER) + read_publishable(dir, "_drafts", Document::DATELESS_FILENAME_MATCHER) end # Read all the files in //_posts and create a new Document @@ -22,7 +25,7 @@ def read_drafts(dir) # # Returns nothing. def read_posts(dir) - read_publishable(dir, '_posts', Document::DATE_FILENAME_MATCHER) + read_publishable(dir, "_posts", Document::DATE_FILENAME_MATCHER) end # Read all the files in // and create a new @@ -32,11 +35,9 @@ def read_posts(dir) # # Returns nothing. def read_publishable(dir, magic_dir, matcher) - read_content(dir, magic_dir, matcher).tap do |docs| - docs.each(&:read) - end.select do |doc| - site.publisher.publish?(doc) - end + read_content(dir, magic_dir, matcher) + .tap { |docs| docs.each(&:read) } + .select { |doc| processable?(doc) } end # Read all the content files from //magic_dir @@ -50,13 +51,35 @@ def read_publishable(dir, magic_dir, matcher) # Returns klass type of content files def read_content(dir, magic_dir, matcher) @site.reader.get_entries(dir, magic_dir).map do |entry| - next unless entry =~ matcher + next unless matcher.match?(entry) + path = @site.in_source_dir(File.join(dir, magic_dir, entry)) - Document.new(path, { - site: @site, - collection: @site.posts - }) - end.reject(&:nil?) + Document.new(path, + :site => @site, + :collection => @site.posts) + end.tap(&:compact!) + end + + private + + def processable?(doc) + if doc.content.nil? + Jekyll.logger.debug "Skipping:", "Content in #{doc.relative_path} is nil" + false + elsif !doc.content.valid_encoding? + Jekyll.logger.debug "Skipping:", "#{doc.relative_path} is not valid UTF-8" + false + else + publishable?(doc) + end + end + + def publishable?(doc) + site.publisher.publish?(doc).tap do |will_publish| + if !will_publish && site.publisher.hidden_in_the_future?(doc) + Jekyll.logger.warn "Skipping:", "#{doc.relative_path} has a future date" + end + end end end end diff --git a/lib/jekyll/readers/static_file_reader.rb b/lib/jekyll/readers/static_file_reader.rb index 279bea46d5e..5c8a67756aa 100644 --- a/lib/jekyll/readers/static_file_reader.rb +++ b/lib/jekyll/readers/static_file_reader.rb @@ -1,20 +1,24 @@ +# frozen_string_literal: true + module Jekyll class StaticFileReader attr_reader :site, :dir, :unfiltered_content + def initialize(site, dir) @site = site @dir = dir - @unfiltered_content = Array.new + @unfiltered_content = [] end - # Read all the files in // for Yaml header and create a new Page - # object for each file. + # Create a new StaticFile object for every entry in a given list of basenames. # - # dir - The String relative path of the directory to read. + # files - an array of file basenames. # # Returns an array of static files. def read(files) - files.map{ |file| @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file)} + files.each do |file| + @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file) + end @unfiltered_content end end diff --git a/lib/jekyll/readers/theme_assets_reader.rb b/lib/jekyll/readers/theme_assets_reader.rb new file mode 100644 index 00000000000..b20a3a087f4 --- /dev/null +++ b/lib/jekyll/readers/theme_assets_reader.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module Jekyll + class ThemeAssetsReader + attr_reader :site + + def initialize(site) + @site = site + end + + def read + return unless site.theme&.assets_path + + Find.find(site.theme.assets_path) do |path| + next if File.directory?(path) + + if File.symlink?(path) + Jekyll.logger.warn "Theme reader:", "Ignored symlinked asset: #{path}" + else + read_theme_asset(path) + end + end + end + + private + + def read_theme_asset(path) + base = site.theme.root + dir = File.dirname(path.sub("#{site.theme.root}/", "")) + name = File.basename(path) + + if Utils.has_yaml_header?(path) + append_unless_exists site.pages, + Jekyll::Page.new(site, base, dir, name) + else + append_unless_exists site.static_files, + Jekyll::StaticFile.new(site, base, "/#{dir}", name) + end + end + + def append_unless_exists(haystack, new_item) + if haystack.any? { |file| file.relative_path == new_item.relative_path } + Jekyll.logger.debug "Theme:", + "Ignoring #{new_item.relative_path} in theme due to existing file " \ + "with that path in site." + return + end + + haystack << new_item + end + end +end diff --git a/lib/jekyll/regenerator.rb b/lib/jekyll/regenerator.rb index 2d84ee34951..88c6a819a9e 100644 --- a/lib/jekyll/regenerator.rb +++ b/lib/jekyll/regenerator.rb @@ -1,6 +1,10 @@ +# frozen_string_literal: true + module Jekyll class Regenerator attr_reader :site, :metadata, :cache + attr_accessor :disabled + private :disabled, :disabled= def initialize(site) @site = site @@ -16,20 +20,16 @@ def initialize(site) # # Returns a boolean. def regenerate?(document) + return true if disabled + case document when Page - document.asset_file? || document.data['regenerate'] || - source_modified_or_dest_missing?( - site.in_source_dir(document.relative_path), document.destination(@site.dest) - ) + regenerate_page?(document) when Document - !document.write? || document.data['regenerate'] || - source_modified_or_dest_missing?( - document.path, document.destination(@site.dest) - ) + regenerate_document?(document) else - source_path = document.respond_to?(:path) ? document.path : nil - dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil + source_path = document.respond_to?(:path) ? document.path : nil + dest_path = document.destination(@site.dest) if document.respond_to?(:destination) source_modified_or_dest_missing?(source_path, dest_path) end end @@ -42,7 +42,7 @@ def add(path) metadata[path] = { "mtime" => File.mtime(path), - "deps" => [] + "deps" => [], } cache[path] = true end @@ -62,7 +62,6 @@ def clear clear_cache end - # Clear just the cache # # Returns nothing @@ -70,13 +69,12 @@ def clear_cache @cache = {} end - # Checks if the source has been modified or the # destination is missing # # returns a boolean def source_modified_or_dest_missing?(source_path, dest_path) - modified?(source_path) || (dest_path and !File.exist?(dest_path)) + modified?(source_path) || (dest_path && !File.exist?(dest_path)) end # Checks if a path's (or one of its dependencies) @@ -90,36 +88,25 @@ def modified?(path) return true if path.nil? # Check for path in cache - if cache.has_key? path - return cache[path] - end + return cache[path] if cache.key? path - # Check path that exists in metadata - data = metadata[path] - if data - data["deps"].each do |dependency| - if modified?(dependency) - return cache[dependency] = cache[path] = true - end - end - if File.exist?(path) && data["mtime"].eql?(File.mtime(path)) - return cache[path] = false - else - return add(path) - end + if metadata[path] + # If we have seen this file before, + # check if it or one of its dependencies has been modified + existing_file_modified?(path) + else + # If we have not seen this file before, add it to the metadata and regenerate it + add(path) end - - # Path does not exist in metadata, add it - return add(path) end # Add a dependency of a path # # Returns nothing. def add_dependency(path, dependency) - return if (metadata[path].nil? || @disabled) + return if metadata[path].nil? || disabled - if !metadata[path]["deps"].include? dependency + unless metadata[path]["deps"].include? dependency metadata[path]["deps"] << dependency add(dependency) unless metadata.include?(dependency) end @@ -131,6 +118,7 @@ def add_dependency(path, dependency) # Returns nothing. def write_metadata unless disabled? + Jekyll.logger.debug "Writing Metadata:", ".jekyll-metadata" File.binwrite(metadata_file, Marshal.dump(metadata)) end end @@ -139,15 +127,15 @@ def write_metadata # # Returns the String path of the file. def metadata_file - site.in_source_dir('.jekyll-metadata') + @metadata_file ||= site.in_source_dir(".jekyll-metadata") end # Check if metadata has been disabled # # Returns a Boolean (true for disabled, false for enabled). def disabled? - @disabled = !site.incremental? if @disabled.nil? - @disabled + self.disabled = !site.incremental? if disabled.nil? + disabled end private @@ -157,19 +145,50 @@ def disabled? # # Returns the read metadata. def read_metadata - @metadata = if !disabled? && File.file?(metadata_file) - content = File.binread(metadata_file) - - begin - Marshal.load(content) - rescue TypeError - SafeYAML.load(content) - rescue ArgumentError => e - Jekyll.logger.warn("Failed to load #{metadata_file}: #{e}") + @metadata = + if !disabled? && File.file?(metadata_file) + content = File.binread(metadata_file) + + begin + Marshal.load(content) + rescue TypeError + SafeYAML.load(content) + rescue ArgumentError => e + Jekyll.logger.warn("Failed to load #{metadata_file}: #{e}") + {} + end + else {} end + end + + def regenerate_page?(document) + document.asset_file? || document.data["regenerate"] || + source_modified_or_dest_missing?( + site.in_source_dir(document.relative_path), document.destination(@site.dest) + ) + end + + def regenerate_document?(document) + !document.write? || document.data["regenerate"] || + source_modified_or_dest_missing?( + document.path, document.destination(@site.dest) + ) + end + + def existing_file_modified?(path) + # If one of this file dependencies have been modified, + # set the regeneration bit for both the dependency and the file to true + metadata[path]["deps"].each do |dependency| + return cache[dependency] = cache[path] = true if modified?(dependency) + end + + if File.exist?(path) && metadata[path]["mtime"].eql?(File.mtime(path)) + # If this file has not been modified, set the regeneration bit to false + cache[path] = false else - {} + # If it has been modified, set it to true + add(path) end end end diff --git a/lib/jekyll/related_posts.rb b/lib/jekyll/related_posts.rb index fbc2837bf4e..98fc4880772 100644 --- a/lib/jekyll/related_posts.rb +++ b/lib/jekyll/related_posts.rb @@ -1,6 +1,7 @@ +# frozen_string_literal: true + module Jekyll class RelatedPosts - class << self attr_accessor :lsi end @@ -10,7 +11,7 @@ class << self def initialize(post) @post = post @site = post.site - Jekyll::External.require_with_graceful_fail('classifier-reborn') if site.lsi + Jekyll::External.require_with_graceful_fail("classifier-reborn") if site.lsi end def build @@ -24,19 +25,18 @@ def build end end - def build_index self.class.lsi ||= begin lsi = ClassifierReborn::LSI.new(:auto_rebuild => false) - display("Populating LSI...") + Jekyll.logger.info("Populating LSI...") site.posts.docs.each do |x| lsi.add_item(x) end - display("Rebuilding index...") + Jekyll.logger.info("Rebuilding index...") lsi.build_index - display("") + Jekyll.logger.info("") lsi end end @@ -46,13 +46,7 @@ def lsi_related_posts end def most_recent_posts - @most_recent_posts ||= (site.posts.docs.reverse - [post]).first(10) - end - - def display(output) - $stdout.print("\n") - $stdout.print(Jekyll.logger.formatted_topic(output)) - $stdout.flush + @most_recent_posts ||= (site.posts.docs.last(11).reverse! - [post]).first(10) end end end diff --git a/lib/jekyll/renderer.rb b/lib/jekyll/renderer.rb index 529ff84bd68..c365a0d7289 100644 --- a/lib/jekyll/renderer.rb +++ b/lib/jekyll/renderer.rb @@ -1,95 +1,114 @@ -# encoding: UTF-8 +# frozen_string_literal: true module Jekyll class Renderer - - attr_reader :document, :site, :site_payload + attr_reader :document, :site + attr_writer :layouts, :payload def initialize(site, document, site_payload = nil) - @site = site - @document = document - @site_payload = site_payload + @site = site + @document = document + @payload = site_payload + @layouts = nil + end + + # Fetches the payload used in Liquid rendering. + # It can be written with #payload=(new_payload) + # Falls back to site.site_payload if no payload is set. + # + # Returns a Jekyll::Drops::UnifiedPayloadDrop + def payload + @payload ||= site.site_payload + end + + # The list of layouts registered for this Renderer. + # It can be written with #layouts=(new_layouts) + # Falls back to site.layouts if no layouts are registered. + # + # Returns a Hash of String => Jekyll::Layout identified + # as basename without the extension name. + def layouts + @layouts || site.layouts end # Determine which converters to use based on this document's # extension. # - # Returns an array of Converter instances. + # Returns Array of Converter instances. def converters - @converters ||= site.converters.select { |c| c.matches(document.extname) } + @converters ||= site.converters.select { |c| c.matches(document.extname) }.tap(&:sort!) end # Determine the extname the outputted file should have # - # Returns the output extname including the leading period. + # Returns String the output extname including the leading period. def output_ext - @output_ext ||= converters.first.output_ext(document.extname) + @output_ext ||= (permalink_ext || converter_output_ext) end - ###################### - ## DAT RENDER THO - ###################### - + # Prepare payload and render the document + # + # Returns String rendered document output def run Jekyll.logger.debug "Rendering:", document.relative_path - payload = Utils.deep_merge_hashes({ - "page" => document.to_liquid - }, site_payload || site.site_payload) - - if document.collection.label == 'posts' && document.is_a?(Document) - payload['site']['related_posts'] = document.related_posts - end + assign_pages! + assign_current_document! + assign_highlighter_options! + assign_layout_data! Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path document.trigger_hooks(:pre_render, payload) + render_document + end + + # Render the document. + # + # Returns String rendered document output + # rubocop: disable Metrics/AbcSize, Metrics/MethodLength + def render_document info = { - filters: [Jekyll::Filters], - registers: { :site => site, :page => payload['page'] } + :registers => { :site => site, :page => payload["page"] }, + :strict_filters => liquid_options["strict_filters"], + :strict_variables => liquid_options["strict_variables"], } - # render and transform content (this becomes the final content of the object) - payload["highlighter_prefix"] = converters.first.highlighter_prefix - payload["highlighter_suffix"] = converters.first.highlighter_suffix - output = document.content - if document.render_with_liquid? Jekyll.logger.debug "Rendering Liquid:", document.relative_path output = render_liquid(output, payload, info, document.path) end Jekyll.logger.debug "Rendering Markup:", document.relative_path - output = convert(output) + output = convert(output.to_s) document.content = output + Jekyll.logger.debug "Post-Convert Hooks:", document.relative_path + document.trigger_hooks(:post_convert) + output = document.content + if document.place_in_layout? Jekyll.logger.debug "Rendering Layout:", document.relative_path - place_in_layouts( - output, - payload, - info - ) - else - output + output = place_in_layouts(output, payload, info) end + + output end + # rubocop: enable Metrics/AbcSize, Metrics/MethodLength - # Convert the given content using the converters which match this renderer's document. - # - # content - the raw, unconverted content + # Convert the document using the converters which match this renderer's document. # - # Returns the converted content. + # Returns String the converted content. def convert(content) converters.reduce(content) do |output, converter| - begin - converter.convert output - rescue => e - Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{document.relative_path}':" - Jekyll.logger.error("", e.to_s) - raise e - end + converter.convert output + rescue StandardError => e + Jekyll.logger.error "Conversion error:", + "#{converter.class} encountered an error while " \ + "converting '#{document.relative_path}':" + Jekyll.logger.error("", e.to_s) + raise e end end @@ -100,74 +119,145 @@ def convert(content) # info - # path - (optional) the path to the file, for use in ex # - # Returns the content, rendered by Liquid. + # Returns String the content, rendered by Liquid. def render_liquid(content, payload, info, path = nil) - site.liquid_renderer.file(path).parse(content).render!(payload, info) - rescue Tags::IncludeTagError => e - Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || document.relative_path}" - raise e + template = site.liquid_renderer.file(path).parse(content) + template.warnings.each do |e| + Jekyll.logger.warn "Liquid Warning:", + LiquidRenderer.format_error(e, path || document.relative_path) + end + template.render!(payload, info) + # rubocop: disable Lint/RescueException rescue Exception => e - Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || document.relative_path}" + Jekyll.logger.error "Liquid Exception:", + LiquidRenderer.format_error(e, path || document.relative_path) raise e end + # rubocop: enable Lint/RescueException # Checks if the layout specified in the document actually exists # # layout - the layout to check # - # Returns true if the layout is invalid, false if otherwise + # Returns Boolean true if the layout is invalid, false if otherwise def invalid_layout?(layout) - !document.data["layout"].nil? && layout.nil? + !document.data["layout"].nil? && layout.nil? && !(document.is_a? Jekyll::Excerpt) end - # Render layouts and place given content inside. + # Render layouts and place document content inside. # - # content - the content to be placed in the layout - # - # - # Returns the content placed in the Liquid-rendered layouts + # Returns String rendered content def place_in_layouts(content, payload, info) output = content.dup - layout = site.layouts[document.data["layout"]] + layout = layouts[document.data["layout"].to_s] + validate_layout(layout) - Jekyll.logger.warn("Build Warning:", "Layout '#{document.data["layout"]}' requested in #{document.relative_path} does not exist.") if invalid_layout? layout + used = Set.new([layout]) - used = Set.new([layout]) + # Reset the payload layout data to ensure it starts fresh for each page. + payload["layout"] = nil while layout - payload = Utils.deep_merge_hashes( - payload, - { - "content" => output, - "page" => document.to_liquid, - "layout" => layout.data - } - ) - - output = render_liquid( - layout.content, - payload, - info, - File.join(site.config['layouts_dir'], layout.name) - ) - - # Add layout to dependency tree - site.regenerator.add_dependency( - site.in_source_dir(document.path), - site.in_source_dir(layout.path) - ) if document.write? - - if layout = site.layouts[layout.data["layout"]] - if used.include?(layout) - layout = nil # avoid recursive chain - else - used << layout - end - end - end + output = render_layout(output, layout, info) + add_regenerator_dependencies(layout) + + next unless (layout = site.layouts[layout.data["layout"]]) + break if used.include?(layout) + used << layout + end output end + private + + # Checks if the layout specified in the document actually exists + # + # layout - the layout to check + # Returns nothing + def validate_layout(layout) + return unless invalid_layout?(layout) + + Jekyll.logger.warn "Build Warning:", "Layout '#{document.data["layout"]}' requested " \ + "in #{document.relative_path} does not exist." + end + + # Render layout content into document.output + # + # Returns String rendered content + def render_layout(output, layout, info) + payload["content"] = output + payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) + + render_liquid( + layout.content, + payload, + info, + layout.path + ) + end + + def add_regenerator_dependencies(layout) + return unless document.write? + + site.regenerator.add_dependency( + site.in_source_dir(document.path), + layout.path + ) + end + + # Set page content to payload and assign pager if document has one. + # + # Returns nothing + def assign_pages! + payload["page"] = document.to_liquid + payload["paginator"] = (document.pager.to_liquid if document.respond_to?(:pager)) + end + + # Set related posts to payload if document is a post. + # + # Returns nothing + def assign_current_document! + payload["site"].current_document = document + end + + # Set highlighter prefix and suffix + # + # Returns nothing + def assign_highlighter_options! + payload["highlighter_prefix"] = converters.first.highlighter_prefix + payload["highlighter_suffix"] = converters.first.highlighter_suffix + end + + def assign_layout_data! + layout = layouts[document.data["layout"]] + payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {}) if layout + end + + def permalink_ext + document_permalink = document.permalink + if document_permalink && !document_permalink.end_with?("/") + permalink_ext = File.extname(document_permalink) + permalink_ext unless permalink_ext.empty? + end + end + + def converter_output_ext + if output_exts.size == 1 + output_exts.last + else + output_exts[-2] + end + end + + def output_exts + @output_exts ||= converters.map do |c| + c.output_ext(document.extname) + end.tap(&:compact!) + end + + def liquid_options + @liquid_options ||= site.config["liquid"] + end end end diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 5e9402f4dbb..adec4cc0612 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -1,92 +1,126 @@ -# encoding: UTF-8 -require 'csv' +# frozen_string_literal: true module Jekyll class Site - attr_reader :source, :dest, :config - attr_accessor :layouts, :pages, :static_files, :drafts, - :exclude, :include, :lsi, :highlighter, :permalink_style, - :time, :future, :unpublished, :safe, :plugins, :limit_posts, - :show_drafts, :keep_files, :baseurl, :data, :file_read_opts, - :gems, :plugin_manager + attr_accessor :baseurl, :converters, :data, :drafts, :exclude, + :file_read_opts, :future, :gems, :generators, :highlighter, + :include, :inclusions, :keep_files, :layouts, :limit_posts, + :lsi, :pages, :permalink_style, :plugin_manager, :plugins, + :reader, :safe, :show_drafts, :static_files, :theme, :time, + :unpublished - attr_accessor :converters, :generators, :reader - attr_reader :regenerator, :liquid_renderer + attr_reader :cache_dir, :config, :dest, :filter_cache, :includes_load_paths, + :liquid_renderer, :profiler, :regenerator, :source # Public: Initialize a new Site. # # config - A Hash containing site configuration details. def initialize(config) - @config = config.clone - - %w[safe lsi highlighter baseurl exclude include future unpublished - show_drafts limit_posts keep_files gems].each do |opt| - self.send("#{opt}=", config[opt]) - end - # Source and destination may not be changed after the site has been created. - @source = File.expand_path(config['source']).freeze - @dest = File.expand_path(config['destination']).freeze + @source = File.expand_path(config["source"]).freeze + @dest = File.expand_path(config["destination"]).freeze - @reader = Jekyll::Reader.new(self) + self.config = config - # Initialize incremental regenerator - @regenerator = Regenerator.new(self) + @cache_dir = in_source_dir(config["cache_dir"]) + @filter_cache = {} + @reader = Reader.new(self) + @profiler = Profiler.new(self) + @regenerator = Regenerator.new(self) @liquid_renderer = LiquidRenderer.new(self) - self.plugin_manager = Jekyll::PluginManager.new(self) - self.plugins = plugin_manager.plugins_path - - self.file_read_opts = {} - self.file_read_opts[:encoding] = config['encoding'] if config['encoding'] - - self.permalink_style = config['permalink'].to_sym - Jekyll.sites << self reset setup + + Jekyll::Hooks.trigger :site, :after_init, self + end + + # Public: Set the site's configuration. This handles side-effects caused by + # changing values in the configuration. + # + # config - a Jekyll::Configuration, containing the new configuration. + # + # Returns the new configuration. + def config=(config) + @config = config.clone + + %w(safe lsi highlighter baseurl exclude include future unpublished + show_drafts limit_posts keep_files).each do |opt| + send(:"#{opt}=", config[opt]) + end + + # keep using `gems` to avoid breaking change + self.gems = config["plugins"] + + configure_cache + configure_plugins + configure_theme + configure_include_paths + configure_file_read_opts + + self.permalink_style = config["permalink"].to_sym + + # Read in a _config.yml from the current theme-gem at the very end. + @config = load_theme_configuration(config) if theme + @config end # Public: Read, process, and write this Site to output. # # Returns nothing. def process + return profiler.profile_process if config["profile"] + reset read generate render cleanup write - print_stats end def print_stats - if @config['profile'] - puts @liquid_renderer.stats_table - end + Jekyll.logger.info @liquid_renderer.stats_table end + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + # # Reset Site details. # # Returns nothing def reset - self.time = (config['time'] ? Utils.parse_date(config['time'].to_s, "Invalid time in _config.yml.") : Time.now) + self.time = if config["time"] + Utils.parse_date(config["time"].to_s, "Invalid time in _config.yml.") + else + Time.now + end self.layouts = {} + self.inclusions = {} self.pages = [] self.static_files = [] self.data = {} + @post_attr_hash = {} + @site_data = nil @collections = nil + @documents = nil + @docs_to_write = nil @regenerator.clear_cache @liquid_renderer.reset + @site_cleaner = nil + frontmatter_defaults.reset - if limit_posts < 0 - raise ArgumentError, "limit_posts must be a non-negative number" - end + raise ArgumentError, "limit_posts must be a non-negative number" if limit_posts.negative? + Jekyll::Cache.clear_if_config_changed config Jekyll::Hooks.trigger :site, :after_reset, self + nil end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize # Load necessary libraries, plugins, converters, and generators. # @@ -106,18 +140,21 @@ def ensure_not_in_dest dest_pathname = Pathname.new(dest) Pathname.new(source).ascend do |path| if path == dest_pathname - raise Errors::FatalException.new "Destination directory cannot be or contain the Source directory." + raise Errors::FatalException, + "Destination directory cannot be or contain the Source directory." end end end # The list of collections and their corresponding Jekyll::Collection instances. - # If config['collections'] is set, a new instance is created for each item in the collection. - # If config['collections'] is not set, a new hash is returned. + # If config['collections'] is set, a new instance is created + # for each item in the collection, a new hash is returned otherwise. # # Returns a Hash containing collection name-to-instance pairs. def collections - @collections ||= Hash[collection_names.map { |coll| [coll, Jekyll::Collection.new(self, coll)] } ] + @collections ||= collection_names.each_with_object({}) do |name, hsh| + hsh[name] = Jekyll::Collection.new(self, name) + end end # The list of collection names. @@ -125,11 +162,11 @@ def collections # Returns an array of collection names from the configuration, # or an empty array if the `collections` key is not set. def collection_names - case config['collections'] + case config["collections"] when Hash - config['collections'].keys + config["collections"].keys when Array - config['collections'] + config["collections"] when nil [] else @@ -144,6 +181,7 @@ def read reader.read limit_posts! Jekyll::Hooks.trigger :site, :post_read, self + nil end # Run each of the Generators. @@ -151,8 +189,12 @@ def read # Returns nothing. def generate generators.each do |generator| + start = Time.now generator.generate(self) + Jekyll.logger.debug "Generating:", + "#{generator.class} finished in #{Time.now - start} seconds." end + nil end # Render the site to the destination. @@ -165,24 +207,11 @@ def render Jekyll::Hooks.trigger :site, :pre_render, self, payload - collections.each do |label, collection| - collection.docs.each do |document| - if regenerator.regenerate?(document) - document.output = Jekyll::Renderer.new(self, document, payload).run - document.trigger_hooks(:post_render) - end - end - end - - pages.flatten.each do |page| - if regenerator.regenerate?(page) - page.render(layouts, payload) - end - end + render_docs(payload) + render_pages(payload) Jekyll::Hooks.trigger :site, :post_render, self, payload - rescue Errno::ENOENT - # ignore missing layout dir + nil end # Remove orphaned files and empty directories in destination. @@ -190,21 +219,24 @@ def render # Returns nothing. def cleanup site_cleaner.cleanup! + nil end # Write static files, pages, and posts. # # Returns nothing. def write - each_site_file { |item| + Jekyll::Commands::Doctor.conflicting_urls(self) + each_site_file do |item| item.write(dest) if regenerator.regenerate?(item) - } + end regenerator.write_metadata Jekyll::Hooks.trigger :site, :post_write, self + nil end def posts - collections['posts'] ||= Collection.new(self, 'posts') + collections["posts"] ||= Collection.new(self, "posts") end # Construct a Hash of Posts indexed by the specified Post attribute. @@ -223,18 +255,22 @@ def posts def post_attr_hash(post_attr) # Build a hash map based on the specified post attribute ( post attr => # array of posts ) then sort each array in reverse order. - hash = Hash.new { |h, key| h[key] = [] } - posts.docs.each { |p| p.data[post_attr].each { |t| hash[t] << p } } - hash.values.each { |posts| posts.sort!.reverse! } - hash + @post_attr_hash[post_attr] ||= begin + hash = Hash.new { |h, key| h[key] = [] } + posts.docs.each do |p| + p.data[post_attr]&.each { |t| hash[t] << p } + end + hash.each_value { |posts| posts.sort!.reverse! } + hash + end end def tags - post_attr_hash('tags') + post_attr_hash("tags") end def categories - post_attr_hash('categories') + post_attr_hash("categories") end # Prepare site data for site payload. The method maintains backward compatibility @@ -242,7 +278,7 @@ def categories # # Returns the Hash to be hooked to site.data. def site_data - config['data'] || data + @site_data ||= (config["data"] || data) end # The Hash payload containing site-wide data. @@ -259,48 +295,30 @@ def site_data # "tags" - The Hash of tag values and Posts. # See Site#post_attr_hash for type info. def site_payload - { - "jekyll" => { - "version" => Jekyll::VERSION, - "environment" => Jekyll.env - }, - "site" => Utils.deep_merge_hashes(config, - Utils.deep_merge_hashes(Hash[collections.map{|label, coll| [label, coll.docs]}], { - "time" => time, - "posts" => posts.docs.sort { |a, b| b <=> a }, - "pages" => pages, - "static_files" => static_files, - "html_pages" => pages.select { |page| page.html? || page.url.end_with?("/") }, - "categories" => post_attr_hash('categories'), - "tags" => post_attr_hash('tags'), - "collections" => collections.values.map(&:to_liquid), - "documents" => documents, - "data" => site_data - })) - } + Drops::UnifiedPayloadDrop.new self end + alias_method :to_liquid, :site_payload # Get the implementation class for the given Converter. - # - # klass - The Class of the Converter to fetch. - # # Returns the Converter instance implementing the given Converter. + # klass - The Class of the Converter to fetch. def find_converter_instance(klass) - converters.find { |c| c.class == klass } || proc { raise "No converter for #{klass}" }.call + @find_converter_instance ||= {} + @find_converter_instance[klass] ||= converters.find do |converter| + converter.instance_of?(klass) + end || \ + raise("No Converters found for #{klass}") end + # klass - class or module containing the subclasses. + # Returns array of instances of subclasses of parameter. # Create array of instances of the subclasses of the class or module - # passed in as argument. - # - # klass - class or module containing the subclasses which should be - # instantiated - # - # Returns array of instances of subclasses of parameter + # passed in as argument. + def instantiate_subclasses(klass) - klass.descendants.select do |c| - !safe || c.safe - end.sort.map do |c| - c.new(config) + klass.descendants.select { |c| !safe || c.safe }.tap do |result| + result.sort! + result.map! { |c| c.new(config) } end end @@ -309,12 +327,12 @@ def instantiate_subclasses(klass) # # Returns def relative_permalinks_are_deprecated - if config['relative_permalinks'] - Jekyll.logger.abort_with "Since v3.0, permalinks for pages" + - " in subfolders must be relative to the" + - " site source directory, not the parent" + - " directory. Check http://jekyllrb.com/docs/upgrading/"+ - " for more info." + if config["relative_permalinks"] + Jekyll.logger.abort_with "Since v3.0, permalinks for pages " \ + "in subfolders must be relative to the " \ + "site source directory, not the parent " \ + "directory. Check https://jekyllrb.com/docs/upgrading/ " \ + "for more info." end end @@ -325,21 +343,26 @@ def docs_to_write documents.select(&:write?) end + # Get the to be written static files + # + # Returns an Array of StaticFiles which should be written + def static_files_to_write + static_files.select(&:write?) + end + # Get all the documents # # Returns an Array of all Documents def documents - collections.reduce(Set.new) do |docs, (_, collection)| - docs + collection.docs + collection.files + collections.each_with_object(Set.new) do |(_, collection), set| + set.merge(collection.docs).merge(collection.files) end.to_a end def each_site_file - %w(pages static_files docs_to_write).each do |type| - send(type).each do |item| - yield item - end - end + pages.each { |page| yield page } + static_files.each { |file| yield(file) if file.write? } + collections.each_value { |coll| coll.docs.each { |doc| yield(doc) if doc.write? } } end # Returns the FrontmatterDefaults or creates a new FrontmatterDefaults @@ -354,7 +377,7 @@ def frontmatter_defaults # # Returns a Boolean: true for a full rebuild, false for normal build def incremental?(override = {}) - override['incremental'] || config['incremental'] + override["incremental"] || config["incremental"] end # Returns the publisher or creates a new publisher if it doesn't @@ -377,6 +400,20 @@ def in_source_dir(*paths) end end + # Public: Prefix a given path with the theme directory. + # + # paths - (optional) path elements to a file or directory within the + # theme directory + # + # Returns a path which is prefixed with the theme root directory. + def in_theme_dir(*paths) + return nil unless theme + + paths.reduce(theme.root) do |base, path| + Jekyll.sanitized_path(base, path) + end + end + # Public: Prefix a given path with the destination directory. # # paths - (optional) path elements to a file or directory within the @@ -389,15 +426,68 @@ def in_dest_dir(*paths) end end + # Public: Prefix a given path with the cache directory. + # + # paths - (optional) path elements to a file or directory within the + # cache directory + # + # Returns a path which is prefixed with the cache directory. + def in_cache_dir(*paths) + paths.reduce(cache_dir) do |base, path| + Jekyll.sanitized_path(base, path) + end + end + + # Public: The full path to the directory that houses all the collections registered + # with the current site. + # + # Returns the source directory or the absolute path to the custom collections_dir + def collections_path + dir_str = config["collections_dir"] + @collections_path ||= dir_str.empty? ? source : in_source_dir(dir_str) + end + + # Public + # + # Returns the object as a debug String. + def inspect + "#<#{self.class} @source=#{@source}>" + end + private + def load_theme_configuration(config) + return config if config["ignore_theme_config"] == true + + theme_config_file = in_theme_dir("_config.yml") + return config unless File.exist?(theme_config_file) + + # Bail out if the theme_config_file is a symlink file irrespective of safe mode + return config if File.symlink?(theme_config_file) + + theme_config = SafeYAML.load_file(theme_config_file) + return config unless theme_config.is_a?(Hash) + + Jekyll.logger.info "Theme Config file:", theme_config_file + + # theme_config should not be overriding Jekyll's defaults + theme_config.delete_if { |key, _| Configuration::DEFAULTS.key?(key) } + + # Override theme_config with existing config and return the result. + # Additionally ensure we return a `Jekyll::Configuration` instance instead of a Hash. + Utils.deep_merge_hashes(theme_config, config) + .each_with_object(Jekyll::Configuration.new) do |(key, value), conf| + conf[key] = value + end + end + # Limits the current posts; removes the posts which exceed the limit_posts # # Returns nothing def limit_posts! - if limit_posts > 0 - limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts - self.posts.docs = posts.docs[-limit, limit] + if limit_posts.positive? + limit = [posts.docs.length, limit_posts].min + posts.docs = posts.docs[-limit, limit] end end @@ -408,5 +498,79 @@ def limit_posts! def site_cleaner @site_cleaner ||= Cleaner.new(self) end + + def hide_cache_dir_from_git + @cache_gitignore_path ||= in_source_dir(config["cache_dir"], ".gitignore") + return if File.exist?(@cache_gitignore_path) + + cache_dir_path = in_source_dir(config["cache_dir"]) + FileUtils.mkdir_p(cache_dir_path) unless File.directory?(cache_dir_path) + + File.open(@cache_gitignore_path, "wb") do |file| + file.puts("# ignore everything in this directory\n*") + end + end + + # Disable Marshaling cache to disk in Safe Mode + def configure_cache + Jekyll::Cache.cache_dir = in_source_dir(config["cache_dir"], "Jekyll/Cache") + if safe || config["disable_disk_cache"] + Jekyll::Cache.disable_disk_cache! + else + hide_cache_dir_from_git + end + end + + def configure_plugins + self.plugin_manager = Jekyll::PluginManager.new(self) + self.plugins = plugin_manager.plugins_path + end + + def configure_theme + self.theme = nil + return if config["theme"].nil? + + self.theme = + if config["theme"].is_a?(String) + Jekyll::Theme.new(config["theme"]) + else + Jekyll.logger.warn "Theme:", "value of 'theme' in config should be String to use " \ + "gem-based themes, but got #{config["theme"].class}" + nil + end + end + + def configure_include_paths + @includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s)) + @includes_load_paths << theme.includes_path if theme&.includes_path + end + + def configure_file_read_opts + self.file_read_opts = {} + file_read_opts[:encoding] = config["encoding"] if config["encoding"] + self.file_read_opts = Jekyll::Utils.merged_file_read_opts(self, {}) + end + + def render_docs(payload) + collections.each_value do |collection| + collection.docs.each do |document| + render_regenerated(document, payload) + end + end + end + + def render_pages(payload) + pages.each do |page| + render_regenerated(page, payload) + end + end + + def render_regenerated(document, payload) + return unless regenerator.regenerate?(document) + + document.renderer.payload = payload + document.output = document.renderer.run + document.trigger_hooks(:post_render) + end end end diff --git a/lib/jekyll/static_file.rb b/lib/jekyll/static_file.rb index 48fa34c5990..13479b0de21 100644 --- a/lib/jekyll/static_file.rb +++ b/lib/jekyll/static_file.rb @@ -1,9 +1,25 @@ +# frozen_string_literal: true + module Jekyll class StaticFile - # The cache of last modification times [path] -> mtime. - @@mtimes = Hash.new + extend Forwardable + + attr_reader :relative_path, :extname, + :type, # Returns the type of the collection if present, nil otherwise. + :name + + def_delegator :to_liquid, :to_json, :to_json + + class << self + # The cache of last modification times [path] -> mtime. + def mtimes + @mtimes ||= {} + end - attr_reader :relative_path, :extname + def reset_cache + @mtimes = nil + end + end # Initialize a new StaticFile. # @@ -11,6 +27,7 @@ class StaticFile # base - The String path to the . # dir - The String path between and the file. # name - The String filename of the file. + # rubocop: disable Metrics/ParameterLists def initialize(site, base, dir, name, collection = nil) @site = site @base = base @@ -19,11 +36,17 @@ def initialize(site, base, dir, name, collection = nil) @collection = collection @relative_path = File.join(*[@dir, @name].compact) @extname = File.extname(@name) + @type = @collection&.label&.to_sym end + # rubocop: enable Metrics/ParameterLists # Returns source file path. def path - File.join(*[@base, @dir, @name].compact) + @path ||= if !@collection.nil? && !@site.config["collections_dir"].empty? + File.join(*[@base, @site.config["collections_dir"], @dir, @name].compact) + else + File.join(*[@base, @dir, @name].compact) + end end # Obtain destination path. @@ -32,7 +55,8 @@ def path # # Returns destination file path. def destination(dest) - @site.in_dest_dir(*[dest, destination_rel_dir, @name].compact) + @destination ||= {} + @destination[dest] ||= @site.in_dest_dir(dest, Jekyll::URL.unescape_path(url)) end def destination_rel_dir @@ -56,7 +80,7 @@ def mtime # # Returns true if modified since last write. def modified? - @@mtimes[path] != mtime + self.class.mtimes[path] != mtime end # Whether to write the file to the filesystem @@ -64,7 +88,10 @@ def modified? # Returns true unless the defaults for the destination path from # _config.yml contain `published: false`. def write? - defaults.fetch('published', true) + publishable = defaults.fetch("published", true) + return publishable unless @collection + + publishable && @collection.write? end # Write the static file to the destination directory (if modified). @@ -74,62 +101,77 @@ def write? # Returns false if the file was not modified since last time (no-op). def write(dest) dest_path = destination(dest) + return false if File.exist?(dest_path) && !modified? - return false if File.exist?(dest_path) and !modified? - @@mtimes[path] = mtime + self.class.mtimes[path] = mtime FileUtils.mkdir_p(File.dirname(dest_path)) FileUtils.rm(dest_path) if File.exist?(dest_path) - FileUtils.cp(path, dest_path) - File.utime(@@mtimes[path], @@mtimes[path], dest_path) + copy_file(dest_path) true end - # Reset the mtimes cache (for testing purposes). - # - # Returns nothing. - def self.reset_cache - @@mtimes = Hash.new - nil + def data + @data ||= @site.frontmatter_defaults.all(relative_path, type) end def to_liquid - { - "extname" => extname, - "modified_time" => modified_time, - "path" => File.join("", relative_path) - } + @to_liquid ||= Drops::StaticFileDrop.new(self) + end + + # Generate "basename without extension" and strip away any trailing periods. + # NOTE: `String#gsub` removes all trailing periods (in comparison to `String#chomp`) + def basename + @basename ||= File.basename(name, extname).gsub(%r!\.*\z!, "") end def placeholders { - collection: @collection.label, - path: relative_path[ - @collection.relative_directory.size..relative_path.size], - output_ext: '', - name: '', - title: '', + :collection => @collection.label, + :path => cleaned_relative_path, + :output_ext => "", + :name => basename, + :title => "", } end + # Similar to Jekyll::Document#cleaned_relative_path. + # Generates a relative path with the collection's directory removed when applicable + # and additionally removes any multiple periods in the string. + # + # NOTE: `String#gsub!` removes all trailing periods (in comparison to `String#chomp!`) + # + # Examples: + # When `relative_path` is "_methods/site/my-cool-avatar...png": + # cleaned_relative_path + # # => "/site/my-cool-avatar" + # + # Returns the cleaned relative path of the static file. + def cleaned_relative_path + @cleaned_relative_path ||= begin + cleaned = relative_path[0..-extname.length - 1] + cleaned.gsub!(%r!\.*\z!, "") + cleaned.sub!(@collection.relative_directory, "") if @collection + cleaned + end + end + # Applies a similar URL-building technique as Jekyll::Document that takes # the collection's URL template into account. The default URL template can - # be overriden in the collection's configuration in _config.yml. + # be overridden in the collection's configuration in _config.yml. def url - @url ||= if @collection.nil? - relative_path - else - ::Jekyll::URL.new({ - template: @collection.url_template, - placeholders: placeholders, - }) - end.to_s.gsub /\/$/, '' - end - - # Returns the type of the collection if present, nil otherwise. - def type - @type ||= @collection.nil? ? nil : @collection.label.to_sym + @url ||= begin + base = if @collection.nil? + cleaned_relative_path + else + Jekyll::URL.new( + :template => @collection.url_template, + :placeholders => placeholders + ) + end.to_s.chomp("/") + base << extname + end end # Returns the front matter defaults defined for the file's URL and/or type @@ -137,5 +179,25 @@ def type def defaults @defaults ||= @site.frontmatter_defaults.all url, type end + + # Returns a debug string on inspecting the static file. + # Includes only the relative path of the object. + def inspect + "#<#{self.class} @relative_path=#{relative_path.inspect}>" + end + + private + + def copy_file(dest_path) + if @site.safe || Jekyll.env == "production" + FileUtils.cp(path, dest_path) + else + FileUtils.copy_entry(path, dest_path) + end + + unless File.symlink?(dest_path) + File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path) + end + end end end diff --git a/lib/jekyll/stevenson.rb b/lib/jekyll/stevenson.rb index 9a9f412ec96..10e5a0b2189 100644 --- a/lib/jekyll/stevenson.rb +++ b/lib/jekyll/stevenson.rb @@ -1,22 +1,20 @@ +# frozen_string_literal: true + module Jekyll class Stevenson < ::Logger def initialize - @progname = nil - @level = DEBUG - @default_formatter = Formatter.new - @logdev = $stdout - @formatter = proc do |severity, datetime, progname, msg| - "#{msg}" + formatter = proc do |_, _, _, msg| + msg.to_s end + super($stdout, :formatter => formatter) end - def add(severity, message = nil, progname = nil, &block) + def add(severity, message = nil, progname = nil) severity ||= UNKNOWN - @logdev = set_logdevice(severity) + @logdev = logdevice(severity) + + return true if @logdev.nil? || severity < @level - if @logdev.nil? or severity < @level - return true - end progname ||= @progname if message.nil? if block_given? @@ -27,7 +25,8 @@ def add(severity, message = nil, progname = nil, &block) end end @logdev.puts( - format_message(format_severity(severity), Time.now, progname, message)) + format_message(format_severity(severity), Time.now, progname, message) + ) true end @@ -47,7 +46,7 @@ def close private - def set_logdevice(severity) + def logdevice(severity) if severity > INFO $stderr else diff --git a/lib/jekyll/tags/highlight.rb b/lib/jekyll/tags/highlight.rb index 454c09a2f80..fcea81ff41a 100644 --- a/lib/jekyll/tags/highlight.rb +++ b/lib/jekyll/tags/highlight.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll module Tags class HighlightBlock < Liquid::Block @@ -8,50 +10,39 @@ class HighlightBlock < Liquid::Block # forms: name, name=value, or name="" # # is a space-separated list of numbers - SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$/ + SYNTAX = %r!^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!.freeze def initialize(tag_name, markup, tokens) super if markup.strip =~ SYNTAX - @lang = $1.downcase - @options = {} - if defined?($2) && $2 != '' - # Split along 3 possible forms -- key="", key=value, or key - $2.scan(/(?:\w="[^"]*"|\w=\w|\w)+/) do |opt| - key, value = opt.split('=') - # If a quoted list, convert to array - if value && value.include?("\"") - value.gsub!(/"/, "") - value = value.split - end - @options[key.to_sym] = value || true - end - end - @options[:linenos] = "inline" if @options.key?(:linenos) and @options[:linenos] == true + @lang = Regexp.last_match(1).downcase + @highlight_options = parse_options(Regexp.last_match(2)) else - raise SyntaxError.new <<-eos -Syntax Error in tag 'highlight' while parsing the following markup: + raise SyntaxError, <<~MSG + Syntax Error in tag 'highlight' while parsing the following markup: + + #{markup} - #{markup} + Valid syntax: highlight [linenos] [mark_lines="3 4 5"] -Valid syntax: highlight [linenos] -eos + See https://jekyllrb.com/docs/liquid/tags/#code-snippet-highlighting for more details. + MSG end end + LEADING_OR_TRAILING_LINE_TERMINATORS = %r!\A(\n|\r)+|(\n|\r)+\z!.freeze + def render(context) prefix = context["highlighter_prefix"] || "" suffix = context["highlighter_suffix"] || "" - code = super.to_s.gsub(/\A(\n|\r)+|(\n|\r)+\z/, '') - - is_safe = !!context.registers[:site].safe + code = super.to_s.gsub(LEADING_OR_TRAILING_LINE_TERMINATORS, "") output = case context.registers[:site].highlighter - when 'pygments' - render_pygments(code, is_safe) - when 'rouge' + when "rouge" render_rouge(code) + when "pygments" + render_pygments(code, context) else render_codehighlighter(code) end @@ -60,64 +51,79 @@ def render(context) prefix + rendered_output + suffix end - def sanitized_opts(opts, is_safe) - if is_safe - Hash[[ - [:startinline, opts.fetch(:startinline, nil)], - [:hl_lines, opts.fetch(:hl_lines, nil)], - [:linenos, opts.fetch(:linenos, nil)], - [:encoding, opts.fetch(:encoding, 'utf-8')], - [:cssclass, opts.fetch(:cssclass, nil)] - ].reject {|f| f.last.nil? }] - else - opts - end - end + private - def render_pygments(code, is_safe) - Jekyll::External.require_with_graceful_fail('pygments') + OPTIONS_REGEX = %r!(?:\w="[^"]*"|\w=\w|\w)+!.freeze - highlighted_code = Pygments.highlight( - code, - :lexer => @lang, - :options => sanitized_opts(@options, is_safe) - ) + def parse_options(input) + options = {} + return options if input.empty? - if highlighted_code.nil? - Jekyll.logger.error "There was an error highlighting your code:" - puts - Jekyll.logger.error code - puts - Jekyll.logger.error "While attempting to convert the above code, Pygments.rb" + - " returned an unacceptable value." - Jekyll.logger.error "This is usually a timeout problem solved by running `jekyll build` again." - raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.") + # Split along 3 possible forms -- key="", key=value, or key + input.scan(OPTIONS_REGEX) do |opt| + key, value = opt.split("=") + # If a quoted list, convert to array + if value&.include?('"') + value.delete!('"') + value = value.split + end + options[key.to_sym] = value || true end - highlighted_code.sub('
    ', '').sub('
    ', '') + options[:linenos] = "inline" if options[:linenos] == true + options + end + + def render_pygments(code, _context) + Jekyll.logger.warn "Warning:", "Highlight Tag no longer supports rendering with Pygments." + Jekyll.logger.warn "", "Using the default highlighter, Rouge, instead." + render_rouge(code) end def render_rouge(code) - Jekyll::External.require_with_graceful_fail('rouge') - formatter = Rouge::Formatters::HTML.new(line_numbers: @options[:linenos], wrap: false) + require "rouge" + formatter = Rouge::Formatters::HTML.new + formatter = line_highlighter_formatter(formatter) if @highlight_options[:mark_lines] + formatter = table_formatter(formatter) if @highlight_options[:linenos] + lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText formatter.format(lexer.lex(code)) end + def line_highlighter_formatter(formatter) + Rouge::Formatters::HTMLLineHighlighter.new( + formatter, + :highlight_lines => mark_lines + ) + end + + def mark_lines + value = @highlight_options[:mark_lines] + return value.map(&:to_i) if value.is_a?(Array) + + raise SyntaxError, "Syntax Error for mark_lines declaration. Expected a " \ + "double-quoted list of integers." + end + + def table_formatter(formatter) + Rouge::Formatters::HTMLTable.new( + formatter, + :css_class => "highlight", + :gutter_class => "gutter", + :code_class => "code" + ) + end + def render_codehighlighter(code) h(code).strip end def add_code_tag(code) - code_attributes = [ - "class=\"language-#{@lang.to_s.gsub('+', '-')}\"", - "data-lang=\"#{@lang.to_s}\"" - ].join(" ") - "
    #{code.chomp}
    " + code_attrs = %(class="language-#{@lang.tr("+", "-")}" data-lang="#{@lang}") + %(
    #{code.chomp}
    ) end - end end end -Liquid::Template.register_tag('highlight', Jekyll::Tags::HighlightBlock) +Liquid::Template.register_tag("highlight", Jekyll::Tags::HighlightBlock) diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 0e944407b59..fa2e1f38a00 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -1,31 +1,30 @@ -# encoding: UTF-8 +# frozen_string_literal: true module Jekyll module Tags - class IncludeTagError < StandardError - attr_accessor :path - - def initialize(msg, path) - super(msg) - @path = path - end - end - class IncludeTag < Liquid::Tag - - attr_reader :includes_dir - - VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/ - VARIABLE_SYNTAX = /(?[^{]*\{\{\s*(?[\w\-\.]+)\s*(\|.*)?\}\}[^\s}]*)(?.*)/ + VALID_SYNTAX = %r! + ([\w-]+)\s*=\s* + (?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w.-]+)) + !x.freeze + VARIABLE_SYNTAX = %r! + (?[^{]*(\{\{\s*[\w\-.]+\s*(\|.*)?\}\}[^\s{}]*)+) + (?.*) + !mx.freeze + + FULL_VALID_SYNTAX = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!.freeze + VALID_FILENAME_CHARS = %r!^[\w/.\-()+~\#@]+$!.freeze + INVALID_SEQUENCES = %r![./]{2,}!.freeze def initialize(tag_name, markup, tokens) super - matched = markup.strip.match(VARIABLE_SYNTAX) + markup = markup.strip + matched = markup.match(VARIABLE_SYNTAX) if matched - @file = matched['variable'].strip - @params = matched['params'].strip + @file = matched["variable"].strip + @params = matched["params"].strip else - @file, @params = markup.strip.split(' ', 2); + @file, @params = markup.split(%r!\s+!, 2) end validate_params if @params @tag_name = tag_name @@ -37,52 +36,47 @@ def syntax_example def parse_params(context) params = {} - markup = @params - - while match = VALID_SYNTAX.match(markup) do - markup = markup[match.end(0)..-1] - - value = if match[2] - match[2].gsub(/\\"/, '"') - elsif match[3] - match[3].gsub(/\\'/, "'") - elsif match[4] - context[match[4]] - end - - params[match[1]] = value + @params.scan(VALID_SYNTAX) do |key, d_quoted, s_quoted, variable| + value = if d_quoted + d_quoted.include?('\\"') ? d_quoted.gsub('\\"', '"') : d_quoted + elsif s_quoted + s_quoted.include?("\\'") ? s_quoted.gsub("\\'", "'") : s_quoted + elsif variable + context[variable] + end + + params[key] = value end params end def validate_file_name(file) - if file !~ /^[a-zA-Z0-9_\/\.-]+$/ || file =~ /\.\// || file =~ /\/\./ - raise ArgumentError.new <<-eos -Invalid syntax for include tag. File contains invalid characters or sequences: + if INVALID_SEQUENCES.match?(file) || !VALID_FILENAME_CHARS.match?(file) + raise ArgumentError, <<~MSG + Invalid syntax for include tag. File contains invalid characters or sequences: - #{file} + #{file} -Valid syntax: + Valid syntax: - #{syntax_example} + #{syntax_example} -eos + MSG end end def validate_params - full_valid_syntax = Regexp.compile('\A\s*(?:' + VALID_SYNTAX.to_s + '(?=\s|\z)\s*)*\z') - unless @params =~ full_valid_syntax - raise ArgumentError.new <<-eos -Invalid syntax for include tag: + unless FULL_VALID_SYNTAX.match?(@params) + raise ArgumentError, <<~MSG + Invalid syntax for include tag: - #{@params} + #{@params} -Valid syntax: + Valid syntax: - #{syntax_example} + #{syntax_example} -eos + MSG end end @@ -93,44 +87,53 @@ def file_read_opts(context) # Render the variable if required def render_variable(context) - if @file.match(VARIABLE_SYNTAX) - partial = context.registers[:site].liquid_renderer.file("(variable)").parse(@file) - partial.render!(context) - end + Liquid::Template.parse(@file).render(context) if VARIABLE_SYNTAX.match?(@file) + end + + def tag_includes_dirs(context) + context.registers[:site].includes_load_paths.freeze end - def tag_includes_dir(context) - context.registers[:site].config['includes_dir'].freeze + def locate_include_file(context, file, safe) + includes_dirs = tag_includes_dirs(context) + includes_dirs.each do |dir| + path = PathManager.join(dir, file) + return path if valid_include_file?(path, dir.to_s, safe) + end + raise IOError, could_not_locate_message(file, includes_dirs, safe) end def render(context) site = context.registers[:site] - @includes_dir = tag_includes_dir(context) - dir = resolved_includes_dir(context) file = render_variable(context) || @file validate_file_name(file) - path = File.join(dir, file) - validate_path(path, dir, site.safe) + path = locate_include_file(context, file, site.safe) + return unless path - # Add include to dependency tree - if context.registers[:page] and context.registers[:page].has_key? "path" - site.regenerator.add_dependency( - site.in_source_dir(context.registers[:page]["path"]), - path - ) - end + add_include_to_dependency(site, path, context) - begin - partial = load_cached_partial(path, context) + partial = load_cached_partial(path, context) - context.stack do - context['include'] = parse_params(context) if @params + context.stack do + context["include"] = parse_params(context) if @params + begin partial.render!(context) + rescue Liquid::Error => e + e.template_name = path + e.markup_context = "included " if e.markup_context.nil? + raise e end - rescue => e - raise IncludeTagError.new e.message, File.join(@includes_dir, @file) + end + end + + def add_include_to_dependency(site, path, context) + if context.registers[:page]&.key?("path") + site.regenerator.add_dependency( + site.in_source_dir(context.registers[:page]["path"]), + path + ) end end @@ -138,54 +141,151 @@ def load_cached_partial(path, context) context.registers[:cached_partials] ||= {} cached_partial = context.registers[:cached_partials] - if cached_partial.has_key?(path) + if cached_partial.key?(path) cached_partial[path] else - cached_partial[path] = context.registers[:site].liquid_renderer.file(path).parse(read_file(path, context)) + unparsed_file = context.registers[:site] + .liquid_renderer + .file(path) + begin + cached_partial[path] = unparsed_file.parse(read_file(path, context)) + rescue Liquid::Error => e + e.template_name = path + e.markup_context = "included " if e.markup_context.nil? + raise e + end end end - def resolved_includes_dir(context) - context.registers[:site].in_source_dir(@includes_dir) - end - - def validate_path(path, dir, safe) - if safe && !realpath_prefixed_with?(path, dir) - raise IOError.new "The included file '#{path}' should exist and should not be a symlink" - elsif !File.exist?(path) - raise IOError.new "Included file '#{path_relative_to_source(dir, path)}' not found" - end + def valid_include_file?(path, dir, safe) + !outside_site_source?(path, dir, safe) && File.file?(path) end - def path_relative_to_source(dir, path) - File.join(@includes_dir, path.sub(Regexp.new("^#{dir}"), "")) + def outside_site_source?(path, dir, safe) + safe && !realpath_prefixed_with?(path, dir) end def realpath_prefixed_with?(path, dir) File.exist?(path) && File.realpath(path).start_with?(dir) + rescue StandardError + false end # This method allows to modify the file content by inheriting from the class. def read_file(file, context) - File.read(file, file_read_opts(context)) + File.read(file, **file_read_opts(context)) + end + + private + + def could_not_locate_message(file, includes_dirs, safe) + message = "Could not locate the included file '#{file}' in any of #{includes_dirs}. " \ + "Ensure it exists in one of those directories and" + message + if safe + " is not a symlink as those are not allowed in safe mode." + else + ", if it is a symlink, does not point outside your site source." + end + end + end + + # Do not inherit from this class. + # TODO: Merge into the `Jekyll::Tags::IncludeTag` in v5.0 + class OptimizedIncludeTag < IncludeTag + def render(context) + @site ||= context.registers[:site] + + file = render_variable(context) || @file + validate_file_name(file) + + @site.inclusions[file] ||= locate_include_file(file) + inclusion = @site.inclusions[file] + + add_include_to_dependency(inclusion, context) if @site.config["incremental"] + + context.stack do + context["include"] = parse_params(context) if @params + inclusion.render(context) + end + end + + private + + def locate_include_file(file) + @site.includes_load_paths.each do |dir| + path = PathManager.join(dir, file) + return Inclusion.new(@site, dir, file) if valid_include_file?(path, dir) + end + raise IOError, could_not_locate_message(file, @site.includes_load_paths, @site.safe) + end + + def valid_include_file?(path, dir) + File.file?(path) && !outside_scope?(path, dir) + end + + def outside_scope?(path, dir) + @site.safe && !realpath_prefixed_with?(path, dir) + end + + def realpath_prefixed_with?(path, dir) + File.realpath(path).start_with?(dir) + rescue StandardError + false + end + + def add_include_to_dependency(inclusion, context) + page = context.registers[:page] + return unless page&.key?("path") + + absolute_path = \ + if page["collection"] + @site.in_source_dir(@site.config["collections_dir"], page["path"]) + else + @site.in_source_dir(page["path"]) + end + + @site.regenerator.add_dependency(absolute_path, inclusion.path) end end class IncludeRelativeTag < IncludeTag - def tag_includes_dir(context) - '.'.freeze + def load_cached_partial(path, context) + context.registers[:cached_partials] ||= {} + context.registers[:cached_partials][path] ||= parse_partial(path, context) + end + + def tag_includes_dirs(context) + Array(page_path(context)).freeze end def page_path(context) - context.registers[:page].nil? ? includes_dir : File.dirname(context.registers[:page]["path"]) + page, site = context.registers.values_at(:page, :site) + return site.source unless page + + site.in_source_dir File.dirname(resource_path(page, site)) + end + + private + + def resource_path(page, site) + path = page["path"] + path = File.join(site.config["collections_dir"], path) if page["collection"] + path.delete_suffix("/#excerpt") end - def resolved_includes_dir(context) - context.registers[:site].in_source_dir(page_path(context)) + # Since Jekyll 4 caches convertibles based on their path within the only instance of + # `LiquidRenderer`, initialize a new LiquidRenderer instance on every render of this + # tag to bypass caching rendered output of page / document. + def parse_partial(path, context) + LiquidRenderer.new(context.registers[:site]).file(path).parse(read_file(path, context)) + rescue Liquid::Error => e + e.template_name = path + e.markup_context = "included " if e.markup_context.nil? + raise e end end end end -Liquid::Template.register_tag('include', Jekyll::Tags::IncludeTag) -Liquid::Template.register_tag('include_relative', Jekyll::Tags::IncludeRelativeTag) +Liquid::Template.register_tag("include", Jekyll::Tags::OptimizedIncludeTag) +Liquid::Template.register_tag("include_relative", Jekyll::Tags::IncludeRelativeTag) diff --git a/lib/jekyll/tags/link.rb b/lib/jekyll/tags/link.rb new file mode 100644 index 00000000000..c986b5a9e14 --- /dev/null +++ b/lib/jekyll/tags/link.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +module Jekyll + module Tags + class Link < Liquid::Tag + include Jekyll::Filters::URLFilters + + class << self + def tag_name + name.split("::").last.downcase + end + end + + def initialize(tag_name, relative_path, tokens) + super + + @relative_path = relative_path.strip + end + + def render(context) + @context = context + site = context.registers[:site] + relative_path = Liquid::Template.parse(@relative_path).render(context) + relative_path_with_leading_slash = PathManager.join("", relative_path) + + site.each_site_file do |item| + return relative_url(item) if item.relative_path == relative_path + # This takes care of the case for static files that have a leading / + return relative_url(item) if item.relative_path == relative_path_with_leading_slash + end + + raise ArgumentError, <<~MSG + Could not find document '#{relative_path}' in tag '#{self.class.tag_name}'. + + Make sure the document exists and the path is correct. + MSG + end + end + end +end + +Liquid::Template.register_tag(Jekyll::Tags::Link.tag_name, Jekyll::Tags::Link) diff --git a/lib/jekyll/tags/post_url.rb b/lib/jekyll/tags/post_url.rb index 5b0d6479f76..5b38327a013 100644 --- a/lib/jekyll/tags/post_url.rb +++ b/lib/jekyll/tags/post_url.rb @@ -1,91 +1,135 @@ +# frozen_string_literal: true + module Jekyll module Tags class PostComparer - MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/ + # Deprecated (soft; No interpreter warnings). + # To be removed in v5.0. + # Use private constant `POST_PATH_MATCHER` instead. + MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!.freeze + + POST_PATH_MATCHER = %r!\A(.+/)*?(\d{2,4}-\d{1,2}-\d{1,2})-([^/]*)\z!.freeze + private_constant :POST_PATH_MATCHER attr_reader :path, :date, :slug, :name def initialize(name) @name = name - all, @path, @date, @slug = *name.sub(/^\//, "").match(MATCHER) - raise ArgumentError.new("'#{name}' does not contain valid date and/or title.") unless all - @name_regex = /^#{path}#{date}-#{slug}\.[^.]+/ + all, @path, @date, @slug = *name.delete_prefix("/").match(POST_PATH_MATCHER) + unless all + raise Jekyll::Errors::InvalidPostNameError, + "'#{name}' does not contain valid date and/or title." + end + + basename_pattern = "#{date}-#{Regexp.escape(slug)}\\.[^.]+" + @name_regex = %r!\A_posts/#{path}#{basename_pattern}|\A#{path}_posts/?#{basename_pattern}! + end + + def post_date + @post_date ||= Utils.parse_date(date, "Path '#{name}' does not contain valid date.") end + # Returns `MatchData` or `nil`. def ==(other) - other.basename.match(@name_regex) + other.relative_path.match(@name_regex) end + # Deprecated. To be removed in v5.0. def deprecated_equality(other) - date = Utils.parse_date(name, "'#{name}' does not contain valid date and/or title.") slug == post_slug(other) && - date.year == other.date.year && - date.month == other.date.month && - date.day == other.date.day + post_date.year == other.date.year && + post_date.month == other.date.month && + post_date.day == other.date.day end private - # Construct the directory-aware post slug for a Jekyll::Post + + # Construct the directory-aware post slug for a Jekyll::Document object. # - # other - the Jekyll::Post + # other - the Jekyll::Document object. # # Returns the post slug with the subdirectory (relative to _posts) def post_slug(other) path = other.basename.split("/")[0...-1].join("/") if path.nil? || path == "" - other.data['slug'] + other.data["slug"] else - path + '/' + other.data['slug'] + "#{path}/#{other.data["slug"]}" end end end class PostUrl < Liquid::Tag - def initialize(tag_name, post, tokens) + include Jekyll::Filters::URLFilters + + def initialize(tag_name, markup, tokens) super - @orig_post = post.strip - begin - @post = PostComparer.new(@orig_post) - rescue - raise ArgumentError.new <<-eos -Could not parse name of post "#{@orig_post}" in tag 'post_url'. + @markup = markup.strip + @template = Liquid::Template.parse(@markup) if @markup.include?("{{") -Make sure the post exists and the name is correct. -eos - end + # Deprecated instance_variables. + # To be removed in Jekyll v5.0. + @orig_post = @markup + @post = nil end def render(context) + @context = context + @resolved_markup = @template&.render(@context) || @markup site = context.registers[:site] - site.posts.docs.each do |p| - if @post == p - return p.url - end + begin + @post_comparer = PostComparer.new(@resolved_markup) + rescue StandardError + raise_markup_parse_error end + # For backwards compatibility only; deprecated instance_variable. + # To be removed in Jekyll v5.0. + @post = @post_comparer - # New matching method did not match, fall back to old method - # with deprecation warning if this matches - - site.posts.docs.each do |p| - if @post.deprecated_equality p - Jekyll::Deprecator.deprecation_message "A call to '{{ post_url #{@post.name} }}' did not match " + - "a post using the new matching method of checking name " + - "(path-date-slug) equality. Please make sure that you " + - "change this tag to match the post's name exactly." - return p.url - end + # First pass-through. + site.posts.docs.each do |post| + return relative_url(post) if @post_comparer == post end - raise ArgumentError.new <<-eos -Could not find post "#{@orig_post}" in tag 'post_url'. + # First pass-through did not yield the requested post. Search again using legacy matching + # method. Log deprecation warning if a post is detected via this round. + site.posts.docs.each do |post| + next unless @post_comparer.deprecated_equality(post) + + log_legacy_usage_deprecation + return relative_url(post) + end + + raise_post_not_found_error + end + + private + + def raise_markup_parse_error + raise Jekyll::Errors::PostURLError, <<~MSG + Could not parse name of post #{@resolved_markup.inspect} in tag 'post_url'. + Make sure the correct name is given to the tag. + MSG + end + + def raise_post_not_found_error + raise Jekyll::Errors::PostURLError, <<~MSG + Could not find post #{@resolved_markup.inspect} in tag 'post_url'. + Make sure the post exists and the correct name is given to the tag. + MSG + end -Make sure the post exists and the name is correct. -eos + def log_legacy_usage_deprecation + Jekyll::Deprecator.deprecation_message( + "A call to '{% post_url #{@resolved_markup} %}' did not match a post using the new " \ + "matching method of checking name (path-date-slug) equality. Please make sure that " \ + "you change this tag to match the post's name exactly." + ) end end end end -Liquid::Template.register_tag('post_url', Jekyll::Tags::PostUrl) +Liquid::Template.register_tag("post_url", Jekyll::Tags::PostUrl) diff --git a/lib/jekyll/theme.rb b/lib/jekyll/theme.rb new file mode 100644 index 00000000000..a3f2a94d1dd --- /dev/null +++ b/lib/jekyll/theme.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +module Jekyll + class Theme + extend Forwardable + attr_reader :name + + def_delegator :gemspec, :version, :version + + def initialize(name) + @name = name.downcase.strip + Jekyll.logger.debug "Theme:", name + Jekyll.logger.debug "Theme source:", root + end + + def root + # Must use File.realpath to resolve symlinks created by rbenv + # Otherwise, Jekyll.sanitized path with prepend the unresolved root + @root ||= File.realpath(gemspec.full_gem_path) + rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP + raise "Path #{gemspec.full_gem_path} does not exist, is not accessible or includes " \ + "a symbolic link loop" + end + + # The name of theme directory + def basename + @basename ||= File.basename(root) + end + + def includes_path + @includes_path ||= path_for "_includes" + end + + def layouts_path + @layouts_path ||= path_for "_layouts" + end + + def sass_path + @sass_path ||= path_for "_sass" + end + + def assets_path + @assets_path ||= path_for "assets" + end + + def data_path + @data_path ||= path_for "_data" + end + + def runtime_dependencies + gemspec.runtime_dependencies + end + + private + + def path_for(folder) + path = realpath_for(folder) + path if path && File.directory?(path) + end + + def realpath_for(folder) + # This resolves all symlinks for the theme subfolder and then ensures that the directory + # remains inside the theme root. This prevents the use of symlinks for theme subfolders to + # escape the theme root. + # However, symlinks are allowed to point to other directories within the theme. + Jekyll.sanitized_path(root, File.realpath(Jekyll.sanitized_path(root, folder.to_s))) + rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP => e + log_realpath_exception(e, folder) + nil + end + + def log_realpath_exception(err, folder) + return if err.is_a?(Errno::ENOENT) + + case err + when Errno::EACCES + Jekyll.logger.error "Theme error:", "Directory '#{folder}' is not accessible." + when Errno::ELOOP + Jekyll.logger.error "Theme error:", "Directory '#{folder}' includes a symbolic link loop." + end + end + + def gemspec + @gemspec ||= Gem::Specification.find_by_name(name) + rescue Gem::LoadError + raise Jekyll::Errors::MissingDependencyException, + "The #{name} theme could not be found." + end + end +end diff --git a/lib/jekyll/theme_builder.rb b/lib/jekyll/theme_builder.rb new file mode 100644 index 00000000000..b03abbf45aa --- /dev/null +++ b/lib/jekyll/theme_builder.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +module Jekyll + class ThemeBuilder + SCAFFOLD_DIRECTORIES = %w( + assets _data _layouts _includes _sass + ).freeze + + attr_reader :name, :path, :code_of_conduct + + def initialize(theme_name, opts) + @name = theme_name.to_s.tr(" ", "_").squeeze("_") + @path = Pathname.new(File.expand_path(name, Dir.pwd)) + @code_of_conduct = !!opts["code_of_conduct"] + end + + def create! + create_directories + create_starter_files + create_gemspec + create_accessories + initialize_git_repo + end + + def user_name + @user_name ||= `git config user.name`.chomp + end + + def user_email + @user_email ||= `git config user.email`.chomp + end + + private + + def root + @root ||= Pathname.new(File.expand_path("../", __dir__)) + end + + def template_file(filename) + [ + root.join("theme_template", "#{filename}.erb"), + root.join("theme_template", filename.to_s), + ].find(&:exist?) + end + + def template(filename) + erb.render(template_file(filename).read) + end + + def erb + @erb ||= ERBRenderer.new(self) + end + + def mkdir_p(directories) + Array(directories).each do |directory| + full_path = path.join(directory) + Jekyll.logger.info "create", full_path.to_s + FileUtils.mkdir_p(full_path) + end + end + + def write_file(filename, contents) + full_path = path.join(filename) + Jekyll.logger.info "create", full_path.to_s + File.write(full_path, contents) + end + + def create_directories + mkdir_p(SCAFFOLD_DIRECTORIES) + end + + def create_starter_files + %w(page post default).each do |layout| + write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html")) + end + end + + def create_gemspec + write_file("Gemfile", template("Gemfile")) + write_file("#{name}.gemspec", template("theme.gemspec")) + end + + def create_accessories + accessories = %w(README.md LICENSE.txt) + accessories << "CODE_OF_CONDUCT.md" if code_of_conduct + accessories.each do |filename| + write_file(filename, template(filename)) + end + end + + def initialize_git_repo + Jekyll.logger.info "initialize", path.join(".git").to_s + Dir.chdir(path.to_s) { `git init` } + write_file(".gitignore", template("gitignore")) + end + + class ERBRenderer + extend Forwardable + + def_delegator :@theme_builder, :name, :theme_name + def_delegator :@theme_builder, :user_name, :user_name + def_delegator :@theme_builder, :user_email, :user_email + + def initialize(theme_builder) + @theme_builder = theme_builder + end + + def jekyll_version_with_minor + Jekyll::VERSION.split(".").take(2).join(".") + end + + def theme_directories + SCAFFOLD_DIRECTORIES + end + + def render(contents) + ERB.new(contents).result binding + end + end + end +end diff --git a/lib/jekyll/url.rb b/lib/jekyll/url.rb index 6e8042b01d9..d57352c4361 100644 --- a/lib/jekyll/url.rb +++ b/lib/jekyll/url.rb @@ -1,4 +1,4 @@ -require 'uri' +# frozen_string_literal: true # Public: Methods that generate a URL for a resource such as a Post or a Page. # @@ -11,7 +11,6 @@ # module Jekyll class URL - # options - One of :permalink or :template must be supplied. # :template - The String used as template for URL generation, # for example "/:path/:basename:output_ext", where @@ -59,22 +58,67 @@ def generated_url # # Returns the unsanitized String URL def generate_url(template) + if @placeholders.is_a? Drops::UrlDrop + generate_url_from_drop(template) + else + generate_url_from_hash(template) + end + end + + def generate_url_from_hash(template) @placeholders.inject(template) do |result, token| - break result if result.index(':').nil? + break result if result.index(":").nil? + if token.last.nil? - # Remove leading '/' to avoid generating urls with `//` - result.gsub(/\/:#{token.first}/, '') + # Remove leading "/" to avoid generating urls with `//` + result.gsub("/:#{token.first}", "") else - result.gsub(/:#{token.first}/, self.class.escape_path(token.last)) + result.gsub(":#{token.first}", self.class.escape_path(token.last)) + end + end + end + + # We include underscores in keys to allow for 'i_month' and so forth. + # This poses a problem for keys which are followed by an underscore + # but the underscore is not part of the key, e.g. '/:month_:day'. + # That should be :month and :day, but our key extraction regexp isn't + # smart enough to know that so we have to make it an explicit + # possibility. + def possible_keys(key) + if key.end_with?("_") + [key, key.chomp("_")] + else + [key] + end + end + + def generate_url_from_drop(template) + template.gsub(%r!:([a-z_]+)!) do |match| + name = Regexp.last_match(1) + pool = name.end_with?("_") ? [name, name.chomp!("_")] : [name] + + winner = pool.find { |key| @placeholders.key?(key) } + if winner.nil? + raise NoMethodError, + "The URL template doesn't have #{pool.join(" or ")} keys. " \ + "Check your permalink template!" end + + value = @placeholders[winner] + value = "" if value.nil? + replacement = self.class.escape_path(value) + + match.sub!(":#{winner}", replacement) end end # Returns a sanitized String URL, stripping "../../" and multiples of "/", # as well as the beginning "/" so we can enforce and ensure it. - def sanitize_url(str) - "/" + str.gsub(/\/{2,}/, "/").gsub(%r!\.+\/|\A/+!, "") + "/#{str}".gsub("..", "/").tap do |result| + result.gsub!("./", "") + result.squeeze!("/") + end end # Escapes a path to be a valid URL path segment @@ -88,7 +132,9 @@ def sanitize_url(str) # # Returns the escaped path. def self.escape_path(path) - # Because URI.escape doesn't escape '?', '[' and ']' by default, + return path if path.empty? || %r!^[a-zA-Z0-9./-]+$!.match?(path) + + # Because URI.escape doesn't escape "?", "[" and "]" by default, # specify unsafe string (except unreserved, sub-delims, ":", "@" and "/"). # # URI path segment is defined in RFC 3986 as follows: @@ -98,7 +144,13 @@ def self.escape_path(path) # pct-encoded = "%" HEXDIG HEXDIG # sub-delims = "!" / "$" / "&" / "'" / "(" / ")" # / "*" / "+" / "," / ";" / "=" - URI.escape(path, /[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]/).encode('utf-8') + # + # `Addressable::URI::CharacterClassesRegexps::PATH` is used to encode + # non-alphanumeric characters such as "[", "]", etc. + Addressable::URI.encode_component( + path, + Addressable::URI::CharacterClassesRegexps::PATH + ).encode("utf-8").sub("#", "%23") end # Unescapes a URL path segment @@ -112,7 +164,10 @@ def self.escape_path(path) # # Returns the unescaped path. def self.unescape_path(path) - URI.unescape(path.encode('utf-8')) + path = path.encode("utf-8") + return path unless path.include?("%") + + Addressable::URI.unencode(path) end end end diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index 7d2490a6864..2a965270481 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -1,12 +1,26 @@ +# frozen_string_literal: true + module Jekyll - module Utils extend self - autoload :Platforms, 'jekyll/utils/platforms' + module Utils + extend self + autoload :Ansi, "jekyll/utils/ansi" + autoload :Exec, "jekyll/utils/exec" + autoload :Internet, "jekyll/utils/internet" + autoload :Platforms, "jekyll/utils/platforms" + autoload :ThreadEvent, "jekyll/utils/thread_event" + autoload :WinTZ, "jekyll/utils/win_tz" # Constants for use in #slugify - SLUGIFY_MODES = %w{raw default pretty} + SLUGIFY_MODES = %w(raw default pretty ascii latin).freeze SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze - SLUGIFY_DEFAULT_REGEXP = Regexp.new('[^[:alnum:]]+').freeze - SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze + SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}]+").freeze + SLUGIFY_PRETTY_REGEXP = Regexp.new("[^\\p{M}\\p{L}\\p{Nd}._~!$&'()+,;=@]+").freeze + SLUGIFY_ASCII_REGEXP = Regexp.new("[^[A-Za-z0-9]]+").freeze + + # Takes a slug and turns it into a simple title. + def titleize_slug(slug) + slug.split("-").map!(&:capitalize).join(" ") + end # Non-destructive version of deep_merge_hashes! See that method. # @@ -25,20 +39,24 @@ def deep_merge_hashes(master_hash, other_hash) # # Thanks to whoever made it. def deep_merge_hashes!(target, overwrite) - overwrite.each_key do |key| - if overwrite[key].is_a? Hash and target[key].is_a? Hash - target[key] = Utils.deep_merge_hashes(target[key], overwrite[key]) - next - end + merge_values(target, overwrite) + merge_default_proc(target, overwrite) + duplicate_frozen_values(target) - target[key] = overwrite[key] - end + target + end - if target.default_proc.nil? - target.default_proc = overwrite.default_proc - end + def mergable?(value) + value.is_a?(Hash) || value.is_a?(Drops::Drop) + end - target + def duplicable?(obj) + case obj + when nil, false, true, Symbol, Numeric + false + else + true + end end # Read array from the supplied hash favouring the singular key @@ -50,13 +68,18 @@ def deep_merge_hashes!(target, overwrite) # # Returns an array def pluralized_array_from_hash(hash, singular_key, plural_key) - [].tap do |array| - array << (value_from_singular_key(hash, singular_key) || value_from_plural_key(hash, plural_key)) - end.flatten.compact + array = [] + value = value_from_singular_key(hash, singular_key) + value ||= value_from_plural_key(hash, plural_key) + + array << value + array.flatten! + array.compact! + array end def value_from_singular_key(hash, key) - hash[key] if (hash.key?(key) || (hash.default_proc && hash[key])) + hash[key] if hash.key?(key) || (hash.default_proc && hash[key]) end def value_from_plural_key(hash, key) @@ -105,23 +128,37 @@ def stringify_hash_keys(hash) # Returns the parsed date if successful, throws a FatalException # if not def parse_date(input, msg = "Input could not be parsed.") - Time.parse(input).localtime + @parse_date_cache ||= {} + @parse_date_cache[input] ||= Time.parse(input).localtime rescue ArgumentError - raise Errors::FatalException.new("Invalid date '#{input}': " + msg) + raise Errors::InvalidDateError, "Invalid date '#{input}': #{msg}" end # Determines whether a given file has # # Returns true if the YAML front matter is present. + # rubocop: disable Naming/PredicateName def has_yaml_header?(file) - !!(File.open(file, 'rb') { |f| f.read(5) } =~ /\A---\r?\n/) + File.open(file, "rb", &:readline).match? %r!\A---\s*\r?\n! + rescue EOFError + false end + # Determine whether the given content string contains Liquid Tags or Variables + # + # Returns true is the string contains sequences of `{%` or `{{` + def has_liquid_construct?(content) + return false if content.nil? || content.empty? + + content.include?("{%") || content.include?("{{") + end + # rubocop: enable Naming/PredicateName + # Slugify a filename or title. # # string - the filename or title to slugify # mode - how string is slugified - # cased - whether to replace all uppercase letters with their + # cased - whether to replace all uppercase letters with their # lowercase counterparts # # When mode is "none", return the given string. @@ -135,6 +172,13 @@ def has_yaml_header?(file) # When mode is "pretty", some non-alphabetic characters (._~!$&'()+,;=@) # are not replaced with hyphen. # + # When mode is "ascii", some everything else except ASCII characters + # a-z (lowercase), A-Z (uppercase) and 0-9 (numbers) are not replaced with hyphen. + # + # When mode is "latin", the input string is first preprocessed so that + # any letters with accents are replaced with the plain letter. Afterwards, + # it follows the "default" mode of operation. + # # If cased is true, all uppercase letters in the result string are # replaced with their lowercase counterparts. # @@ -148,34 +192,35 @@ def has_yaml_header?(file) # slugify("The _config.yml file", "pretty", true) # # => "The-_config.yml file" # + # slugify("The _config.yml file", "ascii") + # # => "the-config-yml-file" + # + # slugify("The _config.yml file", "latin") + # # => "the-config-yml-file" + # # Returns the slugified string. def slugify(string, mode: nil, cased: false) - mode ||= 'default' + mode ||= "default" return nil if string.nil? unless SLUGIFY_MODES.include?(mode) return cased ? string : string.downcase end - # Replace each character sequence with a hyphen - re = case mode - when 'raw' - SLUGIFY_RAW_REGEXP - when 'default' - SLUGIFY_DEFAULT_REGEXP - when 'pretty' - # "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL - # and is allowed in both extN and NTFS. - SLUGIFY_PRETTY_REGEXP + # Drop accent marks from latin characters. Everything else turns to ? + if mode == "latin" + I18n.config.available_locales = :en if I18n.config.available_locales.empty? + string = I18n.transliterate(string) end - slug = string. - # Strip according to the mode - gsub(re, '-'). - # Remove leading/trailing hyphen - gsub(/^\-|\-$/i, '') + slug = replace_character_sequence_with_hyphen(string, :mode => mode) - cased ? slug : slug.downcase + # Remove leading/trailing hyphen + slug.gsub!(%r!^-|-$!i, "") + + slug.downcase! unless cased + Jekyll.logger.warn("Warning:", "Empty `slug` generated for '#{string}'.") if slug.empty? + slug end # Add an appropriate suffix to template so that it matches the specified @@ -206,6 +251,8 @@ def slugify(string, mode: nil, cased: false) # # Returns the updated permalink template def add_permalink_suffix(template, permalink_style) + template = template.dup + case permalink_style when :pretty template << "/" @@ -215,8 +262,110 @@ def add_permalink_suffix(template, permalink_style) template << "/" if permalink_style.to_s.end_with?("/") template << ":output_ext" if permalink_style.to_s.end_with?(":output_ext") end + template end + # Work the same way as Dir.glob but separating the input into two parts + # ('dir' + '/' + 'pattern') to make sure the first part('dir') does not act + # as a pattern. + # + # For example, Dir.glob("path[/*") always returns an empty array, + # because the method fails to find the closing pattern to '[' which is ']' + # + # Examples: + # safe_glob("path[", "*") + # # => ["path[/file1", "path[/file2"] + # + # safe_glob("path", "*", File::FNM_DOTMATCH) + # # => ["path/.", "path/..", "path/file1"] + # + # safe_glob("path", ["**", "*"]) + # # => ["path[/file1", "path[/folder/file2"] + # + # dir - the dir where glob will be executed under + # (the dir will be included to each result) + # patterns - the patterns (or the pattern) which will be applied under the dir + # flags - the flags which will be applied to the pattern + # + # Returns matched paths + def safe_glob(dir, patterns, flags = 0) + return [] unless Dir.exist?(dir) + + pattern = File.join(Array(patterns)) + return [dir] if pattern.empty? + + Dir.chdir(dir) do + Dir.glob(pattern, flags).map { |f| File.join(dir, f) } + end + end + + # Returns merged option hash for File.read of self.site (if exists) + # and a given param + def merged_file_read_opts(site, opts) + merged = (site ? site.file_read_opts : {}).merge(opts) + + # always use BOM when reading UTF-encoded files + if merged[:encoding]&.downcase&.start_with?("utf-") + merged[:encoding] = "bom|#{merged[:encoding]}" + end + if merged["encoding"]&.downcase&.start_with?("utf-") + merged["encoding"] = "bom|#{merged["encoding"]}" + end + + merged + end + + private + + def merge_values(target, overwrite) + target.merge!(overwrite) do |_key, old_val, new_val| + if new_val.nil? + old_val + elsif mergable?(old_val) && mergable?(new_val) + deep_merge_hashes(old_val, new_val) + else + new_val + end + end + end + + def merge_default_proc(target, overwrite) + if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil? + target.default_proc = overwrite.default_proc + end + end + + def duplicate_frozen_values(target) + target.each do |key, val| + target[key] = val.dup if val.frozen? && duplicable?(val) + end + end + + # Replace each character sequence with a hyphen. + # + # See Utils#slugify for a description of the character sequence specified + # by each mode. + def replace_character_sequence_with_hyphen(string, mode: "default") + replaceable_char = + case mode + when "raw" + SLUGIFY_RAW_REGEXP + when "pretty" + # "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL + # and is allowed in both extN and NTFS. + SLUGIFY_PRETTY_REGEXP + when "ascii" + # For web servers not being able to handle Unicode, the safe + # method is to ditch anything else but latin letters and numeric + # digits. + SLUGIFY_ASCII_REGEXP + else + SLUGIFY_DEFAULT_REGEXP + end + + # Strip according to the mode + string.gsub(replaceable_char, "-") + end end end diff --git a/lib/jekyll/utils/ansi.rb b/lib/jekyll/utils/ansi.rb new file mode 100644 index 00000000000..00d1b1db259 --- /dev/null +++ b/lib/jekyll/utils/ansi.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Jekyll + module Utils + module Ansi + extend self + + ESCAPE = format("%c", 27) + MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix.freeze + COLORS = { + :red => 31, + :green => 32, + :black => 30, + :magenta => 35, + :yellow => 33, + :white => 37, + :blue => 34, + :cyan => 36, + }.freeze + + # Strip ANSI from the current string. It also strips cursor stuff, + # well some of it, and it also strips some other stuff that a lot of + # the other ANSI strippers don't. + + def strip(str) + str.gsub MATCH, "" + end + + # + + def has?(str) + !!(str =~ MATCH) + end + + # Reset the color back to the default color so that you do not leak any + # colors when you move onto the next line. This is probably normally + # used as part of a wrapper so that we don't leak colors. + + def reset(str = "") + @ansi_reset ||= format("%c[0m", 27) + "#{@ansi_reset}#{str}" + end + + # SEE: `self::COLORS` for a list of methods. They are mostly + # standard base colors supported by pretty much any xterm-color, we do + # not need more than the base colors so we do not include them. + # Actually... if I'm honest we don't even need most of the + # base colors. + + COLORS.each do |color, num| + define_method color do |str| + "#{format("%c", 27)}[#{num}m#{str}#{reset}" + end + end + end + end +end diff --git a/lib/jekyll/utils/exec.rb b/lib/jekyll/utils/exec.rb new file mode 100644 index 00000000000..5838ecba9e6 --- /dev/null +++ b/lib/jekyll/utils/exec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "open3" + +module Jekyll + module Utils + module Exec + extend self + + # Runs a program in a sub-shell. + # + # *args - a list of strings containing the program name and arguments + # + # Returns a Process::Status and a String of output in an array in + # that order. + def run(*args) + stdin, stdout, stderr, process = Open3.popen3(*args) + out = stdout.read.strip + err = stderr.read.strip + + [stdin, stdout, stderr].each(&:close) + [process.value, out + err] + end + end + end +end diff --git a/lib/jekyll/utils/internet.rb b/lib/jekyll/utils/internet.rb new file mode 100644 index 00000000000..945267f1e5d --- /dev/null +++ b/lib/jekyll/utils/internet.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module Jekyll + module Utils + module Internet + # Public: Determine whether the present device has a connection to + # the Internet. This allows plugin writers which require the outside + # world to have a neat fallback mechanism for offline building. + # + # Example: + # if Internet.connected? + # Typhoeus.get("https://pages.github.com/versions.json") + # else + # Jekyll.logger.warn "Warning:", "Version check has been disabled." + # Jekyll.logger.warn "", "Connect to the Internet to enable it." + # nil + # end + # + # Returns true if a DNS call can successfully be made, or false if not. + + module_function + + def connected? + !dns("example.com").nil? + end + + def dns(domain) + require "resolv" + Resolv::DNS.open do |resolver| + resolver.getaddress(domain) + end + rescue Resolv::ResolvError, Resolv::ResolvTimeout + nil + end + end + end +end diff --git a/lib/jekyll/utils/platforms.rb b/lib/jekyll/utils/platforms.rb index 83858a074a6..a6c6da902d6 100644 --- a/lib/jekyll/utils/platforms.rb +++ b/lib/jekyll/utils/platforms.rb @@ -1,29 +1,66 @@ +# frozen_string_literal: true + module Jekyll module Utils - module Platforms extend self + module Platforms + extend self + + def jruby? + RUBY_ENGINE == "jruby" + end + + def mri? + RUBY_ENGINE == "ruby" + end - # Provides jruby? and mri? which respectively detect these two types of - # tested Engines we support, in the future we might probably support the - # other one that everyone used to talk about. + def windows? + vanilla_windows? || bash_on_windows? + end - { :jruby? => "jruby", :mri? => "ruby" }.each do |k, v| - define_method k do - ::RUBY_ENGINE == v - end + # Not a Windows Subsystem for Linux (WSL) + def vanilla_windows? + rbconfig_host.match?(%r!mswin|mingw|cygwin!) && proc_version.empty? end + alias_method :really_windows?, :vanilla_windows? - # Provides windows?, linux?, osx?, unix? so that we can detect - # platforms. This is mostly useful for `jekyll doctor` and for testing - # where we kick off certain tests based on the platform. + # Determine if Windows Subsystem for Linux (WSL) + def bash_on_windows? + linux_os? && microsoft_proc_version? + end - { :windows? => /mswin|mingw|cygwin/, :linux? => /linux/, \ - :osx? => /darwin|mac os/, :unix? => /solaris|bsd/ }.each do |k, v| + def linux? + linux_os? && !microsoft_proc_version? + end + + def osx? + rbconfig_host.match?(%r!darwin|mac os!) + end + + def unix? + rbconfig_host.match?(%r!solaris|bsd!) + end + + private + + def proc_version + @proc_version ||= \ + begin + File.read("/proc/version").downcase + rescue Errno::ENOENT, Errno::EACCES + "" + end + end + + def rbconfig_host + @rbconfig_host ||= RbConfig::CONFIG["host_os"].downcase + end + + def linux_os? + rbconfig_host.include?("linux") + end - define_method k do - !!( - RbConfig::CONFIG["host_os"] =~ v - ) - end + def microsoft_proc_version? + proc_version.include?("microsoft") end end end diff --git a/lib/jekyll/utils/thread_event.rb b/lib/jekyll/utils/thread_event.rb new file mode 100644 index 00000000000..801022e4721 --- /dev/null +++ b/lib/jekyll/utils/thread_event.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module Jekyll + module Utils + # Based on the pattern and code from + # https://emptysqua.re/blog/an-event-synchronization-primitive-for-ruby/ + class ThreadEvent + attr_reader :flag + + def initialize + @lock = Mutex.new + @cond = ConditionVariable.new + @flag = false + end + + def set + @lock.synchronize do + yield if block_given? + @flag = true + @cond.broadcast + end + end + + def wait + @lock.synchronize do + @cond.wait(@lock) unless @flag + end + end + end + end +end diff --git a/lib/jekyll/utils/win_tz.rb b/lib/jekyll/utils/win_tz.rb new file mode 100644 index 00000000000..ad277d3a6a5 --- /dev/null +++ b/lib/jekyll/utils/win_tz.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +module Jekyll + module Utils + module WinTZ + extend self + + # Public: Calculate the Timezone for Windows when the config file has a defined + # 'timezone' key. + # + # timezone - the IANA Time Zone specified in "_config.yml" + # + # Returns a string that ultimately re-defines ENV["TZ"] in Windows + def calculate(timezone, now = Time.now) + External.require_with_graceful_fail("tzinfo") unless defined?(TZInfo) + tz = TZInfo::Timezone.get(timezone) + + # + # Use period_for_utc and utc_total_offset instead of + # period_for and observed_utc_offset for compatibility with tzinfo v1. + offset = tz.period_for_utc(now.getutc).utc_total_offset + + # + # POSIX style definition reverses the offset sign. + # e.g. Eastern Standard Time (EST) that is 5Hrs. to the 'west' of Prime Meridian + # is denoted as: + # EST+5 (or) EST+05:00 + # Reference: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + sign = offset.positive? ? "-" : "+" + + rational_hours = offset.abs.to_r / 3600 + hours = rational_hours.to_i + minutes = ((rational_hours - hours) * 60).to_i + + # + # Format the hours and minutes as two-digit numbers. + time = format("%02d:%02d", :hours => hours, :minutes => minutes) + + Jekyll.logger.debug "Timezone:", "#{timezone} #{sign}#{time}" + # + # Note: The 3-letter-word below doesn't have a particular significance. + "WTZ#{sign}#{time}" + end + end + end +end diff --git a/lib/jekyll/version.rb b/lib/jekyll/version.rb index 7907aaa5590..eff0d1db03f 100644 --- a/lib/jekyll/version.rb +++ b/lib/jekyll/version.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module Jekyll - VERSION = '3.0.1' + VERSION = "4.4.1" end diff --git a/lib/site_template/.gitignore b/lib/site_template/.gitignore index 45c150536e5..f40fbd8ba56 100644 --- a/lib/site_template/.gitignore +++ b/lib/site_template/.gitignore @@ -1,3 +1,5 @@ _site .sass-cache +.jekyll-cache .jekyll-metadata +vendor diff --git a/lib/site_template/404.html b/lib/site_template/404.html new file mode 100644 index 00000000000..3a16ab5330f --- /dev/null +++ b/lib/site_template/404.html @@ -0,0 +1,25 @@ +--- +permalink: /404.html +layout: page +--- + + + +
    +

    404

    + +

    Page not found :(

    +

    The requested page could not be found.

    +
    diff --git a/lib/site_template/_config.yml b/lib/site_template/_config.yml index 1c5e5bc9c1b..ef7ba7c1391 100644 --- a/lib/site_template/_config.yml +++ b/lib/site_template/_config.yml @@ -1,21 +1,55 @@ # Welcome to Jekyll! # # This config file is meant for settings that affect your whole blog, values -# which you are expected to set up once and rarely need to edit after that. +# which you are expected to set up once and rarely edit after that. If you find +# yourself editing this file very often, consider using Jekyll's data files +# feature for the data you need to update frequently. +# # For technical reasons, this file is *NOT* reloaded automatically when you use -# 'jekyll serve'. If you change this file, please restart the server process. - +# 'bundle exec jekyll serve'. If you change this file, please restart the server process. +# +# If you need help with YAML syntax, here are some quick references for you: +# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml +# https://learnxinyminutes.com/docs/yaml/ +# # Site settings +# These are used to personalize your new site. If you look in the HTML files, +# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on. +# You can create any custom variable you would like, and they will be accessible +# in the templates via {{ site.myvariable }}. + title: Your awesome title -email: your-email@domain.com -description: > # this means to ignore newlines until "baseurl:" +email: your-email@example.com +description: >- # this means to ignore newlines until "baseurl:" Write an awesome description for your new site here. You can edit this line in _config.yml. It will appear in your document head meta (for Google search results) and in your feed.xml site description. baseurl: "" # the subpath of your site, e.g. /blog -url: "http://yourdomain.com" # the base hostname & protocol for your site +url: "" # the base hostname & protocol for your site, e.g. http://example.com twitter_username: jekyllrb github_username: jekyll # Build settings -markdown: kramdown +theme: minima +plugins: + - jekyll-feed + +# Exclude from processing. +# The following items will not be processed, by default. +# Any item listed under the `exclude:` key here will be automatically added to +# the internal "default list". +# +# Excluded items can be processed by explicitly listing the directories or +# their entries' file path in the `include:` list. +# +# exclude: +# - .sass-cache/ +# - .jekyll-cache/ +# - gemfiles/ +# - Gemfile +# - Gemfile.lock +# - node_modules/ +# - vendor/bundle/ +# - vendor/cache/ +# - vendor/gems/ +# - vendor/ruby/ diff --git a/lib/site_template/_includes/footer.html b/lib/site_template/_includes/footer.html deleted file mode 100644 index 72239f1c32b..00000000000 --- a/lib/site_template/_includes/footer.html +++ /dev/null @@ -1,38 +0,0 @@ -
    - -
    - - - - - -
    - -
    diff --git a/lib/site_template/_includes/head.html b/lib/site_template/_includes/head.html deleted file mode 100644 index 41340ae57b4..00000000000 --- a/lib/site_template/_includes/head.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - {% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %} - - - - - - diff --git a/lib/site_template/_includes/header.html b/lib/site_template/_includes/header.html deleted file mode 100644 index b3f86db8f23..00000000000 --- a/lib/site_template/_includes/header.html +++ /dev/null @@ -1,27 +0,0 @@ - diff --git a/lib/site_template/_includes/icon-github.html b/lib/site_template/_includes/icon-github.html deleted file mode 100644 index e501a16b187..00000000000 --- a/lib/site_template/_includes/icon-github.html +++ /dev/null @@ -1 +0,0 @@ -{% include icon-github.svg %}{{ include.username }} diff --git a/lib/site_template/_includes/icon-github.svg b/lib/site_template/_includes/icon-github.svg deleted file mode 100644 index 4422c4f5dcc..00000000000 --- a/lib/site_template/_includes/icon-github.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/site_template/_includes/icon-twitter.html b/lib/site_template/_includes/icon-twitter.html deleted file mode 100644 index e623dbd6efc..00000000000 --- a/lib/site_template/_includes/icon-twitter.html +++ /dev/null @@ -1 +0,0 @@ -{{ include.username }} diff --git a/lib/site_template/_includes/icon-twitter.svg b/lib/site_template/_includes/icon-twitter.svg deleted file mode 100644 index dcf660e7bb3..00000000000 --- a/lib/site_template/_includes/icon-twitter.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/lib/site_template/_layouts/default.html b/lib/site_template/_layouts/default.html deleted file mode 100644 index e4ab96fb0b9..00000000000 --- a/lib/site_template/_layouts/default.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - {% include head.html %} - - - - {% include header.html %} - -
    -
    - {{ content }} -
    -
    - - {% include footer.html %} - - - - diff --git a/lib/site_template/_layouts/page.html b/lib/site_template/_layouts/page.html deleted file mode 100644 index ce233ad75bf..00000000000 --- a/lib/site_template/_layouts/page.html +++ /dev/null @@ -1,14 +0,0 @@ ---- -layout: default ---- -
    - -
    -

    {{ page.title }}

    -
    - -
    - {{ content }} -
    - -
    diff --git a/lib/site_template/_layouts/post.html b/lib/site_template/_layouts/post.html deleted file mode 100644 index 3a0fb52ecf5..00000000000 --- a/lib/site_template/_layouts/post.html +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: default ---- -
    - -
    -

    {{ page.title }}

    - -
    - -
    - {{ content }} -
    - -
    diff --git a/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb b/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb index 6ad2994294b..187a4d9b048 100644 --- a/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb +++ b/lib/site_template/_posts/0000-00-00-welcome-to-jekyll.markdown.erb @@ -6,7 +6,11 @@ categories: jekyll update --- You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. -To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. +Jekyll requires blog post files to be named according to the following format: + +`YEAR-MONTH-DAY-title.MARKUP` + +Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit numbers, and `MARKUP` is the file extension representing the format used in the file. After that, include the necessary front matter. Take a look at the source for this post to get an idea about how it works. Jekyll also offers powerful support for code snippets: @@ -20,6 +24,6 @@ print_hi('Tom') Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll’s GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekyll Talk][jekyll-talk]. -[jekyll-docs]: http://jekyllrb.com/docs/home +[jekyll-docs]: https://jekyllrb.com/docs/home [jekyll-gh]: https://github.com/jekyll/jekyll [jekyll-talk]: https://talk.jekyllrb.com/ diff --git a/lib/site_template/_sass/_base.scss b/lib/site_template/_sass/_base.scss deleted file mode 100644 index 0883c3cdb5d..00000000000 --- a/lib/site_template/_sass/_base.scss +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Reset some basic elements - */ -body, h1, h2, h3, h4, h5, h6, -p, blockquote, pre, hr, -dl, dd, ol, ul, figure { - margin: 0; - padding: 0; -} - - - -/** - * Basic styling - */ -body { - font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family; - color: $text-color; - background-color: $background-color; - -webkit-text-size-adjust: 100%; - -webkit-font-feature-settings: "kern" 1; - -moz-font-feature-settings: "kern" 1; - -o-font-feature-settings: "kern" 1; - font-feature-settings: "kern" 1; - font-kerning: normal; -} - - - -/** - * Set `margin-bottom` to maintain vertical rhythm - */ -h1, h2, h3, h4, h5, h6, -p, blockquote, pre, -ul, ol, dl, figure, -%vertical-rhythm { - margin-bottom: $spacing-unit / 2; -} - - - -/** - * Images - */ -img { - max-width: 100%; - vertical-align: middle; -} - - - -/** - * Figures - */ -figure > img { - display: block; -} - -figcaption { - font-size: $small-font-size; -} - - - -/** - * Lists - */ -ul, ol { - margin-left: $spacing-unit; -} - -li { - > ul, - > ol { - margin-bottom: 0; - } -} - - - -/** - * Headings - */ -h1, h2, h3, h4, h5, h6 { - font-weight: $base-font-weight; -} - - - -/** - * Links - */ -a { - color: $brand-color; - text-decoration: none; - - &:visited { - color: darken($brand-color, 15%); - } - - &:hover { - color: $text-color; - text-decoration: underline; - } -} - - - -/** - * Blockquotes - */ -blockquote { - color: $grey-color; - border-left: 4px solid $grey-color-light; - padding-left: $spacing-unit / 2; - font-size: 18px; - letter-spacing: -1px; - font-style: italic; - - > :last-child { - margin-bottom: 0; - } -} - - - -/** - * Code formatting - */ -pre, -code { - font-size: 15px; - border: 1px solid $grey-color-light; - border-radius: 3px; - background-color: #eef; -} - -code { - padding: 1px 5px; -} - -pre { - padding: 8px 12px; - overflow-x: auto; - - > code { - border: 0; - padding-right: 0; - padding-left: 0; - } -} - - - -/** - * Wrapper - */ -.wrapper { - max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2)); - max-width: calc(#{$content-width} - (#{$spacing-unit} * 2)); - margin-right: auto; - margin-left: auto; - padding-right: $spacing-unit; - padding-left: $spacing-unit; - @extend %clearfix; - - @include media-query($on-laptop) { - max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit})); - max-width: calc(#{$content-width} - (#{$spacing-unit})); - padding-right: $spacing-unit / 2; - padding-left: $spacing-unit / 2; - } -} - - - -/** - * Clearfix - */ -%clearfix { - - &:after { - content: ""; - display: table; - clear: both; - } -} - - - -/** - * Icons - */ -.icon { - - > svg { - display: inline-block; - width: 16px; - height: 16px; - vertical-align: middle; - - path { - fill: $grey-color; - } - } -} diff --git a/lib/site_template/_sass/_layout.scss b/lib/site_template/_sass/_layout.scss deleted file mode 100644 index 9cbfddefefb..00000000000 --- a/lib/site_template/_sass/_layout.scss +++ /dev/null @@ -1,242 +0,0 @@ -/** - * Site header - */ -.site-header { - border-top: 5px solid $grey-color-dark; - border-bottom: 1px solid $grey-color-light; - min-height: 56px; - - // Positioning context for the mobile navigation icon - position: relative; -} - -.site-title { - font-size: 26px; - font-weight: 300; - line-height: 56px; - letter-spacing: -1px; - margin-bottom: 0; - float: left; - - &, - &:visited { - color: $grey-color-dark; - } -} - -.site-nav { - float: right; - line-height: 56px; - - .menu-icon { - display: none; - } - - .page-link { - color: $text-color; - line-height: $base-line-height; - - // Gaps between nav items, but not on the last one - &:not(:last-child) { - margin-right: 20px; - } - } - - @include media-query($on-palm) { - position: absolute; - top: 9px; - right: $spacing-unit / 2; - background-color: $background-color; - border: 1px solid $grey-color-light; - border-radius: 5px; - text-align: right; - - .menu-icon { - display: block; - float: right; - width: 36px; - height: 26px; - line-height: 0; - padding-top: 10px; - text-align: center; - - > svg { - width: 18px; - height: 15px; - - path { - fill: $grey-color-dark; - } - } - } - - .trigger { - clear: both; - display: none; - } - - &:hover .trigger { - display: block; - padding-bottom: 5px; - } - - .page-link { - display: block; - padding: 5px 10px; - - &:not(:last-child) { - margin-right: 0; - } - margin-left: 20px; - } - } -} - - - -/** - * Site footer - */ -.site-footer { - border-top: 1px solid $grey-color-light; - padding: $spacing-unit 0; -} - -.footer-heading { - font-size: 18px; - margin-bottom: $spacing-unit / 2; -} - -.contact-list, -.social-media-list { - list-style: none; - margin-left: 0; -} - -.footer-col-wrapper { - font-size: 15px; - color: $grey-color; - margin-left: -$spacing-unit / 2; - @extend %clearfix; -} - -.footer-col { - float: left; - margin-bottom: $spacing-unit / 2; - padding-left: $spacing-unit / 2; -} - -.footer-col-1 { - width: -webkit-calc(35% - (#{$spacing-unit} / 2)); - width: calc(35% - (#{$spacing-unit} / 2)); -} - -.footer-col-2 { - width: -webkit-calc(20% - (#{$spacing-unit} / 2)); - width: calc(20% - (#{$spacing-unit} / 2)); -} - -.footer-col-3 { - width: -webkit-calc(45% - (#{$spacing-unit} / 2)); - width: calc(45% - (#{$spacing-unit} / 2)); -} - -@include media-query($on-laptop) { - .footer-col-1, - .footer-col-2 { - width: -webkit-calc(50% - (#{$spacing-unit} / 2)); - width: calc(50% - (#{$spacing-unit} / 2)); - } - - .footer-col-3 { - width: -webkit-calc(100% - (#{$spacing-unit} / 2)); - width: calc(100% - (#{$spacing-unit} / 2)); - } -} - -@include media-query($on-palm) { - .footer-col { - float: none; - width: -webkit-calc(100% - (#{$spacing-unit} / 2)); - width: calc(100% - (#{$spacing-unit} / 2)); - } -} - - - -/** - * Page content - */ -.page-content { - padding: $spacing-unit 0; -} - -.page-heading { - font-size: 20px; -} - -.post-list { - margin-left: 0; - list-style: none; - - > li { - margin-bottom: $spacing-unit; - } -} - -.post-meta { - font-size: $small-font-size; - color: $grey-color; -} - -.post-link { - display: block; - font-size: 24px; -} - - - -/** - * Posts - */ -.post-header { - margin-bottom: $spacing-unit; -} - -.post-title { - font-size: 42px; - letter-spacing: -1px; - line-height: 1; - - @include media-query($on-laptop) { - font-size: 36px; - } -} - -.post-content { - margin-bottom: $spacing-unit; - - h2 { - font-size: 32px; - - @include media-query($on-laptop) { - font-size: 28px; - } - } - - h3 { - font-size: 26px; - - @include media-query($on-laptop) { - font-size: 22px; - } - } - - h4 { - font-size: 20px; - - @include media-query($on-laptop) { - font-size: 18px; - } - } -} diff --git a/lib/site_template/_sass/_syntax-highlighting.scss b/lib/site_template/_sass/_syntax-highlighting.scss deleted file mode 100644 index 8fac59776d5..00000000000 --- a/lib/site_template/_sass/_syntax-highlighting.scss +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Syntax highlighting styles - */ -.highlight { - background: #fff; - @extend %vertical-rhythm; - - .highlighter-rouge & { - background: #eef; - } - - .c { color: #998; font-style: italic } // Comment - .err { color: #a61717; background-color: #e3d2d2 } // Error - .k { font-weight: bold } // Keyword - .o { font-weight: bold } // Operator - .cm { color: #998; font-style: italic } // Comment.Multiline - .cp { color: #999; font-weight: bold } // Comment.Preproc - .c1 { color: #998; font-style: italic } // Comment.Single - .cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special - .gd { color: #000; background-color: #fdd } // Generic.Deleted - .gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific - .ge { font-style: italic } // Generic.Emph - .gr { color: #a00 } // Generic.Error - .gh { color: #999 } // Generic.Heading - .gi { color: #000; background-color: #dfd } // Generic.Inserted - .gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific - .go { color: #888 } // Generic.Output - .gp { color: #555 } // Generic.Prompt - .gs { font-weight: bold } // Generic.Strong - .gu { color: #aaa } // Generic.Subheading - .gt { color: #a00 } // Generic.Traceback - .kc { font-weight: bold } // Keyword.Constant - .kd { font-weight: bold } // Keyword.Declaration - .kp { font-weight: bold } // Keyword.Pseudo - .kr { font-weight: bold } // Keyword.Reserved - .kt { color: #458; font-weight: bold } // Keyword.Type - .m { color: #099 } // Literal.Number - .s { color: #d14 } // Literal.String - .na { color: #008080 } // Name.Attribute - .nb { color: #0086B3 } // Name.Builtin - .nc { color: #458; font-weight: bold } // Name.Class - .no { color: #008080 } // Name.Constant - .ni { color: #800080 } // Name.Entity - .ne { color: #900; font-weight: bold } // Name.Exception - .nf { color: #900; font-weight: bold } // Name.Function - .nn { color: #555 } // Name.Namespace - .nt { color: #000080 } // Name.Tag - .nv { color: #008080 } // Name.Variable - .ow { font-weight: bold } // Operator.Word - .w { color: #bbb } // Text.Whitespace - .mf { color: #099 } // Literal.Number.Float - .mh { color: #099 } // Literal.Number.Hex - .mi { color: #099 } // Literal.Number.Integer - .mo { color: #099 } // Literal.Number.Oct - .sb { color: #d14 } // Literal.String.Backtick - .sc { color: #d14 } // Literal.String.Char - .sd { color: #d14 } // Literal.String.Doc - .s2 { color: #d14 } // Literal.String.Double - .se { color: #d14 } // Literal.String.Escape - .sh { color: #d14 } // Literal.String.Heredoc - .si { color: #d14 } // Literal.String.Interpol - .sx { color: #d14 } // Literal.String.Other - .sr { color: #009926 } // Literal.String.Regex - .s1 { color: #d14 } // Literal.String.Single - .ss { color: #990073 } // Literal.String.Symbol - .bp { color: #999 } // Name.Builtin.Pseudo - .vc { color: #008080 } // Name.Variable.Class - .vg { color: #008080 } // Name.Variable.Global - .vi { color: #008080 } // Name.Variable.Instance - .il { color: #099 } // Literal.Number.Integer.Long -} diff --git a/lib/site_template/about.markdown b/lib/site_template/about.markdown new file mode 100644 index 00000000000..8b4e0b28c83 --- /dev/null +++ b/lib/site_template/about.markdown @@ -0,0 +1,18 @@ +--- +layout: page +title: About +permalink: /about/ +--- + +This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](https://jekyllrb.com/) + +You can find the source code for Minima at GitHub: +[jekyll][jekyll-organization] / +[minima](https://github.com/jekyll/minima) + +You can find the source code for Jekyll at GitHub: +[jekyll][jekyll-organization] / +[jekyll](https://github.com/jekyll/jekyll) + + +[jekyll-organization]: https://github.com/jekyll diff --git a/lib/site_template/about.md b/lib/site_template/about.md deleted file mode 100644 index d0e6de5e18a..00000000000 --- a/lib/site_template/about.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -layout: page -title: About -permalink: /about/ ---- - -This is the base Jekyll theme. You can find out more info about customizing your Jekyll theme, as well as basic Jekyll usage documentation at [jekyllrb.com](http://jekyllrb.com/) - -You can find the source code for the Jekyll new theme at: -{% include icon-github.html username="jglovier" %} / -[jekyll-new](https://github.com/jglovier/jekyll-new) - -You can find the source code for Jekyll at -{% include icon-github.html username="jekyll" %} / -[jekyll](https://github.com/jekyll/jekyll) diff --git a/lib/site_template/css/main.scss b/lib/site_template/css/main.scss deleted file mode 100644 index f2e566e2a19..00000000000 --- a/lib/site_template/css/main.scss +++ /dev/null @@ -1,53 +0,0 @@ ---- -# Only the main Sass file needs front matter (the dashes are enough) ---- -@charset "utf-8"; - - - -// Our variables -$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -$base-font-size: 16px; -$base-font-weight: 400; -$small-font-size: $base-font-size * 0.875; -$base-line-height: 1.5; - -$spacing-unit: 30px; - -$text-color: #111; -$background-color: #fdfdfd; -$brand-color: #2a7ae2; - -$grey-color: #828282; -$grey-color-light: lighten($grey-color, 40%); -$grey-color-dark: darken($grey-color, 25%); - -// Width of the content area -$content-width: 800px; - -$on-palm: 600px; -$on-laptop: 800px; - - - -// Use media queries like this: -// @include media-query($on-palm) { -// .wrapper { -// padding-right: $spacing-unit / 2; -// padding-left: $spacing-unit / 2; -// } -// } -@mixin media-query($device) { - @media screen and (max-width: $device) { - @content; - } -} - - - -// Import partials from `sass_dir` (defaults to `_sass`) -@import - "base", - "layout", - "syntax-highlighting" -; diff --git a/lib/site_template/feed.xml b/lib/site_template/feed.xml deleted file mode 100644 index a6628bd842a..00000000000 --- a/lib/site_template/feed.xml +++ /dev/null @@ -1,30 +0,0 @@ ---- -layout: null ---- - - - - {{ site.title | xml_escape }} - {{ site.description | xml_escape }} - {{ site.url }}{{ site.baseurl }}/ - - {{ site.time | date_to_rfc822 }} - {{ site.time | date_to_rfc822 }} - Jekyll v{{ jekyll.version }} - {% for post in site.posts limit:10 %} - - {{ post.title | xml_escape }} - {{ post.content | xml_escape }} - {{ post.date | date_to_rfc822 }} - {{ post.url | prepend: site.baseurl | prepend: site.url }} - {{ post.url | prepend: site.baseurl | prepend: site.url }} - {% for tag in post.tags %} - {{ tag | xml_escape }} - {% endfor %} - {% for cat in post.categories %} - {{ cat | xml_escape }} - {% endfor %} - - {% endfor %} - - diff --git a/lib/site_template/index.html b/lib/site_template/index.html deleted file mode 100644 index 83d9398518b..00000000000 --- a/lib/site_template/index.html +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: default ---- - -
    - -

    Posts

    - -
      - {% for post in site.posts %} -
    • - - -

      - {{ post.title }} -

      -
    • - {% endfor %} -
    - -

    subscribe via RSS

    - -
    diff --git a/lib/site_template/index.markdown b/lib/site_template/index.markdown new file mode 100644 index 00000000000..06715078416 --- /dev/null +++ b/lib/site_template/index.markdown @@ -0,0 +1,6 @@ +--- +# Feel free to add content and custom Front Matter to this file. +# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults + +layout: home +--- diff --git a/lib/theme_template/CODE_OF_CONDUCT.md.erb b/lib/theme_template/CODE_OF_CONDUCT.md.erb new file mode 100644 index 00000000000..2b2c7734f87 --- /dev/null +++ b/lib/theme_template/CODE_OF_CONDUCT.md.erb @@ -0,0 +1,74 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at <%= user_email %>. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/lib/theme_template/Gemfile b/lib/theme_template/Gemfile new file mode 100644 index 00000000000..bb94df82938 --- /dev/null +++ b/lib/theme_template/Gemfile @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +source "https://rubygems.org" +gemspec diff --git a/lib/theme_template/LICENSE.txt.erb b/lib/theme_template/LICENSE.txt.erb new file mode 100644 index 00000000000..38a0eb4e8e7 --- /dev/null +++ b/lib/theme_template/LICENSE.txt.erb @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) <%= Time.now.year %> <%= user_name %> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/lib/theme_template/README.md.erb b/lib/theme_template/README.md.erb new file mode 100644 index 00000000000..9e180340f03 --- /dev/null +++ b/lib/theme_template/README.md.erb @@ -0,0 +1,50 @@ +# <%= theme_name %> + +Welcome to your new Jekyll theme! In this directory, you'll find the files you need to be able to package up your theme into a gem. Put your layouts in `_layouts`, your includes in `_includes`, your sass files in `_sass` and any other assets in `assets`. + +To experiment with this code, add some sample content and run `bundle exec jekyll serve` – this directory is setup just like a Jekyll site! + +TODO: Delete this and the text above, and describe your gem + +## Installation + +Add this line to your Jekyll site's `Gemfile`: + +```ruby +gem <%= theme_name.inspect %> +``` + +And add this line to your Jekyll site's `_config.yml`: + +```yaml +theme: <%= theme_name %> +``` + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install <%= theme_name %> + +## Usage + +TODO: Write usage instructions here. Describe your available layouts, includes, sass and/or assets. + +## Contributing + +Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/<%= theme_name %>. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct. + +## Development + +To set up your environment to develop this theme, run `bundle install`. + +Your theme is setup just like a normal Jekyll site! To test your theme, run `bundle exec jekyll serve` and open your browser at `http://localhost:4000`. This starts a Jekyll server using your theme. Add pages, documents, data, etc. like normal to test your theme's contents. As you make modifications to your theme and to your content, your site will regenerate and you should see the changes in the browser after a refresh, just like normal. + +When your theme is released, only the files in `_layouts`, `_includes`, `_sass` and `assets` tracked with Git will be bundled. +To add a custom directory to your theme-gem, please edit the regexp in `<%= theme_name %>.gemspec` accordingly. + +## License + +The theme is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT). diff --git a/lib/theme_template/_layouts/default.html b/lib/theme_template/_layouts/default.html new file mode 100644 index 00000000000..cddd07099f2 --- /dev/null +++ b/lib/theme_template/_layouts/default.html @@ -0,0 +1 @@ +{{ content }} diff --git a/lib/theme_template/_layouts/page.html b/lib/theme_template/_layouts/page.html new file mode 100644 index 00000000000..5e7112684af --- /dev/null +++ b/lib/theme_template/_layouts/page.html @@ -0,0 +1,5 @@ +--- +layout: default +--- + +{{ content }} diff --git a/lib/theme_template/_layouts/post.html b/lib/theme_template/_layouts/post.html new file mode 100644 index 00000000000..5e7112684af --- /dev/null +++ b/lib/theme_template/_layouts/post.html @@ -0,0 +1,5 @@ +--- +layout: default +--- + +{{ content }} diff --git a/lib/theme_template/example/_config.yml.erb b/lib/theme_template/example/_config.yml.erb new file mode 100644 index 00000000000..82e8d42df7b --- /dev/null +++ b/lib/theme_template/example/_config.yml.erb @@ -0,0 +1 @@ +theme: <%= theme_name %> diff --git a/lib/theme_template/example/_post.md b/lib/theme_template/example/_post.md new file mode 100644 index 00000000000..145b21de42f --- /dev/null +++ b/lib/theme_template/example/_post.md @@ -0,0 +1,12 @@ +--- +layout: post +--- + +Eos eu docendi tractatos sapientem, brute option menandri in vix, quando vivendo accommodare te ius. Nec melius fastidii constituam id, viderer theophrastus ad sit, hinc semper periculis cum id. Noluisse postulant assentior est in, no choro sadipscing repudiandae vix. Vis in euismod delenit dignissim. Ex quod nostrum sit, suas decore animal id ius, nobis solet detracto quo te. + +{% comment %} +Might you have an include in your theme? Why not try it here! +{% include my-themes-great-include.html %} +{% endcomment %} + +No laudem altera adolescens has, volumus lucilius eum no. Eam ei nulla audiam efficiantur. Suas affert per no, ei tale nibh sea. Sea ne magna harum, in denique scriptorem sea, cetero alienum tibique ei eos. Labores persequeris referrentur eos ei. diff --git a/lib/theme_template/example/index.html b/lib/theme_template/example/index.html new file mode 100644 index 00000000000..b688538cd69 --- /dev/null +++ b/lib/theme_template/example/index.html @@ -0,0 +1,14 @@ +--- +layout: page +--- + +Lorem ipsum dolor sit amet, quo id prima corrumpit pertinacia, id ius dolor dolores, an veri pertinax explicari mea. Agam solum et qui, his id ludus graeco adipiscing. Duis theophrastus nam in, at his vidisse atomorum. Tantas gloriatur scripserit ne eos. Est wisi tempor habemus at, ei graeco dissentiet eos. Ne usu aliquip sanctus conceptam, te vis ignota animal, modus latine contentiones ius te. + +{% for post in site.posts %} +

    {{ post.title }}

    +
    {{ post.excerpt }}
    +{% endfor %} + +Te falli veritus sea, at molestiae scribentur deterruisset vix, et mea zril phaedrum vulputate. No cum dicit consulatu. Ut has nostro noluisse expetendis, te pro quaeque disputando, eu sed summo omnes. Eos at tale aperiam, usu cu propriae quaestio constituto, sed aperiam erroribus temporibus an. + +Quo eu liber mediocritatem, vix an delectus eleifend, iuvaret suscipit ei vel. Partem invenire per an, mea postulant dissentias eu, ius tantas audire nominavi eu. Dicunt tritani veritus ex vis, mei in case sententiae. At exerci democritum nam, cu lobortis iracundia mei. Alia eligendi consectetuer eu sed, paulo docendi noluisse sit ex. diff --git a/lib/theme_template/example/style.scss b/lib/theme_template/example/style.scss new file mode 100644 index 00000000000..7388f52b367 --- /dev/null +++ b/lib/theme_template/example/style.scss @@ -0,0 +1,7 @@ +--- +--- + +// Here, you can test out the Sass/SCSS that you include in your theme. +// Simply `@import` the necessary file(s) to get the proper styles on the site. +// E.g.: +// @import "a-file-from-my-theme"; diff --git a/lib/theme_template/gitignore.erb b/lib/theme_template/gitignore.erb new file mode 100644 index 00000000000..736d7400ff4 --- /dev/null +++ b/lib/theme_template/gitignore.erb @@ -0,0 +1,6 @@ +*.gem +.bundle +.jekyll-cache +.sass-cache +_site +Gemfile.lock diff --git a/lib/theme_template/theme.gemspec.erb b/lib/theme_template/theme.gemspec.erb new file mode 100644 index 00000000000..7c13cd30fe7 --- /dev/null +++ b/lib/theme_template/theme.gemspec.erb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = <%= theme_name.inspect %> + spec.version = "0.1.0" + spec.authors = [<%= user_name.inspect %>] + spec.email = [<%= user_email.inspect %>] + + spec.summary = "TODO: Write a short summary, because Rubygems requires one." + spec.homepage = "TODO: Put your gem's website or public repo URL here." + spec.license = "MIT" + + spec.files = `git ls-files -z`.split("\x0").select { |f| f.match(%r!^(<%= theme_directories.join("|") %>|LICENSE|README|_config\.yml)!i) } + + spec.add_runtime_dependency "jekyll", "~> <%= jekyll_version_with_minor %>" +end diff --git a/rake/profile.rake b/rake/profile.rake new file mode 100644 index 00000000000..d8c0f4ef023 --- /dev/null +++ b/rake/profile.rake @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require "jekyll" + +namespace :profile do + desc "Profile allocations from a build session" + task :memory, [:file, :mode] do |_t, args| + args.with_defaults(file: "memprof.txt", mode: "lite") + + build_phases = [:reset, :read, :generate, :render, :cleanup, :write] + safe_mode = false + + if args.mode == "lite" + build_phases -= [:render, :generate] + safe_mode = true + end + + require "memory_profiler" + + report = MemoryProfiler.report do + site = Jekyll::Site.new( + Jekyll.configuration( + "source" => File.expand_path("../docs", __dir__), + "destination" => File.expand_path("../docs/_site", __dir__), + "safe" => safe_mode + ) + ) + + Jekyll.logger.info "Source:", site.source + Jekyll.logger.info "Destination:", site.dest + Jekyll.logger.info "Plugins and Cache:", site.safe ? "disabled" : "enabled" + Jekyll.logger.info "Profiling phases:", build_phases.join(", ").cyan + Jekyll.logger.info "Profiling..." + + build_phases.each { |phase| site.send phase } + + Jekyll.logger.info "", "and done. Generating results.." + Jekyll.logger.info "" + end + + if ENV["CI"] + report.pretty_print(scale_bytes: true, color_output: false, normalize_paths: true) + else + FileUtils.mkdir_p("tmp") + report_file = File.join("tmp", args.file) + + total_allocated_output = report.scale_bytes(report.total_allocated_memsize) + total_retained_output = report.scale_bytes(report.total_retained_memsize) + + Jekyll.logger.info "Total allocated: #{total_allocated_output} (#{report.total_allocated} objects)".cyan + Jekyll.logger.info "Total retained: #{total_retained_output} (#{report.total_retained} objects)".cyan + + report.pretty_print(to_file: report_file, scale_bytes: true, normalize_paths: true) + Jekyll.logger.info "\nDetailed Report saved into:", report_file.cyan + end + end +end diff --git a/rake/rubocop.rake b/rake/rubocop.rake new file mode 100644 index 00000000000..585ce2dcb35 --- /dev/null +++ b/rake/rubocop.rake @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +namespace :rubocop do + desc "Format existing `.rubocop.yml` to improve readability" + task :format_config do + require_relative "./task_utils/rubocop_config_formatter" + + config_file = File.expand_path("../.rubocop.yml", __dir__) + if File.exist?(config_file) + print " Configuration File: " + puts config_file + puts "formating...".rjust(20) + else + puts "#{config_file} not found! Exiting." + exit! + end + + Jekyll::TaskUtils::RuboCopConfigFormatter.new(config_file).format! + puts "done!".rjust(26) + end +end diff --git a/rake/site.rake b/rake/site.rake new file mode 100644 index 00000000000..9e898477eac --- /dev/null +++ b/rake/site.rake @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +############################################################################# +# +# Site tasks - https://jekyllrb.com +# +############################################################################# + +namespace :site do + task :generated_pages => [:history, :latest_version, :conduct, :contributing, :security, :support] + + desc "Generate and view the site locally" + task :preview => :generated_pages do + require "launchy" + require "jekyll" + + browser_launched = false + Jekyll::Hooks.register :site, :post_write do |_site| + next if browser_launched + browser_launched = true + Jekyll.logger.info "Opening in browser..." + Launchy.open("http://localhost:4000") + end + + # Generate the site in server mode. + puts "Running Jekyll..." + options = { + "source" => File.expand_path(docs_folder), + "destination" => File.expand_path("#{docs_folder}/_site"), + "incremental" => true, + "profile" => true, + "watch" => true, + "serving" => true, + } + Jekyll::Commands::Build.process(options) + Jekyll::Commands::Serve.process(options) + end + + desc "Generate the site" + task :generate => :generated_pages do + require "jekyll" + Jekyll::Commands::Build.process({ + "profile" => true, + "source" => File.expand_path(docs_folder), + "destination" => File.expand_path("#{docs_folder}/_site"), + }) + end + task :build => :generate + + desc "Update normalize.css library to the latest version" + task :update_normalize_css do + Dir.chdir("#{docs_folder}/_sass") do + sh 'curl "https://necolas.github.io/normalize.css/latest/normalize.css" -o "_normalize.scss"' + end + end + + desc "Generate generated pages and publish to GitHub Pages" + task :publish => :generated_pages do + puts "GitHub Pages now compiles our docs site on every push to the `master` branch. Cool, huh?" + exit 1 + end + + desc "Create a nicely formatted history page for the jekyll site based on the repo history." + task :history do + siteify_file("History.markdown", { "title" => "History" }) + end + + desc "Copy the Code of Conduct" + task :conduct do + front_matter = { + "redirect_from" => "/conduct/index.html", + "editable" => false, + } + siteify_file(".github/CODE_OF_CONDUCT.markdown", front_matter) + end + + desc "Copy the contributing file" + task :contributing do + siteify_file(".github/CONTRIBUTING.markdown", "title" => "Contributing") + end + + desc "Copy the support file" + task :support do + siteify_file(".github/SUPPORT.markdown", "title" => "Support") + end + + desc "Copy the security policy" + task :security do + siteify_file(".github/SECURITY.markdown", "title" => "Security Policy") + end + + desc "Write the latest Jekyll version" + task :latest_version do + next if version =~ %r!(beta|rc|alpha)!i + require "safe_yaml/load" + config_file = File.join(docs_folder, "_config.yml") + config = SafeYAML.load_file(config_file) + config["version"] = version + File.write(config_file, YAML.dump(config)) + File.open("#{docs_folder}/latest_version.txt", "wb") { |f| f.puts(version) } + end + + namespace :releases do + desc "Create new release post" + task :new, :version do |_t, args| + raise "Specify a version: rake site:releases:new['1.2.3']" unless args.version + today = Time.new.strftime("%Y-%m-%d") + release = args.version.to_s + filename = "#{docs_folder}/_posts/#{today}-jekyll-#{release.split(".").join("-")}-released.markdown" + + File.open(filename, "wb") do |post| + post.puts("---") + post.puts("title: 'Jekyll #{release} Released'") + post.puts("date: #{Time.new.strftime("%Y-%m-%d %H:%M:%S %z")}") + post.puts("author: ") + post.puts("version: #{release}") + post.puts("category: release") + post.puts("---") + post.puts + post.puts + end + + puts "Created #{filename}" + end + end +end diff --git a/rake/task_utils/rubocop_config_formatter.rb b/rake/task_utils/rubocop_config_formatter.rb new file mode 100644 index 00000000000..418b3ac226c --- /dev/null +++ b/rake/task_utils/rubocop_config_formatter.rb @@ -0,0 +1,118 @@ +# frozen_string_literal: true + +require "yaml" + +module Jekyll + module TaskUtils + class RuboCopConfigFormatter + def initialize(config_file) + @registry = Hash.new { |hsh, k| hsh[k] = [] } + @buffer = +"" + @config = sort_hash_by_key(YAML.safe_load_file(config_file)) + @config_file = config_file + end + + def format! + inject_banner + + consume :key => "inherit_from" + consume :key => "require" + consume :key => "AllCops", :comment => "Directive for all cops" do |key, conf| + format_all_cops_config(key, conf) + end + consume :key => "Jekyll/NoPutsAllowed", :comment => "Configure custom cop" + + stream_builtin_cops + File.write(@config_file, @buffer.chomp) + end + + private + + def inject_banner + @buffer << <<~MSG + # ----------------------------------------------------------------------------- + # This file has been formatted via a Rake Task configuring cops from + # RuboCop v#{rubocop_version}. + # + # To add more cops, paste configurations at the end of the file and run + # the rake task via `bundle exec rake rubocop:format_config`. + # ----------------------------------------------------------------------------- + + MSG + end + + def rubocop_version + `bundle exec rubocop --version`.chomp + end + + def consume(key:, comment: nil) + conf = @config.delete(key) + @buffer << "# #{comment}\n" if comment + + entry = block_given? ? yield(key, conf) : normalize_entry(key => conf) + @buffer << entry + @buffer << "\n" + end + + def stream_cops_banner + @buffer << <<~MSG + # Configure built-in cops + # ======================= + + MSG + end + + def group_cops_by_department + @config.each_with_object(@registry) do |(key, conf), registry| + department = key.split("/", 2)[0] + registry[department] << { key => conf } + end + end + + def stream_builtin_cops + stream_cops_banner + group_cops_by_department + + @registry.each do |(dept, cops)| + @buffer << <<~MSG + # #{dept} cops + # #{"-" * 40} + MSG + + while (entry = cops.shift) + @buffer << normalize_entry(entry) + end + + @buffer << "\n" + end + end + + def normalize_entry(entry) + YAML.dump(entry).delete_prefix("---\n") + end + + def format_all_cops_config(key, conf) + all_cops_config = %w(TargetRubyVersion Include Exclude).each_with_object({}) do |k, res| + res[k] = conf.delete(k) + end + normalize_entry(key => all_cops_config) + end + + def sort_hash_by_key(hsh) + sorted = hsh.sort_by { |key, _v| key }.to_h + sorted.each_pair.with_object({}) do |(key, value), result| + new_val = case value + when Array + value.sort + when Hash + sort_hash_by_key(value) + else + value + end + + result[key] = new_val + end + end + end + end +end diff --git a/rubocop/jekyll.rb b/rubocop/jekyll.rb new file mode 100644 index 00000000000..31236b8ab15 --- /dev/null +++ b/rubocop/jekyll.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +Dir[File.join(File.expand_path("jekyll", __dir__), "*.rb")].each do |ruby_file| + require ruby_file +end diff --git a/rubocop/jekyll/assert_equal_literal_actual.rb b/rubocop/jekyll/assert_equal_literal_actual.rb new file mode 100644 index 00000000000..7c7b9f5a71a --- /dev/null +++ b/rubocop/jekyll/assert_equal_literal_actual.rb @@ -0,0 +1,150 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Jekyll + # Checks for `assert_equal(exp, act, msg = nil)` calls containing literal values as + # second argument. The second argument should ideally be a method called on the tested + # instance. + # + # @example + # # bad + # assert_equal @foo.bar, "foobar" + # assert_equal @alpha.beta, { "foo" => "bar", "lorem" => "ipsum" } + # assert_equal @alpha.omega, ["foobar", "lipsum"] + # + # # good + # assert_equal "foobar", @foo.bar + # + # assert_equal( + # { "foo" => "bar", "lorem" => "ipsum" }, + # @alpha.beta + # ) + # + # assert_equal( + # ["foobar", "lipsum"], + # @alpha.omega + # ) + # + class AssertEqualLiteralActual < Base + extend AutoCorrector + + MSG = "Provide the 'expected value' as the first argument to `assert_equal`." + RESTRICT_ON_SEND = %i[assert_equal].freeze + + SIMPLE_LITERALS = %i( + true + false + nil + int + float + str + sym + complex + rational + regopt + ).freeze + + COMPLEX_LITERALS = %i( + array + hash + pair + irange + erange + regexp + ).freeze + + def_node_matcher :literal_actual?, <<-PATTERN + (send nil? :assert_equal $(send ...) $#literal?) + PATTERN + + def_node_matcher :literal_actual_with_msg?, <<-PATTERN + (send nil? :assert_equal $(send ...) $#literal? $#opt_msg?) + PATTERN + + def on_send(node) + return unless literal_actual?(node) || literal_actual_with_msg?(node) + + range = node.loc.expression + add_offense(range) do |corrector| + corrector.replace(range, replacement(node)) + end + end + + private + + def opt_msg?(node) + node&.source + end + + # This is not implement using a NodePattern because it seems + # to not be able to match against an explicit (nil) sexp + def literal?(node) + node && (simple_literal?(node) || complex_literal?(node)) + end + + def simple_literal?(node) + SIMPLE_LITERALS.include?(node.type) + end + + def complex_literal?(node) + COMPLEX_LITERALS.include?(node.type) && + node.each_child_node.all?(&method(:literal?)) + end + + def replacement(node) + _, _, first_param, second_param, optional_param = *node + + replaced_text = \ + if second_param.type == :hash + replace_hash_with_variable(first_param.source, second_param.source) + elsif second_param.type == :array && second_param.source != "[]" + replace_array_with_variable(first_param.source, second_param.source) + else + replace_based_on_line_length(first_param.source, second_param.source) + end + + return "#{replaced_text}, #{optional_param.source}" if optional_param + replaced_text + end + + def replace_based_on_line_length(first_expression, second_expression) + result = "assert_equal #{second_expression}, #{first_expression}" + return result if result.length < 80 + + # fold long lines independent of Rubocop configuration for better readability + <<~TEXT + assert_equal( + #{second_expression}, + #{first_expression} + ) + TEXT + end + + def replace_hash_with_variable(first_expression, second_expression) + expect_expression = if second_expression.start_with?("{") + second_expression + else + "{#{second_expression}}" + end + <<~TEXT + expected = #{expect_expression} + assert_equal expected, #{first_expression} + TEXT + end + + def replace_array_with_variable(first_expression, second_expression) + expect_expression = if second_expression.start_with?("%") + second_expression + else + Array(second_expression) + end + <<~TEXT + expected = #{expect_expression} + assert_equal expected, #{first_expression} + TEXT + end + end + end + end +end diff --git a/rubocop/jekyll/no_p_allowed.rb b/rubocop/jekyll/no_p_allowed.rb new file mode 100644 index 00000000000..b77f8f83c3d --- /dev/null +++ b/rubocop/jekyll/no_p_allowed.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Jekyll + class NoPAllowed < Base + MSG = "Avoid using `p` to print things. Use `Jekyll.logger` instead." + RESTRICT_ON_SEND = %i[p].freeze + + def_node_search :p_called?, <<-PATTERN + (send _ :p _) + PATTERN + + def on_send(node) + if p_called?(node) + add_offense(node.loc.selector) + end + end + end + end + end +end diff --git a/rubocop/jekyll/no_puts_allowed.rb b/rubocop/jekyll/no_puts_allowed.rb new file mode 100644 index 00000000000..81717cc3c70 --- /dev/null +++ b/rubocop/jekyll/no_puts_allowed.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Jekyll + class NoPutsAllowed < Base + MSG = "Avoid using `puts` to print things. Use `Jekyll.logger` instead." + RESTRICT_ON_SEND = %i[puts].freeze + + def_node_search :puts_called?, <<-PATTERN + (send nil? :puts _) + PATTERN + + def on_send(node) + if puts_called?(node) + add_offense(node.loc.selector) + end + end + end + end + end +end diff --git a/script/backport-pr b/script/backport-pr new file mode 100755 index 00000000000..a2b2c33fea1 --- /dev/null +++ b/script/backport-pr @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# This script is pulled from https://github.com/git-lfs/git-lfs/blob/master/script/backport-pr +# Many thanks, git-lfs team! +# +# Backports a PR into a release branch: +# +# # backport PR #1023 into 1.1-stable-backport-1023 +# $ git checkout master +# $ git pull +# $ script/backport-pr 1.1 1023 + +usage() { + echo "usage: $0 " + echo "example: $0 3.4 5623" +} + +if test -z "$1"; then + echo "fatal: no minor release version, e.g. '3.4'" > /dev/stderr + usage + exit 1 +fi + +if test -z "$2"; then + echo "fatal: no pull request number, e.g. '5623'" > /dev/stderr + usage + exit 1 +fi + +relversion="v$1.x" +relbranch="$1-stable" +pr="$2" +prbranch="$relbranch-backport-$pr" +pullsurl="https://api.github.com/repos/jekyll/jekyll/pulls" +prurl="https://api.github.com/repos/jekyll/jekyll/pulls/$pr" +prjson="$(curl -n $pullsurl/$pr 2>/dev/null)" +headref="$(echo $prjson | jq -r -e ".head.ref")" +[ "$?" -ne 0 ] && { + echo "PR #$pr is invalid." + exit 1 +} +prtitle="$(echo $prjson | jq -r ".title" | sed "s/\"/'/g")" + +git checkout -q -f $relbranch +git clean -q -fdx +git pull -q +git checkout -q -f -B $prbranch + +commit=`git log -1 --pretty=%H "--grep=Merge pull request $pr" "--grep=Merge branch '.*$headref'" master` + +echo "Backporting:\n" + +git log -1 $commit + +conflicts="" + +# If we used regular merges, we'd use the `-m 1` flag for the cherry-pick +# command, but since we do squash-merges, we don't want this. +git cherry-pick -x --allow-empty $commit &> /dev/null || { + unmerged=$(git ls-files --unmerged --stage | cut -f 2 -d$'\t' | uniq) + conflicts="\n\nConflicting files:" + for file in $unmerged; do + git add "$file" + conflicts="$conflicts\n- $file" + done + git commit -q --no-edit +} + +commitmsg="Backport $headref from #$pr to $relbranch" +if [ "$conflicts" ]; then + commitmsg="$commitmsg [merge conflicts]" +fi + +git commit -q --allow-empty --amend -m "$commitmsg" +git push -q -f origin $prbranch +git checkout -q -f $relbranch +git branch -q -D $prbranch + +curl -in $pullsurl -d "{ + \"title\": \"Backport #$pr for $relversion: $prtitle\", + \"head\": \"$prbranch\", + \"base\": \"$relbranch\", + \"body\": \"This backports #$pr.$conflicts\" +}" 2>/dev/null diff --git a/script/cibuild b/script/cibuild index afafd7d0990..4cdb6bacd56 100755 --- a/script/cibuild +++ b/script/cibuild @@ -2,10 +2,14 @@ script/branding +set -e + if [[ -z "$TEST_SUITE" ]] then - script/test ci + script/fmt + script/test ci script/cucumber + script/default-site elif [[ -x "script/$TEST_SUITE" ]] then script/$TEST_SUITE diff --git a/script/console b/script/console index 34ad6e8a30d..38ca96a111c 100755 --- a/script/console +++ b/script/console @@ -1,10 +1,10 @@ #!/usr/bin/env ruby require 'pry' -$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w{ .. lib }) +$LOAD_PATH.unshift File.expand_path("../lib", __dir__) require 'jekyll' -TEST_DIR = File.expand_path(File.join(File.dirname(__FILE__), *%w{ .. test })) +TEST_DIR = File.expand_path("../test", __dir__) def fixture_site(overrides = {}) Jekyll::Site.new(site_configuration(overrides)) diff --git a/script/cucumber b/script/cucumber index 13508c84ee2..7466585df45 100755 --- a/script/cucumber +++ b/script/cucumber @@ -1,11 +1,4 @@ #!/usr/bin/env bash -if ruby --version | grep -q "jruby" -then - echo "Move along, we are not testing features on JRuby right now." - exit 0 -else - time ruby -S bundle exec cucumber \ - -f Features::Support::Overview \ - "$@" -fi +time ruby -S bundle exec cucumber \ + --format progress --publish-quiet "$@" diff --git a/script/default-site b/script/default-site new file mode 100755 index 00000000000..7f56c908bd4 --- /dev/null +++ b/script/default-site @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Runs the `jekyll new` command and builds the default site as a sanity check +# Additional flags for `jekyll new` may be passed to this script. + +set -e + +TMP_SOURCE="tmp/default-site" + +echo "$0: setting up tmp directory" +mkdir -p ./tmp +rm -Rf "./$TMP_SOURCE" + +echo "$0: creating new default site" +bundle exec jekyll new "$TMP_SOURCE" "$@" +pushd "$TMP_SOURCE" + +echo "$0: respecifying the jekyll install location" +ruby -e "contents = File.read('Gemfile'); File.write('Gemfile', contents.sub(/gem \"jekyll\".*\\n/, 'gem \"jekyll\", path: \"../../\"'))" +echo "$0: installing default site dependencies" +BUNDLE_GEMFILE=Gemfile bundle install +echo "$0: building the default site" +BUNDLE_GEMFILE=Gemfile bundle exec jekyll build --verbose --profile +popd diff --git a/script/fmt b/script/fmt new file mode 100755 index 00000000000..9a6cd0884cb --- /dev/null +++ b/script/fmt @@ -0,0 +1,8 @@ +#!/bin/bash +echo "RuboCop $(bundle exec rubocop --version)" +bundle exec rubocop -D --disable-pending-cops $@ +success=$? +if ((success != 0)); then + echo -e "\nTry running \`script/fmt -a\` to automatically fix errors" +fi +exit $success diff --git a/script/memprof b/script/memprof new file mode 100755 index 00000000000..df645ea14c3 --- /dev/null +++ b/script/memprof @@ -0,0 +1,5 @@ +#!/bin/bash + +file="memprof.txt" +mode="core" +bundle exec rake profile:memory[$file,$mode] diff --git a/script/profile-docs b/script/profile-docs new file mode 100755 index 00000000000..234782677e1 --- /dev/null +++ b/script/profile-docs @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# +# Build Jekyll's Documentation site in 'debug' mode and outputs the site's profile stats. +# Helps detecting *hard* breaking-changes (`jekyll build` aborts) and optimizations +# in the `build` process. +# +# Usage: bash script/profile-docs + +SOURCE_DIR=$PWD/docs +bundle exec jekyll build -s $SOURCE_DIR -d $SOURCE_DIR/_site --profile --trace --verbose diff --git a/script/proof b/script/proof index c8fff90819b..e8b796b2299 100755 --- a/script/proof +++ b/script/proof @@ -6,16 +6,17 @@ set -e function msg { - printf "\e[0;37m==> $1\e[0m\n" + printf "\e[0;37m==> $1\e[0m\n" } -INGORE_HREFS=$(ruby -e 'puts %w{ +IGNORE_HREFS=$(ruby -e 'puts %w{ Chrononaut twitter.com nearlyfreespeech.net eduardoboucas.com + github.com\/matrix9180 }.map{|h| "/#{h}/"}.join(",")') -SOURCE="site" +SOURCE="docs" DESTINATION="_site" export PROOF=true @@ -27,8 +28,8 @@ bundle install -j8 > /dev/null || bundle install > /dev/null # 2. msg "Building..." -bundle exec jekyll build -s $SOURCE -d $DESTINATION --full-rebuild --trace +bundle exec jekyll build -s $SOURCE -d $DESTINATION --trace # 3. msg "Proofing..." -time bundle exec htmlproof ./$DESTINATION --href-ignore $INGORE_HREFS +time bundle exec htmlproofer ./$DESTINATION --allow-hash-href --url-ignore $IGNORE_HREFS $@ diff --git a/script/rebund b/script/rebund deleted file mode 100755 index d2ff79016cb..00000000000 --- a/script/rebund +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env bash -# -# rebund(1) -# -# Author: Julien Letessier -# Homepage: https://github.com/mezis/rebund -# License: -# -# Copyright (c) 2014 HouseTrip Ltd -# -# MIT License -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - -# Configuration -: ${REBUND_CREDENTIALS:=user:secret} -: ${REBUND_ENDPOINT=http://keyfile-production.herokuapp.com} -: ${REBUND_TARBALL:=bundle.tbz} -: ${REBUND_BUNDLE_DIR:=vendor/bundle} - - - -log() { - echo "rebund: $*" > /dev/stderr -} - -die() { - echo "fatal: $*" > /dev/stderr - exit 1 -} - -success() { - log "$*" - exit 0 -} - -on_error() { - die 'unknown error.' -} - -get_ruby_version() { - bundle exec ruby --version -} - -get_gemfile() { - bundle exec sh -c 'echo $BUNDLE_GEMFILE' -} - -calculate_hash() { - (get_ruby_version ; cat $(get_gemfile)) | openssl sha256 | sed -e 's/.* //' -} - -build_tarball() { - test -e $REBUND_BUNDLE_DIR || die "cannot find bundle directory in ${REBUND_BUNDLE_DIR}" - test -e $REBUND_TARBALL && success 'bundle already uploaded' - tar jcf $REBUND_TARBALL $REBUND_BUNDLE_DIR -} - -upload_tarball() { - curl --fail \ - -F filedata=@${REBUND_TARBALL} \ - --digest --user $REBUND_CREDENTIALS \ - ${REBUND_ENDPOINT}/$(calculate_hash) \ - || success "could not upload bundle" -} - -expand_tarball() { - test -e $REBUND_TARBALL || success "no tarball" - tar jxf $REBUND_TARBALL -} - -download_tarball() { - curl --fail \ - --location \ - -o ${REBUND_TARBALL} \ - --digest --user $REBUND_CREDENTIALS \ - ${REBUND_ENDPOINT}/$(calculate_hash) \ - || success "could not download bundle" -} - -rebund_upload() { - build_tarball - upload_tarball -} - -rebund_download() { - download_tarball - expand_tarball -} - -rebund_usage() { - success "usage: $0 [-v] [upload|download]" -} - -# cath errors -trap on_error ERR - -# inherit the ERR trap in subprocesses -set -E - -while test $# -gt 0 ; do - case $1 in - -v) - set -x - ;; - upload) - rebund_upload - exit 0 - ;; - download) - rebund_download - exit 0 - ;; - *) - rebund_usage - exit 1 - ;; - esac - shift -done - -rebund_usage diff --git a/script/rubies b/script/rubies new file mode 100755 index 00000000000..6b91e90a3a0 --- /dev/null +++ b/script/rubies @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# ----------------------------------------------------------------------------- +# If you send us a ruby then we use that, if you do not then we test with +# whatever we can detect, this way you can run both suites when you test out +# your source, we expect full coverage now, not just MRI. +# ----------------------------------------------------------------------------- + +rubies=() +for r in ruby jruby; do + if which "$r" > /dev/null 2>&1 + then + echo $r + fi +done diff --git a/script/rubyprof b/script/rubyprof index 18c5777b32d..51a89d91f55 100755 --- a/script/rubyprof +++ b/script/rubyprof @@ -1,19 +1,23 @@ -#!/usr/bin/env bash +#!/usr/bin/env ruby -export BENCHMARK=1 +require "ruby-prof" +require File.expand_path("../lib/jekyll", __dir__) -TEST_SCRIPT="Jekyll::Commands::Build.process({'source' => 'site'})" +result = RubyProf.profile do + Jekyll::Commands::Build.process({ + "source" => File.expand_path("../docs", __dir__), + "destination" => File.expand_path("../docs/_site", __dir__), + }) +end -RUBY=$(cat < /dev/null || script/bootstrap +MODE = ARGV.first || "cpu" +PROF_OUTPUT_FILE = File.expand_path("../tmp/stackprof-#{MODE}-#{Time.now.strftime("%Y%m%d%H%M")}.dump", __dir__) -TEST_SCRIPT="Jekyll::Commands::Build.process({'source' => 'site'})" -PROF_OUTPUT_FILE=tmp/stackprof-$(date +%Y%m%d%H%M).dump +puts "Stackprof Mode: #{MODE}" -test -f "$PROF_OUTPUT_FILE" || { - bundle exec ruby -r./lib/jekyll -rstackprof \ - -e "StackProf.run(mode: :cpu, interval: 100, out: '${PROF_OUTPUT_FILE}') { ${TEST_SCRIPT} }" +unless File.exist?(PROF_OUTPUT_FILE) + StackProf.run( + mode: MODE.to_sym, + interval: 100, + raw: true, + out: PROF_OUTPUT_FILE + ) do + puts "GC Stats:", JSON.pretty_generate(GC.stat) + GC.disable + + Jekyll::Commands::Build.process({'source' => 'docs'}) + + puts 'GC Stats:' + GC.start(full_mark: true, immediate_sweep: false) + puts JSON.pretty_generate(GC.stat) + end +end + +options = { + sort: true, + limit: 30, + format: :text, } -bundle exec stackprof $PROF_OUTPUT_FILE $@ +# You can also do other things. Examples: +# https://github.com/tmm1/stackprof/blob/master/bin/stackprof +report = StackProf::Report.new(Marshal.load(IO.binread(PROF_OUTPUT_FILE))) +report.print_text( + options[:sort], + options[:limit], + options[:select_files], + options[:reject_files], + options[:select_names], + options[:reject_names] +) + +puts "Results stored in #{PROF_OUTPUT_FILE}" diff --git a/script/test b/script/test index 5aab2f06cca..23407bf2487 100755 --- a/script/test +++ b/script/test @@ -31,26 +31,21 @@ then shift else - rubies=() - for r in jruby ruby; do - if which "$r" - then - rubies+=( - $r - ) - fi - done + rubies=($(script/rubies)) fi +# Tests only pass when timezone offset is zero. +export TZ=UTC + for ruby in $rubies; do if [[ $# -lt 1 ]] then set -x time $ruby -S bundle exec \ - rake TESTOPTS='--profile' test + rake TESTOPTS=$testopts test else set -x - time $ruby -S bundle exec ruby -Itest \ - "$@" --profile + time $ruby -S bundle exec ruby -I test \ + "$@" $testopts fi done diff --git a/script/travis b/script/travis new file mode 100755 index 00000000000..e7f1a1360e2 --- /dev/null +++ b/script/travis @@ -0,0 +1,40 @@ +#!/bin/bash +# Usage: script/travis [ruby-version [file]] +# Example: script/travis 2.0 test/failing_test.rb +# Example: script/travis 2.3.0 +set -e + +mkdir -p vendor/docker +docker rm -fv docker-travis > /dev/null 2>&1 || true +docker run --volume=$(pwd):/home/travis/builds/jekyll/jekyll \ + --workdir=/home/travis/builds/jekyll/jekyll \ + --volume=$(pwd)/vendor/docker:/home/travis/builds/jekyll/jekyll/vendor/bundle \ + --user=travis --name=docker-travis -dit quay.io/travisci/travis-ruby \ + bash > /dev/null + +status=0 +if [ $# -eq 2 ]; then + docker exec -it docker-travis bash -ilc " \ + rvm use --install --binary --fuzzy $1 + bundle install --path vendor/bundle -j 12 \\ + --without benchmark:site:development + bundle clean + script/test $2 + " || status=$? + +elif [ $# -eq 1 ]; then + docker exec -it docker-travis bash -ilc " \ + rvm use --install --binary --fuzzy $1 + bundle install --path vendor/bundle -j 12 \\ + --without benchmark:site:development + bundle clean + bundle exec rake + " || status=$? + +else + docker exec -it docker-travis \ + bash -il || status=$? +fi + +docker rm -fv docker-travis > /dev/null +exit $status diff --git a/script/vendor-mimes b/script/vendor-mimes index ea77923253e..0242d5395e1 100755 --- a/script/vendor-mimes +++ b/script/vendor-mimes @@ -2,16 +2,41 @@ # Vendors the MIME type config from the mime-db list # usage: script/vendor-mimes +require 'colorator' require 'json' require 'open-uri' -config = File.expand_path "../lib/jekyll/mime.types", File.dirname(__FILE__) +# ---- Helpers ---- -# Create an array of vendored mimetype => [extensions] -mimes = {} -json = open('https://raw.githubusercontent.com/jshttp/mime-db/master/db.json').read +{ + :info => :cyan, + :success => :green, + :error => :red, +}.each do |type, color| + define_method("log_#{type}") do |msg| + puts " #{msg}".send(color) + end +end + +# ---- + +json = begin + log_info "Reading remote data.." + URI.open("https://raw.githubusercontent.com/jshttp/mime-db/master/db.json").read +rescue StandardError => e + log_error "Error reading remote data!" + log_error e.message + log_error "Aborting." + exit 1 +end + +log_info "Parsing remote data.." data = JSON.parse(json) data.reject! { |mime, meta| meta["extensions"].nil? || meta["extensions"].empty? } + +log_info "Generating interim mime data-hashes.." +mimes = {} +charset_data = {} data.each do |mime, meta| # Normalize extensions and mime-types mime = mime.downcase.strip @@ -23,13 +48,30 @@ data.each do |mime, meta| next if extensions.empty? mimes[mime] = [] if mimes[mime].nil? mimes[mime].concat extensions + + # Extract mime-types with "charset" metadata + charset_data[mime] = meta["charset"] if meta.key?("charset") + + # Assign `UTF-8` charset for mime-types under the `text` domain if not already assigned upstream + charset_data[mime] ||= "UTF-8" if mime.start_with?("text/") end +log_info "Formatting primary hash and writing to file.." strlen = mimes.keys.max_by(&:length).length output = "" output << "# Woah there. Do not edit this file directly.\n" output << "# This file is generated automatically by script/vendor-mimes.\n\n" mimes = mimes.sort_by { |k,v| k } -output << mimes.map { |mime,extensions| "#{mime.ljust(strlen)} #{extensions.join(" ")}" }.join("\n") +output << mimes.map { |mime,extensions| "#{mime.ljust(strlen)} #{extensions.sort.join(" ")}" }.join("\n") +config = File.expand_path "../lib/jekyll/mime.types", __dir__ File.write(config, output) +log_info "Done! See: #{config.inspect.white}" + +# --- Generate JSON file from charset_data ---- +puts + +log_info "Dumping mimetype-charset mapping as JSON.." +json_file = File.expand_path "../lib/jekyll/commands/serve/mime_types_charset.json", __dir__ +File.write(json_file, JSON.pretty_generate(charset_data) + "\n") +log_success "and done! See: #{json_file.inspect.white}" diff --git a/site/_config.yml b/site/_config.yml deleted file mode 100644 index d1cd5367b53..00000000000 --- a/site/_config.yml +++ /dev/null @@ -1,21 +0,0 @@ -markdown: kramdown -highlighter: pygments -permalink: /news/:year/:month/:day/:title/ -excerpt_separator: "" - -gauges_id: 503c5af6613f5d0f19000027 -google_analytics_id: UA-50755011-1 - -repository: https://github.com/jekyll/jekyll -help_url: https://github.com/jekyll/jekyll-help - -collections: - docs: - output: true - -name: Jekyll • Simple, blog-aware, static sites -description: Transform your plain text into static websites and blogs -url: http://jekyllrb.com - -gems: - - jekyll-feed diff --git a/site/_data/docs.yml b/site/_data/docs.yml deleted file mode 100644 index dcd9ac2cb35..00000000000 --- a/site/_data/docs.yml +++ /dev/null @@ -1,48 +0,0 @@ -- title: Getting Started - docs: - - home - - quickstart - - installation - - usage - - structure - - configuration - -- title: Your Content - docs: - - frontmatter - - posts - - drafts - - pages - - static-files - - variables - - collections - - datafiles - - assets - - migrations - -- title: Customization - docs: - - templates - - permalinks - - pagination - - plugins - - extras - -- title: Deployment - docs: - - github-pages - - deployment-methods - - continuous-integration - -- title: Miscellaneous - docs: - - troubleshooting - - sites - - resources - - upgrading/0-to-2 - - upgrading/2-to-3 - -- title: Meta - docs: - - contributing - - history diff --git a/site/_docs/collections.md b/site/_docs/collections.md deleted file mode 100644 index ed0a87ef48f..00000000000 --- a/site/_docs/collections.md +++ /dev/null @@ -1,380 +0,0 @@ ---- -layout: docs -title: Collections -permalink: /docs/collections/ ---- - -
    -
    Collections support is unstable and may change
    -

    - This is an experimental feature and the API may change until the feature stabilizes. -

    -
    - -Not everything is a post or a page. Maybe you want to document the various -methods in your open source project, members of a team, or talks at a -conference. Collections allow you to define a new type of document that behave -like Pages or Posts do normally, but also have their own unique properties and -namespace. - -## Using Collections - -### Step 1: Tell Jekyll to read in your collection - -Add the following to your site's `_config.yml` file, replacing `my_collection` -with the name of your collection: - -{% highlight yaml %} -collections: -- my_collection -{% endhighlight %} - -You can optionally specify metadata for your collection in the configuration: - -{% highlight yaml %} -collections: - my_collection: - foo: bar -{% endhighlight %} - -Default attributes can also be set for a collection: - -{% highlight yaml %} -defaults: - - scope: - path: "" - type: my_collection - values: - layout: page -{% endhighlight %} - -### Step 2: Add your content - -Create a corresponding folder (e.g. `/_my_collection`) and add -documents. YAML Front Matter is read in as data if it exists, and everything -after it is stuck in the Document's `content` attribute. If no YAML Front -Matter is provided, Jekyll will not generate the file in your collection. - -
    -
    Be sure to name your directories correctly
    -

    -The folder must be named identically to the collection you defined in -your _config.yml file, with the addition of the preceding _ character. -

    -
    - -### Step 3: Optionally render your collection's documents into independent files - -If you'd like Jekyll to create a public-facing, rendered version of each -document in your collection, set the `output` key to `true` in your collection -metadata in your `_config.yml`: - -{% highlight yaml %} -collections: - my_collection: - output: true -{% endhighlight %} - -This will produce a file for each document in the collection. -For example, if you have `_my_collection/some_subdir/some_doc.md`, -it will be rendered using Liquid and the Markdown converter of your -choice and written out to `/my_collection/some_subdir/some_doc.html`. - -As for posts with [Permalinks](../permalinks/), the document -URL can be customized by setting `permalink` metadata for the collection: - -{% highlight yaml %} -collections: - my_collection: - output: true - permalink: /awesome/:path/ -{% endhighlight %} - -For example, if you have `_my_collection/some_subdir/some_doc.md`, it will be -written out to `/awesome/some_subdir/some_doc/index.html`. - -
    -
    Don't forget to add YAML for processing
    -

    - Files in collections that do not have front matter are treated as - static files and simply copied to their - output location without processing. -

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription
    -

    collection

    -
    -

    Label of the containing collection.

    -
    -

    path

    -
    -

    Path to the document relative to the collection's directory.

    -
    -

    name

    -
    -

    The document's base filename, with every sequence of spaces - and non-alphanumeric characters replaced by a hyphen.

    -
    -

    title

    -
    -

    The document's lowercase title (as defined in its front matter), with every sequence of spaces and non-alphanumeric characters replaced by a hyphen. If the document does not define a title in its front matter, this is equivalent to name.

    -
    -

    output_ext

    -
    -

    Extension of the output file.

    -
    -
    - -## Liquid Attributes - -### Collections - -Each collection is accessible via the `site` Liquid variable. For example, if -you want to access the `albums` collection found in `_albums`, you'd use -`site.albums`. Each collection is itself an array of documents -(e.g. `site.albums` is an array of documents, much like `site.pages` and -`site.posts`). See below for how to access attributes of those documents. - -The collections are also available under `site.collections`, with the metadata -you specified in your `_config.yml` (if present) and the following information: - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription
    -

    label

    -
    -

    - The name of your collection, e.g. my_collection. -

    -
    -

    docs

    -
    -

    - An array of documents. -

    -
    -

    files

    -
    -

    - An array of static files in the collection. -

    -
    -

    relative_directory

    -
    -

    - The path to the collection's source directory, relative to the site - source. -

    -
    -

    directory

    -
    -

    - The full path to the collections's source directory. -

    -
    -

    output

    -
    -

    - Whether the collection's documents will be output as individual - files. -

    -
    -
    - - -### Documents - -In addition to any YAML Front Matter provided in the document's corresponding -file, each document has the following attributes: - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription
    -

    content

    -
    -

    - The (unrendered) content of the document. If no YAML Front Matter is - provided, Jekyll will not generate the file in your collection. If - YAML Front Matter is used, then this is all the contents of the file - after the terminating - `---` of the front matter. -

    -
    -

    output

    -
    -

    - The rendered output of the document, based on the - content. -

    -
    -

    path

    -
    -

    - The full path to the document's source file. -

    -
    -

    relative_path

    -
    -

    - The path to the document's source file relative to the site source. -

    -
    -

    url

    -
    -

    - The URL of the rendered collection. The file is only written to the - destination when the name of the collection to which it belongs is - included in the render key in the site's configuration - file. -

    -
    -

    collection

    -
    -

    - The name of the document's collection. -

    -
    -
    - -## Accessing Collection Attributes - -Attributes from the YAML front matter can be accessed as data anywhere in the -site. Using the above example for configuring a collection as `site.albums`, -one might have front matter in an individual file structured as follows (which -must use a supported markup format, and cannot be saved with a `.yaml` -extension): - -{% highlight yaml %} -title: "Josquin: Missa De beata virgine and Missa Ave maris stella" -artist: "The Tallis Scholars" -director: "Peter Phillips" -works: - - title: "Missa De beata virgine" - composer: "Josquin des Prez" - tracks: - - title: "Kyrie" - duration: "4:25" - - title: "Gloria" - duration: "9:53" - - title: "Credo" - duration: "9:09" - - title: "Sanctus & Benedictus" - duration: "7:47" - - title: "Agnus Dei I, II & III" - duration: "6:49" -{% endhighlight %} - -Every album in the collection could be listed on a single page with a template: - -{% highlight html %} -{% raw %} -{% for album in site.albums %} -

    {{ album.title }}

    -

    Performed by {{ album.artist }}{% if album.director %}, directed by {{ album.director }}{% endif %}

    - {% for work in album.works %} -

    {{ work.title }}

    -

    Composed by {{ work.composer }}

    -
      - {% for track in work.tracks %} -
    • {{ track.title }} ({{ track.duration }})
    • - {% endfor %} -
    - {% endfor %} -{% endfor %} -{% endraw %} -{% endhighlight %} diff --git a/site/_docs/configuration.md b/site/_docs/configuration.md deleted file mode 100644 index 2bb65e822f3..00000000000 --- a/site/_docs/configuration.md +++ /dev/null @@ -1,677 +0,0 @@ ---- -layout: docs -title: Configuration -permalink: /docs/configuration/ ---- - -Jekyll allows you to concoct your sites in any way you can dream up, and it’s -thanks to the powerful and flexible configuration options that this is possible. -These options can either be specified in a `_config.yml` file placed in your -site’s root directory, or can be specified as flags for the `jekyll` executable -in the terminal. - -## Configuration Settings - -### Global Configuration - -The table below lists the available settings for Jekyll, and the various options (specified in the configuration file) and flags (specified on the command-line) that control them. - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Setting - Options and Flags -
    -

    Site Source

    -

    Change the directory where Jekyll will read files

    -
    -

    source: DIR

    -

    -s, --source DIR

    -
    -

    Site Destination

    -

    Change the directory where Jekyll will write files

    -
    -

    destination: DIR

    -

    -d, --destination DIR

    -
    -

    Safe

    -

    Disable custom plugins, and ignore symbolic links.

    -
    -

    safe: BOOL

    -

    --safe

    -
    -

    Exclude

    -

    - Exclude directories and/or files from the - conversion. These exclusions are relative to the site's - source directory and cannot be outside the source directory. -

    -
    -

    exclude: [DIR, FILE, ...]

    -
    -

    Include

    -

    - Force inclusion of directories and/or files in the conversion. - .htaccess is a good example since dotfiles are excluded - by default. -

    -
    -

    include: [DIR, FILE, ...]

    -
    -

    Keep files

    -

    - When clobbering the site destination, keep the selected files. - Useful for files that are not generated by jekyll; e.g. files or - assets that are generated by your build tool. - The paths are relative to the destination. -

    -
    -

    keep_files: [DIR, FILE, ...]

    -
    -

    Time Zone

    -

    - Set the time zone for site generation. This sets the TZ - environment variable, which Ruby uses to handle time and date - creation and manipulation. Any entry from the - IANA Time Zone - Database is valid, e.g. America/New_York. A list of all - available values can be found - here. The default is the local time zone, as set by your operating system. -

    -
    -

    timezone: TIMEZONE

    -
    -

    Encoding

    -

    - Set the encoding of files by name. Only available for Ruby - 1.9 or later). - The default value is utf-8 starting in 2.0.0, - and nil before 2.0.0, which will yield the Ruby - default of ASCII-8BIT. - Available encodings can be shown by the - command ruby -e 'puts Encoding::list.join("\n")'. -

    -
    -

    encoding: ENCODING

    -
    -

    Defaults

    -

    - Set defaults for YAML Front Matter - variables. -

    -
    -

    see below

    -
    -
    - -
    -
    Destination folders are cleaned on site builds
    -

    - The contents of <destination> are automatically - cleaned, by default, when the site is built. Files or folders that are not - created by your site will be removed. Some files could be retained - by specifying them within the <keep_files> configuration directive. -

    -

    - Do not use an important location for <destination>; instead, use it as - a staging area and copy files from there to your web server. -

    -
    - -### Build Command Options - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SettingOptions and Flags
    -

    Regeneration

    -

    Enable auto-regeneration of the site when files are modified.

    -
    -

    -w, --[no-]watch

    -
    -

    Configuration

    -

    Specify config files instead of using _config.yml automatically. Settings in later files override settings in earlier files.

    -
    -

    --config FILE1[,FILE2,...]

    -
    -

    Drafts

    -

    Process and render draft posts.

    -
    -

    --drafts

    -
    -

    Environment

    -

    Use a specific environment value in the build.

    -
    -

    JEKYLL_ENV=production

    -
    -

    Future

    -

    Publish posts with a future date.

    -
    -

    future: BOOL

    -

    --future

    -
    -

    LSI

    -

    Produce an index for related posts.

    -
    -

    lsi: BOOL

    -

    --lsi

    -
    -

    Limit Posts

    -

    Limit the number of posts to parse and publish.

    -
    -

    limit_posts: NUM

    -

    --limit_posts NUM

    -
    -

    Force polling

    -

    Force watch to use polling.

    -
    -

    --force_polling

    -
    -

    Verbose output

    -

    Print verbose output.

    -
    -

    -V, --verbose

    -
    -

    Silence Output

    -

    Silence the normal output from Jekyll - during a build

    -
    -

    -q, --quiet

    -
    -

    Incremental build

    -

    - Enable the experimental incremental build feature. Incremental build only - re-builds posts and pages that have changed, resulting in significant performance - improvements for large sites, but may also break site generation in certain - cases. -

    -
    -

    incremental: BOOL

    -

    -I, --incremental

    -
    -
    - - -### Serve Command Options - -In addition to the options below, the `serve` sub-command can accept any of the options -for the `build` sub-command, which are then applied to the site build which occurs right -before your site is served. - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    SettingOptions and Flags
    -

    Local Server Port

    -

    Listen on the given port.

    -
    -

    port: PORT

    -

    --port PORT

    -
    -

    Local Server Hostname

    -

    Listen at the given hostname.

    -
    -

    host: HOSTNAME

    -

    --host HOSTNAME

    -
    -

    Base URL

    -

    Serve the website from the given base URL

    -
    -

    baseurl: URL

    -

    --baseurl URL

    -
    -

    Detach

    -

    Detach the server from the terminal

    -
    -

    detach: BOOL

    -

    -B, --detach

    -
    -

    Skips the initial site build.

    -

    Skips the initial site build which occurs before the server is started.

    -
    -

    --skip-initial-build

    -
    -
    - -
    -
    Do not use tabs in configuration files
    -

    - This will either lead to parsing errors, or Jekyll will revert to the - default settings. Use spaces instead. -

    -
    - -## Specifying a Jekyll environment at build time - -In the build (or serve) arguments, you can specify a Jekyll environment and value. The build will then apply this value in any conditional statements in your content. - -For example, suppose you set this conditional statement in your code: - -{% highlight liquid %} -{% raw %} -{% if jekyll.environment == "production" %} - {% include disqus.html %} -{% endif %} -{% endraw %} -{% endhighlight %} - -When you build your Jekyll site, the content inside the `if` statement won't be run unless you also specify a `production` environment in the build command, like this: - -{% highlight sh %} -JEKYLL_ENV=production jekyll build -{% endhighlight %} - -Specifying an environment value allows you to make certain content available only within specific environments. - -The default value for `JEKYLL_ENV` is `development`. Therefore if you omit `JEKYLL_ENV` from the build arguments, the default value will be `JEKYLL_ENV=development`. Any content inside `{% raw %}{% if jekyll.environment == "development" %}{% endraw %}` tags will automatically appear in the build. - -Your environment values can be anything you want (not just `development` or `production`). Some elements you might want to hide in development environments include Disqus comment forms or Google Analytics. Conversely, you might want to expose an "Edit me in GitHub" button in a development environment but not include it in production environments. - -By specifying the option in the build command, you avoid having to change values in your configuration files when moving from one environment to another. - -## Front Matter defaults - -Using [YAML Front Matter](../frontmatter/) is one way that you can specify configuration in the pages and posts for your site. Setting things like a default layout, or customizing the title, or specifying a more precise date/time for the post can all be added to your page or post front matter. - -Often times, you will find that you are repeating a lot of configuration options. Setting the same layout in each file, adding the same category - or categories - to a post, etc. You can even add custom variables like author names, which might be the same for the majority of posts on your blog. - -Instead of repeating this configuration each time you create a new post or page, Jekyll provides a way to set these defaults in the site configuration. To do this, you can specify site-wide defaults using the `defaults` key in the `_config.yml` file in your projects root directory. - -The `defaults` key holds an array of scope/values pairs that define what defaults should be set for a particular file path, and optionally, a file type in that path. - -Let's say that you want to add a default layout to all pages and posts in your site. You would add this to your `_config.yml` file: - -{% highlight yaml %} -defaults: - - - scope: - path: "" # an empty string here means all files in the project - values: - layout: "default" -{% endhighlight %} - -Here, we are scoping the `values` to any file that exists in the scopes path. Since the path is set as an empty string, it will apply to **all files** in your project. You probably don't want to set a layout on every file in your project - like css files, for example - so you can also specify a `type` value under the `scope` key. - -{% highlight yaml %} -defaults: - - - scope: - path: "" # an empty string here means all files in the project - type: "posts" # previously `post` in Jekyll 2.2. - values: - layout: "default" -{% endhighlight %} - -Now, this will only set the layout for files where the type is `posts`. -The different types that are available to you are `pages`, `posts`, `drafts` or any collection in your site. While `type` is optional, you must specify a value for `path` when creating a `scope/values` pair. - -As mentioned earlier, you can set multiple scope/values pairs for `defaults`. - -{% highlight yaml %} -defaults: - - - scope: - path: "" - type: "posts" - values: - layout: "my-site" - - - scope: - path: "projects" - type: "pages" # previously `page` in Jekyll 2.2. - values: - layout: "project" # overrides previous default layout - author: "Mr. Hyde" -{% endhighlight %} - -With these defaults, all posts would use the `my-site` layout. Any html files that exist in the `projects/` folder will use the `project` layout, if it exists. Those files will also have the `page.author` [liquid variable](../variables/) set to `Mr. Hyde` as well as have the category for the page set to `project`. - -{% highlight yaml %} -collections: - - my_collection: - output: true - -defaults: - - - scope: - path: "" - type: "my_collection" # a collection in your site, in plural form - values: - layout: "default" -{% endhighlight %} - -In this example the `layout` is set to `default` inside the [collection](../collections/) with the name `my_collection`. - -### Precedence - -Jekyll will apply all of the configuration settings you specify in the `defaults` section of your `_config.yml` file. However, you can choose to override settings from other scope/values pair by specifying a more specific path for the scope. - -You can see that in the last example above. First, we set the default layout to `my-site`. Then, using a more specific path, we set the default layout for files in the `projects/` path to `project`. This can be done with any value that you would set in the page or post front matter. - -Finally, if you set defaults in the site configuration by adding a `defaults` section to your `_config.yml` file, you can override those settings in a post or page file. All you need to do is specify the settings in the post or page front matter. For example: - -{% highlight yaml %} -# In _config.yml -... -defaults: - - - scope: - path: "projects" - type: "pages" - values: - layout: "project" - author: "Mr. Hyde" - category: "project" -... -{% endhighlight %} - -{% highlight yaml %} -# In projects/foo_project.md ---- -author: "John Smith" -layout: "foobar" ---- -The post text goes here... -{% endhighlight %} - -The `projects/foo_project.md` would have the `layout` set to `foobar` instead -of `project` and the `author` set to `John Smith` instead of `Mr. Hyde` when -the site is built. - -## Default Configuration - -Jekyll runs with the following configuration options by default. Alternative -settings for these options can be explicitly specified in the configuration -file or on the command-line. - -
    -
    There are two unsupported kramdown options
    -

    - Please note that both remove_block_html_tags and - remove_span_html_tags are currently unsupported in Jekyll due - to the fact that they are not included within the kramdown HTML converter. -

    -
    - -{% highlight yaml %} -# Where things are -source: . -destination: ./_site -plugins_dir: ./_plugins -layouts_dir: ./_layouts -data_dir: ./_data -includes_dir: ./_includes -collections: null - -# Handling Reading -safe: false -include: [".htaccess"] -exclude: [] -keep_files: [".git", ".svn"] -encoding: "utf-8" -markdown_ext: "markdown,mkdown,mkdn,mkd,md" - -# Filtering Content -show_drafts: null -limit_posts: 0 -future: false -unpublished: false - -# Plugins -whitelist: [] -gems: [] - -# Conversion -markdown: kramdown -highlighter: rouge -lsi: false -excerpt_separator: "\n\n" -incremental: false - -# Serving -detach: false -port: 4000 -host: 127.0.0.1 -baseurl: "" # does not include hostname - -# Outputting -permalink: date -paginate_path: /page:num -timezone: null - -quiet: false -defaults: [] - -# Markdown Processors -rdiscount: - extensions: [] - -redcarpet: - extensions: [] - -kramdown: - auto_ids: true - footnote_nr: 1 - entity_output: as_char - toc_levels: 1..6 - smart_quotes: lsquo,rsquo,ldquo,rdquo - enable_coderay: false - - coderay: - coderay_wrap: div - coderay_line_numbers: inline - coderay_line_number_start: 1 - coderay_tab_width: 4 - coderay_bold_every: 10 - coderay_css: style -{% endhighlight %} - -## Markdown Options - -The various Markdown renderers supported by Jekyll sometimes have extra options -available. - -### Redcarpet - -Redcarpet can be configured by providing an `extensions` sub-setting, whose -value should be an array of strings. Each string should be the name of one of -the `Redcarpet::Markdown` class's extensions; if present in the array, it will -set the corresponding extension to `true`. - -Jekyll handles two special Redcarpet extensions: - -- `no_fenced_code_blocks` --- By default, Jekyll sets the `fenced_code_blocks` -extension (for delimiting code blocks with triple tildes or triple backticks) -to `true`, probably because GitHub's eager adoption of them is starting to make -them inescapable. Redcarpet's normal `fenced_code_blocks` extension is inert -when used with Jekyll; instead, you can use this inverted version of the -extension for disabling fenced code. - -Note that you can also specify a language for highlighting after the first -delimiter: - - ```ruby - # ...ruby code - ``` - -With both fenced code blocks and highlighter enabled, this will statically -highlight the code; without any syntax highlighter, it will add a -`class="LANGUAGE"` attribute to the `` element, which can be used as a -hint by various JavaScript code highlighting libraries. - -- `smart` --- This pseudo-extension turns on SmartyPants, which converts - straight quotes to curly quotes and runs of hyphens to em (`---`) and en (`--`) dashes. - -All other extensions retain their usual names from Redcarpet, and no renderer -options aside from `smart` can be specified in Jekyll. [A list of available -extensions can be found in the Redcarpet README file.][redcarpet_extensions] -Make sure you're looking at the README for the right version of -Redcarpet: Jekyll currently uses v3.2.x. The most commonly used -extensions are: - -- `tables` -- `no_intra_emphasis` -- `autolink` - -[redcarpet_extensions]: https://github.com/vmg/redcarpet/blob/v3.2.2/README.markdown#and-its-like-really-simple-to-use - -### Kramdown - -In addition to the defaults mentioned above, you can also turn on recognition -of Github Flavored Markdown by passing an `input` option with a value of "GFM". - -For example, in your `_config.yml`: - - kramdown: - input: GFM - -### Custom Markdown Processors - -If you're interested in creating a custom markdown processor, you're in luck! Create a new class in the `Jekyll::Converters::Markdown` namespace: - -{% highlight ruby %} -class Jekyll::Converters::Markdown::MyCustomProcessor - def initialize(config) - require 'funky_markdown' - @config = config - rescue LoadError - STDERR.puts 'You are missing a library required for Markdown. Please run:' - STDERR.puts ' $ [sudo] gem install funky_markdown' - raise FatalException.new("Missing dependency: funky_markdown") - end - - def convert(content) - ::FunkyMarkdown.new(content).convert - end -end -{% endhighlight %} - -Once you've created your class and have it properly setup either as a plugin in -the `_plugins` folder or as a gem, specify it in your `_config.yml`: - -{% highlight yaml %} -markdown: MyCustomProcessor -{% endhighlight %} diff --git a/site/_docs/contributing.md b/site/_docs/contributing.md deleted file mode 100644 index 1feec0dc241..00000000000 --- a/site/_docs/contributing.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -layout: docs -title: Contributing -permalink: /docs/contributing/ ---- - -So you've got an awesome idea to throw into Jekyll. Great! Please keep the -following in mind: - -* **Use https://talk.jekyllrb.com for non-technical or indirect Jekyll questions that are not bugs.** -* **Contributions will not be accepted without tests or necessary documentation updates.** -* If you're creating a small fix or patch to an existing feature, just a simple - test will do. Please stay in the confines of the current test suite and use - [Shoulda](https://github.com/thoughtbot/shoulda/tree/master) and - [RSpec-Mocks](https://github.com/rspec/rspec-mocks). -* If it's a brand new feature, make sure to create a new - [Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps - where appropriate. Also, whipping up some documentation in your fork's `site` - would be appreciated, and once merged it will be transferred over to the main - `site`, jekyllrb.com. -* If your contribution changes any Jekyll behavior, make sure to update the - documentation. It lives in `site/_docs`. If the docs are missing information, - please feel free to add it in. Great docs make a great project! -* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby) - when modifying Ruby code. -* Please do your best to submit **small pull requests**. The easier the proposed - change is to review, the more likely it will be merged. -* When submitting a pull request, please make judicious use of the pull request - body. A description of what changes were made, the motivations behind the - changes and [any tasks completed or left to complete](http://git.io/gfm-tasks) - will also speed up review time. - -
    -
    Contributions will not be accepted without tests
    -

    - If you’re creating a small fix or patch to an existing feature, just - a simple test will do. -

    -
    - - -Test Dependencies ------------------ - -To run the test suite and build the gem you'll need to install Jekyll's -dependencies. Simply run this command to get all setup: - -
    $ script/bootstrap
    - -Before you start, run the tests and make sure that they pass (to confirm your -environment is configured properly): - -
    $ script/cibuild
    - -If you are only updating a file in `test/`, you can use the command: - -
    $ script/test test/blah_test.rb
    - -If you are only updating a `.feature` file, you can use the command: - -
    $ script/cucumber features/blah.feature
    - -Both `script/test` and `script/cucumber` can be run without arguments to -run its entire respective suite. - -Workflow --------- - -Here's the most direct way to get your work merged into the project: - -* Fork the project. -* Clone down your fork ( `git clone git@github.com:[username]/jekyll.git` ). -* Create a topic branch to contain your change ( `git checkout -b my_awesome_feature` ). -* Hack away, add tests. Not necessarily in that order. -* Make sure everything still passes by running `script/cibuild`. -* If necessary, rebase your commits into logical chunks, without errors. -* Push the branch up ( `git push origin my_awesome_feature` ). -* Create a pull request against jekyll/jekyll and describe what your change - does and the why you think it should be merged. - -Updating Documentation ----------------------- - -We want the Jekyll documentation to be the best it can be. We've -open-sourced our docs and we welcome any pull requests if you find it -lacking. - -You can find the documentation for jekyllrb.com in the -[site]({{ site.repository }}/tree/master/site) directory of -Jekyll's repo on GitHub.com. - -All documentation pull requests should be directed at `master`. Pull -requests directed at another branch will not be accepted. - -The [Jekyll wiki]({{ site.repository }}/wiki) on GitHub -can be freely updated without a pull request as all GitHub users have access. - -If you want to add your plugin to the [list of plugins](/docs/plugins/#available-plugins), -please submit a pull request modifying the [plugins page source -file]({{ site.repository }}/blob/master/site/_docs/plugins.md) by adding a -link to your plugin under the proper subheading depending upon its type. - -Gotchas -------- - -* Please do not bump the gem version in your pull requests. -* Try to keep your patch(es) based from the latest commit on jekyll/jekyll. - The easier it is to apply your work, the less work the maintainers have to do, - which is always a good thing. -* Please don't tag your GitHub issue with [fix], [feature], etc. The maintainers - actively read the issues and will label it once they come across it. - -Finally... ----------- - -
    -
    Let us know what could be better!
    -

    - Both using and hacking on Jekyll should be fun, simple, and easy, so if for - some reason you find it’s a pain, please create an issue on - GitHub describing your experience so we can make it better. -

    -
    diff --git a/site/_docs/deployment-methods.md b/site/_docs/deployment-methods.md deleted file mode 100644 index c1040b2b780..00000000000 --- a/site/_docs/deployment-methods.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -layout: docs -title: Deployment methods -permalink: /docs/deployment-methods/ ---- - -Sites built using Jekyll can be deployed in a large number of ways due to the static nature of the generated output. A few of the most common deployment techniques are described below. - -## Web hosting providers (FTP) - -Just about any traditional web hosting provider will let you upload files to their servers over FTP. To upload a Jekyll site to a web host using FTP, simply run the `jekyll` command and copy the generated `_site` folder to the root folder of your hosting account. This is most likely to be the `httpdocs` or `public_html` folder on most hosting providers. - -### FTP using Glynn - -There is a project called [Glynn](https://github.com/dmathieu/glynn), which lets you easily generate your Jekyll powered website’s static files and -send them to your host through FTP. - -## Self-managed web server - -If you have direct access yourself to the deployment web server yourself, the process is essentially the same, except you might have other methods available to you (such as `scp`, or even direct filesystem access) for transferring the files. Just remember to make sure the contents of the generated `_site` folder get placed in the appropriate web root directory for your web server. - -## Automated methods - -There are also a number of ways to easily automate the deployment of a Jekyll site. If you’ve got another method that isn’t listed below, we’d love it if you [contributed](../contributing/) so that everyone else can benefit too. - -### Git post-update hook - -If you store your Jekyll site in [Git](http://git-scm.com/) (you are using version control, right?), it’s pretty easy to automate the -deployment process by setting up a post-update hook in your Git -repository, [like -this](http://web.archive.org/web/20091223025644/http://www.taknado.com/en/2009/03/26/deploying-a-jekyll-generated-site/). - -### Git post-receive hook - -To have a remote server handle the deploy for you every time you push changes using Git, you can create a user account which has all the public keys that are authorized to deploy in its `authorized_keys` file. With that in place, setting up the post-receive hook is done as follows: - -{% highlight bash %} -laptop$ ssh deployer@example.com -server$ mkdir myrepo.git -server$ cd myrepo.git -server$ git --bare init -server$ cp hooks/post-receive.sample hooks/post-receive -server$ mkdir /var/www/myrepo -{% endhighlight %} - -Next, add the following lines to hooks/post-receive and be sure Jekyll is -installed on the server: - -{% highlight bash %} -GIT_REPO=$HOME/myrepo.git -TMP_GIT_CLONE=$HOME/tmp/myrepo -PUBLIC_WWW=/var/www/myrepo - -git clone $GIT_REPO $TMP_GIT_CLONE -jekyll build -s $TMP_GIT_CLONE -d $PUBLIC_WWW -rm -Rf $TMP_GIT_CLONE -exit -{% endhighlight %} - -Finally, run the following command on any users laptop that needs to be able to -deploy using this hook: - -{% highlight bash %} -laptops$ git remote add deploy deployer@example.com:~/myrepo.git -{% endhighlight %} - -Deploying is now as easy as telling nginx or Apache to look at -`/var/www/myrepo` and running the following: - -{% highlight bash %} -laptops$ git push deploy master -{% endhighlight %} - -### Jekyll-hook - -You can also use jekyll-hook, a server that listens for webhook posts from -GitHub, generates a website with Jekyll, and moves it somewhere to be -published. Use this to run your own GitHub Pages-style web server. - -This method is useful if you need to serve your websites behind a firewall, -need extra server-level features like HTTP basic authentication or want to -host your site directly on a CDN or file host like S3. - -Setup steps are fully documented -[in the `jekyll-hook` repo](https://github.com/developmentseed/jekyll-hook). - -### Static Publisher - -[Static Publisher](https://github.com/static-publisher/static-publisher) is another automated deployment option with a server listening for webhook posts, though it's not tied to GitHub specifically. It has a one-click deploy to Heroku, it can watch multiple projects from one server, it has an easy to user admin interface and can publish to either S3 or to a git repository (e.g. gh-pages). - -### Rake - -Another way to deploy your Jekyll site is to use [Rake](https://github.com/jimweirich/rake), [HighLine](https://github.com/JEG2/highline), and -[Net::SSH](https://github.com/net-ssh/net-ssh). A more complex example of deploying Jekyll with Rake that deals with multiple branches can be found in [Git Ready](https://github.com/gitready/gitready/blob/cdfbc4ec5321ff8d18c3ce936e9c749dbbc4f190/Rakefile). - - -### scp - -Once you’ve generated the `_site` directory, you can easily scp it using a `tasks/deploy` shell script similar to [this deploy script here](https://github.com/henrik/henrik.nyh.se/blob/master/script/deploy). You’d obviously need to change the values to reflect your site’s details. There is even [a matching TextMate command](http://gist.github.com/214959) that will help you run this script from within Textmate. - -### rsync - -Once you’ve generated the `_site` directory, you can easily rsync it using a `tasks/deploy` shell script similar to [this deploy script here](https://github.com/vitalyrepin/vrepinblog/blob/master/transfer.sh). You’d obviously need to change the values to reflect your site’s details. - -#### Step 1: Install rrsync to your home folder (server-side) - -We will use certificate-based authorization to simplify the publishing process. It makes sense to restrict rsync access only to the directory which it is supposed to sync. - -That's why rrsync wrapper shall be installed. If it is not already installed by your hoster you can do it yourself: - -- [download rrsync](http://ftp.samba.org/pub/unpacked/rsync/support/rrsync) -- Put it to the bin subdirectory of your home folder (```~/bin```) -- Make it executable (```chmod +x```) - -#### Step 2: Setup certificate-based ssh access (server side) - -[This process is described in a lot of places in the net](https://wiki.gentoo.org/wiki/SSH#Passwordless_Authentication). We will not cover it here. What is different from usual approach is to put the restriction to certificate-based authorization in ```~/.ssh/authorized_keys```). We will launch ```rrsync``` utility and supply it with the folder it shall have read-write access to: - -``` -command="$HOME/bin/rrsync ",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa -``` - -`````` is the path to your site. E.g., ```~/public_html/you.org/blog-html/```. - -#### Step 3: Rsync! (client-side) - -Add the script ```deploy``` to the web site source folder: - -{% highlight bash %} -#!/bin/sh - -rsync -avr --rsh='ssh -p2222' --delete-after --delete-excluded @: -{% endhighlight %} - -Command line parameters are: - -- ```--rsh='ssh -p2222'``` It is needed if your hoster provides ssh access using ssh port different from default one (e.g., this is what hostgator is doing) -- `````` is the name of the local folder with generated web content. By default it is ```_site/``` for Jekyll -- `````` — ssh user name for your hosting account -- `````` — your hosting server - -Example command line is: - -{% highlight bash %} -rsync -avr --rsh='ssh -p2222' --delete-after --delete-excluded _site/ hostuser@vrepin.org: -{% endhighlight %} - -Don't forget column ':' after server name! - -#### Optional step 4: exclude transfer.sh from being copied to the output folder by Jekyll - -This step is recommended if you use this how-to to deploy Jekyll-based web site. If you put ```deploy``` script to the root folder of your project, Jekyll copies it to the output folder. -This behavior can be changed in ```_config.yml```. Just add the following line there: - -{% highlight yaml %} -# Do not copy these file to the output directory -exclude: ["deploy"] -{% endhighlight %} - -#### We are done! - -Now it's possible to publish your web site by launching ```deploy``` script. If your ssh certificate is [passphrase-protected](https://martin.kleppmann.com/2013/05/24/improving-security-of-ssh-private-keys.html), you are asked to enter the password. - -## Rack-Jekyll - -[Rack-Jekyll](https://github.com/adaoraul/rack-jekyll/) is an easy way to deploy your site on any Rack server such as Amazon EC2, Slicehost, Heroku, and so forth. It also can run with [shotgun](https://github.com/rtomayko/shotgun/), [rackup](https://github.com/rack/rack), [mongrel](https://github.com/mongrel/mongrel), [unicorn](https://github.com/defunkt/unicorn/), and [others](https://github.com/adaoraul/rack-jekyll#readme). - -Read [this post](http://blog.crowdint.com/2010/08/02/instant-blog-using-jekyll-and-heroku.html) on how to deploy to Heroku using Rack-Jekyll. - -## Jekyll-Admin for Rails - -If you want to maintain Jekyll inside your existing Rails app, [Jekyll-Admin](https://github.com/zkarpinski/Jekyll-Admin) contains drop in code to make this possible. See Jekyll-Admin’s [README](https://github.com/zkarpinski/Jekyll-Admin/blob/master/README) for more details. - -## Amazon S3 - -If you want to host your site in Amazon S3, you can do so by -using the [s3_website](https://github.com/laurilehmijoki/s3_website) -application. It will push your site to Amazon S3 where it can be served like -any web server, -dynamically scaling to almost unlimited traffic. This approach has the -benefit of being about the cheapest hosting option available for -low-volume blogs as you only pay for what you use. - -## OpenShift - -If you'd like to deploy your site to an OpenShift gear, there's [a cartridge -for that](https://github.com/openshift-cartridges/openshift-jekyll-cartridge). - -
    -
    ProTip™: Use GitHub Pages for zero-hassle Jekyll hosting
    -

    GitHub Pages are powered by Jekyll behind the scenes, so if you’re looking for a zero-hassle, zero-cost solution, GitHub Pages are a great way to host your Jekyll-powered website for free.

    -
    diff --git a/site/_docs/drafts.md b/site/_docs/drafts.md deleted file mode 100644 index e50af47435a..00000000000 --- a/site/_docs/drafts.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -layout: docs -title: Working with drafts -permalink: /docs/drafts/ ---- - -Drafts are posts without a date. They're posts you're still working on and -don't want to publish yet. To get up and running with drafts, create a -`_drafts` folder in your site's root (as described in the [site structure](/docs/structure/) section) and create your -first draft: - -{% highlight text %} -|-- _drafts/ -| |-- a-draft-post.md -{% endhighlight %} - -To preview your site with drafts, simply run `jekyll serve` or `jekyll build` -with the `--drafts` switch. Each will be assigned the value modification time -of the draft file for its date, and thus you will see currently edited drafts -as the latest posts. diff --git a/site/_docs/extras.md b/site/_docs/extras.md deleted file mode 100644 index b8b8bb72649..00000000000 --- a/site/_docs/extras.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -layout: docs -title: Extras -permalink: /docs/extras/ ---- - -There are a number of (optional) extra features that Jekyll supports that you -may want to install, depending on how you plan to use Jekyll. - -## Math Support - -Kramdown comes with optional support for LaTeX to PNG rendering via [MathJax](http://www.mathjax.org/) within math blocks. See the Kramdown documentation on [math blocks](http://kramdown.gettalong.org/syntax.html#math-blocks) and [math support](http://kramdown.gettalong.org/converter/html.html#math-support) for more details. MathJax requires you to include JavaScript or CSS to render the LaTeX, e.g. - -{% highlight html %} - -{% endhighlight %} - -For more information about getting started, check out [this excellent blog post](http://gastonsanchez.com/blog/opinion/2014/02/16/Mathjax-with-jekyll.html). - -## Alternative Markdown Processors - -See the Markdown section on the [configuration page](/docs/configuration/#markdown-options) for instructions on how to use and configure alternative Markdown processors, as well as how to create [custom processors](/docs/configuration/#custom-markdown-processors). diff --git a/site/_docs/github-pages.md b/site/_docs/github-pages.md deleted file mode 100644 index c9a4644ca5a..00000000000 --- a/site/_docs/github-pages.md +++ /dev/null @@ -1,134 +0,0 @@ ---- -layout: docs -title: GitHub Pages -permalink: /docs/github-pages/ ---- - -[GitHub Pages](http://pages.github.com) are public web pages for users, -organizations, and repositories, that are freely hosted on GitHub's -`github.io` domain or on a custom domain name of your choice. GitHub Pages are -powered by Jekyll behind the scenes, so in addition to supporting regular HTML -content, they’re also a great way to host your Jekyll-powered website for free. - -## Deploying Jekyll to GitHub Pages - -GitHub Pages work by looking at certain branches of repositories on GitHub. -There are two basic types available: user/organization pages and project pages. -The way to deploy these two types of sites are nearly identical, except for a -few minor details. - -
    -
    Use the github-pages gem
    -

    - Our friends at GitHub have provided the - github-pages - gem which is used to manage Jekyll and its dependencies on - GitHub Pages. Using it in your projects means that when you deploy - your site to GitHub Pages, you will not be caught by unexpected - differences between various versions of the gems. To use the - currently-deployed version of the gem in your project, add the - following to your Gemfile: - -{% highlight ruby %} -source 'https://rubygems.org' - -require 'json' -require 'open-uri' -versions = JSON.parse(open('https://pages.github.com/versions.json').read) - -gem 'github-pages', versions['github-pages'] -{% endhighlight %} - - This will ensure that when you run bundle install, you - have the correct version of the github-pages gem. - - If that fails, simplify it: - -{% highlight ruby %} -source 'https://rubygems.org' - -gem 'github-pages' -{% endhighlight %} - - And be sure to run bundle update often. -

    -
    - -### User and Organization Pages - -User and organization pages live in a special GitHub repository dedicated to -only the GitHub Pages files. This repository must be named after the account -name. For example, [@mojombo’s user page -repository](https://github.com/mojombo/mojombo.github.io) has the name -`mojombo.github.io`. - -Content from the `master` branch of your repository will be used to build and -publish the GitHub Pages site, so make sure your Jekyll site is stored there. - -
    -
    Custom domains do not affect repository names
    -

    - GitHub Pages are initially configured to live under the - username.github.io subdomain, which is why repositories must - be named this way even if a custom domain is being used. -

    -
    - -### Project Pages - -Unlike user and organization Pages, Project Pages are kept in the same -repository as the project they are for, except that the website content is -stored in a specially named `gh-pages` branch. The content of this branch will -be rendered using Jekyll, and the output will become available under a subpath -of your user pages subdomain, such as `username.github.io/project` (unless a -custom domain is specified—see below). - -The Jekyll project repository itself is a perfect example of this branch -structure—the [master branch]({{ site.repository }}) contains the -actual software project for Jekyll, however the Jekyll website (that you’re -looking at right now) is contained in the [gh-pages -branch]({{ site.repository }}/tree/gh-pages) of the same repository. - -
    -
    Source Files Must be in the Root Directory
    -

    -Github Pages overrides the “Site Source” configuration value, so if you locate your files anywhere other than the root directory, your site may not build correctly. -

    -
    - - -### Project Page URL Structure - -Sometimes it's nice to preview your Jekyll site before you push your `gh-pages` -branch to GitHub. However, the subdirectory-like URL structure GitHub uses for -Project Pages complicates the proper resolution of URLs. Here is an approach to -utilizing the GitHub Project Page URL structure (`username.github.io/project-name/`) -whilst maintaining the ability to preview your Jekyll site locally. - -1. In `_config.yml`, set the `baseurl` option to `/project-name` -- note the - leading slash and the **absence** of a trailing slash. -2. When referencing JS or CSS files, do it like this: - `{% raw %}{{ site.baseurl }}/path/to/css.css{% endraw %}` -- note the slash - immediately following the variable (just before "path"). -3. When doing permalinks or internal links, do it like this: - `{% raw %}{{ site.baseurl }}{{ post.url }}{% endraw %}` -- note that there - is **no** slash between the two variables. -4. Finally, if you'd like to preview your site before committing/deploying - using `jekyll serve`, be sure to pass an **empty string** to the `--baseurl` - option, so that you can view everything at `localhost:4000` normally - (without `/project-name` at the beginning): `jekyll serve --baseurl ''` - -This way you can preview your site locally from the site root on localhost, -but when GitHub generates your pages from the gh-pages branch all the URLs -will start with `/project-name` and resolve properly. - -
    -
    GitHub Pages Documentation, Help, and Support
    -

    - For more information about what you can do with GitHub Pages, as well as for - troubleshooting guides, you should check out GitHub’s Pages Help - section. If all else fails, you should contact GitHub Support. -

    -
    diff --git a/site/_docs/history.md b/site/_docs/history.md deleted file mode 100644 index 6a6404015a4..00000000000 --- a/site/_docs/history.md +++ /dev/null @@ -1,2104 +0,0 @@ ---- -layout: docs -title: History -permalink: "/docs/history/" ---- - -## 3.0.1 / 2015-11-17 -{: #v3-0-1} - -### Bug Fixes -{: #bug-fixes-v3-0-1} - -- Document: only superdirectories of the collection are categories ([#4110]({{ site.repository }}/issues/4110)) -- `Convertible#render_liquid` should use `render!` to cause failure on bad Liquid ([#4077]({{ site.repository }}/issues/4077)) -- Don't generate `.jekyll-metadata` in non-incremental build ([#4079]({{ site.repository }}/issues/4079)) -- Set `highlighter` config val to `kramdown.syntax_highlighter` ([#4090]({{ site.repository }}/issues/4090)) -- Align hooks implementation with documentation ([#4104]({{ site.repository }}/issues/4104)) -- Fix the deprecation warning in the doctor command ([#4114]({{ site.repository }}/issues/4114)) -- Fix case in `:title` and add `:slug` which is downcased ([#4100]({{ site.repository }}/issues/4100)) - -### Development Fixes -{: #development-fixes-v3-0-1} - -- Fix test warnings when doing rake {test,spec} or script/test ([#4078]({{ site.repository }}/issues/4078)) - -### Site Enhancements -{: #site-enhancements-v3-0-1} - -- Update normalize.css to v3.0.3. ([#4085]({{ site.repository }}/issues/4085)) -- Update Font Awesome to v4.4.0. ([#4086]({{ site.repository }}/issues/4086)) -- Adds a note about installing the jekyll-gist gem to make gist tag work ([#4101]({{ site.repository }}/issues/4101)) -- Align hooks documentation with implementation ([#4104]({{ site.repository }}/issues/4104)) -- Add Jekyll Flickr Plugin to the list of third party plugins ([#4111]({{ site.repository }}/issues/4111)) -- Remove link to now-deleted blog post ([#4125]({{ site.repository }}/issues/4125)) -- Update the liquid syntax in the pagination docs ([#4130]({{ site.repository }}/issues/4130)) -- Add jekyll-language-plugin to plugins.md ([#4134]({{ site.repository }}/issues/4134)) -- Updated to reflect feedback in [#4129]({{ site.repository }}/issues/4129) ([#4137]({{ site.repository }}/issues/4137)) -- Clarify assets.md based on feedback of [#4129]({{ site.repository }}/issues/4129) ([#4142]({{ site.repository }}/issues/4142)) -- Re-correct the liquid syntax in the pagination docs ([#4140]({{ site.repository }}/issues/4140)) - - -## 3.0.0 / 2015-10-26 -{: #v3-0-0} - -### Major Enhancements -{: #major-enhancements-v3-0-0} - -- Liquid profiler (i.e. know how fast or slow your templates render) ([#3762]({{ site.repository }}/issues/3762)) -- Incremental regeneration ([#3116]({{ site.repository }}/issues/3116)) -- Add Hooks: a new kind of plugin ([#3553]({{ site.repository }}/issues/3553)) -- Upgrade to Liquid 3.0.0 ([#3002]({{ site.repository }}/issues/3002)) -- `site.posts` is now a Collection instead of an Array ([#4055]({{ site.repository }}/issues/4055)) -- Add basic support for JRuby (commit: 0f4477) -- Drop support for Ruby 1.9.3. ([#3235]({{ site.repository }}/issues/3235)) -- Support Ruby v2.2 ([#3234]({{ site.repository }}/issues/3234)) -- Support RDiscount 2 ([#2767]({{ site.repository }}/issues/2767)) -- Remove most runtime deps ([#3323]({{ site.repository }}/issues/3323)) -- Move to Rouge as default highlighter ([#3323]({{ site.repository }}/issues/3323)) -- Mimic GitHub Pages `.html` extension stripping behavior in WEBrick ([#3452]({{ site.repository }}/issues/3452)) -- Always include file extension on output files ([#3490]({{ site.repository }}/issues/3490)) -- Improved permalinks for pages and collections ([#3538]({{ site.repository }}/issues/3538)) -- Sunset (i.e. remove) Maruku ([#3655]({{ site.repository }}/issues/3655)) -- Remove support for relative permalinks ([#3679]({{ site.repository }}/issues/3679)) -- Iterate over `site.collections` as an array instead of a hash. ([#3670]({{ site.repository }}/issues/3670)) -- Adapt StaticFile for collections, config defaults ([#3823]({{ site.repository }}/issues/3823)) -- Add a Code of Conduct for the Jekyll project ([#3925]({{ site.repository }}/issues/3925)) -- Added permalink time variables ([#3990]({{ site.repository }}/issues/3990)) -- Add `--incremental` flag to enable incremental regen (disabled by default) ([#4059]({{ site.repository }}/issues/4059)) - -### Minor Enhancements -{: #minor-enhancements-v3-0-0} - -- Deprecate access to Document#data properties and Collection#docs methods ([#4058]({{ site.repository }}/issues/4058)) -- Sort static files just once, and call `site_payload` once for all collections ([#3204]({{ site.repository }}/issues/3204)) -- Separate `jekyll docs` and optimize external gem handling ([#3241]({{ site.repository }}/issues/3241)) -- Improve `Site#getConverterImpl` and call it `Site#find_converter_instance` ([#3240]({{ site.repository }}/issues/3240)) -- Use relative path for `path` Liquid variable in Documents for consistency ([#2908]({{ site.repository }}/issues/2908)) -- Generalize `Utils#slugify` for any scripts ([#3047]({{ site.repository }}/issues/3047)) -- Added basic microdata to post template in site template ([#3189]({{ site.repository }}/issues/3189)) -- Store log messages in an array of messages. ([#3244]({{ site.repository }}/issues/3244)) -- Allow collection documents to override `output` property in front matter ([#3172]({{ site.repository }}/issues/3172)) -- Keep file modification times between builds for static files ([#3220]({{ site.repository }}/issues/3220)) -- Only downcase mixed-case categories for the URL ([#2571]({{ site.repository }}/issues/2571)) -- Added per post `excerpt_separator` functionality ([#3274]({{ site.repository }}/issues/3274)) -- Allow collections YAML to end with three dots ([#3134]({{ site.repository }}/issues/3134)) -- Add mode parameter to `slugify` Liquid filter ([#2918]({{ site.repository }}/issues/2918)) -- Perf: `Markdown#matches` should avoid regexp ([#3321]({{ site.repository }}/issues/3321)) -- Perf: Use frozen regular expressions for `Utils#slugify` ([#3321]({{ site.repository }}/issues/3321)) -- Split off Textile support into jekyll-textile-converter ([#3319]({{ site.repository }}/issues/3319)) -- Improve the navigation menu alignment in the site template on small - screens ([#3331]({{ site.repository }}/issues/3331)) -- Show the regeneration time after the initial generation ([#3378]({{ site.repository }}/issues/3378)) -- Site template: Switch default font to Helvetica Neue ([#3376]({{ site.repository }}/issues/3376)) -- Make the `include` tag a teensy bit faster. ([#3391]({{ site.repository }}/issues/3391)) -- Add `pkill -f jekyll` to ways to kill. ([#3397]({{ site.repository }}/issues/3397)) -- Site template: collapsed, variable-driven font declaration ([#3360]({{ site.repository }}/issues/3360)) -- Site template: Don't always show the scrollbar in code blocks ([#3419]({{ site.repository }}/issues/3419)) -- Site template: Remove undefined `text` class from `p` element ([#3440]({{ site.repository }}/issues/3440)) -- Site template: Optimize text rendering for legibility ([#3382]({{ site.repository }}/issues/3382)) -- Add `draft?` method to identify if Post is a Draft & expose to Liquid ([#3456]({{ site.repository }}/issues/3456)) -- Write regeneration metadata even on full rebuild ([#3464]({{ site.repository }}/issues/3464)) -- Perf: Use `String#end_with?("/")` instead of regexp when checking paths ([#3516]({{ site.repository }}/issues/3516)) -- Docs: document 'ordinal' built-in permalink style ([#3532]({{ site.repository }}/issues/3532)) -- Upgrade liquid-c to 3.x ([#3531]({{ site.repository }}/issues/3531)) -- Use consistent syntax for deprecation warning ([#3535]({{ site.repository }}/issues/3535)) -- Added build --destination and --source flags ([#3418]({{ site.repository }}/issues/3418)) -- Site template: remove unused `page.meta` attribute ([#3537]({{ site.repository }}/issues/3537)) -- Improve the error message when sorting null objects ([#3520]({{ site.repository }}/issues/3520)) -- Added liquid-md5 plugin ([#3598]({{ site.repository }}/issues/3598)) -- Documentation: RR replaced with RSpec Mocks ([#3600]({{ site.repository }}/issues/3600)) -- Documentation: Fix subpath. ([#3599]({{ site.repository }}/issues/3599)) -- Create 'tmp' dir for test_tags if it doesn't exist ([#3609]({{ site.repository }}/issues/3609)) -- Extract reading of data from `Site` to reduce responsibilities. ([#3545]({{ site.repository }}/issues/3545)) -- Removed the word 'Jekyll' a few times from the comments ([#3617]({{ site.repository }}/issues/3617)) -- `bin/jekyll`: with no args, exit with exit code 1 ([#3619]({{ site.repository }}/issues/3619)) -- Incremental build if destination file missing ([#3614]({{ site.repository }}/issues/3614)) -- Static files `mtime` liquid should return a `Time` obj ([#3596]({{ site.repository }}/issues/3596)) -- Use `Jekyll::Post`s for both LSI indexing and lookup. ([#3629]({{ site.repository }}/issues/3629)) -- Add `charset=utf-8` for HTML and XML pages in WEBrick ([#3649]({{ site.repository }}/issues/3649)) -- Set log level to debug when verbose flag is set ([#3665]({{ site.repository }}/issues/3665)) -- Added a mention on the Gemfile to complete the instructions ([#3671]({{ site.repository }}/issues/3671)) -- Perf: Cache `Document#to_liquid` and invalidate where necessary ([#3693]({{ site.repository }}/issues/3693)) -- Perf: `Jekyll::Cleaner#existing_files`: Call `keep_file_regex` and - `keep_dirs` only once, not once per iteration ([#3696]({{ site.repository }}/issues/3696)) -- Omit jekyll/jekyll-help from list of resources. ([#3698]({{ site.repository }}/issues/3698)) -- Add basic `jekyll doctor` test to detect fsnotify (OSX) anomalies. ([#3704]({{ site.repository }}/issues/3704)) -- Added talk.jekyllrb.com to "Have questions?" ([#3694]({{ site.repository }}/issues/3694)) -- Performance: Sort files only once ([#3707]({{ site.repository }}/issues/3707)) -- Performance: Marshal metadata ([#3706]({{ site.repository }}/issues/3706)) -- Upgrade highlight wrapper from `div` to `figure` ([#3779]({{ site.repository }}/issues/3779)) -- Upgrade mime-types to `~> 2.6` ([#3795]({{ site.repository }}/issues/3795)) -- Update windows.md with Ruby version info ([#3818]({{ site.repository }}/issues/3818)) -- Make the directory for includes configurable ([#3782]({{ site.repository }}/issues/3782)) -- Rename directory configurations to match `*_dir` convention for consistency ([#3782]({{ site.repository }}/issues/3782)) -- Internal: trigger hooks by owner symbol ([#3871]({{ site.repository }}/issues/3871)) -- Update MIME types from mime-db ([#3933]({{ site.repository }}/issues/3933)) -- Add header to site template `_config.yml` for clarity & direction ([#3997]({{ site.repository }}/issues/3997)) -- Site template: add timezone offset to post date frontmatter ([#4001]({{ site.repository }}/issues/4001)) -- Make a constant for the regex to find hidden files ([#4032]({{ site.repository }}/issues/4032)) -- Site template: refactor github & twitter icons into includes ([#4049]({{ site.repository }}/issues/4049)) -- Site template: add background to Kramdown Rouge-ified backtick code blocks ([#4053]({{ site.repository }}/issues/4053)) - -### Bug Fixes -{: #bug-fixes-v3-0-0} - -- `post_url`: fix access deprecation warning & fix deprecation msg ([#4060]({{ site.repository }}/issues/4060)) -- Perform jekyll-paginate deprecation warning correctly. ([#3580]({{ site.repository }}/issues/3580)) -- Make permalink parsing consistent with pages ([#3014]({{ site.repository }}/issues/3014)) -- `time()`pre-filter method should accept a `Date` object ([#3299]({{ site.repository }}/issues/3299)) -- Remove unneeded end tag for `link` in site template ([#3236]({{ site.repository }}/issues/3236)) -- Kramdown: Use `enable_coderay` key instead of `use_coderay` ([#3237]({{ site.repository }}/issues/3237)) -- Unescape `Document` output path ([#2924]({{ site.repository }}/issues/2924)) -- Fix nav items alignment when on multiple rows ([#3264]({{ site.repository }}/issues/3264)) -- Highlight: Only Strip Newlines/Carriage Returns, not Spaces ([#3278]({{ site.repository }}/issues/3278)) -- Find variables in front matter defaults by searching with relative file path. ([#2774]({{ site.repository }}/issues/2774)) -- Allow variables (e.g `:categories`) in YAML front matter permalinks ([#3320]({{ site.repository }}/issues/3320)) -- Handle nil URL placeholders in permalinks ([#3325]({{ site.repository }}/issues/3325)) -- Template: Fix nav items alignment when in "burger" mode ([#3329]({{ site.repository }}/issues/3329)) -- Template: Remove `!important` from nav SCSS introduced in [#3329]({{ site.repository }}/issues/3329) ([#3375]({{ site.repository }}/issues/3375)) -- The `:title` URL placeholder for collections should be the filename slug. ([#3383]({{ site.repository }}/issues/3383)) -- Trim the generate time diff to just 3 places past the decimal place ([#3415]({{ site.repository }}/issues/3415)) -- The highlight tag should only clip the newlines before and after the *entire* block, not in between ([#3401]({{ site.repository }}/issues/3401)) -- highlight: fix problem with linenos and rouge. ([#3436]({{ site.repository }}/issues/3436)) -- `Site#read_data_file`: read CSV's with proper file encoding ([#3455]({{ site.repository }}/issues/3455)) -- Ignore `.jekyll-metadata` in site template ([#3496]({{ site.repository }}/issues/3496)) -- Template: Point documentation link to the documentation pages ([#3502]({{ site.repository }}/issues/3502)) -- Removed the trailing slash from the example `/blog` baseurl comment ([#3485]({{ site.repository }}/issues/3485)) -- Clear the regenerator cache every time we process ([#3592]({{ site.repository }}/issues/3592)) -- Readd (bring back) minitest-profile ([#3628]({{ site.repository }}/issues/3628)) -- Add WOFF2 font MIME type to Jekyll server MIME types ([#3647]({{ site.repository }}/issues/3647)) -- Be smarter about extracting the extname in `StaticFile` ([#3632]({{ site.repository }}/issues/3632)) -- Process metadata for all dependencies ([#3608]({{ site.repository }}/issues/3608)) -- Show error message if the YAML front matter on a page/post is invalid. ([#3643]({{ site.repository }}/issues/3643)) -- Upgrade redcarpet to 3.2 (Security fix: OSVDB-120415) ([#3652]({{ site.repository }}/issues/3652)) -- Create #mock_expects that goes directly to RSpec Mocks. ([#3658]({{ site.repository }}/issues/3658)) -- Open `.jekyll-metadata` in binary mode to read binary Marshal data ([#3713]({{ site.repository }}/issues/3713)) -- Incremental regeneration: handle deleted, renamed, and moved dependencies ([#3717]({{ site.repository }}/issues/3717)) -- Fix typo on line 19 of pagination.md ([#3760]({{ site.repository }}/issues/3760)) -- Fix it so that 'blog.html' matches 'blog.html' ([#3732]({{ site.repository }}/issues/3732)) -- Remove occasionally-problematic `ensure` in `LiquidRenderer` ([#3811]({{ site.repository }}/issues/3811)) -- Fixed an unclear code comment in site template SCSS ([#3837]({{ site.repository }}/issues/3837)) -- Fix reading of binary metadata file ([#3845]({{ site.repository }}/issues/3845)) -- Remove var collision with site template header menu iteration variable ([#3838]({{ site.repository }}/issues/3838)) -- Change non-existent `hl_linenos` to `hl_lines` to allow passthrough in safe mode ([#3787]({{ site.repository }}/issues/3787)) -- Add missing flag to disable the watcher ([#3820]({{ site.repository }}/issues/3820)) -- Update CI guide to include more direct explanations of the flow ([#3891]({{ site.repository }}/issues/3891)) -- Set `future` to `false` in the default config ([#3892]({{ site.repository }}/issues/3892)) -- filters: `where` should compare stringified versions of input & comparator ([#3935]({{ site.repository }}/issues/3935)) -- Read build options for `jekyll clean` command ([#3828]({{ site.repository }}/issues/3828)) -- Fix [#3970]({{ site.repository }}/issues/3970): Use Gem::Version to compare versions, not `>`. -- Abort if no subcommand. Fixes confusing message. ([#3992]({{ site.repository }}/issues/3992)) -- Whole-post excerpts should match the post content ([#4004]({{ site.repository }}/issues/4004)) -- Change default font weight to 400 to fix bold/strong text issues ([#4050]({{ site.repository }}/issues/4050)) -- Document: Only auto-generate the excerpt if it's not overridden ([#4062]({{ site.repository }}/issues/4062)) -- Utils: `deep_merge_hashes` should also merge `default_proc` (45f69bb) -- Defaults: compare paths in `applies_path?` as `String`s to avoid confusion (7b81f00) - -### Development Fixes -{: #development-fixes-v3-0-0} - -- Remove loader.rb and "modernize" `script/test`. ([#3574]({{ site.repository }}/issues/3574)) -- Improve the grammar in the documentation ([#3233]({{ site.repository }}/issues/3233)) -- Update the LICENSE text to match the MIT license exactly ([#3253]({{ site.repository }}/issues/3253)) -- Update rake task `site:publish` to fix minor bugs. ([#3254]({{ site.repository }}/issues/3254)) -- Switch to shields.io for the README badges. ([#3255]({{ site.repository }}/issues/3255)) -- Use `FileList` instead of `Dir.glob` in `site:publish` rake task ([#3261]({{ site.repository }}/issues/3261)) -- Fix test script to be platform-independent ([#3279]({{ site.repository }}/issues/3279)) -- Instead of symlinking `/tmp`, create and symlink a local `tmp` in the tests ([#3258]({{ site.repository }}/issues/3258)) -- Fix some spacing ([#3312]({{ site.repository }}/issues/3312)) -- Fix comment typo in `lib/jekyll/frontmatter_defaults.rb` ([#3322]({{ site.repository }}/issues/3322)) -- Move all `regenerate?` checking to `Regenerator` ([#3326]({{ site.repository }}/issues/3326)) -- Factor out a `read_data_file` call to keep things clean ([#3380]({{ site.repository }}/issues/3380)) -- Proof the site with CircleCI. ([#3427]({{ site.repository }}/issues/3427)) -- Update LICENSE to 2015. ([#3477]({{ site.repository }}/issues/3477)) -- Upgrade tests to use Minitest ([#3492]({{ site.repository }}/issues/3492)) -- Remove trailing whitespace ([#3497]({{ site.repository }}/issues/3497)) -- Use `fixture_site` for Document tests ([#3511]({{ site.repository }}/issues/3511)) -- Remove adapters deprecation warning ([#3529]({{ site.repository }}/issues/3529)) -- Minor fixes to `url.rb` to follow GitHub style guide ([#3544]({{ site.repository }}/issues/3544)) -- Minor changes to resolve deprecation warnings ([#3547]({{ site.repository }}/issues/3547)) -- Convert remaining textile test documents to markdown ([#3528]({{ site.repository }}/issues/3528)) -- Migrate the tests to use rspec-mocks ([#3552]({{ site.repository }}/issues/3552)) -- Remove `activesupport` ([#3612]({{ site.repository }}/issues/3612)) -- Added tests for `Jekyll:StaticFile` ([#3633]({{ site.repository }}/issues/3633)) -- Force minitest version to 5.5.1 ([#3657]({{ site.repository }}/issues/3657)) -- Update the way cucumber accesses Minitest assertions ([#3678]({{ site.repository }}/issues/3678)) -- Add `script/rubyprof` to generate cachegrind callgraphs ([#3692]({{ site.repository }}/issues/3692)) -- Upgrade cucumber to 2.x ([#3795]({{ site.repository }}/issues/3795)) -- Update Kramdown. ([#3853]({{ site.repository }}/issues/3853)) -- Updated the scripts shebang for portability ([#3858]({{ site.repository }}/issues/3858)) -- Update JRuby testing to 9K ([3ab386f](https://github.com/jekyll/jekyll/commit/3ab386f1b096be25a24fe038fc70fd0fb08d545d)) -- Organize dependencies into dev and test groups. ([#3852]({{ site.repository }}/issues/3852)) -- Contributing.md should refer to `script/cucumber` ([#3894]({{ site.repository }}/issues/3894)) -- Update contributing documentation to reflect workflow updates ([#3895]({{ site.repository }}/issues/3895)) -- Add script to vendor mime types ([#3933]({{ site.repository }}/issues/3933)) -- Ignore .bundle dir in SimpleCov ([#4033]({{ site.repository }}/issues/4033)) - -### Site Enhancements -{: #site-enhancements-v3-0-0} - -- Add 'info' labels to certain notes in collections docs ([#3601]({{ site.repository }}/issues/3601)) -- Remove extra spaces, make the last sentence less awkward in permalink docs ([#3603]({{ site.repository }}/issues/3603)) -- Update the permalinks documentation to reflect the updates for 3.0 ([#3556]({{ site.repository }}/issues/3556)) -- Add blog post announcing Jekyll Help ([#3523]({{ site.repository }}/issues/3523)) -- Add Jekyll Talk to Help page on site ([#3518]({{ site.repository }}/issues/3518)) -- Change Ajax pagination resource link to use HTTPS ([#3570]({{ site.repository }}/issues/3570)) -- Fixing the default host on docs ([#3229]({{ site.repository }}/issues/3229)) -- Add `jekyll-thumbnail-filter` to list of third-party plugins ([#2790]({{ site.repository }}/issues/2790)) -- Add link to 'Adding Ajax pagination to Jekyll' to Resources page ([#3186]({{ site.repository }}/issues/3186)) -- Add a Resources link to tutorial on building dynamic navbars ([#3185]({{ site.repository }}/issues/3185)) -- Semantic structure improvements to the post and page layouts ([#3251]({{ site.repository }}/issues/3251)) -- Add new AsciiDoc plugin to list of third-party plugins. ([#3277]({{ site.repository }}/issues/3277)) -- Specify that all transformable collection documents must contain YAML front matter ([#3271]({{ site.repository }}/issues/3271)) -- Assorted accessibility fixes ([#3256]({{ site.repository }}/issues/3256)) -- Update configuration docs to mention `keep_files` for `destination` ([#3288]({{ site.repository }}/issues/3288), [#3296]({{ site.repository }}/issues/3296)) -- Break when we successfully generate nav link to save CPU cycles. ([#3291]({{ site.repository }}/issues/3291)) -- Update usage docs to mention `keep_files` and a warning about `destination` cleaning ([#3295]({{ site.repository }}/issues/3295)) -- Add logic to automatically generate the `next_section` and `prev_section` navigation items ([#3292]({{ site.repository }}/issues/3292)) -- Some small fixes for the Plugins TOC. ([#3306]({{ site.repository }}/issues/3306)) -- Added versioning comment to configuration file ([#3314]({{ site.repository }}/issues/3314)) -- Add `jekyll-minifier` to list of third-party plugins ([#3333]({{ site.repository }}/issues/3333)) -- Add blog post about the Jekyll meet-up ([#3332]({{ site.repository }}/issues/3332)) -- Use `highlight` Liquid tag instead of the four-space tabs for code ([#3336]({{ site.repository }}/issues/3336)) -- 3.0.0.beta1 release post ([#3346]({{ site.repository }}/issues/3346)) -- Add `twa` to the list of third-party plugins ([#3384]({{ site.repository }}/issues/3384)) -- Remove extra spaces ([#3388]({{ site.repository }}/issues/3388)) -- Fix small grammar errors on a couple pages ([#3396]({{ site.repository }}/issues/3396)) -- Fix typo on Templates docs page ([#3420]({{ site.repository }}/issues/3420)) -- s/three/four for plugin type list ([#3424]({{ site.repository }}/issues/3424)) -- Release jekyllrb.com as a locally-compiled site. ([#3426]({{ site.repository }}/issues/3426)) -- Add a jekyllrb.com/help page which elucidates places from which to get help ([#3428]({{ site.repository }}/issues/3428)) -- Remove extraneous dash on Plugins doc page which caused a formatting error ([#3431]({{ site.repository }}/issues/3431)) -- Fix broken link to Jordan Thornquest's website. ([#3438]({{ site.repository }}/issues/3438)) -- Change the link to an extension ([#3457]({{ site.repository }}/issues/3457)) -- Fix Twitter link on the help page ([#3466]({{ site.repository }}/issues/3466)) -- Fix wording in code snippet highlighting section ([#3475]({{ site.repository }}/issues/3475)) -- Add a `/` to `paginate_path` in the Pagination documentation ([#3479]({{ site.repository }}/issues/3479)) -- Add a link on all the docs pages to "Improve this page". ([#3510]({{ site.repository }}/issues/3510)) -- Add jekyll-auto-image generator to the list of third-party plugins ([#3489]({{ site.repository }}/issues/3489)) -- Replace link to the proposed `picture` element spec ([#3530]({{ site.repository }}/issues/3530)) -- Add frontmatter date formatting information ([#3469]({{ site.repository }}/issues/3469)) -- Improve consistency and clarity of plugins options note ([#3546]({{ site.repository }}/issues/3546)) -- Add permalink warning to pagination docs ([#3551]({{ site.repository }}/issues/3551)) -- Fix grammar in Collections docs API stability warning ([#3560]({{ site.repository }}/issues/3560)) -- Restructure `excerpt_separator` documentation for clarity ([#3550]({{ site.repository }}/issues/3550)) -- Fix accidental line break in collections docs ([#3585]({{ site.repository }}/issues/3585)) -- Add information about the `.jekyll-metadata` file ([#3597]({{ site.repository }}/issues/3597)) -- Document addition of variable parameters to an include ([#3581]({{ site.repository }}/issues/3581)) -- Add `jekyll-files` to the list of third-party plugins. ([#3586]({{ site.repository }}/issues/3586)) -- Define the `install` step in the CI example `.travis.yml` ([#3622]({{ site.repository }}/issues/3622)) -- Expand collections documentation. ([#3638]({{ site.repository }}/issues/3638)) -- Add the "warning" note label to excluding `vendor` in the CI docs page ([#3623]({{ site.repository }}/issues/3623)) -- Upgrade pieces of the Ugrading guide for Jekyll 3 ([#3607]({{ site.repository }}/issues/3607)) -- Showing how to access specific data items ([#3468]({{ site.repository }}/issues/3468)) -- Clarify pagination works from within HTML files ([#3467]({{ site.repository }}/issues/3467)) -- Add note to `excerpt_separator` documentation that it can be set globally ([#3667]({{ site.repository }}/issues/3667)) -- Fix some names on Troubleshooting page ([#3683]({{ site.repository }}/issues/3683)) -- Add `remote_file_content` tag plugin to list of third-party plugins ([#3691]({{ site.repository }}/issues/3691)) -- Update the Redcarpet version on the Configuration page. ([#3743]({{ site.repository }}/issues/3743)) -- Update the link in the welcome post to point to Jekyll Talk ([#3745]({{ site.repository }}/issues/3745)) -- Update link for navbars with data attributes tutorial ([#3728]({{ site.repository }}/issues/3728)) -- Add `jekyll-asciinema` to list of third-party plugins ([#3750]({{ site.repository }}/issues/3750)) -- Update pagination example to be agnostic to first pagination dir ([#3763]({{ site.repository }}/issues/3763)) -- Detailed instructions for rsync deployment method ([#3848]({{ site.repository }}/issues/3848)) -- Add Jekyll Portfolio Generator to list of plugins ([#3883]({{ site.repository }}/issues/3883)) -- Add `site.html_files` to variables docs ([#3880]({{ site.repository }}/issues/3880)) -- Add Static Publisher tool to list of deployment methods ([#3865]({{ site.repository }}/issues/3865)) -- Fix a few typos. ([#3897]({{ site.repository }}/issues/3897)) -- Add `jekyll-youtube` to the list of third-party plugins ([#3931]({{ site.repository }}/issues/3931)) -- Add Views Router plugin ([#3950]({{ site.repository }}/issues/3950)) -- Update install docs (Core dependencies, Windows reqs, etc) ([#3769]({{ site.repository }}/issues/3769)) -- Use Jekyll Feed for jekyllrb.com ([#3736]({{ site.repository }}/issues/3736)) -- Add jekyll-umlauts to plugins.md ($3966) -- Troubleshooting: fix broken link, add other mac-specific info ([#3968]({{ site.repository }}/issues/3968)) -- Add a new site for learning purposes ([#3917]({{ site.repository }}/issues/3917)) -- Added documentation for Jekyll environment variables ([#3989]({{ site.repository }}/issues/3989)) -- Fix broken configuration documentation page ([#3994]({{ site.repository }}/issues/3994)) -- Add troubleshooting docs for installing on El Capitan ([#3999]({{ site.repository }}/issues/3999)) -- Add Lazy Tweet Embedding to the list of third-party plugins ([#4015]({{ site.repository }}/issues/4015)) -- Add installation instructions for 2 of 3 options for plugins ([#4013]({{ site.repository }}/issues/4013)) -- Add alternative jekyll gem installation instructions ([#4018]({{ site.repository }}/issues/4018)) -- Fix a few typos and formatting problems. ([#4022]({{ site.repository }}/issues/4022)) -- Fix pretty permalink example ([#4029]({{ site.repository }}/issues/4029)) -- Note that `_config.yml` is not reloaded during regeneration ([#4034]({{ site.repository }}/issues/4034)) -- Apply code block figure syntax to blocks in CONTRIBUTING ([#4046]({{ site.repository }}/issues/4046)) -- Add jekyll-smartify to the list of third-party plugins ([#3572]({{ site.repository }}/issues/3572)) - - -## 2.5.3 / 2014-12-22 -{: #v2-5-3} - -### Bug Fixes -{: #bug-fixes-v2-5-3} - -- When checking a Markdown extname, include position of the `.` ([#3147]({{ site.repository }}/issues/3147)) -- Fix `jsonify` Liquid filter handling of boolean values ([#3154]({{ site.repository }}/issues/3154)) -- Add comma to value of `viewport` meta tag ([#3170]({{ site.repository }}/issues/3170)) -- Set the link type for the RSS feed to `application/rss+xml` ([#3176]({{ site.repository }}/issues/3176)) -- Refactor `#as_liquid` ([#3158]({{ site.repository }}/issues/3158)) - -### Development Fixes -{: #development-fixes-v2-5-3} - -- Exclude built-in bundles from being added to coverage report ([#3180]({{ site.repository }}/issues/3180)) - -### Site Enhancements -{: #site-enhancements-v2-5-3} - -- Add `[@alfredxing](https://github.com/alfredxing)` to the `[@jekyll](https://github.com/jekyll)/core` team. :tada: ([#3218]({{ site.repository }}/issues/3218)) -- Document the `-q` option for the `build` and `serve` commands ([#3149]({{ site.repository }}/issues/3149)) -- Fix some minor typos/flow fixes in documentation website content ([#3165]({{ site.repository }}/issues/3165)) -- Add `keep_files` to configuration documentation ([#3162]({{ site.repository }}/issues/3162)) -- Repeat warning about cleaning of the `destination` directory ([#3161]({{ site.repository }}/issues/3161)) -- Add jekyll-500px-embed to list of third-party plugins ([#3163]({{ site.repository }}/issues/3163)) -- Simplified platform detection in Gemfile example for Windows ([#3177]({{ site.repository }}/issues/3177)) -- Add the `jekyll-jalali` plugin added to the list of third-party plugins. ([#3198]({{ site.repository }}/issues/3198)) -- Add Table of Contents to Troubleshooting page ([#3196]({{ site.repository }}/issues/3196)) -- Add `inline_highlight` plugin to list of third-party plugins ([#3212]({{ site.repository }}/issues/3212)) -- Add `jekyll-mermaid` plugin to list of third-party plugins ([#3222]({{ site.repository }}/issues/3222)) - - -## 2.5.2 / 2014-11-17 -{: #v2-5-2} - -### Minor Enhancements -{: #minor-enhancements-v2-5-2} - -- `post_url` should match `post.name` instead of slugs and dates ([#3058]({{ site.repository }}/issues/3058)) - -### Bug Fixes -{: #bug-fixes-v2-5-2} - -- Fix bundle require for `:jekyll_plugins` ([#3119]({{ site.repository }}/issues/3119)) -- Remove duplicate regexp phrase: `^\A` ([#3089]({{ site.repository }}/issues/3089)) -- Remove duplicate `Conversion error:` message in `Convertible` ([#3088]({{ site.repository }}/issues/3088)) -- Print full conversion error message in `Renderer#convert` ([#3090]({{ site.repository }}/issues/3090)) - -### Site Enhancements -{: #site-enhancements-v2-5-2} - -- Change variable names in Google Analytics script ([#3093]({{ site.repository }}/issues/3093)) -- Mention CSV files in the docs for data files ([#3101]({{ site.repository }}/issues/3101)) -- Add trailing slash to `paginate_path` example. ([#3091]({{ site.repository }}/issues/3091)) -- Get rid of noifniof (`excerpt_separator`) ([#3094]({{ site.repository }}/issues/3094)) -- Sass improvements, around nesting mostly. ([#3123]({{ site.repository }}/issues/3123)) -- Add webmentions.io plugin to the list of third-party plugins ([#3127]({{ site.repository }}/issues/3127)) -- Add Sass mixins and use them. ([#2904]({{ site.repository }}/issues/2904)) -- Slightly compress jekyll-sticker.jpg. ([#3133]({{ site.repository }}/issues/3133)) -- Update gridism and separate out related but custom styles. ([#3132]({{ site.repository }}/issues/3132)) -- Add remote-include plugin to list of third-party plugins ([#3136]({{ site.repository }}/issues/3136)) - - -## 2.5.1 / 2014-11-09 -{: #v2-5-1} - -### Bug Fixes -{: #bug-fixes-v2-5-1} - -- Fix path sanitation bug related to Windows drive names ([#3077]({{ site.repository }}/issues/3077)) - -### Development Fixes -{: #development-fixes-v2-5-1} - -- Add development time dependencies on minitest and test-unit to gemspec for cygwin ([#3064]({{ site.repository }}/issues/3064)) -- Use Travis's built-in caching. ([#3075]({{ site.repository }}/issues/3075)) - - -## 2.5.0 / 2014-11-06 -{: #v2-5-0} - -### Minor Enhancements -{: #minor-enhancements-v2-5-0} - -- Require gems in `:jekyll_plugins` Gemfile group unless `JEKYLL_NO_BUNDLER_REQUIRE` is specified in the environment. ([#2865]({{ site.repository }}/issues/2865)) -- Centralize path sanitation in the `Site` object ([#2882]({{ site.repository }}/issues/2882)) -- Allow placeholders in permalinks ([#3031]({{ site.repository }}/issues/3031)) -- Allow users to specify the log level via `JEKYLL_LOG_LEVEL`. ([#3067]({{ site.repository }}/issues/3067)) -- Fancy Indexing with WEBrick ([#3018]({{ site.repository }}/issues/3018)) -- Allow Enumerables to be used with `where` filter. ([#2986]({{ site.repository }}/issues/2986)) -- Meta descriptions in the site template now use `page.excerpt` if it's available ([#2964]({{ site.repository }}/issues/2964)) -- Change indentation in `head.html` of site template to 2 spaces from 4 ([#2973]({{ site.repository }}/issues/2973)) -- Use a `$content-width` variable instead of a fixed value in the site template CSS ([#2972]({{ site.repository }}/issues/2972)) -- Strip newlines in site template `` description. ([#2982]({{ site.repository }}/issues/2982)) -- Add link to atom feed in `head` of site template files ([#2996]({{ site.repository }}/issues/2996)) -- Performance optimizations ([#2994]({{ site.repository }}/issues/2994)) -- Use `Hash#each_key` instead of `Hash#keys.each` to speed up iteration - over hash keys. ([#3017]({{ site.repository }}/issues/3017)) -- Further minor performance enhancements. ([#3022]({{ site.repository }}/issues/3022)) -- Add 'b' and 's' aliases for build and serve, respectively ([#3065]({{ site.repository }}/issues/3065)) - -### Bug Fixes -{: #bug-fixes-v2-5-0} - -- Fix Rouge's RedCarpet plugin interface integration ([#2951]({{ site.repository }}/issues/2951)) -- Remove `--watch` from the site template blog post since it defaults - to watching in in 2.4.0 ([#2922]({{ site.repository }}/issues/2922)) -- Fix code for media query mixin in site template ([#2946]({{ site.repository }}/issues/2946)) -- Allow post URL's to have `.htm` extensions ([#2925]({{ site.repository }}/issues/2925)) -- `Utils.slugify`: Don't create new objects when gsubbing ([#2997]({{ site.repository }}/issues/2997)) -- The jsonify filter should deep-convert to Liquid when given an Array. ([#3032]({{ site.repository }}/issues/3032)) -- Apply `jsonify` filter to Hashes deeply and effectively ([#3063]({{ site.repository }}/issues/3063)) -- Use `127.0.0.1` as default host instead of `0.0.0.0` ([#3053]({{ site.repository }}/issues/3053)) -- In the case that a Gemfile does not exist, ensure Jekyll doesn't fail on requiring the Gemfile group ([#3066]({{ site.repository }}/issues/3066)) - -### Development Fixes -{: #development-fixes-v2-5-0} - -- Fix a typo in the doc block for `Jekyll::URL.escape_path` ([#3052]({{ site.repository }}/issues/3052)) -- Add integration test for `jekyll new --blank` in TestUnit ([#2913]({{ site.repository }}/issues/2913)) -- Add unit test for `jekyll new --force` logic ([#2929]({{ site.repository }}/issues/2929)) -- Update outdated comment for `Convertible#transform` ([#2957]({{ site.repository }}/issues/2957)) -- Add Hakiri badge to README. ([#2953]({{ site.repository }}/issues/2953)) -- Add some simple benchmarking tools. ([#2993]({{ site.repository }}/issues/2993)) - -### Site Enhancements -{: #site-enhancements-v2-5-0} - -- `NOKOGIRI_USE_SYSTEM_LIBRARIES=true` **decreases** installation time. ([#3040]({{ site.repository }}/issues/3040)) -- Add FormKeep to resources as Jekyll form backend ([#3010]({{ site.repository }}/issues/3010)) -- Fixing a mistake in the name of the new Liquid tag ([#2969]({{ site.repository }}/issues/2969)) -- Update Font Awesome to v4.2.0. ([#2898]({{ site.repository }}/issues/2898)) -- Fix link to [#2895]({{ site.repository }}/issues/2895) in 2.4.0 release post. ([#2899]({{ site.repository }}/issues/2899)) -- Add Big Footnotes for Kramdown plugin to list of third-party plugins ([#2916]({{ site.repository }}/issues/2916)) -- Remove warning regarding GHP use of singular types for front matter defaults ([#2919]({{ site.repository }}/issues/2919)) -- Fix quote character typo in site documentation for templates ([#2917]({{ site.repository }}/issues/2917)) -- Point Liquid links to Liquid’s Github wiki ([#2887]({{ site.repository }}/issues/2887)) -- Add HTTP Basic Auth (.htaccess) plugin to list of third-party plugins ([#2931]({{ site.repository }}/issues/2931)) -- (Minor) Grammar & `_config.yml` filename fixes ([#2911]({{ site.repository }}/issues/2911)) -- Added `mathml.rb` to the list of third-party plugins. ([#2937]({{ site.repository }}/issues/2937)) -- Add `--force_polling` to the list of configuration options ([#2943]({{ site.repository }}/issues/2943)) -- Escape unicode characters in site CSS ([#2906]({{ site.repository }}/issues/2906)) -- Add note about using the github-pages gem via pages.github.com/versions.json ([#2939]({{ site.repository }}/issues/2939)) -- Update usage documentation to reflect 2.4 auto-enabling of `--watch`. ([#2954]({{ site.repository }}/issues/2954)) -- Add `--skip-initial-build` to configuration docs ([#2949]({{ site.repository }}/issues/2949)) -- Fix a minor typo in Templates docs page ([#2959]({{ site.repository }}/issues/2959)) -- Add a ditaa-ditaa plugin under Other section on the Plugins page ([#2967]({{ site.repository }}/issues/2967)) -- Add `build/serve -V` option to configuration documentation ([#2948]({{ site.repository }}/issues/2948)) -- Add 'Jekyll Twitter Plugin' to list of third-party plugins ([#2979]({{ site.repository }}/issues/2979)) -- Docs: Update normalize.css to v3.0.2. ([#2981]({{ site.repository }}/issues/2981)) -- Fix typo in Continuous Integration documentation ([#2984]({{ site.repository }}/issues/2984)) -- Clarify behavior of `:categories` in permalinks ([#3011]({{ site.repository }}/issues/3011)) - - -## 2.4.0 / 2014-09-09 -{: #v2-4-0} - -### Minor Enhancements -{: #minor-enhancements-v2-4-0} - -- Support a new `relative_include` tag ([#2870]({{ site.repository }}/issues/2870)) -- Auto-enable watch on 'serve' ([#2858]({{ site.repository }}/issues/2858)) -- Render Liquid in CoffeeScript files ([#2830]({{ site.repository }}/issues/2830)) -- Array Liquid filters: `push`, `pop`, `unshift`, `shift` ([#2895]({{ site.repository }}/issues/2895)) -- Add `:title` to collection URL template fillers ([#2864]({{ site.repository }}/issues/2864)) -- Add support for CSV files in the `_data` directory ([#2761]({{ site.repository }}/issues/2761)) -- Add the `name` variable to collection permalinks ([#2799]({{ site.repository }}/issues/2799)) -- Add `inspect` liquid filter. ([#2867]({{ site.repository }}/issues/2867)) -- Add a `slugify` Liquid filter ([#2880]({{ site.repository }}/issues/2880)) - -### Bug Fixes -{: #bug-fixes-v2-4-0} - -- Use `Jekyll.sanitized_path` when adding static files to Collections ([#2849]({{ site.repository }}/issues/2849)) -- Fix encoding of `main.scss` in site template ([#2771]({{ site.repository }}/issues/2771)) -- Fix orientation bugs in default site template ([#2862]({{ site.repository }}/issues/2862)) - -### Development Fixes -{: #development-fixes-v2-4-0} - -- Update simplecov gem to 0.9 ([#2748]({{ site.repository }}/issues/2748)) -- Remove `docs/` dir ([#2768]({{ site.repository }}/issues/2768)) -- add class `<< self` idiom to `New` command ([#2817]({{ site.repository }}/issues/2817)) -- Allow Travis to 'parallelize' our tests ([#2859]({{ site.repository }}/issues/2859)) -- Fix test for Liquid rendering in Sass ([#2856]({{ site.repository }}/issues/2856)) -- Fixing "vertycal" typo in site template's `_base.scss` ([#2889]({{ site.repository }}/issues/2889)) - -### Site Enhancements -{: #site-enhancements-v2-4-0} - -- Document the `name` variable for collection permalinks ([#2829]({{ site.repository }}/issues/2829)) -- Adds info about installing jekyll in current dir ([#2839]({{ site.repository }}/issues/2839)) -- Remove deprecated `jekyll-projectlist` plugin from list of third-party - plugins ([#2742]({{ site.repository }}/issues/2742)) -- Remove tag plugins that are built in to Jekyll ([#2751]({{ site.repository }}/issues/2751)) -- Add `markdown-writer` package for Atom Editor to list of third-party - plugins ([#2763]({{ site.repository }}/issues/2763)) -- Fix typo in site documentation for collections ([#2764]({{ site.repository }}/issues/2764)) -- Fix minor typo on plugins docs page ([#2765]({{ site.repository }}/issues/2765)) -- Replace markdown with HTML in `sass_dir` note on assets page ([#2791]({{ site.repository }}/issues/2791)) -- Fixed "bellow" typo in datafiles docs ([#2879]({{ site.repository }}/issues/2879)) -- Fix code/markdown issue in documentation for variables ([#2877]({{ site.repository }}/issues/2877)) -- Remove Good Include third-party plugin from plugins page ([#2881]({{ site.repository }}/issues/2881)) -- Add some more docs on `include_relative` ([#2884]({{ site.repository }}/issues/2884)) - - -## 2.3.0 / 2014-08-10 -{: #v2-3-0} - -### Minor Enhancements -{: #minor-enhancements-v2-3-0} - -- Allow Convertibles to be converted by >= 1 converters ([#2704]({{ site.repository }}/issues/2704)) -- Allow Sass files to be rendered in Liquid, but never place them in layouts. ([#2733]({{ site.repository }}/issues/2733)) -- Add `jekyll help` command ([#2707]({{ site.repository }}/issues/2707)) -- Use `.scss` for `site_template` styles. ([#2667]({{ site.repository }}/issues/2667)) -- Don't require the `scope` key in front matter defaults ([#2659]({{ site.repository }}/issues/2659)) -- No longer set `permalink: pretty` in the `_config.yml` for the site template ([#2680]({{ site.repository }}/issues/2680)) -- Rework site template to utilize Sass ([#2687]({{ site.repository }}/issues/2687)) -- Notify the user when auto-regeneration is disabled. ([#2696]({{ site.repository }}/issues/2696)) -- Allow partial variables in include tag filename argument ([#2693]({{ site.repository }}/issues/2693)) -- Move instances of `Time.parse` into a Utils method ([#2682]({{ site.repository }}/issues/2682)) -- Ignore subfolders in the `_posts` folder ([#2705]({{ site.repository }}/issues/2705)) REVERTS ([#2633]({{ site.repository }}/issues/2633)) -- Front Matter default types should always be pluralized ([#2732]({{ site.repository }}/issues/2732)) -- Read in static files into `collection.files` as `StaticFile`s ([#2737]({{ site.repository }}/issues/2737)) -- Add `sassify` and `scssify` Liquid filters ([#2739]({{ site.repository }}/issues/2739)) -- Replace `classifier` gem with `classifier-reborn` ([#2721]({{ site.repository }}/issues/2721)) - -### Bug Fixes -{: #bug-fixes-v2-3-0} - -- Use only the last extname when multiple converters exist ([#2722]({{ site.repository }}/issues/2722)) -- Call `#to_liquid` before calling `#to_json` in jsonify filter ([#2729]({{ site.repository }}/issues/2729)) -- Use non padded config in `strftime` to avoid parse string twice ([#2673]({{ site.repository }}/issues/2673)) -- Replace deprecated Ruby methods with undeprecated ones ([#2664]({{ site.repository }}/issues/2664)) -- Catch errors when parsing Post `date` front matter value & produce nice error message ([#2649]({{ site.repository }}/issues/2649)) -- Allow static files in Collections ([#2615]({{ site.repository }}/issues/2615)) -- Fixed typo in `Deprecator#gracefully_require` error message ([#2694]({{ site.repository }}/issues/2694)) -- Remove preemptive loading of the 'classifier' gem. ([#2697]({{ site.repository }}/issues/2697)) -- Use case-insensitive checking for the file extensions when loading config files ([#2718]({{ site.repository }}/issues/2718)) -- When Reading Documents, Respect `encoding` Option ([#2720]({{ site.repository }}/issues/2720)) -- Refactor based on jekyll-watch clean-up. ([#2716]({{ site.repository }}/issues/2716)) -- `Document#to_s` should produce just the content of the document ([#2731]({{ site.repository }}/issues/2731)) - -### Development Fixes -{: #development-fixes-v2-3-0} - -- Only include lib files in the gem ([#2671]({{ site.repository }}/issues/2671)) -- Fix `git diff` command in `proof` script ([#2672]({{ site.repository }}/issues/2672)) -- Make default rake task a multitask so tests run in parallel ([#2735]({{ site.repository }}/issues/2735)) - -### Site Enhancements -{: #site-enhancements-v2-3-0} - -- Use Sass and a Docs Collection ([#2651]({{ site.repository }}/issues/2651)) -- Add `latest_version.txt` file to the site ([#2740]({{ site.repository }}/issues/2740)) -- Be more ambiguous about `page.content`. But more transparent. ([#2522]({{ site.repository }}/issues/2522)) -- Streamlining front matter wording (instead of front-matter/frontmatter) ([#2674]({{ site.repository }}/issues/2674)) -- Add note that source directory cannot be modified in GitHub Pages ([#2669]({{ site.repository }}/issues/2669)) -- Fix links from [#2669]({{ site.repository }}/issues/2669) to be actual HTML. Whoops. ([#2679]({{ site.repository }}/issues/2679)) -- Add link to `jekyll-slim` in list of third-party plugins ([#2689]({{ site.repository }}/issues/2689)) -- Add Barry Clark's Smashing Magazine tutorial to resources page ([#2688]({{ site.repository }}/issues/2688)) -- Reorganize and update default configuration settings ([#2456]({{ site.repository }}/issues/2456)) -- Fixing indentation in the configuration docs about Redcarpet exts ([#2717]({{ site.repository }}/issues/2717)) -- Use `null` in YAML instead of `nil` in default config list ([#2719]({{ site.repository }}/issues/2719)) -- Fix typo in Continuous Integration docs ([#2708]({{ site.repository }}/issues/2708)) - - -## 2.2.0 / 2014-07-29 -{: #v2-2-0} - -### Minor Enhancements -{: #minor-enhancements-v2-2-0} - -- Throw a warning if the specified layout does not exist ([#2620]({{ site.repository }}/issues/2620)) -- Whitelist Pygments options in safe mode ([#2642]({{ site.repository }}/issues/2642)) - -### Bug Fixes -{: #bug-fixes-v2-2-0} - -- Remove unnecessary `Jekyll::Tags::IncludeTag#blank?` method ([#2625]({{ site.repository }}/issues/2625)) -- Categories in the path are ignored ([#2633]({{ site.repository }}/issues/2633)) - -### Development Fixes -{: #development-fixes-v2-2-0} - -- Refactoring Errors & Requires of Third-Party stuff ([#2591]({{ site.repository }}/issues/2591)) -- Add further tests for categories ([#2584]({{ site.repository }}/issues/2584)) -- Proof site with html-proofer on change ([#2605]({{ site.repository }}/issues/2605)) -- Fix up bug in [#2605]({{ site.repository }}/issues/2605) which caused proofing the site not to function ([#2608]({{ site.repository }}/issues/2608)) -- Use `bundle exec` in `script/proof` ([#2610]({{ site.repository }}/issues/2610)) - -### Site Enhancements -{: #site-enhancements-v2-2-0} - -- Update Kramdown urls ([#2588]({{ site.repository }}/issues/2588)) -- Add `Jekyll::AutolinkEmail` and `Jekyll::GitMetadata` to the list of - third-party plugins ([#2596]({{ site.repository }}/issues/2596)) -- Fix a bunch of broken links in the site ([#2601]({{ site.repository }}/issues/2601)) -- Replace dead links with working links ([#2611]({{ site.repository }}/issues/2611)) -- Add jekyll-hook to deployment methods ([#2617]({{ site.repository }}/issues/2617)) -- Added kramdown-with-pygments plugin to the list of third-party plugins ([#2623]({{ site.repository }}/issues/2623)) -- Update outdated "Extras" page and remove duplicate documentation ([#2622]({{ site.repository }}/issues/2622)) -- Add co2 plugin to list of third-party plugins ([#2639]({{ site.repository }}/issues/2639)) -- Attempt to clarify the way Sass imports happen ([#2642]({{ site.repository }}/issues/2642)) - - -## 2.1.1 / 2014-07-01 -{: #v2-1-1} - -### Bug Fixes -{: #bug-fixes-v2-1-1} - -- Patch read vulnerabilities for data & confirm none for layouts ([#2563]({{ site.repository }}/issues/2563)) -- Update Maruku dependency to allow use of the latest version ([#2576]({{ site.repository }}/issues/2576)) -- Remove conditional assignment from document URL to prevent stale urls ([#2575]({{ site.repository }}/issues/2575)) - -### Site Enhancements -{: #site-enhancements-v2-1-1} - -- Add vertical margin to `highlight` to separate code blocks ([#2558]({{ site.repository }}/issues/2558)) -- Add `html_pages` to Variables docs ([#2567]({{ site.repository }}/issues/2567)) -- Fixed broken link to Permalinks page ([#2572]({{ site.repository }}/issues/2572)) -- Update link to Windows installation guide ([#2578]({{ site.repository }}/issues/2578)) - - -## 2.1.0 / 2014-06-28 -{: #v2-1-0} - -### Minor Enhancements -{: #minor-enhancements-v2-1-0} - -- Bump to the latest Liquid version, 2.6.1 ([#2495]({{ site.repository }}/issues/2495)) -- Add support for JSON files in the `_data` directory ([#2369]({{ site.repository }}/issues/2369)) -- Allow subclasses to override `EXCERPT_ATTRIBUTES_FOR_LIQUID` ([#2408]({{ site.repository }}/issues/2408)) -- Add `Jekyll.env` and `jekyll.environment` (the Liquid var) ([#2417]({{ site.repository }}/issues/2417)) -- Use `_config.yaml` or `_config.yml` (`.yml` takes precedence) ([#2406]({{ site.repository }}/issues/2406)) -- Override collection url template ([#2418]({{ site.repository }}/issues/2418)) -- Allow subdirectories in `_data` ([#2395]({{ site.repository }}/issues/2395)) -- Extract Pagination Generator into gem: `jekyll-paginate` ([#2455]({{ site.repository }}/issues/2455)) -- Utilize `date_to_rfc822` filter in site template ([#2437]({{ site.repository }}/issues/2437)) -- Add categories, last build datetime, and generator to site template - feed ([#2438]({{ site.repository }}/issues/2438)) -- Configurable, replaceable Logger-compliant logger ([#2444]({{ site.repository }}/issues/2444)) -- Extract `gist` tag into a separate gem ([#2469]({{ site.repository }}/issues/2469)) -- Add `collection` attribute to `Document#to_liquid` to access the - document's collection label. ([#2436]({{ site.repository }}/issues/2436)) -- Upgrade listen to `2.7.6 <= x < 3.0.0` ([#2492]({{ site.repository }}/issues/2492)) -- Allow configuration of different Twitter and GitHub usernames in site template ([#2485]({{ site.repository }}/issues/2485)) -- Bump Pygments to v0.6.0 ([#2504]({{ site.repository }}/issues/2504)) -- Front matter defaults for documents in collections ([#2419]({{ site.repository }}/issues/2419)) -- Include files with a url which ends in `/` in the `site.html_pages` list ([#2524]({{ site.repository }}/issues/2524)) -- Make `highlight` tag use `language-` prefix in CSS class ([#2511]({{ site.repository }}/issues/2511)) -- Lookup item property via `item#to_liquid` before `#data` or `#[]` in filters ([#2493]({{ site.repository }}/issues/2493)) -- Skip initial build of site on serve with flag ([#2477]({{ site.repository }}/issues/2477)) -- Add support for `hl_lines` in `highlight` tag ([#2532]({{ site.repository }}/issues/2532)) -- Spike out `--watch` flag into a separate gem ([#2550]({{ site.repository }}/issues/2550)) - -### Bug Fixes -{: #bug-fixes-v2-1-0} - -- Liquid `sort` filter should sort even if one of the values is `nil` ([#2345]({{ site.repository }}/issues/2345)) -- Remove padding on `pre code` in the site template CSS ([#2383]({{ site.repository }}/issues/2383)) -- Set `log_level` earlier to silence info level configuration output ([#2393]({{ site.repository }}/issues/2393)) -- Only list pages which have `title` in site template ([#2411]({{ site.repository }}/issues/2411)) -- Accept `Numeric` values for dates, not `Number` values ([#2377]({{ site.repository }}/issues/2377)) -- Prevent code from overflowing container in site template ([#2429]({{ site.repository }}/issues/2429)) -- Encode URLs in UTF-8 when escaping and unescaping ([#2420]({{ site.repository }}/issues/2420)) -- No Layouts or Liquid for Asset Files ([#2431]({{ site.repository }}/issues/2431)) -- Allow front matter defaults to set post categories ([#2373]({{ site.repository }}/issues/2373)) -- Fix command in subcommand deprecation warning ([#2457]({{ site.repository }}/issues/2457)) -- Keep all parent directories of files/dirs in `keep_files` ([#2458]({{ site.repository }}/issues/2458)) -- When using RedCarpet and Rouge without Rouge installed, fixed erroneous - error which stated that redcarpet was missing, not rouge. ([#2464]({{ site.repository }}/issues/2464)) -- Ignore *all* directories and files that merit it on auto-generation ([#2459]({{ site.repository }}/issues/2459)) -- Before copying file, explicitly remove the old one ([#2535]({{ site.repository }}/issues/2535)) -- Merge file system categories with categories from YAML. ([#2531]({{ site.repository }}/issues/2531)) -- Deep merge front matter defaults ([#2490]({{ site.repository }}/issues/2490)) -- Ensure exclude and include arrays are arrays of strings ([#2542]({{ site.repository }}/issues/2542)) -- Allow collections to have dots in their filenames ([#2552]({{ site.repository }}/issues/2552)) -- Collections shouldn't try to read in directories as files ([#2552]({{ site.repository }}/issues/2552)) -- Be quiet very quickly. ([#2520]({{ site.repository }}/issues/2520)) - -### Development Fixes -{: #development-fixes-v2-1-0} - -- Test Ruby 2.1.2 instead of 2.1.1 ([#2374]({{ site.repository }}/issues/2374)) -- Add test for sorting UTF-8 characters ([#2384]({{ site.repository }}/issues/2384)) -- Use `https` for GitHub links in documentation ([#2470]({{ site.repository }}/issues/2470)) -- Remove coverage reporting with Coveralls ([#2494]({{ site.repository }}/issues/2494)) -- Fix a bit of missing TomDoc to `Jekyll::Commands::Build#build` ([#2554]({{ site.repository }}/issues/2554)) - -### Site Enhancements -{: #site-enhancements-v2-1-0} - -- Set `timezone` to `America/Los_Angeles` ([#2394]({{ site.repository }}/issues/2394)) -- Improve JavaScript in `anchor_links.html` ([#2368]({{ site.repository }}/issues/2368)) -- Remove note on Quickstart page about default markdown converter ([#2387]({{ site.repository }}/issues/2387)) -- Remove broken link in extras.md to a Maruku fork ([#2401]({{ site.repository }}/issues/2401)) -- Update Font Awesome to v4.1.0. ([#2410]({{ site.repository }}/issues/2410)) -- Fix broken link on Installation page to Templates page ([#2421]({{ site.repository }}/issues/2421)) -- Prevent table from extending parent width in permalink style table ([#2424]({{ site.repository }}/issues/2424)) -- Add collections to info about pagination support ([#2389]({{ site.repository }}/issues/2389)) -- Add `jekyll_github_sample` plugin to list of third-party plugins ([#2463]({{ site.repository }}/issues/2463)) -- Clarify documentation around front matter defaults and add details - about defaults for collections. ([#2439]({{ site.repository }}/issues/2439)) -- Add Jekyll Project Version Tag to list of third-party plugins ([#2468]({{ site.repository }}/issues/2468)) -- Use `https` for GitHub links across whole site ([#2470]({{ site.repository }}/issues/2470)) -- Add StickerMule + Jekyll post ([#2476]({{ site.repository }}/issues/2476)) -- Add Jekyll Asset Pipeline Reborn to list of third-party plugins ([#2479]({{ site.repository }}/issues/2479)) -- Add link to jekyll-compress-html to list of third-party plugins ([#2514]({{ site.repository }}/issues/2514)) -- Add Piwigo Gallery to list of third-party plugins ([#2526]({{ site.repository }}/issues/2526)) -- Set `show_drafts` to `false` in default configuration listing ([#2536]({{ site.repository }}/issues/2536)) -- Provide an updated link for Windows installation instructions ([#2544]({{ site.repository }}/issues/2544)) -- Remove `url` from configuration docs ([#2547]({{ site.repository }}/issues/2547)) -- Documentation for Continuous Integration for your Jekyll Site ([#2432]({{ site.repository }}/issues/2432)) - - -## 2.0.3 / 2014-05-08 -{: #v2-0-3} - -### Bug Fixes -{: #bug-fixes-v2-0-3} - -- Properly prefix links in site template with URL or baseurl depending upon - need. ([#2319]({{ site.repository }}/issues/2319)) -- Update gist tag comments and error message to require username ([#2326]({{ site.repository }}/issues/2326)) -- Fix `permalink` setting in site template ([#2331]({{ site.repository }}/issues/2331)) -- Don't fail if any of the path objects are nil ([#2325]({{ site.repository }}/issues/2325)) -- Instantiate all descendants for converters and generators, not just - direct subclasses ([#2334]({{ site.repository }}/issues/2334)) -- Replace all instances of `site.name` with `site.title` in site template ([#2324]({{ site.repository }}/issues/2324)) -- `Jekyll::Filters#time` now accepts UNIX timestamps in string or number form ([#2339]({{ site.repository }}/issues/2339)) -- Use `item_property` for `where` filter so it doesn't break on collections ([#2359]({{ site.repository }}/issues/2359)) -- Rescue errors thrown so `--watch` doesn't fail ([#2364]({{ site.repository }}/issues/2364)) - -### Site Enhancements -{: #site-enhancements-v2-0-3} - -- Add missing "as" to assets docs page ([#2337]({{ site.repository }}/issues/2337)) -- Update docs to reflect new `baseurl` default ([#2341]({{ site.repository }}/issues/2341)) -- Add links to headers who have an ID. ([#2342]({{ site.repository }}/issues/2342)) -- Use symbol instead of HTML number in `upgrading.md` ([#2351]({{ site.repository }}/issues/2351)) -- Fix link to front matter defaults docs ([#2353]({{ site.repository }}/issues/2353)) -- Fix for `History.markdown` in order to fix history page in docs ([#2363]({{ site.repository }}/issues/2363)) - - -## 2.0.2 / 2014-05-07 -{: #v2-0-2} - -### Bug Fixes -{: #bug-fixes-v2-0-2} - -- Correct use of `url` and `baseurl` in the site template. ([#2317]({{ site.repository }}/issues/2317)) -- Default `baseurl` to `""` ([#2317]({{ site.repository }}/issues/2317)) - -### Site Enhancements -{: #site-enhancements-v2-0-2} - -- Correct docs for the `gist` plugin so it always includes the username. ([#2314]({{ site.repository }}/issues/2314)) -- Clarify new (defaults, `where` filter) features in docs ([#2316]({{ site.repository }}/issues/2316)) - - -## 2.0.1 / 2014-05-06 -{: #v2-0-1} - -### Bug Fixes -{: #bug-fixes-v2-0-1} - -- Require `kramdown` gem instead of `maruku` gem - - -## 2.0.0 / 2014-05-06 -{: #v2-0-0} - -### Major Enhancements -{: #major-enhancements-v2-0-0} -- Add "Collections" feature ([#2199]({{ site.repository }}/issues/2199)) -- Add gem-based plugin whitelist to safe mode ([#1657]({{ site.repository }}/issues/1657)) -- Replace the commander command line parser with a more robust - solution for our needs called `mercenary` ([#1706]({{ site.repository }}/issues/1706)) -- Remove support for Ruby 1.8.x ([#1780]({{ site.repository }}/issues/1780)) -- Move to jekyll/jekyll from mojombo/jekyll ([#1817]({{ site.repository }}/issues/1817)) -- Allow custom markdown processors ([#1872]({{ site.repository }}/issues/1872)) -- Provide support for the Rouge syntax highlighter ([#1859]({{ site.repository }}/issues/1859)) -- Provide support for Sass ([#1932]({{ site.repository }}/issues/1932)) -- Provide a 300% improvement when generating sites that use - `Post#next` or `Post#previous` ([#1983]({{ site.repository }}/issues/1983)) -- Provide support for CoffeeScript ([#1991]({{ site.repository }}/issues/1991)) -- Replace Maruku with Kramdown as Default Markdown Processor ([#1988]({{ site.repository }}/issues/1988)) -- Expose `site.static_files` to Liquid ([#2075]({{ site.repository }}/issues/2075)) -- Complete redesign of the template site generated by `jekyll new` ([#2050]({{ site.repository }}/issues/2050)) -- Update Listen from 1.x to 2.x ([#2097]({{ site.repository }}/issues/2097)) -- Front matter defaults ([#2205]({{ site.repository }}/issues/2205)) -- Deprecate `relative_permalinks` configuration option (default to `false`) ([#2307]({{ site.repository }}/issues/2307)) -- Exclude files based on prefix as well as `fnmatch?` ([#2303]({{ site.repository }}/issues/2303)) - -### Minor Enhancements -{: #minor-enhancements-v2-0-0} -- Move the EntryFilter class into the Jekyll module to avoid polluting the - global namespace ([#1800]({{ site.repository }}/issues/1800)) -- Add `group_by` Liquid filter create lists of items grouped by a common - property's value ([#1788]({{ site.repository }}/issues/1788)) -- Add support for Maruku's `fenced_code_blocks` option ([#1799]({{ site.repository }}/issues/1799)) -- Update Redcarpet dependency to ~> 3.0 ([#1815]({{ site.repository }}/issues/1815)) -- Automatically sort all pages by name ([#1848]({{ site.repository }}/issues/1848)) -- Better error message when time is not parseable ([#1847]({{ site.repository }}/issues/1847)) -- Allow `include` tag variable arguments to use filters ([#1841]({{ site.repository }}/issues/1841)) -- `post_url` tag should raise `ArgumentError` for invalid name ([#1825]({{ site.repository }}/issues/1825)) -- Bump dependency `mercenary` to `~> 0.2.0` ([#1879]({{ site.repository }}/issues/1879)) -- Bump dependency `safe_yaml` to `~> 1.0` ([#1886]({{ site.repository }}/issues/1886)) -- Allow sorting of content by custom properties ([#1849]({{ site.repository }}/issues/1849)) -- Add `--quiet` flag to silence output during build and serve ([#1898]({{ site.repository }}/issues/1898)) -- Add a `where` filter to filter arrays based on a key/value pair - ([#1875]({{ site.repository }}/issues/1875)) -- Route 404 errors to a custom 404 page in development ([#1899]({{ site.repository }}/issues/1899)) -- Excludes are now relative to the site source ([#1916]({{ site.repository }}/issues/1916)) -- Bring MIME Types file for `jekyll serve` to complete parity with GH Pages - servers ([#1993]({{ site.repository }}/issues/1993)) -- Adding Breakpoint to make new site template more responsive ([#2038]({{ site.repository }}/issues/2038)) -- Default to using the UTF-8 encoding when reading files. ([#2031]({{ site.repository }}/issues/2031)) -- Update Redcarpet dependency to ~> 3.1 ([#2044]({{ site.repository }}/issues/2044)) -- Remove support for Ruby 1.9.2 ([#2045]({{ site.repository }}/issues/2045)) -- Add `.mkdown` as valid Markdown extension ([#2048]({{ site.repository }}/issues/2048)) -- Add `index.xml` to the list of WEBrick directory index files ([#2041]({{ site.repository }}/issues/2041)) -- Make the `layouts` config key relative to CWD or to source ([#2058]({{ site.repository }}/issues/2058)) -- Update Kramdown to `~> 1.3` ([#1894]({{ site.repository }}/issues/1894)) -- Remove unnecessary references to `self` ([#2090]({{ site.repository }}/issues/2090)) -- Update to Mercenary v0.3.x ([#2085]({{ site.repository }}/issues/2085)) -- Ship Sass support as a separate gem ([#2098]({{ site.repository }}/issues/2098)) -- Extract core extensions into a Utils module ([#2112]({{ site.repository }}/issues/2112)) -- Refactor CLI & Commands For Greater Happiness ([#2143]({{ site.repository }}/issues/2143)) -- Provide useful error when Pygments returns `nil` and error out ([#2148]({{ site.repository }}/issues/2148)) -- Add support for unpublished drafts ([#2164]({{ site.repository }}/issues/2164)) -- Add `force_polling` option to the `serve` command ([#2165]({{ site.repository }}/issues/2165)) -- Clean up the `` in the site template ([#2186]({{ site.repository }}/issues/2186)) -- Permit YAML blocks to end with three dots to better conform with the - YAML spec ([#2110]({{ site.repository }}/issues/2110)) -- Use `File.exist?` instead of deprecated `File.exists?` ([#2214]({{ site.repository }}/issues/2214)) -- Require newline after start of YAML Front Matter header ([#2211]({{ site.repository }}/issues/2211)) -- Add the ability for pages to be marked as `published: false` ([#1492]({{ site.repository }}/issues/1492)) -- Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy - looking up of variable values in a Liquid context. ([#2253]({{ site.repository }}/issues/2253)) -- Remove literal lang name from class ([#2292]({{ site.repository }}/issues/2292)) -- Return `utf-8` encoding in header for webrick error page response ([#2289]({{ site.repository }}/issues/2289)) -- Make template site easier to customize ([#2268]({{ site.repository }}/issues/2268)) -- Add two-digit year to permalink template option ([#2301]({{ site.repository }}/issues/2301)) -- Add `site.documents` to Liquid payload (list of all docs) ([#2295]({{ site.repository }}/issues/2295)) -- Take into account missing values in the Liquid sort filter ([#2299]({{ site.repository }}/issues/2299)) - -### Bug Fixes -{: #bug-fixes-v2-0-0} -- Don't allow nil entries when loading posts ([#1796]({{ site.repository }}/issues/1796)) -- Remove the scrollbar that's always displayed in new sites generated - from the site template ([#1805]({{ site.repository }}/issues/1805)) -- Add `#path` to required methods in `Jekyll::Convertible` ([#1866]({{ site.repository }}/issues/1866)) -- Default Maruku fenced code blocks to ON for 2.0.0-dev ([#1831]({{ site.repository }}/issues/1831)) -- Change short opts for host and port for `jekyll docs` to be consistent with - other subcommands ([#1877]({{ site.repository }}/issues/1877)) -- Fix typos ([#1910]({{ site.repository }}/issues/1910)) -- Lock Maruku at 0.7.0 to prevent bugs caused by Maruku 0.7.1 ([#1958]({{ site.repository }}/issues/1958)) -- Fixes full path leak to source directory when using include tag ([#1951]({{ site.repository }}/issues/1951)) -- Don't generate pages that aren't being published ([#1931]({{ site.repository }}/issues/1931)) -- Use `SafeYAML.load` to avoid conflicts with other projects ([#1982]({{ site.repository }}/issues/1982)) -- Relative posts should never fail to build ([#1976]({{ site.repository }}/issues/1976)) -- Remove executable bits of non executable files ([#2056]({{ site.repository }}/issues/2056)) -- `#path` for a draft is now `_drafts` instead of `_posts` ([#2042]({{ site.repository }}/issues/2042)) -- Patch a couple show-stopping security vulnerabilities ([#1946]({{ site.repository }}/issues/1946)) -- Sanitize paths uniformly, in a Windows-friendly way ([#2065]({{ site.repository }}/issues/2065), [#2109]({{ site.repository }}/issues/2109)) -- Update gem build steps to work correctly on Windows ([#2118]({{ site.repository }}/issues/2118)) -- Remove obsolete `normalize_options` method call from `bin/jekyll` ([#2121]({{ site.repository }}/issues/2121)). -- Remove `+` characters from Pygments lexer names when adding as a CSS - class ([#994]({{ site.repository }}/issues/994)) -- Remove some code that caused Ruby interpreter warnings ([#2178]({{ site.repository }}/issues/2178)) -- Only strip the drive name if it begins the string ([#2175]({{ site.repository }}/issues/2175)) -- Remove default post with invalid date from site template ([#2200]({{ site.repository }}/issues/2200)) -- Fix `Post#url` and `Page#url` escape ([#1568]({{ site.repository }}/issues/1568)) -- Strip newlines from the {% raw %}`{% highlight %}`{% endraw %} block content ([#1823]({{ site.repository }}/issues/1823)) -- Load in `rouge` only when it's been requested as the highlighter ([#2189]({{ site.repository }}/issues/2189)) -- Convert input to string before XML escaping (`xml_escape` liquid filter) ([#2244]({{ site.repository }}/issues/2244)) -- Modify configuration key for Collections and reset properly. ([#2238]({{ site.repository }}/issues/2238)) -- Avoid duplicated output using `highlight` tag ([#2264]({{ site.repository }}/issues/2264)) -- Only use Jekyll.logger for output ([#2307]({{ site.repository }}/issues/2307)) -- Close the file descriptor in `has_yaml_header?` ([#2310]({{ site.repository }}/issues/2310)) -- Add `output` to `Document` liquid output hash ([#2309]({{ site.repository }}/issues/2309)) - -### Development Fixes -{: #development-fixes-v2-0-0} -- Add a link to the site in the README.md file ([#1795]({{ site.repository }}/issues/1795)) -- Add in History and site changes from `v1-stable` branch ([#1836]({{ site.repository }}/issues/1836)) -- Testing additions on the Excerpt class ([#1893]({{ site.repository }}/issues/1893)) -- Fix the `highlight` tag feature ([#1859]({{ site.repository }}/issues/1859)) -- Test Jekyll under Ruby 2.1.0 ([#1900]({{ site.repository }}/issues/1900)) -- Add script/cibuild for fun and profit ([#1912]({{ site.repository }}/issues/1912)) -- Use `Forwardable` for delegation between `Excerpt` and `Post` - ([#1927]({{ site.repository }}/issues/1927)) -- Rename `read_things` to `read_content` ([#1928]({{ site.repository }}/issues/1928)) -- Add `script/branding` script for ASCII art lovin' ([#1936]({{ site.repository }}/issues/1936)) -- Update the README to reflect the repo move ([#1943]({{ site.repository }}/issues/1943)) -- Add the project vision to the README ([#1935]({{ site.repository }}/issues/1935)) -- Speed up Travis CI builds by using Rebund ([#1985]({{ site.repository }}/issues/1985)) -- Use Yarp as a Gem proxy for Travis CI ([#1984]({{ site.repository }}/issues/1984)) -- Remove Yarp as a Gem proxy for Travis CI ([#2004]({{ site.repository }}/issues/2004)) -- Move the reading of layouts into its own class ([#2020]({{ site.repository }}/issues/2020)) -- Test Sass import ([#2009]({{ site.repository }}/issues/2009)) -- Switch Maruku and Kramdown in lists of Runtime vs. Development dependencies ([#2049]({{ site.repository }}/issues/2049)) -- Clean up the gemspec for the project ([#2095]({{ site.repository }}/issues/2095)) -- Add Japanese translation of README and CONTRIBUTING docs. ([#2081]({{ site.repository }}/issues/2081)) -- Re-align the tables in Cucumber ([#2108]({{ site.repository }}/issues/2108)) -- Trim trailing spaces and convert tabs to spaces ([#2122]({{ site.repository }}/issues/2122)) -- Fix the failing Travis scenarios due to Cucumber issues ([#2155]({{ site.repository }}/issues/2155)) -- Wrap `bundle install` in `travis_retry` to retry when RubyGems fails ([#2160]({{ site.repository }}/issues/2160)) -- Refactor tags and categories ([#1639]({{ site.repository }}/issues/1639)) -- Extract plugin management into its own class ([#2197]({{ site.repository }}/issues/2197)) -- Add missing tests for `Command` ([#2216]({{ site.repository }}/issues/2216)) -- Update `rr` link in CONTRIBUTING doc ([#2247]({{ site.repository }}/issues/2247)) -- Streamline Cucumber execution of `jekyll` subcommands ([#2258]({{ site.repository }}/issues/2258)) -- Refactor `Commands::Serve`. ([#2269]({{ site.repository }}/issues/2269)) -- Refactor `highlight` tag ([#2154]({{ site.repository }}/issues/2154)) -- Update `Util` hash functions with latest from Rails ([#2273]({{ site.repository }}/issues/2273)) -- Workaround for Travis bug ([#2290]({{ site.repository }}/issues/2290)) - -### Site Enhancements -{: #site-enhancements-v2-0-0} -- Document Kramdown's GFM parser option ([#1791]({{ site.repository }}/issues/1791)) -- Move CSS to includes & update normalize.css to v2.1.3 ([#1787]({{ site.repository }}/issues/1787)) -- Minify CSS only in production ([#1803]({{ site.repository }}/issues/1803)) -- Fix broken link to installation of Ruby on Mountain Lion blog post on - Troubleshooting docs page ([#1797]({{ site.repository }}/issues/1797)) -- Fix issues with 1.4.1 release blog post ([#1804]({{ site.repository }}/issues/1804)) -- Add note about deploying to OpenShift ([#1812]({{ site.repository }}/issues/1812)) -- Collect all Windows-related docs onto one page ([#1818]({{ site.repository }}/issues/1818)) -- Fixed typo in datafiles doc page ([#1854]({{ site.repository }}/issues/1854)) -- Clarify how to access `site` in docs ([#1864]({{ site.repository }}/issues/1864)) -- Add closing `` tag to `context.registers[:site]` note ([#1867]({{ site.repository }}/issues/1867)) -- Fix link to [@mojombo](https://github.com/mojombo)'s site source ([#1897]({{ site.repository }}/issues/1897)) -- Add `paginate: nil` to default configuration in docs ([#1896]({{ site.repository }}/issues/1896)) -- Add link to our License in the site footer ([#1889]({{ site.repository }}/issues/1889)) -- Add a charset note in "Writing Posts" doc page ([#1902]({{ site.repository }}/issues/1902)) -- Disallow selection of path and prompt in bash examples -- Add jekyll-compass to the plugin list ([#1923]({{ site.repository }}/issues/1923)) -- Add note in Posts docs about stripping `

    ` tags from excerpt ([#1933]({{ site.repository }}/issues/1933)) -- Add additional info about the new exclude behavior ([#1938]({{ site.repository }}/issues/1938)) -- Linkify 'awesome contributors' to point to the contributors graph on - GitHub ([#1940]({{ site.repository }}/issues/1940)) -- Update `docs/sites.md` link to GitHub Training materials ([#1949]({{ site.repository }}/issues/1949)) -- Update `master` with the release info from 1.4.3 ([#1947]({{ site.repository }}/issues/1947)) -- Define docs nav in datafile ([#1953]({{ site.repository }}/issues/1953)) -- Clarify the docs around the naming convention for posts ([#1971]({{ site.repository }}/issues/1971)) -- Add missing `next` and `previous` docs for post layouts and templates ([#1970]({{ site.repository }}/issues/1970)) -- Add note to `Writing posts` page about how to strip html from excerpt ([#1962]({{ site.repository }}/issues/1962)) -- Add `jekyll-humanize` plugin to plugin list ([#1998]({{ site.repository }}/issues/1998)) -- Add `jekyll-font-awesome` plugin to plugin list ([#1999]({{ site.repository }}/issues/1999)) -- Add `sublime-jekyll` to list of Editor plugins ([#2001]({{ site.repository }}/issues/2001)) -- Add `vim-jekyll` to the list of Editor plugins ([#2005]({{ site.repository }}/issues/2005)) -- Fix non-semantic nesting of `p` tags in `news_item` layout ([#2013]({{ site.repository }}/issues/2013)) -- Document destination folder cleaning ([#2016]({{ site.repository }}/issues/2016)) -- Updated instructions for NearlyFreeSpeech.NET installation ([#2015]({{ site.repository }}/issues/2015)) -- Update link to rack-jekyll on "Deployment Methods" page ([#2047]({{ site.repository }}/issues/2047)) -- Fix typo in /docs/configuration ([#2073]({{ site.repository }}/issues/2073)) -- Fix count in docs for `site.static_files` ([#2077]({{ site.repository }}/issues/2077)) -- Update configuration docs to indicate utf-8 is the default for 2.0.0 - and ASCII for 1.9.3 ([#2074]({{ site.repository }}/issues/2074)) -- Add info about unreleased feature to the site ([#2061]({{ site.repository }}/issues/2061)) -- Add whitespace to liquid example in GitHub Pages docs ([#2084]({{ site.repository }}/issues/2084)) -- Clarify the way Sass and CoffeeScript files are read in and output ([#2067]({{ site.repository }}/issues/2067)) -- Add lyche gallery tag plugin link to list of plugins ([#2094]({{ site.repository }}/issues/2094)) -- Add Jekyll Pages Directory plugin to list of plugins ([#2096]({{ site.repository }}/issues/2096)) -- Update Configuration docs page with new markdown extension ([#2102]({{ site.repository }}/issues/2102)) -- Add `jekyll-image-set` to the list of third-party plugins ([#2105]({{ site.repository }}/issues/2105)) -- Losslessly compress images ([#2128]({{ site.repository }}/issues/2128)) -- Update normalize.css to 3.0.0 ([#2126]({{ site.repository }}/issues/2126)) -- Update modernizr to v2.7.1 ([#2129]({{ site.repository }}/issues/2129)) -- Add `jekyll-ordinal` to list of third-party plugins ([#2150]({{ site.repository }}/issues/2150)) -- Add `jekyll_figure` to list of third-party plugins ([#2158]({{ site.repository }}/issues/2158)) -- Clarify the documentation for safe mode ([#2163]({{ site.repository }}/issues/2163)) -- Some HTML tidying ([#2130]({{ site.repository }}/issues/2130)) -- Remove modernizr and use html5shiv.js directly for IE less than v9 ([#2131]({{ site.repository }}/issues/2131)) -- Remove unused images ([#2187]({{ site.repository }}/issues/2187)) -- Use `array_to_sentence_string` filter when outputting news item - categories ([#2191]({{ site.repository }}/issues/2191)) -- Add link to Help repo in primary navigation bar ([#2177]({{ site.repository }}/issues/2177)) -- Switch to using an ico file for the shortcut icon ([#2193]({{ site.repository }}/issues/2193)) -- Use numbers to specify font weights and only bring in font weights used ([#2185]({{ site.repository }}/issues/2185)) -- Add a link to the list of all tz database time zones ([#1824]({{ site.repository }}/issues/1824)) -- Clean-up and improve documentation `feed.xml` ([#2192]({{ site.repository }}/issues/2192)) -- Remove duplicate entry in list of third-party plugins ([#2206]({{ site.repository }}/issues/2206)) -- Reduce the whitespace in the favicon. ([#2213]({{ site.repository }}/issues/2213)) -- Add `jekyll-page-collections` to list of third-party plugins ([#2215]({{ site.repository }}/issues/2215)) -- Add a cross-reference about `post_url` ([#2243]({{ site.repository }}/issues/2243)) -- Add `jekyll-live-tiles` to list of third-party plugins ([#2250]({{ site.repository }}/issues/2250)) -- Fixed broken link to GitHub training material site source ([#2257]({{ site.repository }}/issues/2257)) -- Update link to help repo, now called `jekyll-help` ([#2277]({{ site.repository }}/issues/2277)) -- Fix capitalization of 'Jekyll' on Deployment Methods page ([#2291]({{ site.repository }}/issues/2291)) -- Include plugins by sonnym in list of third-party plugins ([#2297]({{ site.repository }}/issues/2297)) -- Add deprecated articles keeper filter to list of third-party plugins ([#2300]({{ site.repository }}/issues/2300)) -- Simplify and improve our CSS. ([#2127]({{ site.repository }}/issues/2127)) -- Use black text color for the mobile navbar ([#2306]({{ site.repository }}/issues/2306)) -- Use the built in date filter and `site.time` for the copyright year. ([#2305]({{ site.repository }}/issues/2305)) -- Update html5shiv to v3.7.2 ([#2304]({{ site.repository }}/issues/2304)) -- Add 2.0.0 release post ([#2298]({{ site.repository }}/issues/2298)) -- Add docs for custom markdown processors ([#2298]({{ site.repository }}/issues/2298)) -- Add docs for `where` and `group_by` Liquid filters ([#2298]({{ site.repository }}/issues/2298)) -- Remove notes in docs for unreleased features ([#2309]({{ site.repository }}/issues/2309)) - - -## 1.5.1 / 2014-03-27 -{: #v1-5-1} - -### Bug Fixes -{: #bug-fixes-v1-5-1} - -- Only strip the drive name if it begins the string ([#2176]({{ site.repository }}/issues/2176)) - - -## 1.5.0 / 2014-03-24 -{: #v1-5-0} - -### Minor Enhancements -{: #minor-enhancements-v1-5-0} - -- Loosen `safe_yaml` dependency to `~> 1.0` ([#2167]({{ site.repository }}/issues/2167)) -- Bump `safe_yaml` dependency to `~> 1.0.0` ([#1942]({{ site.repository }}/issues/1942)) - -### Bug Fixes -{: #bug-fixes-v1-5-0} - -- Fix issue where filesystem traversal restriction broke Windows ([#2167]({{ site.repository }}/issues/2167)) -- Lock `maruku` at `0.7.0` ([#2167]({{ site.repository }}/issues/2167)) - -### Development Fixes -{: #development-fixes-v1-5-0} - -- Lock `cucumber` at `1.3.11` ([#2167]({{ site.repository }}/issues/2167)) - - -## 1.4.3 / 2014-01-13 -{: #v1-4-3} - -### Bug Fixes -{: #bug-fixes-v1-4-3} -- Patch show-stopping security vulnerabilities ([#1944]({{ site.repository }}/issues/1944)) - - -## 1.4.2 / 2013-12-16 -{: #v1-4-2} - -### Bug Fixes -{: #bug-fixes-v1-4-2} -- Turn on Maruku fenced code blocks by default ([#1830]({{ site.repository }}/issues/1830)) - - -## 1.4.1 / 2013-12-09 -{: #v1-4-1} - -### Bug Fixes -{: #bug-fixes-v1-4-1} -- Don't allow nil entries when loading posts ([#1796]({{ site.repository }}/issues/1796)) - - -## 1.4.0 / 2013-12-07 -{: #v1-4-0} - -### Major Enhancements -{: #major-enhancements-v1-4-0} -- Add support for TOML config files ([#1765]({{ site.repository }}/issues/1765)) - -### Minor Enhancements -{: #minor-enhancements-v1-4-0} -- Sort plugins as a way to establish a load order ([#1682]({{ site.repository }}/issues/1682)) -- Update Maruku to 0.7.0 ([#1775]({{ site.repository }}/issues/1775)) - -### Bug Fixes -{: #bug-fixes-v1-4-0} -- Add a space between two words in a Pagination warning message ([#1769]({{ site.repository }}/issues/1769)) -- Upgrade `toml` gem to `v0.1.0` to maintain compat with Ruby 1.8.7 ([#1778]({{ site.repository }}/issues/1778)) - -### Development Fixes -{: #development-fixes-v1-4-0} -- Remove some whitespace in the code ([#1755]({{ site.repository }}/issues/1755)) -- Remove some duplication in the reading of posts and drafts ([#1779]({{ site.repository }}/issues/1779)) - -### Site Enhancements -{: #site-enhancements-v1-4-0} -- Fixed case of a word in the Jekyll v1.3.0 release post ([#1762]({{ site.repository }}/issues/1762)) -- Fixed the mime type for the favicon ([#1772]({{ site.repository }}/issues/1772)) - - -## 1.3.1 / 2013-11-26 -{: #v1-3-1} - -### Minor Enhancements -{: #minor-enhancements-v1-3-1} -- Add a `--prefix` option to passthrough for the importers ([#1669]({{ site.repository }}/issues/1669)) -- Push the paginator plugin lower in the plugin priority order so - other plugins run before it ([#1759]({{ site.repository }}/issues/1759)) - -### Bug Fixes -{: #bug-fixes-v1-3-1} -- Fix the include tag when ran in a loop ([#1726]({{ site.repository }}/issues/1726)) -- Fix errors when using `--watch` on 1.8.7 ([#1730]({{ site.repository }}/issues/1730)) -- Specify where the include is called from if an included file is - missing ([#1746]({{ site.repository }}/issues/1746)) - -### Development Fixes -{: #development-fixes-v1-3-1} -- Extract `Site#filter_entries` into its own object ([#1697]({{ site.repository }}/issues/1697)) -- Enable Travis' bundle caching ([#1734]({{ site.repository }}/issues/1734)) -- Remove trailing whitespace in some files ([#1736]({{ site.repository }}/issues/1736)) -- Fix a duplicate test name ([#1754]({{ site.repository }}/issues/1754)) - -### Site Enhancements -{: #site-enhancements-v1-3-1} -- Update link to example Rakefile to point to specific commit ([#1741]({{ site.repository }}/issues/1741)) -- Fix drafts docs to indicate that draft time is based on file modification - time, not `Time.now` ([#1695]({{ site.repository }}/issues/1695)) -- Add `jekyll-monthly-archive-plugin` and `jekyll-category-archive-plugin` to - list of third-party plugins ([#1693]({{ site.repository }}/issues/1693)) -- Add `jekyll-asset-path-plugin` to list of third-party plugins ([#1670]({{ site.repository }}/issues/1670)) -- Add `emoji-for-jekyll` to list of third-part plugins ([#1708]({{ site.repository }}/issues/1708)) -- Fix previous section link on plugins page to point to pagination page ([#1707]({{ site.repository }}/issues/1707)) -- Add `org-mode` converter plugin to third-party plugins ([#1711]({{ site.repository }}/issues/1711)) -- Point "Blog migrations" page to http://import.jekyllrb.com ([#1732]({{ site.repository }}/issues/1732)) -- Add docs for `post_url` when posts are in subdirectories ([#1718]({{ site.repository }}/issues/1718)) -- Update the docs to point to `example.com` ([#1448]({{ site.repository }}/issues/1448)) - - -## 1.3.0 / 2013-11-04 -{: #v1-3-0} - -### Major Enhancements -{: #major-enhancements-v1-3-0} -- Add support for adding data as YAML files under a site's `_data` - directory ([#1003]({{ site.repository }}/issues/1003)) -- Allow variables to be used with `include` tags ([#1495]({{ site.repository }}/issues/1495)) -- Allow using gems for plugin management ([#1557]({{ site.repository }}/issues/1557)) - -### Minor Enhancements -{: #minor-enhancements-v1-3-0} -- Decrease the specificity in the site template CSS ([#1574]({{ site.repository }}/issues/1574)) -- Add `encoding` configuration option ([#1449]({{ site.repository }}/issues/1449)) -- Provide better error handling for Jekyll's custom Liquid tags - ([#1514]({{ site.repository }}/issues/1514)) -- If an included file causes a Liquid error, add the path to the - include file that caused the error to the error message ([#1596]({{ site.repository }}/issues/1596)) -- If a layout causes a Liquid error, change the error message so that - we know it comes from the layout ([#1601]({{ site.repository }}/issues/1601)) -- Update Kramdown dependency to `~> 1.2` ([#1610]({{ site.repository }}/issues/1610)) -- Update `safe_yaml` dependency to `~> 0.9.7` ([#1602]({{ site.repository }}/issues/1602)) -- Allow layouts to be in subfolders like includes ([#1622]({{ site.repository }}/issues/1622)) -- Switch to listen for site watching while serving ([#1589]({{ site.repository }}/issues/1589)) -- Add a `json` liquid filter to be used in sites ([#1651]({{ site.repository }}/issues/1651)) -- Point people to the migration docs when the `jekyll-import` gem is - missing ([#1662]({{ site.repository }}/issues/1662)) - -### Bug Fixes -{: #bug-fixes-v1-3-0} -- Fix up matching against source and destination when the two - locations are similar ([#1556]({{ site.repository }}/issues/1556)) -- Fix the missing `pathname` require in certain cases ([#1255]({{ site.repository }}/issues/1255)) -- Use `+` instead of `Array#concat` when building `Post` attribute list ([#1571]({{ site.repository }}/issues/1571)) -- Print server address when launching a server ([#1586]({{ site.repository }}/issues/1586)) -- Downgrade to Maruku `~> 0.6.0` in order to avoid changes in rendering ([#1598]({{ site.repository }}/issues/1598)) -- Fix error with failing include tag when variable was file name ([#1613]({{ site.repository }}/issues/1613)) -- Downcase lexers before passing them to pygments ([#1615]({{ site.repository }}/issues/1615)) -- Capitalize the short verbose switch because it conflicts with the - built-in Commander switch ([#1660]({{ site.repository }}/issues/1660)) -- Fix compatibility with 1.8.x ([#1665]({{ site.repository }}/issues/1665)) -- Fix an error with the new file watching code due to library version - incompatibilities ([#1687]({{ site.repository }}/issues/1687)) - -### Development Fixes -{: #development-fixes-v1-3-0} -- Add coverage reporting with Coveralls ([#1539]({{ site.repository }}/issues/1539)) -- Refactor the Liquid `include` tag ([#1490]({{ site.repository }}/issues/1490)) -- Update launchy dependency to `~> 2.3` ([#1608]({{ site.repository }}/issues/1608)) -- Update rr dependency to `~> 1.1` ([#1604]({{ site.repository }}/issues/1604)) -- Update cucumber dependency to `~> 1.3` ([#1607]({{ site.repository }}/issues/1607)) -- Update coveralls dependency to `~> 0.7.0` ([#1606]({{ site.repository }}/issues/1606)) -- Update rake dependency to `~> 10.1` ([#1603]({{ site.repository }}/issues/1603)) -- Clean up `site.rb` comments to be more concise/uniform ([#1616]({{ site.repository }}/issues/1616)) -- Use the master branch for the build badge in the readme ([#1636]({{ site.repository }}/issues/1636)) -- Refactor Site#render ([#1638]({{ site.repository }}/issues/1638)) -- Remove duplication in command line options ([#1637]({{ site.repository }}/issues/1637)) -- Add tests for all the coderay options ([#1543]({{ site.repository }}/issues/1543)) -- Improve some of the Cucumber test code ([#1493]({{ site.repository }}/issues/1493)) -- Improve comparisons of timestamps by ignoring the seconds ([#1582]({{ site.repository }}/issues/1582)) - -### Site Enhancements -{: #site-enhancements-v1-3-0} -- Fix params for `JekyllImport::WordPress.process` arguments ([#1554]({{ site.repository }}/issues/1554)) -- Add `jekyll-suggested-tweet` to list of third-party plugins ([#1555]({{ site.repository }}/issues/1555)) -- Link to Liquid's docs for tags and filters ([#1553]({{ site.repository }}/issues/1553)) -- Add note about installing Xcode on the Mac in the Installation docs ([#1561]({{ site.repository }}/issues/1561)) -- Simplify/generalize pagination docs ([#1577]({{ site.repository }}/issues/1577)) -- Add documentation for the new data sources feature ([#1503]({{ site.repository }}/issues/1503)) -- Add more information on how to create generators ([#1590]({{ site.repository }}/issues/1590), [#1592]({{ site.repository }}/issues/1592)) -- Improve the instructions for mimicking GitHub Flavored Markdown - ([#1614]({{ site.repository }}/issues/1614)) -- Add `jekyll-import` warning note of missing dependencies ([#1626]({{ site.repository }}/issues/1626)) -- Fix grammar in the Usage section ([#1635]({{ site.repository }}/issues/1635)) -- Add documentation for the use of gems as plugins ([#1656]({{ site.repository }}/issues/1656)) -- Document the existence of a few additional plugins ([#1405]({{ site.repository }}/issues/1405)) -- Document that the `date_to_string` always returns a two digit day ([#1663]({{ site.repository }}/issues/1663)) -- Fix navigation in the "Working with Drafts" page ([#1667]({{ site.repository }}/issues/1667)) -- Fix an error with the data documentation ([#1691]({{ site.repository }}/issues/1691)) - - -## 1.2.1 / 2013-09-14 -{: #v1-2-1} - -### Minor Enhancements -{: #minor-enhancements-v1-2-1} -- Print better messages for detached server. Mute output on detach. ([#1518]({{ site.repository }}/issues/1518)) -- Disable reverse lookup when running `jekyll serve` ([#1363]({{ site.repository }}/issues/1363)) -- Upgrade RedCarpet dependency to `~> 2.3.0` ([#1515]({{ site.repository }}/issues/1515)) -- Upgrade to Liquid `>= 2.5.2, < 2.6` ([#1536]({{ site.repository }}/issues/1536)) - -### Bug Fixes -{: #bug-fixes-v1-2-1} -- Fix file discrepancy in gemspec ([#1522]({{ site.repository }}/issues/1522)) -- Force rendering of Include tag ([#1525]({{ site.repository }}/issues/1525)) - -### Development Fixes -{: #development-fixes-v1-2-1} -- Add a rake task to generate a new release post ([#1404]({{ site.repository }}/issues/1404)) -- Mute LSI output in tests ([#1531]({{ site.repository }}/issues/1531)) -- Update contributor documentation ([#1537]({{ site.repository }}/issues/1537)) - -### Site Enhancements -{: #site-enhancements-v1-2-1} -- Fix a couple of validation errors on the site ([#1511]({{ site.repository }}/issues/1511)) -- Make navigation menus reusable ([#1507]({{ site.repository }}/issues/1507)) -- Fix link to History page from Release v1.2.0 notes post. -- Fix markup in History file for command line options ([#1512]({{ site.repository }}/issues/1512)) -- Expand 1.2 release post title to 1.2.0 ([#1516]({{ site.repository }}/issues/1516)) - - -## 1.2.0 / 2013-09-06 -{: #v1-2-0} - -### Major Enhancements -{: #major-enhancements-v1-2-0} -- Disable automatically-generated excerpts when `excerpt_separator` is `""`. ([#1386]({{ site.repository }}/issues/1386)) -- Add checking for URL conflicts when running `jekyll doctor` ([#1389]({{ site.repository }}/issues/1389)) - -### Minor Enhancements -{: #minor-enhancements-v1-2-0} -- Catch and fix invalid `paginate` values ([#1390]({{ site.repository }}/issues/1390)) -- Remove superfluous `div.container` from the default html template for - `jekyll new` ([#1315]({{ site.repository }}/issues/1315)) -- Add `-D` short-form switch for the drafts option ([#1394]({{ site.repository }}/issues/1394)) -- Update the links in the site template for Twitter and GitHub ([#1400]({{ site.repository }}/issues/1400)) -- Update dummy email address to example.com domain ([#1408]({{ site.repository }}/issues/1408)) -- Update normalize.css to v2.1.2 and minify; add rake task to update - normalize.css with greater ease. ([#1430]({{ site.repository }}/issues/1430)) -- Add the ability to detach the server ran by `jekyll serve` from it's - controlling terminal ([#1443]({{ site.repository }}/issues/1443)) -- Improve permalink generation for URLs with special characters ([#944]({{ site.repository }}/issues/944)) -- Expose the current Jekyll version to posts and pages via a new - `jekyll.version` variable ([#1481]({{ site.repository }}/issues/1481)) - -### Bug Fixes -{: #bug-fixes-v1-2-0} -- Markdown extension matching matches only exact matches ([#1382]({{ site.repository }}/issues/1382)) -- Fixed NoMethodError when message passed to `Stevenson#message` is nil ([#1388]({{ site.repository }}/issues/1388)) -- Use binary mode when writing file ([#1364]({{ site.repository }}/issues/1364)) -- Fix 'undefined method `encoding` for "mailto"' errors w/ Ruby 1.8 and - Kramdown > 0.14.0 ([#1397]({{ site.repository }}/issues/1397)) -- Do not force the permalink to be a dir if it ends on .html ([#963]({{ site.repository }}/issues/963)) -- When a Liquid Exception is caught, show the full path rel. to site source ([#1415]({{ site.repository }}/issues/1415)) -- Properly read in the config options when serving the docs locally - ([#1444]({{ site.repository }}/issues/1444)) -- Fixed `--layouts` option for `build` and `serve` commands ([#1458]({{ site.repository }}/issues/1458)) -- Remove kramdown as a runtime dependency since it's optional ([#1498]({{ site.repository }}/issues/1498)) -- Provide proper error handling for invalid file names in the include - tag ([#1494]({{ site.repository }}/issues/1494)) - -### Development Fixes -{: #development-fixes-v1-2-0} -- Remove redundant argument to - Jekyll::Commands::New#scaffold_post_content ([#1356]({{ site.repository }}/issues/1356)) -- Add new dependencies to the README ([#1360]({{ site.repository }}/issues/1360)) -- Fix link to contributing page in README ([#1424]({{ site.repository }}/issues/1424)) -- Update TomDoc in Pager#initialize to match params ([#1441]({{ site.repository }}/issues/1441)) -- Refactor `Site#cleanup` into `Jekyll::Site::Cleaner` class ([#1429]({{ site.repository }}/issues/1429)) -- Several other small minor refactorings ([#1341]({{ site.repository }}/issues/1341)) -- Ignore `_site` in jekyllrb.com deploy ([#1480]({{ site.repository }}/issues/1480)) -- Add Gem version and dependency badge to README ([#1497]({{ site.repository }}/issues/1497)) - -### Site Enhancements -{: #site-enhancements-v1-2-0} -- Add info about new releases ([#1353]({{ site.repository }}/issues/1353)) -- Update plugin list with jekyll-rss plugin ([#1354]({{ site.repository }}/issues/1354)) -- Update the site list page with Ruby's official site ([#1358]({{ site.repository }}/issues/1358)) -- Add `jekyll-ditaa` to list of third-party plugins ([#1370]({{ site.repository }}/issues/1370)) -- Add `postfiles` to list of third-party plugins ([#1373]({{ site.repository }}/issues/1373)) -- For internal links, use full path including trailing `/` ([#1411]({{ site.repository }}/issues/1411)) -- Use curly apostrophes in the docs ([#1419]({{ site.repository }}/issues/1419)) -- Update the docs for Redcarpet in Jekyll ([#1418]({{ site.repository }}/issues/1418)) -- Add `pluralize` and `reading_time` filters to docs ([#1439]({{ site.repository }}/issues/1439)) -- Fix markup for the Kramdown options ([#1445]({{ site.repository }}/issues/1445)) -- Fix typos in the History file ([#1454]({{ site.repository }}/issues/1454)) -- Add trailing slash to site's post URL ([#1462]({{ site.repository }}/issues/1462)) -- Clarify that `--config` will take multiple files ([#1474]({{ site.repository }}/issues/1474)) -- Fix docs/templates.md private gist example ([#1477]({{ site.repository }}/issues/1477)) -- Use `site.repository` for Jekyll's GitHub URL ([#1463]({{ site.repository }}/issues/1463)) -- Add `jekyll-pageless-redirects` to list of third-party plugins ([#1486]({{ site.repository }}/issues/1486)) -- Clarify that `date_to_xmlschema` returns an ISO 8601 string ([#1488]({{ site.repository }}/issues/1488)) -- Add `jekyll-good-include` to list of third-party plugins ([#1491]({{ site.repository }}/issues/1491)) -- XML escape the blog post title in our feed ([#1501]({{ site.repository }}/issues/1501)) -- Add `jekyll-toc-generator` to list of third-party plugins ([#1506]({{ site.repository }}/issues/1506)) - - -## 1.1.2 / 2013-07-25 -{: #v1-1-2} - -### Bug Fixes -{: #bug-fixes-v1-1-2} -- Require Liquid 2.5.1 ([#1349]({{ site.repository }}/issues/1349)) - - -## 1.1.1 / 2013-07-24 -{: #v1-1-1} - -### Minor Enhancements -{: #minor-enhancements-v1-1-1} -- Remove superfluous `table` selector from main.css in `jekyll new` template ([#1328]({{ site.repository }}/issues/1328)) -- Abort with non-zero exit codes ([#1338]({{ site.repository }}/issues/1338)) - -### Bug Fixes -{: #bug-fixes-v1-1-1} -- Fix up the rendering of excerpts ([#1339]({{ site.repository }}/issues/1339)) - -### Site Enhancements -{: #site-enhancements-v1-1-1} -- Add Jekyll Image Tag to the plugins list ([#1306]({{ site.repository }}/issues/1306)) -- Remove erroneous statement that `site.pages` are sorted alphabetically. -- Add info about the `_drafts` directory to the directory structure - docs ([#1320]({{ site.repository }}/issues/1320)) -- Improve the layout of the plugin listing by organizing it into - categories ([#1310]({{ site.repository }}/issues/1310)) -- Add generator-jekyllrb and grunt-jekyll to plugins page ([#1330]({{ site.repository }}/issues/1330)) -- Mention Kramdown as option for markdown parser on Extras page ([#1318]({{ site.repository }}/issues/1318)) -- Update Quick-Start page to include reminder that all requirements must be installed ([#1327]({{ site.repository }}/issues/1327)) -- Change filename in `include` example to an HTML file so as not to indicate that Jekyll - will automatically convert them. ([#1303]({{ site.repository }}/issues/1303)) -- Add an RSS feed for commits to Jekyll ([#1343]({{ site.repository }}/issues/1343)) - - -## 1.1.0 / 2013-07-14 -{: #v1-1-0} - -### Major Enhancements -{: #major-enhancements-v1-1-0} -- Add `docs` subcommand to read Jekyll's docs when offline. ([#1046]({{ site.repository }}/issues/1046)) -- Support passing parameters to templates in `include` tag ([#1204]({{ site.repository }}/issues/1204)) -- Add support for Liquid tags to post excerpts ([#1302]({{ site.repository }}/issues/1302)) - -### Minor Enhancements -{: #minor-enhancements-v1-1-0} -- Search the hierarchy of pagination path up to site root to determine template page for - pagination. ([#1198]({{ site.repository }}/issues/1198)) -- Add the ability to generate a new Jekyll site without a template ([#1171]({{ site.repository }}/issues/1171)) -- Use redcarpet as the default markdown engine in newly generated - sites ([#1245]({{ site.repository }}/issues/1245), [#1247]({{ site.repository }}/issues/1247)) -- Add `redcarpet` as a runtime dependency so `jekyll build` works out-of-the-box for new - sites. ([#1247]({{ site.repository }}/issues/1247)) -- In the generated site, remove files that will be replaced by a - directory ([#1118]({{ site.repository }}/issues/1118)) -- Fail loudly if a user-specified configuration file doesn't exist ([#1098]({{ site.repository }}/issues/1098)) -- Allow for all options for Kramdown HTML Converter ([#1201]({{ site.repository }}/issues/1201)) - -### Bug Fixes -{: #bug-fixes-v1-1-0} -- Fix pagination in subdirectories. ([#1198]({{ site.repository }}/issues/1198)) -- Fix an issue with directories and permalinks that have a plus sign - (+) in them ([#1215]({{ site.repository }}/issues/1215)) -- Provide better error reporting when generating sites ([#1253]({{ site.repository }}/issues/1253)) -- Latest posts first in non-LSI `related_posts` ([#1271]({{ site.repository }}/issues/1271)) - -### Development Fixes -{: #development-fixes-v1-1-0} -- Merge the theme and layout Cucumber steps into one step ([#1151]({{ site.repository }}/issues/1151)) -- Restrict activesupport dependency to pre-4.0.0 to maintain compatibility with `<= 1.9.2` -- Include/exclude deprecation handling simplification ([#1284]({{ site.repository }}/issues/1284)) -- Convert README to Markdown. ([#1267]({{ site.repository }}/issues/1267)) -- Refactor Jekyll::Site ([#1144]({{ site.repository }}/issues/1144)) - -### Site Enhancements -{: #site-enhancements-v1-1-0} -- Add "News" section for release notes, along with an RSS feed ([#1093]({{ site.repository }}/issues/1093), [#1285]({{ site.repository }}/issues/1285), [#1286]({{ site.repository }}/issues/1286)) -- Add "History" page. -- Restructured docs sections to include "Meta" section. -- Add message to "Templates" page that specifies that Python must be installed in order - to use Pygments. ([#1182]({{ site.repository }}/issues/1182)) -- Update link to the official Maruku repo ([#1175]({{ site.repository }}/issues/1175)) -- Add documentation about `paginate_path` to "Templates" page in docs ([#1129]({{ site.repository }}/issues/1129)) -- Give the quick-start guide its own page ([#1191]({{ site.repository }}/issues/1191)) -- Update ProTip on Installation page in docs to point to all the info about Pygments and - the 'highlight' tag. ([#1196]({{ site.repository }}/issues/1196)) -- Run `site/img` through ImageOptim (thanks [@qrush](https://github.com/qrush)!) ([#1208]({{ site.repository }}/issues/1208)) -- Added Jade Converter to `site/docs/plugins` ([#1210]({{ site.repository }}/issues/1210)) -- Fix location of docs pages in Contributing pages ([#1214]({{ site.repository }}/issues/1214)) -- Add ReadInXMinutes plugin to the plugin list ([#1222]({{ site.repository }}/issues/1222)) -- Remove plugins from the plugin list that have equivalents in Jekyll - proper ([#1223]({{ site.repository }}/issues/1223)) -- Add jekyll-assets to the plugin list ([#1225]({{ site.repository }}/issues/1225)) -- Add jekyll-pandoc-mulitple-formats to the plugin list ([#1229]({{ site.repository }}/issues/1229)) -- Remove dead link to "Using Git to maintain your blog" ([#1227]({{ site.repository }}/issues/1227)) -- Tidy up the third-party plugins listing ([#1228]({{ site.repository }}/issues/1228)) -- Update contributor information ([#1192]({{ site.repository }}/issues/1192)) -- Update URL of article about Blogger migration ([#1242]({{ site.repository }}/issues/1242)) -- Specify that RedCarpet is the default for new Jekyll sites on Quickstart page ([#1247]({{ site.repository }}/issues/1247)) -- Added `site.pages` to Variables page in docs ([#1251]({{ site.repository }}/issues/1251)) -- Add Youku and Tudou Embed link on Plugins page. ([#1250]({{ site.repository }}/issues/1250)) -- Add note that `gist` tag supports private gists. ([#1248]({{ site.repository }}/issues/1248)) -- Add `jekyll-timeago` to list of third-party plugins. ([#1260]({{ site.repository }}/issues/1260)) -- Add `jekyll-swfobject` to list of third-party plugins. ([#1263]({{ site.repository }}/issues/1263)) -- Add `jekyll-picture-tag` to list of third-party plugins. ([#1280]({{ site.repository }}/issues/1280)) -- Update the GitHub Pages documentation regarding relative URLs - ([#1291]({{ site.repository }}/issues/1291)) -- Update the S3 deployment documentation ([#1294]({{ site.repository }}/issues/1294)) -- Add suggestion for Xcode CLT install to troubleshooting page in docs ([#1296]({{ site.repository }}/issues/1296)) -- Add 'Working with drafts' page to docs ([#1289]({{ site.repository }}/issues/1289)) -- Add information about time zones to the documentation for a page's - date ([#1304]({{ site.repository }}/issues/1304)) - - -## 1.0.3 / 2013-06-07 -{: #v1-0-3} - -### Minor Enhancements -{: #minor-enhancements-v1-0-3} -- Add support to gist tag for private gists. ([#1189]({{ site.repository }}/issues/1189)) -- Fail loudly when Maruku errors out ([#1190]({{ site.repository }}/issues/1190)) -- Move the building of related posts into their own class ([#1057]({{ site.repository }}/issues/1057)) -- Removed trailing spaces in several places throughout the code ([#1116]({{ site.repository }}/issues/1116)) -- Add a `--force` option to `jekyll new` ([#1115]({{ site.repository }}/issues/1115)) -- Convert IDs in the site template to classes ([#1170]({{ site.repository }}/issues/1170)) - -### Bug Fixes -{: #bug-fixes-v1-0-3} -- Fix typo in Stevenson constant "ERROR". ([#1166]({{ site.repository }}/issues/1166)) -- Rename Jekyll::Logger to Jekyll::Stevenson to fix inheritance issue ([#1106]({{ site.repository }}/issues/1106)) -- Exit with a non-zero exit code when dealing with a Liquid error ([#1121]({{ site.repository }}/issues/1121)) -- Make the `exclude` and `include` options backwards compatible with - versions of Jekyll prior to 1.0 ([#1114]({{ site.repository }}/issues/1114)) -- Fix pagination on Windows ([#1063]({{ site.repository }}/issues/1063)) -- Fix the application of Pygments' Generic Output style to Go code - ([#1156]({{ site.repository }}/issues/1156)) - -### Site Enhancements -{: #site-enhancements-v1-0-3} -- Add a Pro Tip to docs about front matter variables being optional ([#1147]({{ site.repository }}/issues/1147)) -- Add changelog to site as History page in /docs/ ([#1065]({{ site.repository }}/issues/1065)) -- Add note to Upgrading page about new config options in 1.0.x ([#1146]({{ site.repository }}/issues/1146)) -- Documentation for `date_to_rfc822` and `uri_escape` ([#1142]({{ site.repository }}/issues/1142)) -- Documentation highlight boxes shouldn't show scrollbars if not necessary ([#1123]({{ site.repository }}/issues/1123)) -- Add link to jekyll-minibundle in the doc's plugins list ([#1035]({{ site.repository }}/issues/1035)) -- Quick patch for importers documentation -- Fix prefix for WordpressDotCom importer in docs ([#1107]({{ site.repository }}/issues/1107)) -- Add jekyll-contentblocks plugin to docs ([#1068]({{ site.repository }}/issues/1068)) -- Make code bits in notes look more natural, more readable ([#1089]({{ site.repository }}/issues/1089)) -- Fix logic for `relative_permalinks` instructions on Upgrading page ([#1101]({{ site.repository }}/issues/1101)) -- Add docs for post excerpt ([#1072]({{ site.repository }}/issues/1072)) -- Add docs for gist tag ([#1072]({{ site.repository }}/issues/1072)) -- Add docs indicating that Pygments does not need to be installed - separately ([#1099]({{ site.repository }}/issues/1099), [#1119]({{ site.repository }}/issues/1119)) -- Update the migrator docs to be current ([#1136]({{ site.repository }}/issues/1136)) -- Add the Jekyll Gallery Plugin to the plugin list ([#1143]({{ site.repository }}/issues/1143)) - -### Development Fixes -{: #development-fixes-v1-0-3} -- Use Jekyll.logger instead of Jekyll::Stevenson to log things ([#1149]({{ site.repository }}/issues/1149)) -- Fix pesky Cucumber infinite loop ([#1139]({{ site.repository }}/issues/1139)) -- Do not write posts with timezones in Cucumber tests ([#1124]({{ site.repository }}/issues/1124)) -- Use ISO formatted dates in Cucumber features ([#1150]({{ site.repository }}/issues/1150)) - - -## 1.0.2 / 2013-05-12 -{: #v1-0-2} - -### Major Enhancements -{: #major-enhancements-v1-0-2} -- Add `jekyll doctor` command to check site for any known compatibility problems ([#1081]({{ site.repository }}/issues/1081)) -- Backwards-compatibilize relative permalinks ([#1081]({{ site.repository }}/issues/1081)) - -### Minor Enhancements -{: #minor-enhancements-v1-0-2} -- Add a `data-lang=""` attribute to Redcarpet code blocks ([#1066]({{ site.repository }}/issues/1066)) -- Deprecate old config `server_port`, match to `port` if `port` isn't set ([#1084]({{ site.repository }}/issues/1084)) -- Update pygments.rb version to 0.5.0 ([#1061]({{ site.repository }}/issues/1061)) -- Update Kramdown version to 1.0.2 ([#1067]({{ site.repository }}/issues/1067)) - -### Bug Fixes -{: #bug-fixes-v1-0-2} -- Fix issue when categories are numbers ([#1078]({{ site.repository }}/issues/1078)) -- Catching that Redcarpet gem isn't installed ([#1059]({{ site.repository }}/issues/1059)) - -### Site Enhancements -{: #site-enhancements-v1-0-2} -- Add documentation about `relative_permalinks` ([#1081]({{ site.repository }}/issues/1081)) -- Remove pygments-installation instructions, as pygments.rb is bundled with it ([#1079]({{ site.repository }}/issues/1079)) -- Move pages to be Pages for realz ([#985]({{ site.repository }}/issues/985)) -- Updated links to Liquid documentation ([#1073]({{ site.repository }}/issues/1073)) - - -## 1.0.1 / 2013-05-08 -{: #v1-0-1} - -### Minor Enhancements -{: #minor-enhancements-v1-0-1} -- Do not force use of `toc_token` when using `generate_tok` in RDiscount ([#1048]({{ site.repository }}/issues/1048)) -- Add newer `language-` class name prefix to code blocks ([#1037]({{ site.repository }}/issues/1037)) -- Commander error message now preferred over process abort with incorrect args ([#1040]({{ site.repository }}/issues/1040)) - -### Bug Fixes -{: #bug-fixes-v1-0-1} -- Make Redcarpet respect the pygments configuration option ([#1053]({{ site.repository }}/issues/1053)) -- Fix the index build with LSI ([#1045]({{ site.repository }}/issues/1045)) -- Don't print deprecation warning when no arguments are specified. ([#1041]({{ site.repository }}/issues/1041)) -- Add missing `

    ` to site template used by `new` subcommand, fixed typos in code ([#1032]({{ site.repository }}/issues/1032)) - -### Site Enhancements -{: #site-enhancements-v1-0-1} -- Changed https to http in the GitHub Pages link ([#1051]({{ site.repository }}/issues/1051)) -- Remove CSS cruft, fix typos, fix HTML errors ([#1028]({{ site.repository }}/issues/1028)) -- Removing manual install of Pip and Distribute ([#1025]({{ site.repository }}/issues/1025)) -- Updated URL for Markdown references plugin ([#1022]({{ site.repository }}/issues/1022)) - -### Development Fixes -{: #development-fixes-v1-0-1} -- Markdownify history file ([#1027]({{ site.repository }}/issues/1027)) -- Update links on README to point to new jekyllrb.com ([#1018]({{ site.repository }}/issues/1018)) - - -## 1.0.0 / 2013-05-06 -{: #v1-0-0} - -### Major Enhancements -{: #major-enhancements-v1-0-0} -- Add `jekyll new` subcommand: generate a Jekyll scaffold ([#764]({{ site.repository }}/issues/764)) -- Refactored Jekyll commands into subcommands: build, serve, and migrate. ([#690]({{ site.repository }}/issues/690)) -- Removed importers/migrators from main project, migrated to jekyll-import sub-gem ([#793]({{ site.repository }}/issues/793)) -- Added ability to render drafts in `_drafts` folder via command line ([#833]({{ site.repository }}/issues/833)) -- Add ordinal date permalink style (/:categories/:year/:y_day/:title.html) ([#928]({{ site.repository }}/issues/928)) - -### Minor Enhancements -{: #minor-enhancements-v1-0-0} -- Site template HTML5-ified ([#964]({{ site.repository }}/issues/964)) -- Use post's directory path when matching for the `post_url` tag ([#998]({{ site.repository }}/issues/998)) -- Loosen dependency on Pygments so it's only required when it's needed ([#1015]({{ site.repository }}/issues/1015)) -- Parse strings into Time objects for date-related Liquid filters ([#1014]({{ site.repository }}/issues/1014)) -- Tell the user if there is no subcommand specified ([#1008]({{ site.repository }}/issues/1008)) -- Freak out if the destination of `jekyll new` exists and is non-empty ([#981]({{ site.repository }}/issues/981)) -- Add `timezone` configuration option for compilation ([#957]({{ site.repository }}/issues/957)) -- Add deprecation messages for pre-1.0 CLI options ([#959]({{ site.repository }}/issues/959)) -- Refactor and colorize logging ([#959]({{ site.repository }}/issues/959)) -- Refactor Markdown parsing ([#955]({{ site.repository }}/issues/955)) -- Added application/vnd.apple.pkpass to mime.types served by WEBrick ([#907]({{ site.repository }}/issues/907)) -- Move template site to default markdown renderer ([#961]({{ site.repository }}/issues/961)) -- Expose new attribute to Liquid via `page`: `page.path` ([#951]({{ site.repository }}/issues/951)) -- Accept multiple config files from command line ([#945]({{ site.repository }}/issues/945)) -- Add page variable to liquid custom tags and blocks ([#413]({{ site.repository }}/issues/413)) -- Add `paginator.previous_page_path` and `paginator.next_page_path` ([#942]({{ site.repository }}/issues/942)) -- Backwards compatibility for 'auto' ([#821]({{ site.repository }}/issues/821), [#934]({{ site.repository }}/issues/934)) -- Added date_to_rfc822 used on RSS feeds ([#892]({{ site.repository }}/issues/892)) -- Upgrade version of pygments.rb to 0.4.2 ([#927]({{ site.repository }}/issues/927)) -- Added short month (e.g. "Sep") to permalink style options for posts ([#890]({{ site.repository }}/issues/890)) -- Expose site.baseurl to Liquid templates ([#869]({{ site.repository }}/issues/869)) -- Adds excerpt attribute to posts which contains first paragraph of content ([#837]({{ site.repository }}/issues/837)) -- Accept custom configuration file via CLI ([#863]({{ site.repository }}/issues/863)) -- Load in GitHub Pages MIME Types on `jekyll serve` ([#847]({{ site.repository }}/issues/847), [#871]({{ site.repository }}/issues/871)) -- Improve debugability of error message for a malformed highlight tag ([#785]({{ site.repository }}/issues/785)) -- Allow symlinked files in unsafe mode ([#824]({{ site.repository }}/issues/824)) -- Add 'gist' Liquid tag to core ([#822]({{ site.repository }}/issues/822), [#861]({{ site.repository }}/issues/861)) -- New format of Jekyll output ([#795]({{ site.repository }}/issues/795)) -- Reinstate `--limit_posts` and `--future` switches ([#788]({{ site.repository }}/issues/788)) -- Remove ambiguity from command descriptions ([#815]({{ site.repository }}/issues/815)) -- Fix SafeYAML Warnings ([#807]({{ site.repository }}/issues/807)) -- Relaxed Kramdown version to 0.14 ([#808]({{ site.repository }}/issues/808)) -- Aliased `jekyll server` to `jekyll serve`. ([#792]({{ site.repository }}/issues/792)) -- Updated gem versions for Kramdown, Rake, Shoulda, Cucumber, and RedCarpet. ([#744]({{ site.repository }}/issues/744)) -- Refactored Jekyll subcommands into Jekyll::Commands submodule, which now contains them ([#768]({{ site.repository }}/issues/768)) -- Rescue from import errors in Wordpress.com migrator ([#671]({{ site.repository }}/issues/671)) -- Massively accelerate LSI performance ([#664]({{ site.repository }}/issues/664)) -- Truncate post slugs when importing from Tumblr ([#496]({{ site.repository }}/issues/496)) -- Add glob support to include, exclude option ([#743]({{ site.repository }}/issues/743)) -- Layout of Page or Post defaults to 'page' or 'post', respectively ([#580]({{ site.repository }}/issues/580)) - REPEALED by ([#977]({{ site.repository }}/issues/977)) -- "Keep files" feature ([#685]({{ site.repository }}/issues/685)) -- Output full path & name for files that don't parse ([#745]({{ site.repository }}/issues/745)) -- Add source and destination directory protection ([#535]({{ site.repository }}/issues/535)) -- Better YAML error message ([#718]({{ site.repository }}/issues/718)) -- Bug Fixes -- Paginate in subdirectories properly ([#1016]({{ site.repository }}/issues/1016)) -- Ensure post and page URLs have a leading slash ([#992]({{ site.repository }}/issues/992)) -- Catch all exceptions, not just StandardError descendents ([#1007]({{ site.repository }}/issues/1007)) -- Bullet-proof `limit_posts` option ([#1004]({{ site.repository }}/issues/1004)) -- Read in YAML as UTF-8 to accept non-ASCII chars ([#836]({{ site.repository }}/issues/836)) -- Fix the CLI option `--plugins` to actually accept dirs and files ([#993]({{ site.repository }}/issues/993)) -- Allow 'excerpt' in YAML front matter to override the extracted excerpt ([#946]({{ site.repository }}/issues/946)) -- Fix cascade problem with site.baseurl, site.port and site.host. ([#935]({{ site.repository }}/issues/935)) -- Filter out directories with valid post names ([#875]({{ site.repository }}/issues/875)) -- Fix symlinked static files not being correctly built in unsafe mode ([#909]({{ site.repository }}/issues/909)) -- Fix integration with directory_watcher 1.4.x ([#916]({{ site.repository }}/issues/916)) -- Accepting strings as arguments to jekyll-import command ([#910]({{ site.repository }}/issues/910)) -- Force usage of older directory_watcher gem as 1.5 is broken ([#883]({{ site.repository }}/issues/883)) -- Ensure all Post categories are downcase ([#842]({{ site.repository }}/issues/842), [#872]({{ site.repository }}/issues/872)) -- Force encoding of the rdiscount TOC to UTF8 to avoid conversion errors ([#555]({{ site.repository }}/issues/555)) -- Patch for multibyte URI problem with `jekyll serve` ([#723]({{ site.repository }}/issues/723)) -- Order plugin execution by priority ([#864]({{ site.repository }}/issues/864)) -- Fixed Page#dir and Page#url for edge cases ([#536]({{ site.repository }}/issues/536)) -- Fix broken `post_url` with posts with a time in their YAML front matter ([#831]({{ site.repository }}/issues/831)) -- Look for plugins under the source directory ([#654]({{ site.repository }}/issues/654)) -- Tumblr Migrator: finds `_posts` dir correctly, fixes truncation of long - post names ([#775]({{ site.repository }}/issues/775)) -- Force Categories to be Strings ([#767]({{ site.repository }}/issues/767)) -- Safe YAML plugin to prevent vulnerability ([#777]({{ site.repository }}/issues/777)) -- Add SVG support to Jekyll/WEBrick. ([#407]({{ site.repository }}/issues/407), [#406]({{ site.repository }}/issues/406)) -- Prevent custom destination from causing continuous regen on watch ([#528]({{ site.repository }}/issues/528), [#820]({{ site.repository }}/issues/820), [#862]({{ site.repository }}/issues/862)) - -### Site Enhancements -{: #site-enhancements-v1-0-0} -- Responsify ([#860]({{ site.repository }}/issues/860)) -- Fix spelling, punctuation and phrasal errors ([#989]({{ site.repository }}/issues/989)) -- Update quickstart instructions with `new` command ([#966]({{ site.repository }}/issues/966)) -- Add docs for page.excerpt ([#956]({{ site.repository }}/issues/956)) -- Add docs for page.path ([#951]({{ site.repository }}/issues/951)) -- Clean up site docs to prepare for 1.0 release ([#918]({{ site.repository }}/issues/918)) -- Bring site into master branch with better preview/deploy ([#709]({{ site.repository }}/issues/709)) -- Redesigned site ([#583]({{ site.repository }}/issues/583)) - -### Development Fixes -{: #development-fixes-v1-0-0} -- Exclude Cucumber 1.2.4, which causes tests to fail in 1.9.2 ([#938]({{ site.repository }}/issues/938)) -- Added "features:html" rake task for debugging purposes, cleaned up - Cucumber profiles ([#832]({{ site.repository }}/issues/832)) -- Explicitly require HTTPS rubygems source in Gemfile ([#826]({{ site.repository }}/issues/826)) -- Changed Ruby version for development to 1.9.3-p374 from p362 ([#801]({{ site.repository }}/issues/801)) -- Including a link to the GitHub Ruby style guide in CONTRIBUTING.md ([#806]({{ site.repository }}/issues/806)) -- Added script/bootstrap ([#776]({{ site.repository }}/issues/776)) -- Running Simplecov under 2 conditions: ENV(COVERAGE)=true and with Ruby version - of greater than 1.9 ([#771]({{ site.repository }}/issues/771)) -- Switch to Simplecov for coverage report ([#765]({{ site.repository }}/issues/765)) - - -## 0.12.1 / 2013-02-19 -{: #v0-12-1} - -### Minor Enhancements -{: #minor-enhancements-v0-12-1} -- Update Kramdown version to 0.14.1 ([#744]({{ site.repository }}/issues/744)) -- Test Enhancements -- Update Rake version to 10.0.3 ([#744]({{ site.repository }}/issues/744)) -- Update Shoulda version to 3.3.2 ([#744]({{ site.repository }}/issues/744)) -- Update Redcarpet version to 2.2.2 ([#744]({{ site.repository }}/issues/744)) - - -## 0.12.0 / 2012-12-22 -{: #v0-12-0} - -### Minor Enhancements -{: #minor-enhancements-v0-12-0} -- Add ability to explicitly specify included files ([#261]({{ site.repository }}/issues/261)) -- Add `--default-mimetype` option ([#279]({{ site.repository }}/issues/279)) -- Allow setting of RedCloth options ([#284]({{ site.repository }}/issues/284)) -- Add `post_url` Liquid tag for internal post linking ([#369]({{ site.repository }}/issues/369)) -- Allow multiple plugin dirs to be specified ([#438]({{ site.repository }}/issues/438)) -- Inline TOC token support for RDiscount ([#333]({{ site.repository }}/issues/333)) -- Add the option to specify the paginated url format ([#342]({{ site.repository }}/issues/342)) -- Swap out albino for pygments.rb ([#569]({{ site.repository }}/issues/569)) -- Support Redcarpet 2 and fenced code blocks ([#619]({{ site.repository }}/issues/619)) -- Better reporting of Liquid errors ([#624]({{ site.repository }}/issues/624)) -- Bug Fixes -- Allow some special characters in highlight names -- URL escape category names in URL generation ([#360]({{ site.repository }}/issues/360)) -- Fix error with `limit_posts` ([#442]({{ site.repository }}/issues/442)) -- Properly select dotfile during directory scan ([#363]({{ site.repository }}/issues/363), [#431]({{ site.repository }}/issues/431), [#377]({{ site.repository }}/issues/377)) -- Allow setting of Kramdown `smart_quotes` ([#482]({{ site.repository }}/issues/482)) -- Ensure front matter is at start of file ([#562]({{ site.repository }}/issues/562)) - - -## 0.11.2 / 2011-12-27 -{: #v0-11-2} -- Bug Fixes -- Fix gemspec - - -## 0.11.1 / 2011-12-27 -{: #v0-11-1} -- Bug Fixes -- Fix extra blank line in highlight blocks ([#409]({{ site.repository }}/issues/409)) -- Update dependencies - - -## 0.11.0 / 2011-07-10 -{: #v0-11-0} - -### Major Enhancements -{: #major-enhancements-v0-11-0} -- Add command line importer functionality ([#253]({{ site.repository }}/issues/253)) -- Add Redcarpet Markdown support ([#318]({{ site.repository }}/issues/318)) -- Make markdown/textile extensions configurable ([#312]({{ site.repository }}/issues/312)) -- Add `markdownify` filter - -### Minor Enhancements -{: #minor-enhancements-v0-11-0} -- Switch to Albino gem -- Bundler support -- Use English library to avoid hoops ([#292]({{ site.repository }}/issues/292)) -- Add Posterous importer ([#254]({{ site.repository }}/issues/254)) -- Fixes for Wordpress importer ([#274]({{ site.repository }}/issues/274), [#252]({{ site.repository }}/issues/252), [#271]({{ site.repository }}/issues/271)) -- Better error message for invalid post date ([#291]({{ site.repository }}/issues/291)) -- Print formatted fatal exceptions to stdout on build failure -- Add Tumblr importer ([#323]({{ site.repository }}/issues/323)) -- Add Enki importer ([#320]({{ site.repository }}/issues/320)) -- Bug Fixes -- Secure additional path exploits - - -## 0.10.0 / 2010-12-16 -{: #v0-10-0} -- Bug Fixes -- Add `--no-server` option. - - -## 0.9.0 / 2010-12-15 -{: #v0-9-0} - -### Minor Enhancements -{: #minor-enhancements-v0-9-0} -- Use OptionParser's `[no-]` functionality for better boolean parsing. -- Add Drupal migrator ([#245]({{ site.repository }}/issues/245)) -- Complain about YAML and Liquid errors ([#249]({{ site.repository }}/issues/249)) -- Remove orphaned files during regeneration ([#247]({{ site.repository }}/issues/247)) -- Add Marley migrator ([#28]({{ site.repository }}/issues/28)) - - -## 0.8.0 / 2010-11-22 -{: #v0-8-0} - -### Minor Enhancements -{: #minor-enhancements-v0-8-0} -- Add wordpress.com importer ([#207]({{ site.repository }}/issues/207)) -- Add `--limit-posts` cli option ([#212]({{ site.repository }}/issues/212)) -- Add `uri_escape` filter ([#234]({{ site.repository }}/issues/234)) -- Add `--base-url` cli option ([#235]({{ site.repository }}/issues/235)) -- Improve MT migrator ([#238]({{ site.repository }}/issues/238)) -- Add kramdown support ([#239]({{ site.repository }}/issues/239)) -- Bug Fixes -- Fixed filename basename generation ([#208]({{ site.repository }}/issues/208)) -- Set mode to UTF8 on Sequel connections ([#237]({{ site.repository }}/issues/237)) -- Prevent `_includes` dir from being a symlink - - -## 0.7.0 / 2010-08-24 -{: #v0-7-0} - -### Minor Enhancements -{: #minor-enhancements-v0-7-0} -- Add support for rdiscount extensions ([#173]({{ site.repository }}/issues/173)) -- Bug Fixes -- Highlight should not be able to render local files -- The site configuration may not always provide a 'time' setting ([#184]({{ site.repository }}/issues/184)) - - -## 0.6.2 / 2010-06-25 -{: #v0-6-2} -- Bug Fixes -- Fix Rakefile 'release' task (tag pushing was missing origin) -- Ensure that RedCloth is loaded when textilize filter is used ([#183]({{ site.repository }}/issues/183)) -- Expand source, destination, and plugin paths ([#180]({{ site.repository }}/issues/180)) -- Fix `page.url` to include full relative path ([#181]({{ site.repository }}/issues/181)) - - -## 0.6.1 / 2010-06-24 -{: #v0-6-1} -- Bug Fixes -- Fix Markdown Pygments prefix and suffix ([#178]({{ site.repository }}/issues/178)) - - -## 0.6.0 / 2010-06-23 -{: #v0-6-0} - -### Major Enhancements -{: #major-enhancements-v0-6-0} -- Proper plugin system ([#19]({{ site.repository }}/issues/19), [#100]({{ site.repository }}/issues/100)) -- Add safe mode so unsafe converters/generators can be added -- Maruku is now the only processor dependency installed by default. - Other processors will be lazy-loaded when necessary (and prompt the - user to install them when necessary) ([#57]({{ site.repository }}/issues/57)) - -### Minor Enhancements -{: #minor-enhancements-v0-6-0} -- Inclusion/exclusion of future dated posts ([#59]({{ site.repository }}/issues/59)) -- Generation for a specific time ([#59]({{ site.repository }}/issues/59)) -- Allocate `site.time` on render not per site_payload invocation ([#59]({{ site.repository }}/issues/59)) -- Pages now present in the site payload and can be used through the - `site.pages` and `site.html_pages` variables -- Generate phase added to site#process and pagination is now a generator -- Switch to RakeGem for build/test process -- Only regenerate static files when they have changed ([#142]({{ site.repository }}/issues/142)) -- Allow arbitrary options to Pygments ([#31]({{ site.repository }}/issues/31)) -- Allow URL to be set via command line option ([#147]({{ site.repository }}/issues/147)) -- Bug Fixes -- Render highlighted code for non markdown/textile pages ([#116]({{ site.repository }}/issues/116)) -- Fix highlighting on Ruby 1.9 ([#65]({{ site.repository }}/issues/65)) -- Fix extension munging when pretty permalinks are enabled ([#64]({{ site.repository }}/issues/64)) -- Stop sorting categories ([#33]({{ site.repository }}/issues/33)) -- Preserve generated attributes over front matter ([#119]({{ site.repository }}/issues/119)) -- Fix source directory binding using `Dir.pwd` ([#75]({{ site.repository }}/issues/75)) - - -## 0.5.7 / 2010-01-12 -{: #v0-5-7} - -### Minor Enhancements -{: #minor-enhancements-v0-5-7} -- Allow overriding of post date in the front matter ([#62]({{ site.repository }}/issues/62), [#38]({{ site.repository }}/issues/38)) -- Bug Fixes -- Categories isn't always an array ([#73]({{ site.repository }}/issues/73)) -- Empty tags causes error in read_posts ([#84]({{ site.repository }}/issues/84)) -- Fix pagination to adhere to read/render/write paradigm -- Test Enhancement -- Cucumber features no longer use site.posts.first where a better - alternative is available - - -## 0.5.6 / 2010-01-08 -{: #v0-5-6} -- Bug Fixes -- Require redcloth >= 4.2.1 in tests ([#92]({{ site.repository }}/issues/92)) -- Don't break on triple dashes in yaml front matter ([#93]({{ site.repository }}/issues/93)) - -### Minor Enhancements -{: #minor-enhancements-v0-5-6} -- Allow .mkd as markdown extension -- Use $stdout/err instead of constants ([#99]({{ site.repository }}/issues/99)) -- Properly wrap code blocks ([#91]({{ site.repository }}/issues/91)) -- Add javascript mime type for webrick ([#98]({{ site.repository }}/issues/98)) - - -## 0.5.5 / 2010-01-08 -{: #v0-5-5} -- Bug Fixes -- Fix pagination % 0 bug ([#78]({{ site.repository }}/issues/78)) -- Ensure all posts are processed first ([#71]({{ site.repository }}/issues/71)) - - -## NOTE -- After this point I will no longer be giving credit in the history; - that is what the commit log is for. - - -## 0.5.4 / 2009-08-23 -{: #v0-5-4} -- Bug Fixes -- Do not allow symlinks (security vulnerability) - - -## 0.5.3 / 2009-07-14 -{: #v0-5-3} -- Bug Fixes -- Solving the permalink bug where non-html files wouldn't work - ([@jeffrydegrande](https://github.com/jeffrydegrande)) - - -## 0.5.2 / 2009-06-24 -{: #v0-5-2} -- Enhancements -- Added --paginate option to the executable along with a paginator object - for the payload ([@calavera](https://github.com/calavera)) -- Upgraded RedCloth to 4.2.1, which makes `` tags work once - again. -- Configuration options set in config.yml are now available through the - site payload ([@vilcans](https://github.com/vilcans)) -- Posts can now have an empty YAML front matter or none at all - (@ bahuvrihi) -- Bug Fixes -- Fixing Ruby 1.9 issue that requires `#to_s` on the err object - ([@Chrononaut](https://github.com/Chrononaut)) -- Fixes for pagination and ordering posts on the same day ([@ujh](https://github.com/ujh)) -- Made pages respect permalinks style and permalinks in yml front matter - ([@eugenebolshakov](https://github.com/eugenebolshakov)) -- Index.html file should always have index.html permalink - ([@eugenebolshakov](https://github.com/eugenebolshakov)) -- Added trailing slash to pretty permalink style so Apache is happy - ([@eugenebolshakov](https://github.com/eugenebolshakov)) -- Bad markdown processor in config fails sooner and with better message - (@ gcnovus) -- Allow CRLFs in yaml front matter ([@juretta](https://github.com/juretta)) -- Added Date#xmlschema for Ruby versions < 1.9 - - -## 0.5.1 / 2009-05-06 -{: #v0-5-1} - -### Major Enhancements -{: #major-enhancements-v0-5-1} -- Next/previous posts in site payload ([@pantulis](https://github.com/pantulis), [@tomo](https://github.com/tomo)) -- Permalink templating system -- Moved most of the README out to the GitHub wiki -- Exclude option in configuration so specified files won't be brought over - with generated site ([@duritong](https://github.com/duritong)) -- Bug Fixes -- Making sure config.yaml references are all gone, using only config.yml -- Fixed syntax highlighting breaking for UTF-8 code ([@henrik](https://github.com/henrik)) -- Worked around RDiscount bug that prevents Markdown from getting parsed - after highlight ([@henrik](https://github.com/henrik)) -- CGI escaped post titles ([@Chrononaut](https://github.com/Chrononaut)) - - -## 0.5.0 / 2009-04-07 -{: #v0-5-0} - -### Minor Enhancements -{: #minor-enhancements-v0-5-0} -- Ability to set post categories via YAML ([@qrush](https://github.com/qrush)) -- Ability to set prevent a post from publishing via YAML ([@qrush](https://github.com/qrush)) -- Add textilize filter ([@willcodeforfoo](https://github.com/willcodeforfoo)) -- Add 'pretty' permalink style for wordpress-like urls ([@dysinger](https://github.com/dysinger)) -- Made it possible to enter categories from YAML as an array ([@Chrononaut](https://github.com/Chrononaut)) -- Ignore Emacs autosave files ([@Chrononaut](https://github.com/Chrononaut)) -- Bug Fixes -- Use block syntax of popen4 to ensure that subprocesses are properly disposed ([@jqr](https://github.com/jqr)) -- Close open4 streams to prevent zombies ([@rtomayko](https://github.com/rtomayko)) -- Only query required fields from the WP Database ([@ariejan](https://github.com/ariejan)) -- Prevent `_posts` from being copied to the destination directory ([@bdimcheff](https://github.com/bdimcheff)) -- Refactors -- Factored the filtering code into a method ([@Chrononaut](https://github.com/Chrononaut)) -- Fix tests and convert to Shoulda ([@qrush](https://github.com/qrush), [@technicalpickles](https://github.com/technicalpickles)) -- Add Cucumber acceptance test suite ([@qrush](https://github.com/qrush), [@technicalpickles](https://github.com/technicalpickles)) - - -## 0.4.1 - -### Minor Enhancements -{: #minor-enhancements-v--} -- Changed date format on wordpress converter (zeropadding) ([@dysinger](https://github.com/dysinger)) -- Bug Fixes -- Add Jekyll binary as executable to gemspec ([@dysinger](https://github.com/dysinger)) - - -## 0.4.0 / 2009-02-03 -{: #v0-4-0} - -### Major Enhancements -{: #major-enhancements-v0-4-0} -- Switch to Jeweler for packaging tasks - -### Minor Enhancements -{: #minor-enhancements-v0-4-0} -- Type importer ([@codeslinger](https://github.com/codeslinger)) -- `site.topics` accessor ([@baz](https://github.com/baz)) -- Add `array_to_sentence_string` filter ([@mchung](https://github.com/mchung)) -- Add a converter for textpattern ([@PerfectlyNormal](https://github.com/PerfectlyNormal)) -- Add a working Mephisto / MySQL converter ([@ivey](https://github.com/ivey)) -- Allowing .htaccess files to be copied over into the generated site ([@briandoll](https://github.com/briandoll)) -- Add option to not put file date in permalink URL ([@mreid](https://github.com/mreid)) -- Add line number capabilities to highlight blocks ([@jcon](https://github.com/jcon)) -- Bug Fixes -- Fix permalink behavior ([@cavalle](https://github.com/cavalle)) -- Fixed an issue with pygments, markdown, and newlines ([@zpinter](https://github.com/zpinter)) -- Ampersands need to be escaped ([@pufuwozu](https://github.com/pufuwozu), [@ap](https://github.com/ap)) -- Test and fix the site.categories hash ([@zzot](https://github.com/zzot)) -- Fix site payload available to files ([@matrix9180](https://github.com/matrix9180)) - - -## 0.3.0 / 2008-12-24 -{: #v0-3-0} - -### Major Enhancements -{: #major-enhancements-v0-3-0} -- Added `--server` option to start a simple WEBrick server on destination - directory ([@johnreilly](https://github.com/johnreilly) and [@mchung](https://github.com/mchung)) - -### Minor Enhancements -{: #minor-enhancements-v0-3-0} -- Added post categories based on directories containing `_posts` ([@mreid](https://github.com/mreid)) -- Added post topics based on directories underneath `_posts` -- Added new date filter that shows the full month name ([@mreid](https://github.com/mreid)) -- Merge Post's YAML front matter into its to_liquid payload ([@remi](https://github.com/remi)) -- Restrict includes to regular files underneath `_includes` -- Bug Fixes -- Change YAML delimiter matcher so as to not chew up 2nd level markdown - headers ([@mreid](https://github.com/mreid)) -- Fix bug that meant page data (such as the date) was not available in - templates ([@mreid](https://github.com/mreid)) -- Properly reject directories in `_layouts` - - -## 0.2.1 / 2008-12-15 -{: #v0-2-1} -- Major Changes -- Use Maruku (pure Ruby) for Markdown by default ([@mreid](https://github.com/mreid)) -- Allow use of RDiscount with `--rdiscount` flag - -### Minor Enhancements -{: #minor-enhancements-v0-2-1} -- Don't load directory_watcher unless it's needed ([@pjhyett](https://github.com/pjhyett)) - - -## 0.2.0 / 2008-12-14 -{: #v0-2-0} -- Major Changes -- related_posts is now found in `site.related_posts` - - -## 0.1.6 / 2008-12-13 -{: #v0-1-6} -- Major Features -- Include files in `_includes` with {% raw %}`{% include x.textile %}`{% endraw %} - - -## 0.1.5 / 2008-12-12 -{: #v0-1-5} - -### Major Enhancements -{: #major-enhancements-v0-1-5} -- Code highlighting with Pygments if `--pygments` is specified -- Disable true LSI by default, enable with `--lsi` - -### Minor Enhancements -{: #minor-enhancements-v0-1-5} -- Output informative message if RDiscount is not available ([@JackDanger](https://github.com/JackDanger)) -- Bug Fixes -- Prevent Jekyll from picking up the output directory as a source ([@JackDanger](https://github.com/JackDanger)) -- Skip `related_posts` when there is only one post ([@JackDanger](https://github.com/JackDanger)) - - -## 0.1.4 / 2008-12-08 -{: #v0-1-4} -- Bug Fixes -- DATA does not work properly with rubygems - - -## 0.1.3 / 2008-12-06 -{: #v0-1-3} -- Major Features -- Markdown support ([@vanpelt](https://github.com/vanpelt)) -- Mephisto and CSV converters ([@vanpelt](https://github.com/vanpelt)) -- Code hilighting ([@vanpelt](https://github.com/vanpelt)) -- Autobuild -- Bug Fixes -- Accept both `\r\n` and `\n` in YAML header ([@vanpelt](https://github.com/vanpelt)) - - -## 0.1.2 / 2008-11-22 -{: #v0-1-2} -- Major Features -- Add a real "related posts" implementation using Classifier -- Command Line Changes -- Allow cli to be called with 0, 1, or 2 args intuiting dir paths - if they are omitted - - -## 0.1.1 / 2008-11-22 -{: #v0-1-1} -- Minor Additions -- Posts now support introspectional data e.g. {% raw %}`{{ page.url }}`{% endraw %} - - -## 0.1.0 / 2008-11-05 -{: #v0-1-0} -- First release -- Converts posts written in Textile -- Converts regular site pages -- Simple copy of binary files - - -## 0.0.0 / 2008-10-19 -{: #v0-0-0} -- Birthday! diff --git a/site/_docs/index.md b/site/_docs/index.md deleted file mode 100644 index bbb180871c3..00000000000 --- a/site/_docs/index.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -layout: docs -title: Welcome -permalink: /docs/home/ ---- - -This site aims to be a comprehensive guide to Jekyll. We’ll cover topics such -as getting your site up and running, creating and managing your content, -customizing the way your site works and looks, deploying to various -environments, and give you some advice on participating in the future -development of Jekyll itself. - -## So what is Jekyll, exactly? - -Jekyll is a simple, blog-aware, static site generator. It takes a template -directory containing raw text files in various formats, runs it through -a converter (like [Markdown](http://daringfireball.net/projects/markdown/)) -and our [Liquid](https://github.com/Shopify/liquid/wiki) renderer, and -spits out a complete, ready-to-publish static website suitable -for serving with your favorite web server. Jekyll also happens to be the engine -behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll -to host your project’s page, blog, or website from GitHub’s servers **for -free**. - -## Helpful Hints - -Throughout this guide there are a number of small-but-handy pieces of -information that can make using Jekyll easier, more interesting, and less -hazardous. Here’s what to look out for. - -
    -
    ProTips™ help you get more from Jekyll
    -

    These are tips and tricks that will help you be a Jekyll wizard!

    -
    - -
    -
    Notes are handy pieces of information
    -

    These are for the extra tidbits sometimes necessary to understand - Jekyll.

    -
    - -
    -
    Warnings help you not blow things up
    -

    Be aware of these messages if you wish to avoid certain death.

    -
    - -
    -
    You'll see this by a feature that hasn't been released
    -

    Some pieces of this website are for future versions of Jekyll that - are not yet released.

    -
    - -If you come across anything along the way that we haven’t covered, or if you -know of a tip you think others would find handy, please [file an -issue]({{ site.repository }}/issues/new) and we’ll see about -including it in this guide. diff --git a/site/_docs/installation.md b/site/_docs/installation.md deleted file mode 100644 index f0c091f0d30..00000000000 --- a/site/_docs/installation.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -layout: docs -title: Installation -permalink: /docs/installation/ ---- - -Getting Jekyll installed and ready-to-go should only take a few minutes. If it -ever becomes a pain in the ass, please [file an -issue]({{ site.repository }}/issues/new) (or submit a pull request) -describing the issue you encountered and how we might make the process easier. - -### Requirements - -Installing Jekyll is easy and straight-forward, but there are a few -requirements you’ll need to make sure your system has before you start. - -- [Ruby](http://www.ruby-lang.org/en/downloads/) (including development - headers, v1.9.3 or above for Jekyll 2 and v2 or above for Jekyll 3) -- [RubyGems](http://rubygems.org/pages/download) -- Linux, Unix, or Mac OS X -- [NodeJS](http://nodejs.org), or another JavaScript runtime (Jekyll 2 and -earlier, for CoffeeScript support). -- [Python 2.7](https://www.python.org/downloads/) (for Jekyll 2 and earlier) - -
    -
    Running Jekyll on Windows
    -

    - While Windows is not officially supported, it is possible to get it running - on Windows. Special instructions can be found on our - Windows-specific docs page. -

    -
    - -## Install with RubyGems - -The best way to install Jekyll is via -[RubyGems](http://rubygems.org/pages/download). At the terminal prompt, -simply run the following command to install Jekyll: - -{% highlight bash %} -$ gem install jekyll -{% endhighlight %} - -All of Jekyll’s gem dependencies are automatically installed by the above -command, so you won’t have to worry about them at all. If you have problems -installing Jekyll, check out the [troubleshooting](../troubleshooting/) page or -[report an issue]({{ site.repository }}/issues/new) so the Jekyll -community can improve the experience for everyone. - -
    -
    Installing Xcode Command-Line Tools
    -

    - If you run into issues installing Jekyll's dependencies which make use of - native extensions and are using Mac OS X, you will need to install Xcode - and the Command-Line Tools it ships with. Download in - Preferences → Downloads → Components. -

    -
    - -## Pre-releases - -In order to install a pre-release, make sure you have all the requirements -installed properly and run: - -{% highlight bash %} -gem install jekyll --pre -{% endhighlight %} - -This will install the latest pre-release. If you want a particular pre-release, -use the `-v` switch to indicate the version you'd like to install: - -{% highlight bash %} -gem install jekyll -v '2.0.0.alpha.1' -{% endhighlight %} - -If you'd like to install a development version of Jekyll, the process is a bit -more involved. This gives you the advantage of having the latest and greatest, -but may be unstable. - -{% highlight bash %} -$ git clone git://github.com/jekyll/jekyll.git -$ cd jekyll -$ script/bootstrap -$ bundle exec rake build -$ ls pkg/*.gem | head -n 1 | xargs gem install -l -{% endhighlight %} - -## Optional Extras - -There are a number of (optional) extra features that Jekyll supports that you -may want to install, depending on how you plan to use Jekyll. These extras -include LaTeX support, and the use of alternative content rendering engines. -Check out [the extras page](../extras/) for more information. - -
    -
    ProTip™: Enable Syntax Highlighting
    -

    - If you’re the kind of person who is using Jekyll, then chances are you’ll - want to enable syntax highlighting using Pygments - or Rouge. You should really - check out how to - do that before you go any farther. -

    -
    - -Now that you’ve got everything installed, let’s get to work! diff --git a/site/_docs/pages.md b/site/_docs/pages.md deleted file mode 100644 index fa76a9fb1b1..00000000000 --- a/site/_docs/pages.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -layout: docs -title: Creating pages -permalink: /docs/pages/ ---- - -In addition to [writing posts](../posts/), another thing you may want to do -with your Jekyll site is create static pages. By taking advantage of the way -Jekyll copies files and directories, this is easy to do. - -## Homepage - -Just about every web server configuration you come across will look for an HTML -file called `index.html` (by convention) in the site's root folder and display -that as the homepage. Unless the web server you’re using is configured to look -for some different filename as the default, this file will turn into the -homepage of your Jekyll-generated site. - -
    -
    ProTip™: Use layouts on your homepage
    -

    - Any HTML file on your site can use layouts and/or includes, even the - homepage. Common content, like headers and footers, make excellent - candidates for extraction into a layout. -

    -
    - -## Where additional pages live - -Where you put HTML files for pages depends on how you want the pages to work. -There are two main ways of creating pages: - -- Place named HTML files for each page in your site's root folder. -- Create a folder in the site's root for each page, and place an index.html -file in each page folder. - -Both methods work fine (and can be used in conjunction with each other), -with the only real difference being the resulting URLs. - -### Named HTML files - -The simplest way of adding a page is just to add an HTML file in the root -directory with a suitable name for the page you want to create. For a site with -a homepage, an about page, and a contact page, here’s what the root directory -and associated URLs might look like: - -{% highlight bash %} -. -|-- _config.yml -|-- _includes/ -|-- _layouts/ -|-- _posts/ -|-- _site/ -|-- about.html # => http://example.com/about.html -|-- index.html # => http://example.com/ -└── contact.html # => http://example.com/contact.html -{% endhighlight %} - -### Named folders containing index HTML files - -There is nothing wrong with the above method. However, some people like to keep -their URLs free from things like filename extensions. To achieve clean URLs for -pages using Jekyll, you simply need to create a folder for each top-level page -you want, and then place an `index.html` file in each page’s folder. This way -the page URL ends up being the folder name, and the web server will serve up -the respective `index.html` file. Here's an example of what this structure -might look like: - -{% highlight bash %} -. -├── _config.yml -├── _includes/ -├── _layouts/ -├── _posts/ -├── _site/ -├── about/ -| └── index.html # => http://example.com/about/ -├── contact/ -| └── index.html # => http://example.com/contact/ -└── index.html # => http://example.com/ -{% endhighlight %} - -This approach may not suit everyone, but for people who like clean URLs it’s -simple and it works. In the end the decision is yours! diff --git a/site/_docs/permalinks.md b/site/_docs/permalinks.md deleted file mode 100644 index 5aa0449aac5..00000000000 --- a/site/_docs/permalinks.md +++ /dev/null @@ -1,307 +0,0 @@ ---- -layout: docs -title: Permalinks -permalink: /docs/permalinks/ ---- - -Jekyll supports a flexible way to build your site’s URLs. You can specify the -permalinks for your site through the [Configuration](../configuration/) or in -the [YAML Front Matter](../frontmatter/) for each post. You’re free to choose -one of the built-in styles to create your links or craft your own. The default -style is `date`. - -Permalinks are constructed by creating a template URL where dynamic elements -are represented by colon-prefixed keywords. For example, the default `date` -permalink is defined according to the format `/:categories/:year/:month/:day/:title.html`. - -## Template variables - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription
    -

    year

    -
    -

    Year from the Post’s filename

    -
    -

    month

    -
    -

    Month from the Post’s filename

    -
    -

    i_month

    -
    -

    Month from the Post’s filename without leading zeros.

    -
    -

    day

    -
    -

    Day from the Post’s filename

    -
    -

    i_day

    -
    -

    Day from the Post’s filename without leading zeros.

    -
    -

    short_year

    -
    -

    Year from the Post’s filename without the century.

    -
    -

    hour

    -
    -

    - Hour of the day, 24-hour clock, zero-padded from the Post’s filename. (00..23) -

    -
    -

    minute

    -
    -

    - Minute of the hour from the Post’s filename. (00..59) -

    -
    -

    second

    -
    -

    - Second of the minute from the Post’s filename. (00..60) -

    -
    -

    title

    -
    -

    - Title from the document’s filename. May be overridden via - the document’s slug YAML front matter. -

    -
    -

    slug

    -
    -

    - Slugified title from the document’s filename ( any character - except numbers and letters is replaced as hyphen ). May be - overridden via the document’s slug YAML front matter. -

    -
    -

    categories

    -
    -

    - The specified categories for this Post. If a post has multiple - categories, Jekyll will create a hierarchy (e.g. /category1/category2). - Also Jekyll automatically parses out double slashes in the URLs, - so if no categories are present, it will ignore this. -

    -
    -
    - -## Built-in permalink styles - -While you can specify a custom permalink style using [template variables](#template-variables), -Jekyll also provides the following built-in styles for convenience. - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    Permalink StyleURL Template
    -

    date

    -
    -

    /:categories/:year/:month/:day/:title.html

    -
    -

    pretty

    -
    -

    /:categories/:year/:month/:day/:title/

    -
    -

    ordinal

    -
    -

    /:categories/:year/:y_day/:title.html

    -
    -

    none

    -
    -

    /:categories/:title.html

    -
    -
    - -## Pages and collections - -The `permalink` configuration setting specifies the permalink style used for -posts. Pages and collections each have their own default permalink style; the -default style for pages is `/:path/:basename` and the default for collections is -`/:collection/:path`. - -These styles are modified to match the suffix style specified in the post -permalink setting. For example, a permalink style of `pretty`, which contains a -trailing slash, will update page permalinks to also contain a trailing slash: -`/:path/:basename/`. A permalink style of `date`, which contains a trailing -file extension, will update page permalinks to also contain a file extension: -`/:path/:basename:output_ext`. The same is true for any custom permalink style. - -The permalink for an individual page or collection document can always be -overridden in the [YAML Front Matter](../frontmatter/) for the page or document. -Additionally, permalinks for a given collection can be customized [in the -collections configuration](../collections/). - -## Permalink style examples - -Given a post named: `/2009-04-29-slap-chop.md` - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    URL TemplateResulting Permalink URL
    -

    None specified, or permalink: date

    -
    -

    /2009/04/29/slap-chop.html

    -
    -

    pretty

    -
    -

    /2009/04/29/slap-chop/

    -
    -

    /:month-:day-:year/:title.html

    -
    -

    /04-29-2009/slap-chop.html

    -
    -

    /blog/:year/:month/:day/:title/

    -
    -

    /blog/2009/04/29/slap-chop/

    -
    -

    /:year/:month/:title

    -

    See extensionless permalinks for details.

    -
    -

    /2009/04/slap-chop

    -
    -
    - -## Extensionless permalinks - -Jekyll supports permalinks that contain neither a trailing slash nor a file -extension, but this requires additional support from the web server to properly -serve. When using extensionless permalinks, output files written to disk will -still have the proper file extension (typically `.html`), so the web server -must be able to map requests without file extensions to these files. - -Both [GitHub Pages](../github-pages/) and the Jekyll's built-in WEBrick server -handle these requests properly without any additional work. - -### Apache - -The Apache web server has very extensive support for content negotiation and can -handle extensionless URLs by setting the [multiviews][] option in your -`httpd.conf` or `.htaccess` file: - -[multiviews]: https://httpd.apache.org/docs/current/content-negotiation.html#multiviews - -{% highlight apache %} -Options +MultiViews -{% endhighlight %} - -### Nginx - -The [try_files][] directive allows you to specify a list of files to search for -to process a request. The following configuration will instruct nginx to search -for a file with an `.html` extension if an exact match for the requested URI is -not found. - -[try_files]: http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files - -{% highlight nginx %} -try_files $uri $uri.html $uri/ =404; -{% endhighlight %} diff --git a/site/_docs/plugins.md b/site/_docs/plugins.md deleted file mode 100644 index 37ca947d9c5..00000000000 --- a/site/_docs/plugins.md +++ /dev/null @@ -1,894 +0,0 @@ ---- -layout: docs -title: Plugins -permalink: /docs/plugins/ ---- - -Jekyll has a plugin system with hooks that allow you to create custom generated -content specific to your site. You can run custom code for your site without -having to modify the Jekyll source itself. - -
    -
    Plugins on GitHub Pages
    -

    - GitHub Pages is powered by Jekyll. - However, all Pages sites are generated using the --safe option - to disable custom plugins for security reasons. Unfortunately, this means - your plugins won’t work if you’re deploying to GitHub Pages.

    - You can still use GitHub Pages to publish your site, but you’ll need to - convert the site locally and push the generated static files to your GitHub - repository instead of the Jekyll source files. -

    -
    - -## Installing a plugin - -You have 3 options for installing plugins: - -1. In your site source root, make a `_plugins` directory. Place your plugins -here. Any file ending in `*.rb` inside this directory will be loaded before -Jekyll generates your site. -2. In your `_config.yml` file, add a new array with the key `gems` and the -values of the gem names of the plugins you'd like to use. An example: - - - gems: [jekyll-test-plugin, jekyll-jsonify, jekyll-assets] - # This will require each of these gems automatically. - - Then install your plugins using `gem install jekyll-test-plugin jekyll-jsonify jekyll-assets` - -3. Add the relevant plugins to a Bundler group in your `Gemfile`. An - example: - - group :jekyll_plugins do - gem "my-jekyll-plugin" - gem "another-jekyll-plugin" - end - - Now you need to install all plugins from your Bundler group by running single command `bundle install` - - -
    -
    - _plugins, _config.yml and Gemfile - can be used simultaneously -
    -

    - You may use any of the aforementioned plugin options simultaneously in the - same site if you so choose. Use of one does not restrict the use of the - others. -

    -
    - -In general, plugins you make will fall into one of four categories: - -1. [Generators](#generators) -2. [Converters](#converters) -3. [Commands](#commands) -4. [Tags](#tags) - -## Generators - -You can create a generator when you need Jekyll to create additional content -based on your own rules. - -A generator is a subclass of `Jekyll::Generator` that defines a `generate` -method, which receives an instance of -[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). The -return value of `generate` is ignored. - -Generators run after Jekyll has made an inventory of the existing content, and -before the site is generated. Pages with YAML Front Matters are stored as -instances of -[`Jekyll::Page`]({{ site.repository }}/blob/master/lib/jekyll/page.rb) -and are available via `site.pages`. Static files become instances of -[`Jekyll::StaticFile`]({{ site.repository }}/blob/master/lib/jekyll/static_file.rb) -and are available via `site.static_files`. See -[the Variables documentation page](/docs/variables/) and -[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb) -for more details. - -For instance, a generator can inject values computed at build time for template -variables. In the following example the template `reading.html` has two -variables `ongoing` and `done` that we fill in the generator: - -{% highlight ruby %} -module Reading - class Generator < Jekyll::Generator - def generate(site) - ongoing, done = Book.all.partition(&:ongoing?) - - reading = site.pages.detect {|page| page.name == 'reading.html'} - reading.data['ongoing'] = ongoing - reading.data['done'] = done - end - end -end -{% endhighlight %} - -This is a more complex generator that generates new pages: - -{% highlight ruby %} -module Jekyll - - class CategoryPage < Page - def initialize(site, base, dir, category) - @site = site - @base = base - @dir = dir - @name = 'index.html' - - self.process(@name) - self.read_yaml(File.join(base, '_layouts'), 'category_index.html') - self.data['category'] = category - - category_title_prefix = site.config['category_title_prefix'] || 'Category: ' - self.data['title'] = "#{category_title_prefix}#{category}" - end - end - - class CategoryPageGenerator < Generator - safe true - - def generate(site) - if site.layouts.key? 'category_index' - dir = site.config['category_dir'] || 'categories' - site.categories.each_key do |category| - site.pages << CategoryPage.new(site, site.source, File.join(dir, category), category) - end - end - end - end - -end -{% endhighlight %} - -In this example, our generator will create a series of files under the -`categories` directory for each category, listing the posts in each category -using the `category_index.html` layout. - -Generators are only required to implement one method: - -
    - - - - - - - - - - - - - -
    MethodDescription
    -

    generate

    -
    -

    Generates content as a side-effect.

    -
    -
    - -## Converters - -If you have a new markup language you’d like to use with your site, you can -include it by implementing your own converter. Both the Markdown and -[Textile](https://github.com/jekyll/jekyll-textile-converter) markup -languages are implemented using this method. - -
    -
    Remember your YAML Front Matter
    -

    - Jekyll will only convert files that have a YAML header at the top, even for - converters you add using a plugin. -

    -
    - -Below is a converter that will take all posts ending in `.upcase` and process -them using the `UpcaseConverter`: - -{% highlight ruby %} -module Jekyll - class UpcaseConverter < Converter - safe true - priority :low - - def matches(ext) - ext =~ /^\.upcase$/i - end - - def output_ext(ext) - ".html" - end - - def convert(content) - content.upcase - end - end -end -{% endhighlight %} - -Converters should implement at a minimum 3 methods: - -
    - - - - - - - - - - - - - - - - - - - - - -
    MethodDescription
    -

    matches

    -

    - Does the given extension match this converter’s list of acceptable - extensions? Takes one argument: the file’s extension (including the - dot). Must return true if it matches, false - otherwise. -

    -

    output_ext

    -

    - The extension to be given to the output file (including the dot). - Usually this will be ".html". -

    -

    convert

    -

    - Logic to do the content conversion. Takes one argument: the raw content - of the file (without YAML Front Matter). Must return a String. -

    -
    - -In our example, `UpcaseConverter#matches` checks if our filename extension is -`.upcase`, and will render using the converter if it is. It will call -`UpcaseConverter#convert` to process the content. In our simple converter we’re -simply uppercasing the entire content string. Finally, when it saves the page, -it will do so with a `.html` extension. - -## Commands - -As of version 2.5.0, Jekyll can be extended with plugins which provide -subcommands for the `jekyll` executable. This is possible by including the -relevant plugins in a `Gemfile` group called `:jekyll_plugins`: - -{% highlight ruby %} -group :jekyll_plugins do - gem "my_fancy_jekyll_plugin" -end -{% endhighlight %} - -Each `Command` must be a subclass of the `Jekyll::Command` class and must -contain one class method: `init_with_program`. An example: - -{% highlight ruby %} -class MyNewCommand < Jekyll::Command - class << self - def init_with_program(prog) - prog.command(:new) do |c| - c.syntax "new [options]" - c.description 'Create a new Jekyll site.' - - c.option 'dest', '-d DEST', 'Where the site should go.' - - c.action do |args, options| - Jekyll::Site.new_site_at(options['dest']) - end - end - end - end -end -{% endhighlight %} - -Commands should implement this single class method: - -
    - - - - - - - - - - - - - -
    MethodDescription
    -

    init_with_program

    -

    - This method accepts one parameter, the - Mercenary::Program - instance, which is the Jekyll program itself. Upon the program, - commands may be created using the above syntax. For more details, - visit the Mercenary repository on GitHub.com. -

    -
    - -## Tags - -If you’d like to include custom liquid tags in your site, you can do so by -hooking into the tagging system. Built-in examples added by Jekyll include the -`highlight` and `include` tags. Below is an example of a custom liquid tag that -will output the time the page was rendered: - -{% highlight ruby %} -module Jekyll - class RenderTimeTag < Liquid::Tag - - def initialize(tag_name, text, tokens) - super - @text = text - end - - def render(context) - "#{@text} #{Time.now}" - end - end -end - -Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag) -{% endhighlight %} - -At a minimum, liquid tags must implement: - -
    - - - - - - - - - - - - - -
    MethodDescription
    -

    render

    -
    -

    Outputs the content of the tag.

    -
    -
    - -You must also register the custom tag with the Liquid template engine as -follows: - -{% highlight ruby %} -Liquid::Template.register_tag('render_time', Jekyll::RenderTimeTag) -{% endhighlight %} - -In the example above, we can place the following tag anywhere in one of our -pages: - -{% highlight ruby %} -{% raw %} -

    {% render_time page rendered at: %}

    -{% endraw %} -{% endhighlight %} - -And we would get something like this on the page: - -{% highlight html %} -

    page rendered at: Tue June 22 23:38:47 –0500 2010

    -{% endhighlight %} - -### Liquid filters - -You can add your own filters to the Liquid template system much like you can -add tags above. Filters are simply modules that export their methods to liquid. -All methods will have to take at least one parameter which represents the input -of the filter. The return value will be the output of the filter. - -{% highlight ruby %} -module Jekyll - module AssetFilter - def asset_url(input) - "http://www.example.com/#{input}?#{Time.now.to_i}" - end - end -end - -Liquid::Template.register_filter(Jekyll::AssetFilter) -{% endhighlight %} - -
    -
    ProTip™: Access the site object using Liquid
    -

    - Jekyll lets you access the site object through the - context.registers feature of Liquid at context.registers[:site]. For example, you can - access the global configuration file _config.yml using - context.registers[:site].config. -

    -
    - -### Flags - -There are two flags to be aware of when writing a plugin: - -
    - - - - - - - - - - - - - - - - - -
    FlagDescription
    -

    safe

    -
    -

    - A boolean flag that informs Jekyll whether this plugin may be safely - executed in an environment where arbitrary code execution is not - allowed. This is used by GitHub Pages to determine which core plugins - may be used, and which are unsafe to run. If your plugin does not - allow for arbitrary code execution, set this to true. - GitHub Pages still won’t load your plugin, but if you submit it for - inclusion in core, it’s best for this to be correct! -

    -
    -

    priority

    -
    -

    - This flag determines what order the plugin is loaded in. Valid values - are: :lowest, :low, :normal, - :high, and :highest. Highest priority - matches are applied first, lowest priority are applied last. -

    -
    -
    - -To use one of the example plugins above as an illustration, here is how you’d -specify these two flags: - -{% highlight ruby %} -module Jekyll - class UpcaseConverter < Converter - safe true - priority :low - ... - end -end -{% endhighlight %} - -## Hooks - -Using hooks, your plugin can exercise fine-grained control over various aspects -of the build process. If your plugin defines any hooks, Jekyll will call them -at pre-defined points. - -Hooks are registered to a container and an event name. To register one, you -call Jekyll::Hooks.register, and pass the container, event name, and code to -call whenever the hook is triggered. For example, if you want to execute some -custom functionality every time Jekyll renders a post, you could register a -hook like this: - -{% highlight ruby %} -Jekyll::Hooks.register :posts, :post_render do |post| - # code to call after Jekyll renders a post -end -{% endhighlight %} - -Jekyll provides hooks for :site, :pages, -:posts, and :documents. In all cases, Jekyll calls your -hooks with the container object as the first callback parameter. But in the -case of :pre_render, your hook will also receive a payload hash as -a second parameter which allows you full control over the variables that are -available while rendering. - -The complete list of available hooks is below: - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ContainerEventCalled
    -

    :site

    -
    -

    :after_reset

    -
    -

    Just after site reset

    -
    -

    :site

    -
    -

    :post_read

    -
    -

    After site data has been read and loaded from disk

    -
    -

    :site

    -
    -

    :pre_render

    -
    -

    Just before rendering the whole site

    -
    -

    :site

    -
    -

    :post_render

    -
    -

    After rendering the whole site, but before writing any files

    -
    -

    :site

    -
    -

    :post_write

    -
    -

    After writing the whole site to disk

    -
    -

    :pages

    -
    -

    :post_init

    -
    -

    Whenever a page is initialized

    -
    -

    :pages

    -
    -

    :pre_render

    -
    -

    Just before rendering a page

    -
    -

    :pages

    -
    -

    :post_render

    -
    -

    After rendering a page, but before writing it to disk

    -
    -

    :pages

    -
    -

    :post_write

    -
    -

    After writing a page to disk

    -
    -

    :posts

    -
    -

    :post_init

    -
    -

    Whenever a post is initialized

    -
    -

    :posts

    -
    -

    :pre_render

    -
    -

    Just before rendering a post

    -
    -

    :posts

    -
    -

    :post_render

    -
    -

    After rendering a post, but before writing it to disk

    -
    -

    :posts

    -
    -

    :post_write

    -
    -

    After writing a post to disk

    -
    -

    :documents

    -
    -

    :post_init

    -
    -

    Whenever a document is initialized

    -
    -

    :documents

    -
    -

    :pre_render

    -
    -

    Just before rendering a document

    -
    -

    :documents

    -
    -

    :post_render

    -
    -

    After rendering a document, but before writing it to disk

    -
    -

    :documents

    -
    -

    :post_write

    -
    -

    After writing a document to disk

    -
    -
    - -## Available Plugins - -You can find a few useful plugins at the following locations: - -#### Generators - -- [ArchiveGenerator by Ilkka Laukkanen](https://gist.github.com/707909): Uses [this archive page](https://gist.github.com/707020) to generate archives. -- [LESS.js Generator by Andy Fowler](https://gist.github.com/642739): Renders -LESS.js files during generation. -- [Version Reporter by Blake Smith](https://gist.github.com/449491): Creates a version.html file containing the Jekyll version. -- [Sitemap.xml Generator by Michael Levin](https://github.com/kinnetica/jekyll-plugins): Generates a sitemap.xml file by traversing all of the available posts and pages. -- [Full-text search by Pascal Widdershoven](https://github.com/PascalW/jekyll_indextank): Adds full-text search to your Jekyll site with a plugin and a bit of JavaScript. -- [AliasGenerator by Thomas Mango](https://github.com/tsmango/jekyll_alias_generator): Generates redirect pages for posts when an alias is specified in the YAML Front Matter. -- [Pageless Redirect Generator by Nick Quinlan](https://github.com/nquinlan/jekyll-pageless-redirects): Generates redirects based on files in the Jekyll root, with support for htaccess style redirects. -- [RssGenerator by Assaf Gelber](https://github.com/agelber/jekyll-rss): Automatically creates an RSS 2.0 feed from your posts. -- [Monthly archive generator by Shigeya Suzuki](https://github.com/shigeya/jekyll-monthly-archive-plugin): Generator and template which renders monthly archive like MovableType style, based on the work by Ilkka Laukkanen and others above. -- [Category archive generator by Shigeya Suzuki](https://github.com/shigeya/jekyll-category-archive-plugin): Generator and template which renders category archive like MovableType style, based on Monthly archive generator. -- [Emoji for Jekyll](https://github.com/yihangho/emoji-for-jekyll): Seamlessly enable emoji for all posts and pages. -- [Compass integration for Jekyll](https://github.com/mscharley/jekyll-compass): Easily integrate Compass and Sass with your Jekyll website. -- [Pages Directory by Ben Baker-Smith](https://github.com/bbakersmith/jekyll-pages-directory): Defines a `_pages` directory for page files which routes its output relative to the project root. -- [Page Collections by Jeff Kolesky](https://github.com/jeffkole/jekyll-page-collections): Generates collections of pages with functionality that resembles posts. -- [Windows 8.1 Live Tile Generation by Matt Sheehan](https://github.com/sheehamj13/jekyll-live-tiles): Generates Internet Explorer 11 config.xml file and Tile Templates for pinning your site to Windows 8.1. -- [Typescript Generator by Matt Sheehan](https://github.com/sheehamj13/jekyll_ts): Generate Javascript on build from your Typescript. -- [Jekyll::AutolinkEmail by Ivan Tse](https://github.com/ivantsepp/jekyll-autolink_email): Autolink your emails. -- [Jekyll::GitMetadata by Ivan Tse](https://github.com/ivantsepp/jekyll-git_metadata): Expose Git metadata for your templates. -- [Jekyll Http Basic Auth Plugin](https://gist.github.com/snrbrnjna/422a4b7e017192c284b3): Plugin to manage http basic auth for jekyll generated pages and directories. -- [Jekyll Auto Image by Merlos](https://github.com/merlos/jekyll-auto-image): Gets the first image of a post. Useful to list your posts with images or to add [twitter cards](https://dev.twitter.com/cards/overview) to your site. -- [Jekyll Portfolio Generator by Shannon Babincsak](https://github.com/codeinpink/jekyll-portfolio-generator): Generates project pages and computes related projects out of project data files. -- [Jekyll-Umlauts by Arne Gockeln](https://github.com/webchef/jekyll-umlauts): This generator replaces all german umlauts (äöüß) case sensitive with html. -- [Jekyll Flickr Plugin](https://github.com/lawmurray/indii-jekyll-flickr) by [Lawrence Murray](http://www.indii.org): Generates posts for photos uploaded to a Flickr photostream. - -#### Converters - -- [Textile converter](https://github.com/jekyll/jekyll-textile-converter): Convert `.textile` files into HTML. Also includes the `textilize` Liquid filter. -- [Slim plugin](https://github.com/slim-template/jekyll-slim): Slim converter and includes for Jekyll with support for Liquid tags. -- [Jade plugin by John Papandriopoulos](https://github.com/snappylabs/jade-jekyll-plugin): Jade converter for Jekyll. -- [HAML plugin by Sam Z](https://gist.github.com/517556): HAML converter for Jekyll. -- [HAML-Sass Converter by Adam Pearson](https://gist.github.com/481456): Simple HAML-Sass converter for Jekyll. [Fork](https://gist.github.com/528642) by Sam X. -- [Sass SCSS Converter by Mark Wolfe](https://gist.github.com/960150): Sass converter which uses the new CSS compatible syntax, based Sam X’s fork above. -- [LESS Converter by Jason Graham](https://gist.github.com/639920): Convert LESS files to CSS. -- [LESS Converter by Josh Brown](https://gist.github.com/760265): Simple LESS converter. -- [Upcase Converter by Blake Smith](https://gist.github.com/449463): An example Jekyll converter. -- [CoffeeScript Converter by phaer](https://gist.github.com/959938): A [CoffeeScript](http://coffeescript.org) to Javascript converter. -- [Markdown References by Olov Lassus](https://github.com/olov/jekyll-references): Keep all your markdown reference-style link definitions in one \_references.md file. -- [Stylus Converter](https://gist.github.com/988201): Convert .styl to .css. -- [ReStructuredText Converter](https://github.com/xdissent/jekyll-rst): Converts ReST documents to HTML with Pygments syntax highlighting. -- [Jekyll-pandoc-plugin](https://github.com/dsanson/jekyll-pandoc-plugin): Use pandoc for rendering markdown. -- [Jekyll-pandoc-multiple-formats](https://github.com/fauno/jekyll-pandoc-multiple-formats) by [edsl](https://github.com/edsl): Use pandoc to generate your site in multiple formats. Supports pandoc’s markdown extensions. -- [Transform Layouts](https://gist.github.com/1472645): Allows HAML layouts (you need a HAML Converter plugin for this to work). -- [Org-mode Converter](https://gist.github.com/abhiyerra/7377603): Org-mode converter for Jekyll. -- [Customized Kramdown Converter](https://github.com/mvdbos/kramdown-with-pygments): Enable Pygments syntax highlighting for Kramdown-parsed fenced code blocks. -- [Bigfootnotes Plugin](https://github.com/TheFox/jekyll-bigfootnotes): Enables big footnotes for Kramdown. -- [AsciiDoc Plugin](https://github.com/asciidoctor/jekyll-asciidoc): AsciiDoc convertor for Jekyll using [Asciidoctor](http://asciidoctor.org/). -- [Lazy Tweet Embedding](https://github.com/takuti/jekyll-lazy-tweet-embedding): Automatically convert tweet urls into twitter cards. - -#### Filters - -- [Truncate HTML](https://github.com/MattHall/truncatehtml) by [Matt Hall](http://codebeef.com): A Jekyll filter that truncates HTML while preserving markup structure. -- [Domain Name Filter by Lawrence Woodman](https://github.com/LawrenceWoodman/domain_name-liquid_filter): Filters the input text so that just the domain name is left. -- [Summarize Filter by Mathieu Arnold](https://gist.github.com/731597): Remove markup after a `
    ` tag. -- [i18n_filter](https://github.com/gacha/gacha.id.lv/blob/master/_plugins/i18n_filter.rb): Liquid filter to use I18n localization. -- [Smilify](https://github.com/SaswatPadhi/jekyll_smilify) by [SaswatPadhi](https://github.com/SaswatPadhi): Convert text emoticons in your content to themeable smiley pics. -- [Read in X Minutes](https://gist.github.com/zachleat/5792681) by [zachleat](https://github.com/zachleat): Estimates the reading time of a string (for blog post content). -- [Jekyll-timeago](https://github.com/markets/jekyll-timeago): Converts a time value to the time ago in words. -- [pluralize](https://github.com/bdesham/pluralize): Easily combine a number and a word into a grammatically-correct amount like “1 minute” or “2 minute**s**”. -- [reading_time](https://github.com/bdesham/reading_time): Count words and estimate reading time for a piece of text, ignoring HTML elements that are unlikely to contain running text. -- [Table of Content Generator](https://github.com/dafi/jekyll-toc-generator): Generate the HTML code containing a table of content (TOC), the TOC can be customized in many way, for example you can decide which pages can be without TOC. -- [jekyll-humanize](https://github.com/23maverick23/jekyll-humanize): This is a port of the Django app humanize which adds a "human touch" to data. Each method represents a Fluid type filter that can be used in your Jekyll site templates. Given that Jekyll produces static sites, some of the original methods do not make logical sense to port (e.g. naturaltime). -- [Jekyll-Ordinal](https://github.com/PatrickC8t/Jekyll-Ordinal): Jekyll liquid filter to output a date ordinal such as "st", "nd", "rd", or "th". -- [Deprecated articles keeper](https://github.com/kzykbys/JekyllPlugins) by [Kazuya Kobayashi](http://blog.kazuya.co/): A simple Jekyll filter which monitor how old an article is. -- [Jekyll-jalali](https://github.com/mehdisadeghi/jekyll-jalali) by [Mehdi Sadeghi](http://mehdix.ir): A simple Gregorian to Jalali date converter filter. -- [Jekyll Thumbnail Filter](https://github.com/matallo/jekyll-thumbnail-filter): Related posts thumbnail filter. -- [Jekyll-Smartify](https://github.com/pathawks/jekyll-smartify): SmartyPants filter. Make "quotes" “curly” -- [liquid-md5](https://github.com/pathawks/liquid-md5): Returns an MD5 hash. Helpful for generating Gravatars in templates. -- [jekyll-roman](https://github.com/paulrobertlloyd/jekyll-roman): A liquid filter for Jekyll that converts numbers into Roman numerals. -- [jekyll-typogrify](https://github.com/myles/jekyll-typogrify): A Jekyll plugin that brings the functions of [typogruby](http://avdgaag.github.io/typogruby/). -- [Jekyll Email Protect](https://github.com/vwochnik/jekyll-email-protect): Email protection liquid filter for Jekyll - -#### Tags - -- [Asset Path Tag](https://github.com/samrayner/jekyll-asset-path-plugin) by [Sam Rayner](http://www.samrayner.com/): Allows organisation of assets into subdirectories by outputting a path for a given file relative to the current post or page. -- [Delicious Plugin by Christian Hellsten](https://github.com/christianhellsten/jekyll-plugins): Fetches and renders bookmarks from delicious.com. -- [Ultraviolet Plugin by Steve Alex](https://gist.github.com/480380): Jekyll tag for the [Ultraviolet](https://github.com/grosser/ultraviolet) code highligher. -- [Tag Cloud Plugin by Ilkka Laukkanen](https://gist.github.com/710577): Generate a tag cloud that links to tag pages. -- [GIT Tag by Alexandre Girard](https://gist.github.com/730347): Add Git activity inside a list. -- [MathJax Liquid Tags by Jessy Cowan-Sharp](https://gist.github.com/834610): Simple liquid tags for Jekyll that convert inline math and block equations to the appropriate MathJax script tags. -- [Non-JS Gist Tag by Brandon Tilley](https://gist.github.com/1027674) A Liquid tag that embeds Gists and shows code for non-JavaScript enabled browsers and readers. -- [Render Time Tag by Blake Smith](https://gist.github.com/449509): Displays the time a Jekyll page was generated. -- [Status.net/OStatus Tag by phaer](https://gist.github.com/912466): Displays the notices in a given status.net/ostatus feed. -- [Embed.ly client by Robert Böhnke](https://github.com/robb/jekyll-embedly-client): Autogenerate embeds from URLs using oEmbed. -- [Logarithmic Tag Cloud](https://gist.github.com/2290195): Flexible. Logarithmic distribution. Documentation inline. -- [oEmbed Tag by Tammo van Lessen](https://gist.github.com/1455726): Enables easy content embedding (e.g. from YouTube, Flickr, Slideshare) via oEmbed. -- [FlickrSetTag by Thomas Mango](https://github.com/tsmango/jekyll_flickr_set_tag): Generates image galleries from Flickr sets. -- [Tweet Tag by Scott W. Bradley](https://github.com/scottwb/jekyll-tweet-tag): Liquid tag for [Embedded Tweets](https://dev.twitter.com/docs/embedded-tweets) using Twitter’s shortcodes. -- [Jekyll Twitter Plugin](https://github.com/rob-murray/jekyll-twitter-plugin): A Liquid tag plugin that renders Tweets from Twitter API. Currently supports the [oEmbed](https://dev.twitter.com/rest/reference/get/statuses/oembed) API. -- [Jekyll-contentblocks](https://github.com/rustygeldmacher/jekyll-contentblocks): Lets you use Rails-like content_for tags in your templates, for passing content from your posts up to your layouts. -- [Generate YouTube Embed](https://gist.github.com/1805814) by [joelverhagen](https://github.com/joelverhagen): Jekyll plugin which allows you to embed a YouTube video in your page with the YouTube ID. Optionally specify width and height dimensions. Like “oEmbed Tag” but just for YouTube. -- [Jekyll-beastiepress](https://github.com/okeeblow/jekyll-beastiepress): FreeBSD utility tags for Jekyll sites. -- [Jsonball](https://gist.github.com/1895282): Reads json files and produces maps for use in Jekyll files. -- [Bibjekyll](https://github.com/pablooliveira/bibjekyll): Render BibTeX-formatted bibliographies/citations included in posts and pages using bibtex2html. -- [Jekyll-citation](https://github.com/archome/jekyll-citation): Render BibTeX-formatted bibliographies/citations included in posts and pages (pure Ruby). -- [Jekyll Dribbble Set Tag](https://github.com/ericdfields/Jekyll-Dribbble-Set-Tag): Builds Dribbble image galleries from any user. -- [Debbugs](https://gist.github.com/2218470): Allows posting links to Debian BTS easily. -- [Refheap_tag](https://github.com/aburdette/refheap_tag): Liquid tag that allows embedding pastes from [refheap](https://www.refheap.com/). -- [Jekyll-devonly_tag](https://gist.github.com/2403522): A block tag for including markup only during development. -- [JekyllGalleryTag](https://github.com/redwallhp/JekyllGalleryTag) by [redwallhp](https://github.com/redwallhp): Generates thumbnails from a directory of images and displays them in a grid. -- [Youku and Tudou Embed](https://gist.github.com/Yexiaoxing/5891929): Liquid plugin for embedding Youku and Tudou videos. -- [Jekyll-swfobject](https://github.com/sectore/jekyll-swfobject): Liquid plugin for embedding Adobe Flash files (.swf) using [SWFObject](http://code.google.com/p/swfobject/). -- [Jekyll Picture Tag](https://github.com/robwierzbowski/jekyll-picture-tag): Easy responsive images for Jekyll. Based on the proposed [``](https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element) element, polyfilled with Scott Jehl’s [Picturefill](https://github.com/scottjehl/picturefill). -- [Jekyll Image Tag](https://github.com/robwierzbowski/jekyll-image-tag): Better images for Jekyll. Save image presets, generate resized images, and add classes, alt text, and other attributes. -- [Ditaa Tag](https://github.com/matze/jekyll-ditaa) by [matze](https://github.com/matze): Renders ASCII diagram art into PNG images and inserts a figure tag. -- [Jekyll Suggested Tweet](https://github.com/davidensinger/jekyll-suggested-tweet) by [David Ensinger](https://github.com/davidensinger/): A Liquid tag for Jekyll that allows for the embedding of suggested tweets via Twitter’s Web Intents API. -- [Jekyll Date Chart](https://github.com/GSI/jekyll_date_chart) by [GSI](https://github.com/GSI): Block that renders date line charts based on textile-formatted tables. -- [Jekyll Image Encode](https://github.com/GSI/jekyll_image_encode) by [GSI](https://github.com/GSI): Tag that renders base64 codes of images fetched from the web. -- [Jekyll Quick Man](https://github.com/GSI/jekyll_quick_man) by [GSI](https://github.com/GSI): Tag that renders pretty links to man page sources on the internet. -- [jekyll-font-awesome](https://gist.github.com/23maverick23/8532525): Quickly and easily add Font Awesome icons to your posts. -- [Lychee Gallery Tag](https://gist.github.com/tobru/9171700) by [tobru](https://github.com/tobru): Include [Lychee](http://lychee.electerious.com/) albums into a post. For an introduction, see [Jekyll meets Lychee - A Liquid Tag plugin](https://tobrunet.ch/articles/jekyll-meets-lychee-a-liquid-tag-plugin/) -- [Image Set/Gallery Tag](https://github.com/callmeed/jekyll-image-set) by [callmeed](https://github.com/callmeed): Renders HTML for an image gallery from a folder in your Jekyll site. Just pass it a folder name and class/tag options. -- [jekyll_figure](https://github.com/lmullen/jekyll_figure): Generate figures and captions with links to the figure in a variety of formats -- [Jekyll Github Sample Tag](https://github.com/bwillis/jekyll-github-sample): A liquid tag to include a sample of a github repo file in your Jekyll site. -- [Jekyll Project Version Tag](https://github.com/rob-murray/jekyll-version-plugin): A Liquid tag plugin that renders a version identifier for your Jekyll site sourced from the git repository containing your code. -- [Piwigo Gallery](https://github.com/AlessandroLorenzi/piwigo_gallery) by [Alessandro Lorenzi](http://www.alorenzi.eu/): Jekyll plugin to generate thumbnails from a Piwigo gallery and display them with a Liquid tag -- [mathml.rb](https://github.com/tmthrgd/jekyll-plugins) by Tom Thorogood: A plugin to convert TeX mathematics into MathML for display. -- [webmention_io.rb](https://github.com/aarongustafson/jekyll-webmention_io) by [Aaron Gustafson](http://aaron-gustafson.com/): A plugin to enable [webmention](http://indiewebcamp.com/webmention) integration using [Webmention.io](http://webmention.io). Includes an optional JavaScript for updating webmentions automatically between publishes and, if available, in realtime using WebSockets. -- [Jekyll 500px Embed](https://github.com/lkorth/jekyll-500px-embed) by Luke Korth. A Liquid tag plugin that embeds [500px](https://500px.com/) photos. -- [inline\_highlight](https://github.com/bdesham/inline_highlight): A tag for inline syntax highlighting. -- [jekyll-mermaid](https://github.com/jasonbellamy/jekyll-mermaid): Simplify the creation of mermaid diagrams and flowcharts in your posts and pages. -- [twa](https://github.com/Ezmyrelda/twa): Twemoji Awesome plugin for Jekyll. Liquid tag allowing you to use twitter emoji in your jekyll pages. -- [jekyll-files](https://github.com/x43x61x69/jekyll-files) by [Zhi-Wei Cai](http://vox.vg/): Output relative path strings and other info regarding specific assets. -- [Fetch remote file content](https://github.com/dimitri-koenig/jekyll-plugins) by [Dimitri König](https://www.dimitrikoenig.net/): Using `remote_file_content` tag you can fetch the content of a remote file and include it as if you would put the content right into your markdown file yourself. Very useful for including code from github repo's to always have a current repo version. -- [jekyll-asciinema](https://github.com/mnuessler/jekyll-asciinema): A tag for embedding asciicasts recorded with [asciinema](https://asciinema.org) in your Jekyll pages. -- [Jekyll-Youtube](https://github.com/dommmel/jekyll-youtube) A Liquid tag that embeds Youtube videos. The default emded markup is responsive but you can also specify your own by using an include/partial. -- [Jekyll Flickr Plugin](https://github.com/lawmurray/indii-jekyll-flickr) by [Lawrence Murray](http://www.indii.org): Embeds Flickr photosets (albums) as a gallery of thumbnails, with lightbox links to larger images. -- [jekyll-figure](https://github.com/paulrobertlloyd/jekyll-figure): A liquid tag for Jekyll that generates `
    ` elements. - -#### Collections - -- [Jekyll Plugins by Recursive Design](https://github.com/recurser/jekyll-plugins): Plugins to generate Project pages from GitHub readmes, a Category page, and a Sitemap generator. -- [Company website and blog plugins](https://github.com/flatterline/jekyll-plugins) by Flatterline, a [Ruby on Rails development company](http://flatterline.com/): Portfolio/project page generator, team/individual page generator, an author bio liquid tag for use on posts, and a few other smaller plugins. -- [Jekyll plugins by Aucor](https://github.com/aucor/jekyll-plugins): Plugins for trimming unwanted newlines/whitespace and sorting pages by weight attribute. - -#### Other - -- [ditaa-ditaa](https://github.com/tmthrgd/ditaa-ditaa) by Tom Thorogood: a drastic revision of jekyll-ditaa that renders diagrams drawn using ASCII art into PNG images. -- [Pygments Cache Path by Raimonds Simanovskis](https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb): Plugin to cache syntax-highlighted code from Pygments. -- [Draft/Publish Plugin by Michael Ivey](https://gist.github.com/49630): Save posts as drafts. -- [Growl Notification Generator by Tate Johnson](https://gist.github.com/490101): Send Jekyll notifications to Growl. -- [Growl Notification Hook by Tate Johnson](https://gist.github.com/525267): Better alternative to the above, but requires his “hook” fork. -- [Related Posts by Lawrence Woodman](https://github.com/LawrenceWoodman/related_posts-jekyll_plugin): Overrides `site.related_posts` to use categories to assess relationship. -- [Tiered Archives by Eli Naeher](https://gist.github.com/88cda643aa7e3b0ca1e5): Create tiered template variable that allows you to group archives by year and month. -- [Jekyll-localization](https://github.com/blackwinter/jekyll-localization): Jekyll plugin that adds localization features to the rendering engine. -- [Jekyll-rendering](https://github.com/blackwinter/jekyll-rendering): Jekyll plugin to provide alternative rendering engines. -- [Jekyll-pagination](https://github.com/blackwinter/jekyll-pagination): Jekyll plugin to extend the pagination generator. -- [Jekyll-tagging](https://github.com/pattex/jekyll-tagging): Jekyll plugin to automatically generate a tag cloud and tag pages. -- [Jekyll-scholar](https://github.com/inukshuk/jekyll-scholar): Jekyll extensions for the blogging scholar. -- [Jekyll-asset_bundler](https://github.com/moshen/jekyll-asset_bundler): Bundles and minifies JavaScript and CSS. -- [Jekyll-assets](http://ixti.net/jekyll-assets/) by [ixti](https://github.com/ixti): Rails-alike assets pipeline (write assets in CoffeeScript, Sass, LESS etc; specify dependencies for automatic bundling using simple declarative comments in assets; minify and compress; use JST templates; cache bust; and many-many more). -- [JAPR](https://github.com/kitsched/japr): Jekyll Asset Pipeline Reborn - Powerful asset pipeline for Jekyll that collects, converts and compresses JavaScript and CSS assets. -- [File compressor](https://gist.github.com/2758691) by [mytharcher](https://github.com/mytharcher): Compress HTML and JavaScript files on site build. -- [Jekyll-minibundle](https://github.com/tkareine/jekyll-minibundle): Asset bundling and cache busting using external minification tool of your choice. No gem dependencies. -- [Singlepage-jekyll](https://github.com/JCB-K/singlepage-jekyll) by [JCB-K](https://github.com/JCB-K): Turns Jekyll into a dynamic one-page website. -- [generator-jekyllrb](https://github.com/robwierzbowski/generator-jekyllrb): A generator that wraps Jekyll in [Yeoman](http://yeoman.io/), a tool collection and workflow for builing modern web apps. -- [grunt-jekyll](https://github.com/dannygarcia/grunt-jekyll): A straightforward [Grunt](http://gruntjs.com/) plugin for Jekyll. -- [jekyll-postfiles](https://github.com/indirect/jekyll-postfiles): Add `_postfiles` directory and {% raw %}`{{ postfile }}`{% endraw %} tag so the files a post refers to will always be right there inside your repo. -- [A layout that compresses HTML](http://jch.penibelst.de/): Github Pages compatible, configurable way to compress HTML files on site build. -- [Jekyll CO₂](https://github.com/wdenton/jekyll-co2): Generates HTML showing the monthly change in atmospheric CO₂ at the Mauna Loa observatory in Hawaii. -- [remote-include](http://www.northfieldx.co.uk/remote-include/): Includes files using remote URLs -- [jekyll-minifier](https://github.com/digitalsparky/jekyll-minifier): Minifies HTML, XML, CSS, and Javascript both inline and as separate files utilising yui-compressor and htmlcompressor. -- [Jekyll views router](https://bitbucket.org/nyufac/jekyll-views-router): Simple router between generator plugins and templates. -- [Jekyll Language Plugin](https://github.com/vwochnik/jekyll-language-plugin): Jekyll 3.0-compatible multi-language plugin for posts, pages and includes. - -#### Editors - -- [sublime-jekyll](https://github.com/23maverick23/sublime-jekyll): A Sublime Text package for Jekyll static sites. This package should help creating Jekyll sites and posts easier by providing access to key template tags and filters, as well as common completions and a current date/datetime command (for dating posts). You can install this package manually via GitHub, or via [Package Control](https://packagecontrol.io/packages/Jekyll). -- [vim-jekyll](https://github.com/parkr/vim-jekyll): A vim plugin to generate - new posts and run `jekyll build` all without leaving vim. -- [markdown-writer](https://atom.io/packages/markdown-writer): An Atom package for Jekyll. It can create new posts/drafts, manage tags/categories, insert link/images and add many useful key mappings. - -
    -
    Jekyll Plugins Wanted
    -

    - If you have a Jekyll plugin that you would like to see added to this list, - you should read the contributing page to find - out how to make that happen. -

    -
    diff --git a/site/_docs/posts.md b/site/_docs/posts.md deleted file mode 100644 index ee02d06b0a0..00000000000 --- a/site/_docs/posts.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -layout: docs -title: Writing posts -permalink: /docs/posts/ ---- - -One of Jekyll’s best aspects is that it is “blog aware”. What does this mean, -exactly? Well, simply put, it means that blogging is baked into Jekyll’s -functionality. If you write articles and publish them online, this means that -you can publish and maintain a blog simply by managing a folder of text-files on -your computer. Compared to the hassle of configuring and maintaining databases -and web-based CMS systems, this will be a welcome change! - -## The Posts Folder - -As explained on the [directory structure](../structure/) page, the `_posts` -folder is where your blog posts will live. These files are generally -[Markdown](http://daringfireball.net/projects/markdown/) or HTML, but can -be other formats with the proper converter installed. -All posts must have [YAML Front Matter](../frontmatter/), and they will be -converted from their source format into an HTML page that is part of your -static site. - -### Creating Post Files - -To create a new post, all you need to do is create a new file in the `_posts` -directory. How you name files in this folder is important. Jekyll requires blog -post files to be named according to the following format: - -{% highlight bash %} -YEAR-MONTH-DAY-title.MARKUP -{% endhighlight %} - -Where `YEAR` is a four-digit number, `MONTH` and `DAY` are both two-digit -numbers, and `MARKUP` is the file extension representing the format used in the -file. For example, the following are examples of valid post filenames: - -{% highlight bash %} -2011-12-31-new-years-eve-is-awesome.md -2012-09-12-how-to-write-a-blog.textile -{% endhighlight %} - -
    -
    ProTip™: Link to other posts
    -

    - Use the post_url - tag to link to other posts without having to worry about the URL's - breaking when the site permalink style changes. -

    -
    - -### Content Formats - -All blog post files must begin with [YAML Front Matter](../frontmatter/). After -that, it's simply a matter of deciding which format you prefer. Jekyll supports -[Markdown](http://daringfireball.net/projects/markdown/) out of the box, -and has [myriad extensions for other formats as well](/docs/plugins/#converters-1), -including the popular [Textile](http://redcloth.org/textile) format. These -formats each have their own way of marking up different types of content -within a post, so you should familiarize yourself with these formats and -decide which one best suits your needs. - -
    -
    Be aware of character sets
    -

    - Content processors can modify certain characters to make them look nicer. - For example, the smart extension in Redcarpet converts standard, - ASCII quotation characters to curly, Unicode ones. In order for the browser - to display those characters properly, define the charset meta value by - including <meta charset="utf-8"> in the - <head> of your layout. -

    -
    - -## Including images and resources - -Chances are, at some point, you'll want to include images, downloads, or other -digital assets along with your text content. While the syntax for linking to -these resources differs between Markdown and Textile, the problem of working -out where to store these files in your site is something everyone will face. - -Because of Jekyll’s flexibility, there are many solutions to how to do this. -One common solution is to create a folder in the root of the project directory -called something like `assets` or `downloads`, into which any images, downloads -or other resources are placed. Then, from within any post, they can be linked -to using the site’s root as the path for the asset to include. Again, this will -depend on the way your site’s (sub)domain and path are configured, but here -some examples (in Markdown) of how you could do this using the `site.url` -variable in a post. - -Including an image asset in a post: - -{% highlight text %} -… which is shown in the screenshot below: -![My helpful screenshot]({% raw %}{{ site.url }}{% endraw %}/assets/screenshot.jpg) -{% endhighlight %} - -Linking to a PDF for readers to download: - -{% highlight text %} -… you can [get the PDF]({% raw %}{{ site.url }}{% endraw %}/assets/mydoc.pdf) directly. -{% endhighlight %} - -
    -
    ProTip™: Link using just the site root URL
    -

    - You can skip the {% raw %}{{ site.url }}{% endraw %} variable - if you know your site will only ever be displayed at the - root URL of your domain. In this case you can reference assets directly with - just /path/file.jpg. -

    -
    - -## Displaying an index of posts - -It’s all well and good to have posts in a folder, but a blog is no use unless -you have a list of posts somewhere. Creating an index of posts on another page -(or in a [template](../templates/)) is easy, thanks to the [Liquid template -language](http://wiki.shopify.com/Liquid) and its tags. Here’s a basic example -of how to create a list of links to your blog posts: - -{% highlight html %} - -{% endhighlight %} - -Of course, you have full control over how (and where) you display your posts, -and how you structure your site. You should read more about [how templates -work](../templates/) with Jekyll if you want to know more. - -Note that the `post` variable only exists inside the `for` loop above. If -you wish to access the currently-rendering page/posts's variables (the -variables of the post/page that has the `for` loop in it), use the `page` -variable instead. - -## Post excerpts - -Each post automatically takes the first block of text, from the beginning of -the content to the first occurrence of `excerpt_separator`, and sets it as the `post.excerpt`. -Take the above example of an index of posts. Perhaps you want to include -a little hint about the post's content by adding the first paragraph of each of -your posts: - -{% highlight html %} - -{% endhighlight %} - -Because Jekyll grabs the first paragraph you will not need to wrap the excerpt -in `p` tags, which is already done for you. These tags can be removed with the -following if you'd prefer: - -{% highlight html %} -{% raw %}{{ post.excerpt | remove: '

    ' | remove: '

    ' }}{% endraw %} -{% endhighlight %} - -If you don't like the automatically-generated post excerpt, it can be -explicitly overridden by adding an `excerpt` value to your post's YAML -Front Matter. Alternatively, you can choose to define a custom -`excerpt_separator` in the post's YAML front matter: - -{% highlight text %} ---- -excerpt_separator: ---- - -Excerpt - -Out-of-excerpt -{% endhighlight %} - -You can also set the `excerpt_separator` globally in your `_config.yml` -configuration file. - -Completely disable excerpts by setting your `excerpt_separator` to `""`. - -Also, as with any output generated by Liquid tags, you can pass the -`| strip_html` filter to remove any html tags in the output. This is -particularly helpful if you wish to output a post excerpt as a -`meta="description"` tag within the post `head`, or anywhere else having -html tags along with the content is not desirable. - -## Highlighting code snippets - -Jekyll also has built-in support for syntax highlighting of code snippets using -either Pygments or Rouge, and including a code snippet in any post is easy. -Just use the dedicated Liquid tag as follows: - -{% highlight text %} -{% raw %}{% highlight ruby %}{% endraw %} -def show - @widget = Widget(params[:id]) - respond_to do |format| - format.html # show.html.erb - format.json { render json: @widget } - end -end -{% raw %}{% endhighlight %}{% endraw %} -{% endhighlight %} - -And the output will look like this: - -{% highlight ruby %} -def show - @widget = Widget(params[:id]) - respond_to do |format| - format.html # show.html.erb - format.json { render json: @widget } - end -end -{% endhighlight %} - -
    -
    ProTip™: Show line numbers
    -

    - You can make code snippets include line-numbers by adding the word - linenos to the end of the opening highlight tag like this: - {% raw %}{% highlight ruby linenos %}{% endraw %}. -

    -
    - -These basics should be enough to get you started writing your first posts. When -you’re ready to dig into what else is possible, you might be interested in -doing things like [customizing post permalinks](../permalinks/) or -using [custom variables](../variables/) in your posts and elsewhere on your -site. diff --git a/site/_docs/quickstart.md b/site/_docs/quickstart.md deleted file mode 100644 index d8ad5511943..00000000000 --- a/site/_docs/quickstart.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: docs -title: Quick-start guide -permalink: /docs/quickstart/ ---- - -For the impatient, here's how to get a boilerplate Jekyll site up and running. - -{% highlight bash %} -~ $ gem install jekyll -~ $ jekyll new myblog -~ $ cd myblog -~/myblog $ jekyll serve -# => Now browse to http://localhost:4000 -{% endhighlight %} - -If you wish to install jekyll into the current directory, you can do so by -alternatively running `jekyll new .` instead of a new directory name. - -That's nothing, though. The real magic happens when you start creating blog -posts, using the front matter to control templates and layouts, and taking -advantage of all the awesome configuration options Jekyll makes available. - -If you're running into problems, ensure you have all the [requirements -installed][Installation]. - -[Installation]: /docs/installation/ diff --git a/site/_docs/resources.md b/site/_docs/resources.md deleted file mode 100644 index 8ede6a68da0..00000000000 --- a/site/_docs/resources.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -layout: docs -title: Resources -permalink: /docs/resources/ ---- - -Jekyll’s growing use is producing a wide variety of tutorials, frameworks, extensions, examples, and other resources that can be very helpful. Below is a collection of links to some of the most popular Jekyll resources. - -### Jekyll tips & tricks, and examples - -- [Tips for working with GitHub Pages Integration](https://gist.github.com/2890453) - - Code example reuse, and keeping documentation up to date. - -- [Use FormKeep for Jekyll form backend and webhooks](https://formkeep.com/) -- [Use Simple Form to integrate a simple contact - form](http://getsimpleform.com/) -- [JekyllBootstrap.com](http://jekyllbootstrap.com) - - Provides detailed explanations, examples, and helper-code to make - getting started with Jekyll easier. - -### Tutorials - -#### Integrating Jekyll with Git - -- [Blogging with Git, Emacs and Jekyll](http://metajack.im/2009/01/23/blogging-with-git-emacs-and-jekyll/) - -#### Other hacks - -- [Integrating Twitter with Jekyll](http://www.justkez.com/integrating-twitter-with-jekyll/) - > “Having migrated Justkez.com to be based on Jekyll, I was pondering how I might include my recent twitterings on the front page of the site. In the WordPress world, this would have been done via a plugin which may or may not have hung the loading of the page, might have employed caching, but would certainly have had some overheads. … Not in Jekyll.” -- [‘My Jekyll Fork’, by Mike West](http://mikewest.org/2009/11/my-jekyll-fork) - > “Jekyll is a well-architected throwback to a time before WordPress, when men were men, and HTML was static. I like the ideas it espouses, and have made a few improvements to it’s core. Here, I’ll point out some highlights of my fork in the hopes that they see usage beyond this site.” -- [‘About this Website’, by Carter Allen](http://cartera.me/2010/08/12/about-this-website/) - > “Jekyll is everything that I ever wanted in a blogging engine. Really. It isn’t perfect, but what’s excellent about it is that if there’s something wrong, I know exactly how it works and how to fix it. It runs on the your machine only, and is essentially an added”build" step between you and the browser. I coded this entire site in TextMate using standard HTML5 and CSS3, and then at the end I added just a few little variables to the markup. Presto-chango, my site is built and I am at peace with the world.” -- [‘Build A Blog With Jekyll And GitHub Pages’, by Barry Clark](http://www.smashingmagazine.com/2014/08/01/build-blog-jekyll-github-pages/) - > “I recently migrated my blog from WordPress to Jekyll, a fantastic website generator that’s designed for building minimal, static blogs to be hosted on GitHub Pages. The simplicity of Jekyll’s theming layer and writing workflow is fantastic; however, setting up my website took a lot longer than expected. In this article we'll walk through: the quickest way to set up a Jekyll powered blog, how to avoid common problems with using Jekyll, how to import your content from Wordpress, and more.” -- [Generating a Tag Cloud in Jekyll](http://www.justkez.com/generating-a-tag-cloud-in-jekyll/) -A guide to implementing a tag cloud and per-tag content pages using Jekyll. - -- A way to [extend Jekyll](https://github.com/rfelix/jekyll_ext) without forking and modifying the Jekyll gem codebase and some [portable Jekyll extensions](https://wiki.github.com/rfelix/jekyll_ext/extensions) that can be reused and shared. - -- [Using your Rails layouts in Jekyll](http://numbers.brighterplanet.com/2010/08/09/sharing-rails-views-with-jekyll) - -- [Adding Ajax pagination to Jekyll](https://eduardoboucas.com/blog/2014/11/10/adding-ajax-pagination-to-jekyll.html) diff --git a/site/_docs/sites.md b/site/_docs/sites.md deleted file mode 100644 index 42d0492148e..00000000000 --- a/site/_docs/sites.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -layout: docs -title: Sites using Jekyll -permalink: /docs/sites/ ---- - -It’s interesting to see what designs and features others have come up -with. Below are some Jekyll-powered blogs which were hand-picked for -learning purposes. - -- [Tom Preston-Werner](http://tom.preston-werner.com/) - ([source](https://github.com/mojombo/mojombo.github.io)) -- [Nick Quaranto](http://quaran.to/) - ([source](https://github.com/qrush/qrush.github.com)) -- [Roger Chapman](http://rogchap.com/) - ([source](https://github.com/rogchap/rogchap.github.com)) -- [GitHub Official Teaching Materials](http://training.github.com) - ([source](https://github.com/github/training.github.com/tree/7049d7532a6856411e34046aedfce43a4afaf424)) -- [Rasmus Andersson](http://rsms.me/) - ([source](https://github.com/rsms/rsms.github.com)) -- [Scott Chacon](http://schacon.github.com) - ([source](https://github.com/schacon/schacon.github.com)) -- [Leonard Lamprecht](http://leo.im) - ([source](https://github.com/leo/leo.github.io)) - -If you would like to explore more examples, you can find a list of sites -and their sources on the ["Sites" page in the Jekyll wiki][jekyll-sites]. - -[jekyll-sites]: {{ site.repository }}/wiki/Sites diff --git a/site/_docs/static_files.md b/site/_docs/static_files.md deleted file mode 100644 index 00afbaecbe0..00000000000 --- a/site/_docs/static_files.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -layout: docs -title: Static Files -permalink: /docs/static-files/ ---- - -In addition to renderable and convertible content, we also have **static -files**. - -A static file is a file that does not contain any YAML front matter. These -include images, PDFs, and other un-rendered content. - -They're accessible in Liquid via `site.static_files` and contain the -following metadata: - -
    - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription

    file.path

    - - The relative path to the file. - -

    file.modified_time

    - - The `Time` the file was last modified. - -

    file.extname

    - - The extension name for the file, e.g. - .jpg for image.jpg - -

    -
    diff --git a/site/_docs/structure.md b/site/_docs/structure.md deleted file mode 100644 index eb6a0892784..00000000000 --- a/site/_docs/structure.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -layout: docs -title: Directory structure -permalink: /docs/structure/ ---- - -Jekyll is, at its core, a text transformation engine. The concept behind the -system is this: you give it text written in your favorite markup language, be -that Markdown, Textile, or just plain HTML, and it churns that through a layout -or series of layout files. Throughout that process you can tweak how you want -the site URLs to look, what data gets displayed in the layout, and more. This -is all done through editing text files, and the static web site is the final -product. - -A basic Jekyll site usually looks something like this: - -{% highlight bash %} -. -├── _config.yml -├── _drafts -| ├── begin-with-the-crazy-ideas.textile -| └── on-simplicity-in-technology.markdown -├── _includes -| ├── footer.html -| └── header.html -├── _layouts -| ├── default.html -| └── post.html -├── _posts -| ├── 2007-10-29-why-every-programmer-should-play-nethack.textile -| └── 2009-04-26-barcamp-boston-4-roundup.textile -├── _data -| └── members.yml -├── _site -├── .jekyll-metadata -└── index.html -{% endhighlight %} - -An overview of what each of these does: - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    File / DirectoryDescription
    -

    _config.yml

    -
    -

    - - Stores configuration data. Many of - these options can be specified from the command line executable but - it’s easier to specify them here so you don’t have to remember them. - -

    -
    -

    _drafts

    -
    -

    - - Drafts are unpublished posts. The format of these files is without a - date: title.MARKUP. Learn how to - work with drafts. - -

    -
    -

    _includes

    -
    -

    - - These are the partials that can be mixed and matched by your layouts - and posts to facilitate reuse. The liquid tag - {% raw %}{% include file.ext %}{% endraw %} - can be used to include the partial in - _includes/file.ext. - -

    -
    -

    _layouts

    -
    -

    - - These are the templates that wrap posts. Layouts are chosen on a - post-by-post basis in the - YAML Front Matter, - which is described in the next section. The liquid tag - {% raw %}{{ content }}{% endraw %} - is used to inject content into the web page. - -

    -
    -

    _posts

    -
    -

    - - Your dynamic content, so to speak. The naming convention of these - files is important, and must follow the format: - YEAR-MONTH-DAY-title.MARKUP. - The permalinks can be customized for - each post, but the date and markup language are determined solely by - the file name. - -

    -
    -

    _data

    -
    -

    - - Well-formatted site data should be placed here. The jekyll engine - will autoload all YAML files in this directory (using either the - .yml, .yaml, .json or - .csv formats and extensions) and they will be - accessible via `site.data`. If there's a file - members.yml under the directory, then you can access - contents of the file through site.data.members. - -

    -
    -

    _site

    -
    -

    - - This is where the generated site will be placed (by default) once - Jekyll is done transforming it. It’s probably a good idea to add this - to your .gitignore file. - -

    -
    -

    .jekyll-metadata

    -
    -

    - - This helps Jekyll keep track of which files have not been modified - since the site was last built, and which files will need to be - regenerated on the next build. This file will not be included in the - generated site. It’s probably a good idea to add this to your - .gitignore file. - -

    -
    -

    index.html and other HTML, Markdown, Textile files

    -
    -

    - - Provided that the file has a YAML Front - Matter section, it will be transformed by Jekyll. The same will - happen for any .html, .markdown, - .md, or .textile file in your site’s root - directory or directories not listed above. - -

    -
    -

    Other Files/Folders

    -
    -

    - - Every other directory and file except for those listed above—such as - css and images folders, - favicon.ico files, and so forth—will be copied verbatim - to the generated site. There are plenty of sites - already using Jekyll if you’re curious to see how they’re laid - out. - -

    -
    -
    diff --git a/site/_docs/templates.md b/site/_docs/templates.md deleted file mode 100644 index 7a4ed049294..00000000000 --- a/site/_docs/templates.md +++ /dev/null @@ -1,425 +0,0 @@ ---- -layout: docs -title: Templates -permalink: /docs/templates/ ---- - -Jekyll uses the [Liquid](https://github.com/Shopify/liquid/wiki) templating language to -process templates. All of the standard Liquid [tags](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers#tags) and -[filters](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers#standard-filters) are -supported. Jekyll even adds a few handy filters and tags of its own to make -common tasks easier. - -## Filters - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    DescriptionFilter and Output
    -

    Date to XML Schema

    -

    Convert a Date into XML Schema (ISO 8601) format.

    -
    -

    - {% raw %}{{ site.time | date_to_xmlschema }}{% endraw %} -

    -

    - 2008-11-07T13:07:54-08:00 -

    -
    -

    Date to RFC-822 Format

    -

    Convert a Date into the RFC-822 format used for RSS feeds.

    -
    -

    - {% raw %}{{ site.time | date_to_rfc822 }}{% endraw %} -

    -

    - Mon, 07 Nov 2008 13:07:54 -0800 -

    -
    -

    Date to String

    -

    Convert a date to short format.

    -
    -

    - {% raw %}{{ site.time | date_to_string }}{% endraw %} -

    -

    - 07 Nov 2008 -

    -
    -

    Date to Long String

    -

    Format a date to long format.

    -
    -

    - {% raw %}{{ site.time | date_to_long_string }}{% endraw %} -

    -

    - 07 November 2008 -

    -
    -

    Where

    -

    Select all the objects in an array where the key has the given value.

    -
    -

    - {% raw %}{{ site.members | where:"graduation_year","2014" }}{% endraw %} -

    -
    -

    Group By

    -

    Group an array's items by a given property.

    -
    -

    - {% raw %}{{ site.members | group_by:"graduation_year" }}{% endraw %} -

    -

    - [{"name"=>"2013", "items"=>[...]}, -{"name"=>"2014", "items"=>[...]}] -

    -
    -

    XML Escape

    -

    Escape some text for use in XML.

    -
    -

    - {% raw %}{{ page.content | xml_escape }}{% endraw %} -

    -
    -

    CGI Escape

    -

    - CGI escape a string for use in a URL. Replaces any special characters - with appropriate %XX replacements. -

    -
    -

    - {% raw %}{{ "foo,bar;baz?" | cgi_escape }}{% endraw %} -

    -

    - foo%2Cbar%3Bbaz%3F -

    -
    -

    URI Escape

    -

    - URI escape a string. -

    -
    -

    - {% raw %}{{ "foo, bar \baz?" | uri_escape }}{% endraw %} -

    -

    - foo,%20bar%20%5Cbaz? -

    -
    -

    Number of Words

    -

    Count the number of words in some text.

    -
    -

    - {% raw %}{{ page.content | number_of_words }}{% endraw %} -

    -

    - 1337 -

    -
    -

    Array to Sentence

    -

    Convert an array into a sentence. Useful for listing tags.

    -
    -

    - {% raw %}{{ page.tags | array_to_sentence_string }}{% endraw %} -

    -

    - foo, bar, and baz -

    -
    -

    Markdownify

    -

    Convert a Markdown-formatted string into HTML.

    -
    -

    - {% raw %}{{ page.excerpt | markdownify }}{% endraw %} -

    -
    -

    Converting Sass/SCSS

    -

    Convert a Sass- or SCSS-formatted string into CSS.

    -
    -

    - {% raw %}{{ some_scss | scssify }}{% endraw %} - {% raw %}{{ some_sass | sassify }}{% endraw %} -

    -
    -

    Slugify

    -

    Convert a string into a lowercase URL "slug". See below for options.

    -
    -

    - {% raw %}{{ "The _config.yml file" | slugify }}{% endraw %} -

    -

    - the-config-yml-file -

    -

    - {% raw %}{{ "The _config.yml file" | slugify: 'pretty' }}{% endraw %} -

    -

    - the-_config.yml-file -

    -
    -

    Data To JSON

    -

    Convert Hash or Array to JSON.

    -
    -

    - {% raw %}{{ site.data.projects | jsonify }}{% endraw %} -

    -
    -

    Sort

    -

    Sort an array. Optional arguments for hashes: 1. property name 2. nils order (first or last).

    -
    -

    - {% raw %}{{ page.tags | sort }}{% endraw %} -

    -

    - {% raw %}{{ site.posts | sort: 'author' }}{% endraw %} -

    -

    - {% raw %}{{ site.pages | sort: 'title', 'last' }}{% endraw %} -

    -
    -
    - -### Options for the `slugify` filter - -The `slugify` filter accepts an option, each specifying what to filter. -The default is `default`. They are as follows (with what they filter): - -- `none`: no characters -- `raw`: spaces -- `default`: spaces and non-alphanumeric characters -- `pretty`: spaces and non-alphanumeric characters except for `._~!$&'()+,;=@` - -## Tags - -### Includes - -If you have small page fragments that you wish to include in multiple places on -your site, you can use the `include` tag. - -{% highlight ruby %} -{% raw %}{% include footer.html %}{% endraw %} -{% endhighlight %} - -Jekyll expects all include files to be placed in an `_includes` directory at the -root of your source directory. This will embed the contents of -`/_includes/footer.html` into the calling file. - -
    -
    ProTip™: Use variables as file name
    -

    - - The name of the file you wish to embed can be literal (as in the example above), - or you can use a variable, using liquid-like variable syntax as in - {% raw %}{% include {{my_variable}} %}{% endraw %}. - -

    -
    - -You can also pass parameters to an include. Omit the quotation marks to send a variable's value. Liquid curly brackets should not be used here: - -{% highlight ruby %} -{% raw %}{% include footer.html param="value" variable-param=page.variable %}{% endraw %} -{% endhighlight %} - -These parameters are available via Liquid in the include: - -{% highlight ruby %} -{% raw %}{{ include.param }}{% endraw %} -{% endhighlight %} - -#### Including files relative to another file - -You can also choose to include file fragments relative to the current file: - -{% highlight ruby %} -{% raw %}{% include_relative somedir/footer.html %}{% endraw %} -{% endhighlight %} - -You won't need to place your included content within the `_includes` directory. Instead, -the inclusion is specifically relative to the file where the tag is being used. For example, -if `_posts/2014-09-03-my-file.markdown` uses the `include_relative` tag, the included file -must be within the `_posts` directory, or one of its subdirectories. You cannot include -files in other locations. - -All the other capabilities of the `include` tag are available to the `include_relative` tag, -such as using variables. - -### Code snippet highlighting - -Jekyll has built in support for syntax highlighting of [over 100 -languages](http://pygments.org/languages/) thanks to -[Pygments](http://pygments.org/). To use Pygments, you must have Python installed -on your system and set `highlighter` to `pygments` in your site's configuration -file. - -Alternatively, you can use [Rouge](https://github.com/jayferd/rouge) to highlight -your code snippets. It doesn't support as many languages as Pygments, however it -should suit most use cases. Also, since [Rouge](https://github.com/jayferd/rouge) -is written in pure Ruby, you don't need Python on your system! - -To render a code block with syntax highlighting, surround your code as follows: - -{% highlight text %} -{% raw %} -{% highlight ruby %} -def foo - puts 'foo' -end -{% endhighlight %} -{% endraw %} -{% endhighlight %} - -The argument to the `highlight` tag (`ruby` in the example above) is the -language identifier. To find the appropriate identifier to use for the language -you want to highlight, look for the “short name” on the [Pygments' Lexers -page](http://pygments.org/docs/lexers/) or the [Rouge -wiki](https://github.com/jayferd/rouge/wiki/List-of-supported-languages-and-lexers). - -#### Line numbers - -There is a second argument to `highlight` called `linenos` that is optional. -Including the `linenos` argument will force the highlighted code to include line -numbers. For instance, the following code block would include line numbers next -to each line: - -{% highlight text %} -{% raw %} -{% highlight ruby linenos %} -def foo - puts 'foo' -end -{% endhighlight %} -{% endraw %} -{% endhighlight %} - -#### Stylesheets for syntax highlighting - -In order for the highlighting to show up, you’ll need to include a highlighting -stylesheet. For an example stylesheet you can look at -[syntax.css](https://github.com/mojombo/tpw/tree/master/css/syntax.css). These -are the same styles as used by GitHub and you are free to use them for your own -site. If you use `linenos`, you might want to include an additional CSS class -definition for the `.lineno` class in `syntax.css` to distinguish the line -numbers from the highlighted code. - -### Post URL - -If you would like to include a link to a post on your site, the `post_url` tag -will generate the correct permalink URL for the post you specify. - -{% highlight text %} -{% raw %} -{% post_url 2010-07-21-name-of-post %} -{% endraw %} -{% endhighlight %} - -If you organize your posts in subdirectories, you need to include subdirectory -path to the post: - -{% highlight text %} -{% raw %} -{% post_url /subdir/2010-07-21-name-of-post %} -{% endraw %} -{% endhighlight %} - -There is no need to include the file extension when using the `post_url` tag. - -You can also use this tag to create a link to a post in Markdown as follows: - -{% highlight text %} -{% raw %} -[Name of Link]({% post_url 2010-07-21-name-of-post %}) -{% endraw %} -{% endhighlight %} - -### Gist - -Use the `gist` tag to easily embed a GitHub Gist onto your site. This works -with public or secret gists: - -{% highlight text %} -{% raw %} -{% gist parkr/931c1c8d465a04042403 %} -{% endraw %} -{% endhighlight %} - -You may also optionally specify the filename in the gist to display: - -{% highlight text %} -{% raw %} -{% gist parkr/931c1c8d465a04042403 jekyll-private-gist.markdown %} -{% endraw %} -{% endhighlight %} - -To use the `gist` tag, you'll need to add the [jekyll-gist](https://github.com/jekyll/jekyll-gist) gem to your project. diff --git a/site/_docs/troubleshooting.md b/site/_docs/troubleshooting.md deleted file mode 100644 index 5d7b1ad9b5c..00000000000 --- a/site/_docs/troubleshooting.md +++ /dev/null @@ -1,207 +0,0 @@ ---- -layout: docs -title: Troubleshooting -permalink: /docs/troubleshooting/ ---- - -If you ever run into problems installing or using Jekyll, here are a few tips -that might be of help. If the problem you’re experiencing isn’t covered below, -**please [check out our other help resources](/help/)** as well. - -- [Installation Problems](#installation-problems) -- [Problems running Jekyll](#problems-running-jekyll) -- [Base-URL Problems](#base-url-problems) -- [Configuration problems](#configuration-problems) -- [Markup Problems](#markup-problems) - -## Installation Problems - -If you encounter errors during gem installation, you may need to install -the header files for compiling extension modules for Ruby 2.0.0. This -can be done on Ubuntu or Debian by running: - -{% highlight bash %} -sudo apt-get install ruby2.0.0-dev -{% endhighlight %} - -On Red Hat, CentOS, and Fedora systems you can do this by running: - -{% highlight bash %} -sudo yum install ruby-devel -{% endhighlight %} - -On [NearlyFreeSpeech](https://www.nearlyfreespeech.net/) you need to run the -following commands before installing Jekyll: - -{% highlight bash %} -export GEM_HOME=/home/private/gems -export GEM_PATH=/home/private/gems:/usr/local/lib/ruby/gems/1.8/ -export PATH=$PATH:/home/private/gems/bin -export RB_USER_INSTALL='true' -{% endhighlight %} - -To install RubyGems on Gentoo: - -{% highlight bash %} -sudo emerge -av dev-ruby/rubygems -{% endhighlight %} - -On Windows, you may need to install [RubyInstaller -DevKit](https://wiki.github.com/oneclick/rubyinstaller/development-kit). - -On Mac OS X, you may need to update RubyGems (using `sudo` only if necessary): - -{% highlight bash %} -sudo gem update --system -{% endhighlight %} - -If you still have issues, you can download and install new Command Line -Tools (such as `gcc`) using the command - -{% highlight bash %} -xcode-select --install -{% endhighlight %} - -which may allow you to install native gems using this command (again using -`sudo` only if necessary): - -{% highlight bash %} -sudo gem install jekyll -{% endhighlight %} - -Note that upgrading Mac OS X does not automatically upgrade Xcode itself -(that can be done separately via the App Store), and having an out-of-date -Xcode.app can interfere with the command line tools downloaded above. If -you run into this issue, upgrade Xcode and install the upgraded Command -Line Tools. - -### Jekyll & Mac OS X 10.11 - -With the introduction of System Integrity Protection, several directories -that were previously writable are now considered system locations and are no -longer available. Given these changes, there are a couple of simple ways to get -up and running. One option is to change the location where the gem will be -installed (again using `sudo` only if necessary): - -{% highlight bash %} -sudo gem install -n /usr/local/bin jekyll -{% endhighlight %} - -Alternatively, Homebrew can be installed and used to set up Ruby. This can be -done as follows: - -{% highlight bash %} -ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" -{% endhighlight %} - -Once Homebrew is installed, the second step is easy: - -{% highlight bash %} -brew install ruby -{% endhighlight %} - -Advanced users (with more complex needs) may find it helpful to choose one of a -number of Ruby version managers ([RVM][], [rbenv][], [chruby][], [etc][].) in -which to install Jekyll. - -[RVM]: https://rvm.io -[rbenv]: http://rbenv.org -[chruby]: https://github.com/postmodern/chruby -[etc]: https://github.com/rvm/rvm/blob/master/docs/alt.md - -If you elect to use one of the above methods to install Ruby, it might be -necessary to modify your `$PATH` variable using the following command: - -{% highlight bash %} -export PATH=/usr/local/bin:$PATH -{% endhighlight %} - -GUI apps can modify the `$PATH` as follows: - -{% highlight bash %} -launchctl setenv PATH "/usr/local/bin:$PATH" -{% endhighlight %} - -Either of these approaches are useful because `/usr/local` is considered a -"safe" location on systems which have SIP enabled, they avoid potential -conflicts with the version of Ruby included by Apple, and it keeps Jekyll and -its dependencies in a sandboxed environment. This also has the added -benefit of not requiring `sudo` when you want to add or remove a gem. - -### Could not find a JavaScript runtime. (ExecJS::RuntimeUnavailable) - -This error can occur during the installation of `jekyll-coffeescript` when -you don't have a proper JavaScript runtime. To solve this, either install -`execjs` and `therubyracer` gems, or install `nodejs`. Check out -[issue #2327](https://github.com/jekyll/jekyll/issues/2327) for more info. - -## Problems running Jekyll - -On Debian or Ubuntu, you may need to add `/var/lib/gems/1.8/bin/` to your path -in order to have the `jekyll` executable be available in your Terminal. - -## Base-URL Problems - -If you are using base-url option like: - -{% highlight bash %} -jekyll serve --baseurl '/blog' -{% endhighlight %} - -… then make sure that you access the site at: - -{% highlight bash %} -http://localhost:4000/blog/index.html -{% endhighlight %} - -It won’t work to just access: - -{% highlight bash %} -http://localhost:4000/blog -{% endhighlight %} - -## Configuration problems - -The order of precedence for conflicting [configuration settings](../configuration/) -is as follows: - -1. Command-line flags -2. Configuration file settings -3. Defaults - -That is: defaults are overridden by options specified in `_config.yml`, -and flags specified at the command-line will override all other settings -specified elsewhere. - -## Markup Problems - -The various markup engines that Jekyll uses may have some issues. This -page will document them to help others who may run into the same -problems. - -### Liquid - -The latest version, version 2.0, seems to break the use of `{{ "{{" }}` in -templates. Unlike previous versions, using `{{ "{{" }}` in 2.0 triggers the -following error: - -{% highlight bash %} -'{{ "{{" }}' was not properly terminated with regexp: /\}\}/ (Liquid::SyntaxError) -{% endhighlight %} - -### Excerpts - -Since v1.0.0, Jekyll has had automatically-generated post excerpts. Since -v1.1.0, Jekyll also passes these excerpts through Liquid, which can cause -strange errors where references don't exist or a tag hasn't been closed. If you -run into these errors, try setting `excerpt_separator: ""` in your -`_config.yml`, or set it to some nonsense string. - -
    -
    Please report issues you encounter!
    -

    - If you come across a bug, please create an issue - on GitHub describing the problem and any work-arounds you find so we can - document it here for others. -

    -
    diff --git a/site/_docs/upgrading.md b/site/_docs/upgrading.md deleted file mode 100644 index a1280672d96..00000000000 --- a/site/_docs/upgrading.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: docs -title: Upgrading -permalink: /docs/upgrading/ ---- - -Upgrading from an older version of Jekyll? Upgrading to a new major version of Jekyll (e.g. from v2.x to v3.x) may cause some headaches. Take the following guides to aid your upgrade: - -- [From 0.x to 1.x and 2.x](/docs/upgrading/0-to-2/) -- [From 2.x to 3.x](/docs/upgrading/2-to-3/) diff --git a/site/_docs/upgrading/2-to-3.md b/site/_docs/upgrading/2-to-3.md deleted file mode 100644 index 25d38b00aad..00000000000 --- a/site/_docs/upgrading/2-to-3.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -layout: docs -title: Upgrading from 2.x to 3.x -permalink: /docs/upgrading/2-to-3/ ---- - -Upgrading from an older version of Jekyll? A few things have changed in 3.0 -that you'll want to know about. - -Before we dive in, go ahead and fetch the latest version of Jekyll: - -{% highlight bash %} -$ gem update jekyll -{% endhighlight %} - -
    -
    Diving in
    -

    Want to get a new Jekyll site up and running quickly? Simply - run jekyll new SITENAME to create a new folder with a bare bones - Jekyll site.

    -
    - -### site.collections has changed - -In 2.x, your iterations over `site.collections` yielded an array with the collection -label and the collection object as the first and second items, respectively. In 3.x, -this complication has been removed and iterations now yield simply the collection object. -A simple conversion must be made in your templates: - -- `collection[0]` becomes `collection.label` -- `collection[1]` becomes `collection` - -When iterating over `site.collections`, ensure the above conversions are made. - -### Dropped dependencies - -We dropped a number of dependencies the Core Team felt were optional. As such, in 3.0, they must be explicitly installed and included if you use any of the features. They are: - -- jekyll-paginate – Jekyll's pagination solution from days past -- jekyll-coffeescript – processing of CoffeeScript -- jekyll-gist – the `gist` Liquid tag -- pygments.rb – the Pygments highlighter -- redcarpet – the Markdown processor -- toml – an alternative to YAML for configuration files -- classifier-reborn – for `site.related_posts` - -### Future posts - -A seeming feature regression in 2.x, the `--future` flag was automatically _enabled_. -The future flag allows post authors to give the post a date in the future and to have -it excluded from the build until the system time is equal or after the post time. -In Jekyll 3, this has been corrected. **Now, `--future` is disabled by default.** -This means you will need to include `--future` if you want your future-dated posts to -generate when running `jekyll build` or `jekyll serve`. - -### Layout metadata - -Introducing: `layout`. In Jekyll 2 and below, any metadata in the layout was munged onto -the `page` variable in Liquid. This caused a lot of confusion in the way the data was -merged and some unexpected behaviour. In Jekyll 3, all layout data is accessible via `layout` -in Liquid. For example, if your layout has `class: my-layout` in its YAML front matter, -then the layout can access that via `{% raw %}{{ layout.class }}{% endraw %}`. - -_Did we miss something? Please click "Improve this page" above and add a section. Thanks!_ diff --git a/site/_docs/usage.md b/site/_docs/usage.md deleted file mode 100644 index 28c4efb0a06..00000000000 --- a/site/_docs/usage.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -layout: docs -title: Basic Usage -permalink: /docs/usage/ ---- - -The Jekyll gem makes a `jekyll` executable available to you in your Terminal -window. You can use this command in a number of ways: - -{% highlight bash %} -$ jekyll build -# => The current folder will be generated into ./_site - -$ jekyll build --destination -# => The current folder will be generated into - -$ jekyll build --source --destination -# => The folder will be generated into - -$ jekyll build --watch -# => The current folder will be generated into ./_site, -# watched for changes, and regenerated automatically. -{% endhighlight %} - -
    -
    Changes to _config.yml are not included during automatic regeneration.
    -

    - The _config.yml master configuration file contains global configurations - and variable definitions that are read once at execution time. Changes made to _config.yml - during automatic regeneration are not loaded until the next execution. -

    -

    - Note Data Files are included and reloaded during automatic regeneration. -

    -
    - -
    -
    Destination folders are cleaned on site builds
    -

    - The contents of <destination> are automatically - cleaned, by default, when the site is built. Files or folders that are not - created by your site will be removed. Files and folders you wish to retain - in <destination> may be specified within the <keep_files> - configuration directive. -

    -

    - Do not use an important location for <destination>; - instead, use it as a staging area and copy files from there to your web server. -

    -
    - -Jekyll also comes with a built-in development server that will allow you to -preview what the generated site will look like in your browser locally. - -{% highlight bash %} -$ jekyll serve -# => A development server will run at http://localhost:4000/ -# Auto-regeneration: enabled. Use `--no-watch` to disable. - -$ jekyll serve --detach -# => Same as `jekyll serve` but will detach from the current terminal. -# If you need to kill the server, you can `kill -9 1234` where "1234" is the PID. -# If you cannot find the PID, then do, `ps aux | grep jekyll` and kill the instance. [Read more](http://unixhelp.ed.ac.uk/shell/jobz5.html). -{% endhighlight %} - -
    -
    Be aware of default behavior
    -

    - As of version 2.4, the serve command will watch for changes automatically. To disable this, you can use jekyll serve --no-watch, which preserves the old behavior. -

    -
    - -{% highlight bash %} -$ jekyll serve --no-watch -# => Same as `jekyll serve` but will not watch for changes. -{% endhighlight %} - -These are just a few of the available [configuration options](../configuration/). -Many configuration options can either be specified as flags on the command line, -or alternatively (and more commonly) they can be specified in a `_config.yml` -file at the root of the source directory. Jekyll will automatically use the -options from this file when run. For example, if you place the following lines -in your `_config.yml` file: - -{% highlight yaml %} -source: _source -destination: _deploy -{% endhighlight %} - -Then the following two commands will be equivalent: - -{% highlight bash %} -$ jekyll build -$ jekyll build --source _source --destination _deploy -{% endhighlight %} - -For more about the possible configuration options, see the -[configuration](../configuration/) page. - -If you're interested in browsing these docs on-the-go, install the -`jekyll-docs` gem and run `jekyll docs` in your terminal. diff --git a/site/_docs/variables.md b/site/_docs/variables.md deleted file mode 100644 index d4fb5293ddf..00000000000 --- a/site/_docs/variables.md +++ /dev/null @@ -1,390 +0,0 @@ ---- -layout: docs -title: Variables -permalink: /docs/variables/ ---- - -Jekyll traverses your site looking for files to process. Any files with [YAML -front matter](../frontmatter/) are subject to processing. For each of these -files, Jekyll makes a variety of data available via the [Liquid templating -system](https://github.com/Shopify/liquid/wiki). The -following is a reference of the available data. - -## Global Variables - -
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription

    site

    - - Sitewide information + configuration settings from - _config.yml. See below for details. - -

    page

    - - Page specific information + the YAML front - matter. Custom variables set via the YAML Front Matter will be - available here. See below for details. - -

    content

    - - In layout files, the rendered content of the Post or Page being wrapped. - Not defined in Post or Page files. - -

    paginator

    - - When the paginate configuration option is set, this - variable becomes available for use. See Pagination for details. - -

    -
    - -## Site Variables - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription

    site.time

    - - The current time (when you run the jekyll command). - -

    site.pages

    - - A list of all Pages. - -

    site.posts

    - - A reverse chronological list of all Posts. - -

    site.related_posts

    - - If the page being processed is a Post, this contains a list of up to ten - related Posts. By default, these are the ten most recent posts. - For high quality but slow to compute results, run the - jekyll command with the --lsi (latent semantic - indexing) option. Also note Github pages does not support the lsi option when generating sites. - -

    site.static_files

    - - A list of all static files (i.e. - files not processed by Jekyll's converters or the Liquid renderer). - Each file has three properties: path, - modified_time and extname. - -

    site.html_pages

    - - A subset of `site.pages` listing those which end in `.html`. - -

    site.html_files

    - - A subset of `site.static_files` listing those which end in `.html`. - -

    site.collections

    - - A list of all the collections. - -

    site.data

    - - A list containing the data loaded from the YAML files located in the _data directory. - -

    site.documents

    - - A list of all the documents in every collection. - -

    site.categories.CATEGORY

    - - The list of all Posts in category CATEGORY. - -

    site.tags.TAG

    - - The list of all Posts with tag TAG. - -

    site.[CONFIGURATION_DATA]

    - - All the variables set via the command line and your - _config.yml are available through the site - variable. For example, if you have url: http://mysite.com - in your configuration file, then in your Posts and Pages it will be - stored in site.url. Jekyll does not parse changes to - _config.yml in watch mode, you must restart - Jekyll to see changes to variables. - -

    -
    - -## Page Variables - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription

    page.content

    - - The content of the Page, rendered or un-rendered depending upon - what Liquid is being processed and what page is. - -

    page.title

    - - The title of the Page. - -

    page.excerpt

    - - The un-rendered excerpt of the Page. - -

    page.url

    - - The URL of the Post without the domain, but - with a leading slash, e.g. - /2008/12/14/my-post.html - -

    page.date

    - - The Date assigned to the Post. This can be overridden in a Post’s front - matter by specifying a new date/time in the format - YYYY-MM-DD HH:MM:SS (assuming UTC), or - YYYY-MM-DD HH:MM:SS +/-TTTT (to specify a time zone using - an offset from UTC. e.g. 2008-12-14 10:30:00 +0900). - -

    page.id

    - - An identifier unique to the Post (useful in RSS feeds). e.g. - /2008/12/14/my-post - -

    page.categories

    - - The list of categories to which this post belongs. Categories are - derived from the directory structure above the _posts - directory. For example, a post at - /work/code/_posts/2008-12-24-closures.md would have this - field set to ['work', 'code']. These can also be specified - in the YAML Front Matter. - -

    page.tags

    - - The list of tags to which this post belongs. These can be specified in - the YAML Front Matter. - -

    page.path

    - - The path to the raw post or page. Example usage: Linking back to the - page or post’s source on GitHub. This can be overridden in the - YAML Front Matter. - -

    page.next

    - - The next post relative to the position of the current post in - site.posts. Returns nil for the last entry. - -

    page.previous

    - - The previous post relative to the position of the current post in - site.posts. Returns nil for the first entry. - -

    -
    - -
    -
    ProTip™: Use Custom Front Matter
    -

    - - Any custom front matter that you specify will be available under - page. For example, if you specify custom_css: true - in a page’s front matter, that value will be available as - page.custom_css. - -

    -
    - -## Paginator - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableDescription

    paginator.per_page

    Number of Posts per page.

    paginator.posts

    Posts available for that page.

    paginator.total_posts

    Total number of Posts.

    paginator.total_pages

    Total number of Pages.

    paginator.page

    The number of the current page.

    paginator.previous_page

    The number of the previous page.

    paginator.previous_page_path

    The path to the previous page.

    paginator.next_page

    The number of the next page.

    paginator.next_page_path

    The path to the next page.

    -
    - -
    -
    Paginator variable availability
    -

    - - These are only available in index files, however they can be located in a - subdirectory, such as /blog/index.html. - -

    -
    diff --git a/site/_docs/windows.md b/site/_docs/windows.md deleted file mode 100644 index a3e6b5f0677..00000000000 --- a/site/_docs/windows.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -layout: docs -title: Jekyll on Windows -permalink: /docs/windows/ ---- - -While Windows is not an officially-supported platform, it can be used to run -Jekyll with the proper tweaks. This page aims to collect some of the general -knowledge and lessons that have been unearthed by Windows users. - -## Installation - -Julian Thilo has written up instructions to get -[Jekyll running on Windows][windows-installation] and it seems to work for most. -The instructions were written for Ruby 2.0.0, but should work for later versions -[prior to 2.2][hitimes-issue]. - -## Encoding - -If you use UTF-8 encoding, make sure that no `BOM` header -characters exist in your files or very, very bad things will happen to -Jekyll. This is especially relevant if you're running Jekyll on Windows. - -Additionally, you might need to change the code page of the console window to UTF-8 -in case you get a "Liquid Exception: Incompatible character encoding" error during -the site generation process. It can be done with the following command: - -{% highlight bash %} -$ chcp 65001 -{% endhighlight %} - -[windows-installation]: http://jekyll-windows.juthilo.com/ -[hitimes-issue]: https://github.com/copiousfreetime/hitimes/issues/40 - -## Auto-regeneration - -As of v1.3.0, Jekyll uses the `listen` gem to watch for changes when the -`--watch` switch is specified during a build or serve. While `listen` has -built-in support for UNIX systems, it requires an extra gem for compatibility -with Windows. Add the following to the Gemfile for your site: - -{% highlight ruby %} -gem 'wdm', '~> 0.1.0' if Gem.win_platform? -{% endhighlight %} diff --git a/site/_includes/analytics.html b/site/_includes/analytics.html deleted file mode 100644 index 5bbfc88858e..00000000000 --- a/site/_includes/analytics.html +++ /dev/null @@ -1,30 +0,0 @@ -{% if site.gauges_id %} - - -{% endif %} - -{% if site.google_analytics_id %} - - -{% endif %} diff --git a/site/_includes/anchor_links.html b/site/_includes/anchor_links.html deleted file mode 100644 index c584ce5d7c8..00000000000 --- a/site/_includes/anchor_links.html +++ /dev/null @@ -1,33 +0,0 @@ - diff --git a/site/_includes/docs_contents.html b/site/_includes/docs_contents.html deleted file mode 100644 index 2ac64bb497d..00000000000 --- a/site/_includes/docs_contents.html +++ /dev/null @@ -1,8 +0,0 @@ -
    - -
    diff --git a/site/_includes/docs_contents_mobile.html b/site/_includes/docs_contents_mobile.html deleted file mode 100644 index b3e0110cdfe..00000000000 --- a/site/_includes/docs_contents_mobile.html +++ /dev/null @@ -1,10 +0,0 @@ -
    - -
    diff --git a/site/_includes/docs_option.html b/site/_includes/docs_option.html deleted file mode 100644 index c2593971921..00000000000 --- a/site/_includes/docs_option.html +++ /dev/null @@ -1,11 +0,0 @@ -{% assign items = include.items %} - -{% for item in items %} - {% assign item_url = item | prepend:"/docs/" | append:"/" %} - - {% for p in site.docs %} - {% if p.url == item_url %} - - {% endif %} - {% endfor %} -{% endfor %} diff --git a/site/_includes/docs_ul.html b/site/_includes/docs_ul.html deleted file mode 100644 index 34b6278a84f..00000000000 --- a/site/_includes/docs_ul.html +++ /dev/null @@ -1,17 +0,0 @@ -{% assign items = include.items %} - -
      -{% for item in items %} - {% assign item_url = item | prepend:"/docs/" | append:"/" %} - - {% if item_url == page.url %} - {% assign c = "current" %} - {% else %} - {% assign c = "" %} - {% endif %} - - {% assign p = site.docs | where:"url",item_url | first %} -
    • {{ p.title }}
    • - -{% endfor %} -
    diff --git a/site/_includes/footer.html b/site/_includes/footer.html deleted file mode 100644 index 09bab7375da..00000000000 --- a/site/_includes/footer.html +++ /dev/null @@ -1,15 +0,0 @@ - diff --git a/site/_includes/header.html b/site/_includes/header.html deleted file mode 100644 index 517776706ca..00000000000 --- a/site/_includes/header.html +++ /dev/null @@ -1,18 +0,0 @@ -
    - -
    - - -
    -
    diff --git a/site/_includes/news_contents.html b/site/_includes/news_contents.html deleted file mode 100644 index 5c5452113cd..00000000000 --- a/site/_includes/news_contents.html +++ /dev/null @@ -1,33 +0,0 @@ -
    - -
    diff --git a/site/_includes/news_contents_mobile.html b/site/_includes/news_contents_mobile.html deleted file mode 100644 index e8fb55e7228..00000000000 --- a/site/_includes/news_contents_mobile.html +++ /dev/null @@ -1,11 +0,0 @@ -
    - -
    diff --git a/site/_includes/news_item.html b/site/_includes/news_item.html deleted file mode 100644 index aaf0521742d..00000000000 --- a/site/_includes/news_item.html +++ /dev/null @@ -1,24 +0,0 @@ - diff --git a/site/_includes/primary-nav-items.html b/site/_includes/primary-nav-items.html deleted file mode 100644 index df5b939f967..00000000000 --- a/site/_includes/primary-nav-items.html +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/site/_includes/section_nav.html b/site/_includes/section_nav.html deleted file mode 100644 index 2016997e03d..00000000000 --- a/site/_includes/section_nav.html +++ /dev/null @@ -1,39 +0,0 @@ -{% comment %} -Map grabs the doc sections, giving us an array of arrays. Join, flattens all -the items to a comma delimited string. Split turns it into an array again. -{% endcomment %} -{% assign docs = site.data.docs | map: 'docs' | join: ',' | split: ',' %} - -{% comment %} -Because this is built for every page, lets find where we are in the ordered -document list by comparing url strings. Then if there's something previous or -next, lets build a link to it. -{% endcomment %} - -{% for document in docs %} - {% assign document_url = document | prepend:"/docs/" | append:"/" %} - {% if document_url == page.url %} -
    -
    - {% if forloop.first %} - Back - {% else %} - {% assign previous = forloop.index0 | minus: 1 %} - {% assign previous_page = docs[previous] | prepend:"/docs/" | append:"/" %} - - {% endif %} -
    -
    - {% if forloop.last %} - Next - {% else %} - {% assign next = forloop.index0 | plus: 1 %} - {% assign next_page = docs[next] | prepend:"/docs/" | append:"/" %} - - {% endif %} -
    -
    -
    - {% break %} - {% endif %} -{% endfor %} \ No newline at end of file diff --git a/site/_includes/top.html b/site/_includes/top.html deleted file mode 100644 index 2d12d1bd929..00000000000 --- a/site/_includes/top.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - {{ page.title }} - - - {% feed_meta %} - - - - - - diff --git a/site/_layouts/default.html b/site/_layouts/default.html deleted file mode 100644 index 77ebd5f7d82..00000000000 --- a/site/_layouts/default.html +++ /dev/null @@ -1,13 +0,0 @@ -{% include top.html %} - - - {% include header.html %} - - {{ content }} - - {% include footer.html %} - {% include anchor_links.html %} - {% include analytics.html %} - - - diff --git a/site/_layouts/docs.html b/site/_layouts/docs.html deleted file mode 100644 index 0456c4cc9ae..00000000000 --- a/site/_layouts/docs.html +++ /dev/null @@ -1,26 +0,0 @@ ---- -layout: default ---- - -
    -
    - - {% include docs_contents_mobile.html %} - -
    - -
    - - {% include docs_contents.html %} - -
    - -
    -
    diff --git a/site/_layouts/news.html b/site/_layouts/news.html deleted file mode 100644 index 8f7945f345a..00000000000 --- a/site/_layouts/news.html +++ /dev/null @@ -1,19 +0,0 @@ ---- -layout: default ---- - -
    -
    - - {% include news_contents_mobile.html %} - -
    - {{ content }} -
    - - {% include news_contents.html %} - -
    - -
    -
    diff --git a/site/_layouts/news_item.html b/site/_layouts/news_item.html deleted file mode 100644 index 57ba62228bc..00000000000 --- a/site/_layouts/news_item.html +++ /dev/null @@ -1,27 +0,0 @@ ---- -layout: news ---- - -
    -

    - {{ page.title }} - -

    - - -
    - {{ content }} -
    -
    diff --git a/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown b/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown deleted file mode 100644 index 2d0096b1fe7..00000000000 --- a/site/_posts/2013-07-24-jekyll-1-1-1-released.markdown +++ /dev/null @@ -1,31 +0,0 @@ ---- -layout: news_item -title: "Jekyll 1.1.1 Released" -date: "2013-07-24 22:24:14 +0200" -author: parkr -version: 1.1.1 -categories: [release] ---- - - -Coming just 10 days after the release of v1.1.0, v1.1.1 is out with a patch for the nasty -excerpt inception bug ([#1339][]) and non-zero exit codes for invalid commands -([#1338][]). - -To all those affected by the [strange excerpt bug in v1.1.0][#1321], I'm sorry. I think we -have it all patched up and it should be deployed to [GitHub Pages][gh_pages] in the next -couple weeks. Thank you for your patience! - -If you're checking out v1.1.x for the first time, definitely check out [what shipped with -v1.1.0!][v1_1_0] - -See the [GitHub Release][] page for more a more detailed changelog for this release. - -{% assign issue_numbers = "1339|1338|1321" | split: "|" %} -{% for issue in issue_numbers %} -[#{{ issue }}]: {{ site.repository }}/issues/{{ issue }} -{% endfor %} - -[GitHub Release]: {{ site.repository }}/releases/tag/v1.1.1 -[gh_pages]: http://pages.github.com -[v1_1_0]: {{ site.repository }}/releases/tag/v1.1.0 diff --git a/site/_sass/_font-awesome.scss b/site/_sass/_font-awesome.scss deleted file mode 100644 index 681011e131d..00000000000 --- a/site/_sass/_font-awesome.scss +++ /dev/null @@ -1,25 +0,0 @@ -/*! - * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */ -@font-face { - font-family: 'FontAwesome'; - src: url('../fonts/fontawesome-webfont.eot?v=4.4.0'); - src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.4.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.4.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.4.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.4.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.4.0#fontawesomeregular') format('svg'); - font-weight: normal; - font-style: normal; -} -.fa { - display: inline-block; - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.fa-link:before { - content: "\f0c1"; -} -.fa-pencil:before { - content: "\f040"; -} diff --git a/site/_sass/_normalize.scss b/site/_sass/_normalize.scss deleted file mode 100644 index ba2f36c169f..00000000000 --- a/site/_sass/_normalize.scss +++ /dev/null @@ -1 +0,0 @@ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/site/_sass/_pygments.scss b/site/_sass/_pygments.scss deleted file mode 100644 index 2858bcd2fb7..00000000000 --- a/site/_sass/_pygments.scss +++ /dev/null @@ -1,78 +0,0 @@ -.highlight { - .hll { background-color: #ffffcc } - .c { color: #87ceeb} /* Comment */ - .err { color: #ffffff} /* Error */ - .g { color: #ffffff} /* Generic */ - .k { color: #f0e68c} /* Keyword */ - .l { color: #ffffff} /* Literal */ - .n { color: #ffffff} /* Name */ - .o { color: #ffffff} /* Operator */ - .x { color: #ffffff} /* Other */ - .p { color: #ffffff} /* Punctuation */ - .cm { color: #87ceeb} /* Comment.Multiline */ - .cp { color: #cd5c5c} /* Comment.Preproc */ - .c1 { color: #87ceeb} /* Comment.Single */ - .cs { color: #87ceeb} /* Comment.Special */ - .gd { color: #0000c0; font-weight: bold; background-color: #008080 } /* Generic.Deleted */ - .ge { color: #c000c0; text-decoration: underline} /* Generic.Emph */ - .gr { color: #c0c0c0; font-weight: bold; background-color: #c00000 } /* Generic.Error */ - .gh { color: #cd5c5c} /* Generic.Heading */ - .gi { color: #ffffff; background-color: #0000c0 } /* Generic.Inserted */ - span.go { color: #add8e6; font-weight: bold; background-color: #4d4d4d } /* Generic.Output, qualified with span to prevent applying this style to the Go language, see #1153. */ - .gp { color: #ffffff} /* Generic.Prompt */ - .gs { color: #ffffff} /* Generic.Strong */ - .gu { color: #cd5c5c} /* Generic.Subheading */ - .gt { color: #c0c0c0; font-weight: bold; background-color: #c00000 } /* Generic.Traceback */ - .kc { color: #f0e68c} /* Keyword.Constant */ - .kd { color: #f0e68c} /* Keyword.Declaration */ - .kn { color: #f0e68c} /* Keyword.Namespace */ - .kp { color: #f0e68c} /* Keyword.Pseudo */ - .kr { color: #f0e68c} /* Keyword.Reserved */ - .kt { color: #bdb76b} /* Keyword.Type */ - .ld { color: #ffffff} /* Literal.Date */ - .m { color: #ffffff} /* Literal.Number */ - .s { color: #ffffff} /* Literal.String */ - .na { color: #ffffff} /* Name.Attribute */ - .nb { color: #ffffff} /* Name.Builtin */ - .nc { color: #ffffff} /* Name.Class */ - .no { color: #ffa0a0} /* Name.Constant */ - .nd { color: #ffffff} /* Name.Decorator */ - .ni { color: #ffdead} /* Name.Entity */ - .ne { color: #ffffff} /* Name.Exception */ - .nf { color: #ffffff} /* Name.Function */ - .nl { color: #ffffff} /* Name.Label */ - .nn { color: #ffffff} /* Name.Namespace */ - .nx { color: #ffffff} /* Name.Other */ - .py { color: #ffffff} /* Name.Property */ - .nt { color: #f0e68c} /* Name.Tag */ - .nv { color: #98fb98} /* Name.Variable */ - .ow { color: #ffffff} /* Operator.Word */ - .w { color: #ffffff} /* Text.Whitespace */ - .mf { color: #ffffff} /* Literal.Number.Float */ - .mh { color: #ffffff} /* Literal.Number.Hex */ - .mi { color: #ffffff} /* Literal.Number.Integer */ - .mo { color: #ffffff} /* Literal.Number.Oct */ - .sb { color: #ffffff} /* Literal.String.Backtick */ - .sc { color: #ffffff} /* Literal.String.Char */ - .sd { color: #ffffff} /* Literal.String.Doc */ - .s2 { color: #ffffff} /* Literal.String.Double */ - .se { color: #ffffff} /* Literal.String.Escape */ - .sh { color: #ffffff} /* Literal.String.Heredoc */ - .si { color: #ffffff} /* Literal.String.Interpol */ - .sx { color: #ffffff} /* Literal.String.Other */ - .sr { color: #ffffff} /* Literal.String.Regex */ - .s1 { color: #ffffff} /* Literal.String.Single */ - .ss { color: #ffffff} /* Literal.String.Symbol */ - .bp { color: #ffffff} /* Name.Builtin.Pseudo */ - .vc { color: #98fb98} /* Name.Variable.Class */ - .vg { color: #98fb98} /* Name.Variable.Global */ - .vi { color: #98fb98} /* Name.Variable.Instance */ - .il { color: #ffffff} /* Literal.Number.Integer.Long */ - .bash .nv { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - } -} \ No newline at end of file diff --git a/site/fonts/fontawesome-webfont.eot b/site/fonts/fontawesome-webfont.eot deleted file mode 100755 index a30335d748c..00000000000 Binary files a/site/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/site/fonts/fontawesome-webfont.svg b/site/fonts/fontawesome-webfont.svg deleted file mode 100755 index 6fd19abcb9e..00000000000 --- a/site/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,640 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/site/fonts/fontawesome-webfont.ttf b/site/fonts/fontawesome-webfont.ttf deleted file mode 100755 index d7994e13086..00000000000 Binary files a/site/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/site/fonts/fontawesome-webfont.woff b/site/fonts/fontawesome-webfont.woff deleted file mode 100755 index 6fd4ede0f30..00000000000 Binary files a/site/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/site/fonts/fontawesome-webfont.woff2 b/site/fonts/fontawesome-webfont.woff2 deleted file mode 100644 index 5560193ccc5..00000000000 Binary files a/site/fonts/fontawesome-webfont.woff2 and /dev/null differ diff --git a/site/freenode.txt b/site/freenode.txt deleted file mode 100644 index 898ed7291d6..00000000000 --- a/site/freenode.txt +++ /dev/null @@ -1 +0,0 @@ -aS3gAc4g diff --git a/site/help/index.md b/site/help/index.md deleted file mode 100644 index 5ce0846c71d..00000000000 --- a/site/help/index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -layout: page -title: Getting Help ---- - -Need help with Jekyll? Try these resources. - -### [Google](https://google.com) - -Add **jekyll** to almost any query, and you'll find just what you need. - -### [Jekyll Talk](https://talk.jekyllrb.com/) - -Jekyll Talk is our official Discourse forum. Here, users and contributors -can ask questions and discuss all aspects of Jekyll. - -### [Jekyll on StackOverflow](http://stackoverflow.com/questions/tagged/jekyll) - -StackOverflow is a staple of any developer's diet. Check out the Jekyll tag -on StackOverflow for an answer to your question. Not there? Ask a new -question! - -### [Jekyll IRC Channel](irc:irc.freenode.net/jekyll) - -Get live support at **#jekyll** on **irc.freenode.net**, the official -Jekyll IRC channel. - -### [jekyll/jekyll](https://github.com/jekyll/jekyll/issues) - -Search through the issues on the main Jekyll development. Think you've -found a bug? File a new issue. - -### [@jekyllrb on Twitter](https://twitter.com/jekyllrb) - -The official Jekyll Twitter account. It's not checked often, so try the -above first. diff --git a/site/img/article-footer.png b/site/img/article-footer.png deleted file mode 100644 index d000cf08cd1..00000000000 Binary files a/site/img/article-footer.png and /dev/null differ diff --git a/site/img/footer-logo.png b/site/img/footer-logo.png deleted file mode 100644 index 721b856283c..00000000000 Binary files a/site/img/footer-logo.png and /dev/null differ diff --git a/site/img/logo-2x.png b/site/img/logo-2x.png deleted file mode 100644 index 28b9cd8d1c0..00000000000 Binary files a/site/img/logo-2x.png and /dev/null differ diff --git a/site/latest_version.txt b/site/latest_version.txt deleted file mode 100644 index cb2b00e4f7a..00000000000 --- a/site/latest_version.txt +++ /dev/null @@ -1 +0,0 @@ -3.0.1 diff --git a/site/news/index.html b/site/news/index.html deleted file mode 100644 index 94139fc00db..00000000000 --- a/site/news/index.html +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: news -title: News -permalink: /news/ -author: all ---- - -{% for post in site.posts %} - {% include news_item.html %} -{% endfor %} diff --git a/site/news/releases/index.html b/site/news/releases/index.html deleted file mode 100644 index 153d022c133..00000000000 --- a/site/news/releases/index.html +++ /dev/null @@ -1,10 +0,0 @@ ---- -layout: news -title: Releases -permalink: /news/releases/ -author: all ---- - -{% for post in site.categories.release %} - {% include news_item.html %} -{% endfor %} diff --git a/test/fixtures/empty_permalink.erb b/test/fixtures/empty_permalink.erb new file mode 100644 index 00000000000..6dabf63b805 --- /dev/null +++ b/test/fixtures/empty_permalink.erb @@ -0,0 +1,4 @@ +--- +permalink: '' +--- +Empty Permalink diff --git a/test/fixtures/no_liquid.erb b/test/fixtures/no_liquid.erb new file mode 100644 index 00000000000..bfb7fc46fe7 --- /dev/null +++ b/test/fixtures/no_liquid.erb @@ -0,0 +1,4 @@ +--- +render_with_liquid: false +--- +{% raw %}{% endraw %} diff --git a/test/fixtures/physical.html b/test/fixtures/physical.html new file mode 100644 index 00000000000..8913980af32 --- /dev/null +++ b/test/fixtures/physical.html @@ -0,0 +1,6 @@ +--- +title: Physical file +permalink: /physical/ +--- + +A physical file entity diff --git a/test/fixtures/sample.csv b/test/fixtures/sample.csv new file mode 100644 index 00000000000..b4b36e6d3b7 --- /dev/null +++ b/test/fixtures/sample.csv @@ -0,0 +1,3 @@ +id,field_a +1,"foo" +2,"bar" diff --git a/test/fixtures/sample.tsv b/test/fixtures/sample.tsv new file mode 100644 index 00000000000..c467a88a470 --- /dev/null +++ b/test/fixtures/sample.tsv @@ -0,0 +1,3 @@ +id field_a +1 "foo" +2 "bar" diff --git a/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec b/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec new file mode 100644 index 00000000000..ebc8a83c3a1 --- /dev/null +++ b/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = "test-dependency-theme" + s.version = "0.1.0" + s.licenses = ["MIT"] + s.summary = "This is another theme used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = "https://github.com/jekyll/jekyll" + + s.add_runtime_dependency "jekyll_test_plugin" +end diff --git a/test/fixtures/test-theme-skinny/_layouts/default.html b/test/fixtures/test-theme-skinny/_layouts/default.html new file mode 100644 index 00000000000..837a4dc7696 --- /dev/null +++ b/test/fixtures/test-theme-skinny/_layouts/default.html @@ -0,0 +1,11 @@ + + + + + Skinny + + +

    Hello World

    + {{ content }} + + diff --git a/test/fixtures/test-theme-skinny/_layouts/home.html b/test/fixtures/test-theme-skinny/_layouts/home.html new file mode 100644 index 00000000000..6d9ce5c7ef1 --- /dev/null +++ b/test/fixtures/test-theme-skinny/_layouts/home.html @@ -0,0 +1,5 @@ +--- +layout: default +--- + +Message: {{ content }} diff --git a/test/fixtures/test-theme-skinny/test-theme-skinny.gemspec b/test/fixtures/test-theme-skinny/test-theme-skinny.gemspec new file mode 100644 index 00000000000..84f59b9d709 --- /dev/null +++ b/test/fixtures/test-theme-skinny/test-theme-skinny.gemspec @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = "test-theme-skinny" + s.version = "0.1.0" + s.licenses = ["MIT"] + s.summary = "This is a theme with just layouts used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = "https://github.com/jekyll/jekyll" +end diff --git a/test/fixtures/test-theme-symlink/test-theme-symlink.gemspec b/test/fixtures/test-theme-symlink/test-theme-symlink.gemspec new file mode 100644 index 00000000000..b0a915e3308 --- /dev/null +++ b/test/fixtures/test-theme-symlink/test-theme-symlink.gemspec @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = "test-theme-symlink" + s.version = "0.1.0" + s.licenses = ["MIT"] + s.summary = "This is a theme with a symlink used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = "https://github.com/jekyll/jekyll" +end diff --git a/test/fixtures/test-theme-w-empty-data/_data/.gitkeep b/test/fixtures/test-theme-w-empty-data/_data/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/fixtures/test-theme-w-empty-data/_layouts/default.html b/test/fixtures/test-theme-w-empty-data/_layouts/default.html new file mode 100644 index 00000000000..837a4dc7696 --- /dev/null +++ b/test/fixtures/test-theme-w-empty-data/_layouts/default.html @@ -0,0 +1,11 @@ + + + + + Skinny + + +

    Hello World

    + {{ content }} + + diff --git a/test/fixtures/test-theme-w-empty-data/test-theme-w-empty-data.gemspec b/test/fixtures/test-theme-w-empty-data/test-theme-w-empty-data.gemspec new file mode 100644 index 00000000000..013f1b1e51f --- /dev/null +++ b/test/fixtures/test-theme-w-empty-data/test-theme-w-empty-data.gemspec @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = "test-theme-w-empty-data" + s.version = "0.1.0" + s.licenses = ["MIT"] + s.summary = "This is a theme with just one layout and an empty _data folder used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = "https://github.com/jekyll/jekyll" +end diff --git a/test/fixtures/test-theme/_config.yml b/test/fixtures/test-theme/_config.yml new file mode 100644 index 00000000000..27c61828cf2 --- /dev/null +++ b/test/fixtures/test-theme/_config.yml @@ -0,0 +1,14 @@ +title: Hello World +baseurl: "/test-theme" +include: ["_extras/banner.md"] +exclude: + - README.md + - CHANGELOG.md + - Rakefile + - test/**/* + +# theme-specific settings +test_theme: + skin: aero # aero / chrome / dark / neon + date_format: "%b -d %Y" # any format supported by strftime + header_links: true # generate header links automatically diff --git a/test/fixtures/test-theme/_data/cars.yml b/test/fixtures/test-theme/_data/cars.yml new file mode 100644 index 00000000000..86adb8944e7 --- /dev/null +++ b/test/fixtures/test-theme/_data/cars.yml @@ -0,0 +1,6 @@ +manufacturer: Mercedes +models: +- model: A-Klasse + price: 32,000.00 +- model: B-Klasse + price: 35,000.00 diff --git a/test/fixtures/test-theme/_data/categories/dairy.yaml b/test/fixtures/test-theme/_data/categories/dairy.yaml new file mode 100644 index 00000000000..54497fa9a13 --- /dev/null +++ b/test/fixtures/test-theme/_data/categories/dairy.yaml @@ -0,0 +1,6 @@ +name: Cheese Dairy +products: +- name: spread cheese + price: 1.2 +- name: cheddar cheese + price: 4.5 diff --git a/test/fixtures/test-theme/_data/greetings.yml b/test/fixtures/test-theme/_data/greetings.yml new file mode 100644 index 00000000000..250f1e69cca --- /dev/null +++ b/test/fixtures/test-theme/_data/greetings.yml @@ -0,0 +1 @@ +foo: "Hello! I’m bar. What’s up so far?" diff --git a/test/fixtures/test-theme/_data/i18n/testimonials.yml b/test/fixtures/test-theme/_data/i18n/testimonials.yml new file mode 100644 index 00000000000..19e0cd1317d --- /dev/null +++ b/test/fixtures/test-theme/_data/i18n/testimonials.yml @@ -0,0 +1,2 @@ +header: Testimonials +footer: Design by FTC diff --git a/test/fixtures/test-theme/_includes/include.html b/test/fixtures/test-theme/_includes/include.html new file mode 100644 index 00000000000..9860839255d --- /dev/null +++ b/test/fixtures/test-theme/_includes/include.html @@ -0,0 +1 @@ +include.html from test-theme diff --git a/test/fixtures/test-theme/_includes/testimonials.html b/test/fixtures/test-theme/_includes/testimonials.html new file mode 100644 index 00000000000..44b054e041a --- /dev/null +++ b/test/fixtures/test-theme/_includes/testimonials.html @@ -0,0 +1,9 @@ +
    +

    {{ site.data.i18n.testimonials.header }}

    + + … + +
    + {{ site.data.i18n.testimonials.footer }} +
    +
    diff --git a/test/fixtures/test-theme/_layouts/default.html b/test/fixtures/test-theme/_layouts/default.html new file mode 100644 index 00000000000..902c61c31a2 --- /dev/null +++ b/test/fixtures/test-theme/_layouts/default.html @@ -0,0 +1 @@ +default.html from test-theme: {{ content }} diff --git a/test/fixtures/test-theme/_sass/test-theme-black.scss b/test/fixtures/test-theme/_sass/test-theme-black.scss new file mode 100644 index 00000000000..a1e07da69f6 --- /dev/null +++ b/test/fixtures/test-theme/_sass/test-theme-black.scss @@ -0,0 +1,3 @@ +.sample { + color: black; +} diff --git a/test/fixtures/test-theme/_sass/test-theme-red.scss b/test/fixtures/test-theme/_sass/test-theme-red.scss new file mode 100644 index 00000000000..0307e17abb3 --- /dev/null +++ b/test/fixtures/test-theme/_sass/test-theme-red.scss @@ -0,0 +1,3 @@ +.sample { + color: red; +} diff --git a/test/fixtures/test-theme/_symlink b/test/fixtures/test-theme/_symlink new file mode 120000 index 00000000000..d2d6aac5ca2 --- /dev/null +++ b/test/fixtures/test-theme/_symlink @@ -0,0 +1 @@ +_layouts \ No newline at end of file diff --git a/test/fixtures/test-theme/assets/application.coffee b/test/fixtures/test-theme/assets/application.coffee new file mode 100644 index 00000000000..02f335154b5 --- /dev/null +++ b/test/fixtures/test-theme/assets/application.coffee @@ -0,0 +1,3 @@ +--- +--- +alert "From your theme." diff --git a/test/fixtures/test-theme/assets/base.js b/test/fixtures/test-theme/assets/base.js new file mode 100644 index 00000000000..00c238eddbc --- /dev/null +++ b/test/fixtures/test-theme/assets/base.js @@ -0,0 +1 @@ +alert("From your theme."); diff --git a/test/fixtures/test-theme/assets/img/another-logo.png b/test/fixtures/test-theme/assets/img/another-logo.png new file mode 120000 index 00000000000..bd36e718eaa --- /dev/null +++ b/test/fixtures/test-theme/assets/img/another-logo.png @@ -0,0 +1 @@ +logo.png \ No newline at end of file diff --git a/test/fixtures/test-theme/assets/img/logo.png b/test/fixtures/test-theme/assets/img/logo.png new file mode 100644 index 00000000000..95f0a3bb8f6 Binary files /dev/null and b/test/fixtures/test-theme/assets/img/logo.png differ diff --git a/test/fixtures/test-theme/assets/style.scss b/test/fixtures/test-theme/assets/style.scss new file mode 100644 index 00000000000..00096523507 --- /dev/null +++ b/test/fixtures/test-theme/assets/style.scss @@ -0,0 +1,3 @@ +--- +--- +@import "test-theme-{{ site.theme-color | default: 'red' }}"; diff --git a/test/fixtures/test-theme/test-theme.gemspec b/test/fixtures/test-theme/test-theme.gemspec new file mode 100644 index 00000000000..970e1b8abdd --- /dev/null +++ b/test/fixtures/test-theme/test-theme.gemspec @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +Gem::Specification.new do |s| + s.name = "test-theme" + s.version = "0.1.0" + s.licenses = ["MIT"] + s.summary = "This is a theme used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = "https://github.com/jekyll/jekyll" +end diff --git a/test/fixtures/webrick/bar.html b/test/fixtures/webrick/bar.html new file mode 100644 index 00000000000..76870bf2f38 --- /dev/null +++ b/test/fixtures/webrick/bar.html @@ -0,0 +1 @@ +Content of bar.html diff --git a/test/fixtures/webrick/bar/baz.html b/test/fixtures/webrick/bar/baz.html new file mode 100644 index 00000000000..794d5f2202d --- /dev/null +++ b/test/fixtures/webrick/bar/baz.html @@ -0,0 +1 @@ +Content of baz.html diff --git a/test/fixtures/webrick/bar/foo.xhtml b/test/fixtures/webrick/bar/foo.xhtml new file mode 100644 index 00000000000..6890fdca3df --- /dev/null +++ b/test/fixtures/webrick/bar/foo.xhtml @@ -0,0 +1 @@ +Content of foo.xhtml diff --git a/test/helper.rb b/test/helper.rb index dc0217676d1..f6b1f925199 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,107 +1,202 @@ +# frozen_string_literal: true + +$stdout.puts "# -------------------------------------------------------------" +$stdout.puts "# SPECS AND TESTS ARE RUNNING WITH WARNINGS OFF." +$stdout.puts "# SEE: https://github.com/Shopify/liquid/issues/730" +$stdout.puts "# SEE: https://github.com/jekyll/jekyll/issues/4719" +$stdout.puts "# -------------------------------------------------------------" +$VERBOSE = nil + def jruby? - defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' + defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby" end -unless ENV['TRAVIS'] - require File.expand_path('../simplecov_custom_profile', __FILE__) - SimpleCov.start('gem') do - add_filter "/vendor/bundle" +if ENV["CI"] + require "simplecov" + SimpleCov.start +else + require File.expand_path("simplecov_custom_profile", __dir__) + SimpleCov.start "gem" do add_filter "/vendor/gem" + add_filter "/vendor/bundle" add_filter ".bundle" end end -require 'rubygems' -require 'ostruct' -require 'minitest/autorun' -require 'minitest/reporters' -require 'minitest/profile' -require 'rspec/mocks' - -require 'jekyll' +require "nokogiri" +require "rubygems" +require "ostruct" +require "minitest/autorun" +require "minitest/reporters" +require "minitest/profile" +require "rspec/mocks" +require_relative "../lib/jekyll" -Jekyll.logger = Logger.new(StringIO.new) +Jekyll.logger = Logger.new(StringIO.new, :error) -unless jruby? - require 'rdiscount' - require 'redcarpet' -end - -require 'kramdown' -require 'shoulda' +require "kramdown" +require "shoulda-context" include Jekyll -# FIXME: If we really need this we lost the game. -# STDERR.reopen(test(?e, '/dev/null') ? '/dev/null' : 'NUL:') +require "jekyll/commands/serve/servlet" # Report with color. Minitest::Reporters.use! [ Minitest::Reporters::DefaultReporter.new( :color => true - ) + ), ] +module Minitest::Assertions + def assert_exist(filename, msg = nil) + msg = message(msg) { "Expected '#{filename}' to exist" } + assert_path_exists(filename, msg) + end + + def refute_exist(filename, msg = nil) + msg = message(msg) { "Expected '#{filename}' not to exist" } + refute_path_exists(filename, msg) + end +end + +module DirectoryHelpers + def root_dir(*subdirs) + File.expand_path(File.join("..", *subdirs), __dir__) + end + + def dest_dir(*subdirs) + test_dir("dest", *subdirs) + end + + def source_dir(*subdirs) + test_dir("source", *subdirs) + end + + def theme_dir(*subdirs) + test_dir("fixtures", "test-theme", *subdirs) + end + + def test_dir(*subdirs) + root_dir("test", *subdirs) + end + + def temp_dir(*subdirs) + if Utils::Platforms.vanilla_windows? + drive = Dir.pwd.sub(%r!^([^/]+).*!, '\1') + temp_root = File.join(drive, "tmp") + else + temp_root = "/tmp" + end + + File.join(temp_root, *subdirs) + end +end + +module Jekyll + # + # --- NOTE: --- + # + # This monkey-patch was introduced because GitHub Actions on Windows acknowledges symlinked test + # file `test/source/symlink-test/symlinked-file-outside-source` but errors out since the linked + # location `/etc/passwd` does not exist on Windows. + # + # --- TODO: --- + # + # Consider having the `symlinked-file-outside-source` point to a file that is outside the + # `source_dir` (defaults to `test/source`) yet is certain to exist on tested platforms. + # For example, `jekyll.gemspec` is a good candidate. + # + # This monkey-patch will then no longer be necessary. + # + class ModifiedReader < Reader + def read_directories(dir = "") + if dir.start_with?("/symlink") && Utils::Platforms.really_windows? + Jekyll.logger.debug "Skipping:", "Jekyll does not support symlinks on Windows" + else + super + end + end + end + + Hooks.register :site, :after_init do |site| + site.instance_variable_set(:@reader, ModifiedReader.new(site)) + end +end + class JekyllUnitTest < Minitest::Test include ::RSpec::Mocks::ExampleMethods + include DirectoryHelpers + extend DirectoryHelpers + + def mu_pp(obj) + s = obj.is_a?(Hash) ? JSON.pretty_generate(obj) : obj.inspect + s = s.encode Encoding.default_external if defined? Encoding + s + end def mocks_expect(*args) - RSpec::Mocks::ExampleMethods::ExpectHost.instance_method(:expect).\ - bind(self).call(*args) + RSpec::Mocks::ExampleMethods::ExpectHost.instance_method(:expect).bind(self).call(*args) end def before_setup - ::RSpec::Mocks.setup + RSpec::Mocks.setup super end def after_teardown super - ::RSpec::Mocks.verify + RSpec::Mocks.verify ensure - ::RSpec::Mocks.teardown + RSpec::Mocks.teardown end - def fixture_site(overrides = {}) - Jekyll::Site.new(site_configuration(overrides)) + def fixture_document(relative_path) + site = fixture_site( + "collections" => { + "methods" => { + "output" => true, + }, + } + ) + site.read + matching_doc = site.collections["methods"].docs.find do |doc| + doc.relative_path == relative_path + end + [site, matching_doc] end - def build_configs(overrides, base_hash = Jekyll::Configuration::DEFAULTS) - Utils.deep_merge_hashes(base_hash, overrides) - .fix_common_issues.backwards_compatibilize.add_default_collections + def fixture_site(overrides = {}) + Jekyll::Site.new(site_configuration(overrides)) end - def site_configuration(overrides = {}) - full_overrides = build_configs(overrides, build_configs({ - "destination" => dest_dir, - "incremental" => false - })) - build_configs({ - "source" => source_dir - }, full_overrides) + def default_configuration + Marshal.load(Marshal.dump(Jekyll::Configuration::DEFAULTS)) end - def dest_dir(*subdirs) - test_dir('dest', *subdirs) + def build_configs(overrides, base_hash = default_configuration) + Utils.deep_merge_hashes(base_hash, overrides) end - def source_dir(*subdirs) - test_dir('source', *subdirs) + def site_configuration(overrides = {}) + full_overrides = build_configs(overrides, build_configs( + "destination" => dest_dir, + "incremental" => false + )) + Configuration.from(full_overrides.merge( + "source" => source_dir + )) end def clear_dest FileUtils.rm_rf(dest_dir) - FileUtils.rm_rf(source_dir('.jekyll-metadata')) - end - - def test_dir(*subdirs) - File.join(File.dirname(__FILE__), *subdirs) + FileUtils.rm_rf(source_dir(".jekyll-metadata")) end def directory_with_contents(path) FileUtils.rm_rf(path) FileUtils.mkdir(path) - File.open("#{path}/index.html", "w"){ |f| f.write("I was previously generated.") } + File.write("#{path}/index.html", "I was previously generated.") end def with_env(key, value) @@ -111,13 +206,122 @@ def with_env(key, value) ENV[key] = old_value end - def capture_output - stderr = StringIO.new - Jekyll.logger = Logger.new stderr + def capture_output(level = :debug) + buffer = StringIO.new + Jekyll.logger = Logger.new(buffer) + Jekyll.logger.log_level = level yield - stderr.rewind - return stderr.string.to_s + buffer.rewind + buffer.string.to_s + ensure + Jekyll.logger = Logger.new(StringIO.new, :error) end alias_method :capture_stdout, :capture_output alias_method :capture_stderr, :capture_output + + def nokogiri_fragment(str) + Nokogiri::HTML.fragment( + str + ) + end + + def skip_if_windows(msg = nil) + if Utils::Platforms.really_windows? + msg ||= "Jekyll does not currently support this feature on Windows." + skip msg.to_s.magenta + end + end + + def symlink_if_allowed(target, sym_file) + FileUtils.ln_sf(target, sym_file) + rescue Errno::EACCES + skip "Permission denied for creating a symlink to #{target.inspect} " \ + "on this machine".magenta + rescue NotImplementedError => e + skip e.to_s.magenta + end +end + +class FakeLogger + def <<(str); end +end + +module TestWEBrick + module_function + + def mount_server(&block) + server = WEBrick::HTTPServer.new(config) + + begin + server.mount("/", Jekyll::Commands::Serve::Servlet, document_root, + document_root_options) + + server.start + addr = server.listeners[0].addr + block.yield([server, addr[3], addr[1]]) + rescue StandardError => e + raise e + ensure + server.shutdown + sleep 0.1 until server.status == :Stop + end + end + + def config + logger = FakeLogger.new + { + :BindAddress => "127.0.0.1", :Port => 0, + :ShutdownSocketWithoutClose => true, + :ServerType => Thread, + :Logger => WEBrick::Log.new(logger), + :AccessLog => [[logger, ""]], + :MimeTypesCharset => Jekyll::Commands::Serve.send(:mime_types_charset), + :JekyllOptions => {}, + } + end + + def document_root + "#{File.dirname(__FILE__)}/fixtures/webrick" + end + + def document_root_options + WEBrick::Config::FileHandler.merge( + :FancyIndexing => true, + :NondisclosureName => [ + ".ht*", "~*", + ] + ) + end +end + +class TagUnitTest < JekyllUnitTest + def render_content(content, override = {}) + base_config = { + "source" => source_dir, + "destination" => dest_dir, + } + site = fixture_site(base_config.merge(override)) + + if override["read_posts"] + site.posts.docs.concat(PostReader.new(site).read_posts("")) + elsif override["read_collections"] + CollectionReader.new(site).read + elsif override["read_all"] + site.read + end + + @result = render_with(site, content) + end + + private + + def render_with(site, content) + converter = site.converters.find { |c| c.instance_of?(Jekyll::Converters::Markdown) } + payload = { "highlighter_prefix" => converter.highlighter_prefix, + "highlighter_suffix" => converter.highlighter_suffix, } + info = { :registers => { :site => site } } + converter.convert( + Liquid::Template.parse(content).render!(payload, info) + ) + end end diff --git a/test/safe_glob_test[/find_me.txt b/test/safe_glob_test[/find_me.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/simplecov_custom_profile.rb b/test/simplecov_custom_profile.rb index d7f4914cbce..555acec3d7e 100644 --- a/test/simplecov_custom_profile.rb +++ b/test/simplecov_custom_profile.rb @@ -1,10 +1,12 @@ -require 'simplecov' +# frozen_string_literal: true -SimpleCov.profiles.define 'gem' do - add_filter '/test/' - add_filter '/features/' - add_filter '/autotest/' +require "simplecov" - add_group 'Binaries', '/bin/' - add_group 'Libraries', '/lib/' +SimpleCov.profiles.define "gem" do + add_filter "/test/" + add_filter "/features/" + add_filter "/autotest/" + + add_group "Binaries", "/bin/" + add_group "Libraries", "/lib/" end diff --git a/test/source/+/foo.md b/test/source/+/foo.md index 30f9535f3a9..bd2d1482285 100644 --- a/test/source/+/foo.md +++ b/test/source/+/foo.md @@ -1,7 +1,7 @@ --- layout: default title : Page inside + -permalink: /+/plus+in+url +permalink: /+/plus+in+url.html --- Line 1 {{ page.title }} diff --git a/test/source/.gitattributes b/test/source/.gitattributes new file mode 100644 index 00000000000..fa1385d99a3 --- /dev/null +++ b/test/source/.gitattributes @@ -0,0 +1 @@ +* -text diff --git a/test/source/_broken/bad_post.md b/test/source/_broken/bad_post.md new file mode 100644 index 00000000000..f895dd26ebb --- /dev/null +++ b/test/source/_broken/bad_post.md @@ -0,0 +1,4 @@ +--- +bad yaml: [ +--- +Real content starts here diff --git a/test/source/_config_folded.yml b/test/source/_config_folded.yml new file mode 100644 index 00000000000..9b0bfa4c2c5 --- /dev/null +++ b/test/source/_config_folded.yml @@ -0,0 +1,8 @@ +folded_string: > + This string of text will ignore + newlines till the next key. +foo: bar +clean_folded_string: >- + This string of text will ignore + newlines till the next key. +baz: foo diff --git a/test/source/_data/categories.01/dairy.yaml b/test/source/_data/categories.01/dairy.yaml new file mode 100644 index 00000000000..30a09ba35af --- /dev/null +++ b/test/source/_data/categories.01/dairy.yaml @@ -0,0 +1,6 @@ +name: Dairy +products: +- name: cheese + price: 5.5 +- name: milk + price: 2.75 diff --git a/test/source/_data/greetings.yml b/test/source/_data/greetings.yml new file mode 100644 index 00000000000..07d47500469 --- /dev/null +++ b/test/source/_data/greetings.yml @@ -0,0 +1 @@ +foo: "Hello! I’m foo. And who are you?" diff --git a/test/source/_data/i18n.yml b/test/source/_data/i18n.yml new file mode 100644 index 00000000000..2c769323476 --- /dev/null +++ b/test/source/_data/i18n.yml @@ -0,0 +1,3 @@ +testimonials: + header: Kundenstimmen + # footer omitted by design diff --git a/test/source/_dates/date_without_time.md b/test/source/_dates/date_without_time.md new file mode 100644 index 00000000000..7e5ee003808 --- /dev/null +++ b/test/source/_dates/date_without_time.md @@ -0,0 +1,4 @@ +--- +date: 2015-10-01 +--- +Here is the content. diff --git a/test/source/_dates/time_with_timezone.md b/test/source/_dates/time_with_timezone.md new file mode 100644 index 00000000000..5a7c9277bc0 --- /dev/null +++ b/test/source/_dates/time_with_timezone.md @@ -0,0 +1,4 @@ +--- +date: 2015-10-01 01:00:00 +0800 +--- +Here is the content. diff --git a/test/source/_dates/time_without_timezone.md b/test/source/_dates/time_without_timezone.md new file mode 100644 index 00000000000..ae0423e10cb --- /dev/null +++ b/test/source/_dates/time_without_timezone.md @@ -0,0 +1,4 @@ +--- +date: 2015-10-01 01:00:00 +--- +Here is the content. diff --git a/test/source/_encodings/UTF8CRLFandBOM.md b/test/source/_encodings/UTF8CRLFandBOM.md new file mode 100755 index 00000000000..36390cc3464 --- /dev/null +++ b/test/source/_encodings/UTF8CRLFandBOM.md @@ -0,0 +1,11 @@ +--- +layout: post +title: "UTF8CRLFandBOM" +date: 2017-04-05 16:16:01 -0800 +categories: bom +--- +This file was created with CR/LFs, and encoded as UTF8 with a BOM + +You’ll find this post in your `_posts` directory. Go ahead and edit it and re-build the site to see your changes. You can rebuild the site in many different ways, but the most common way is to run `bundle exec jekyll serve`, which launches a web server and auto-regenerates your site when a file is updated. + +To add new posts, simply add a file in the `_posts` directory that follows the convention `YYYY-MM-DD-name-of-post.ext` and includes the necessary front matter. Take a look at the source for this post to get an idea about how it works. diff --git a/test/source/_encodings/Unicode16LECRLFandBOM.md b/test/source/_encodings/Unicode16LECRLFandBOM.md new file mode 100755 index 00000000000..8941716a1d0 Binary files /dev/null and b/test/source/_encodings/Unicode16LECRLFandBOM.md differ diff --git a/test/source/_glob_include_test/_is_dir/include_me.txt b/test/source/_glob_include_test/_is_dir/include_me.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/source/_glob_include_test/_not_dir b/test/source/_glob_include_test/_not_dir new file mode 100644 index 00000000000..e69de29bb2d diff --git a/test/source/_includes/params@2.0.html b/test/source/_includes/params@2.0.html new file mode 100644 index 00000000000..65a00018ca6 --- /dev/null +++ b/test/source/_includes/params@2.0.html @@ -0,0 +1,7 @@ +{{include.param}} + +
      + {% for param in include %} +
    • {{param[0]}} = {{param[1]}}
    • + {% endfor %} +
    \ No newline at end of file diff --git a/test/source/_layouts/default.html b/test/source/_layouts/default.html index 1d51c496796..ef2d4384ba2 100644 --- a/test/source/_layouts/default.html +++ b/test/source/_layouts/default.html @@ -1,3 +1,6 @@ +--- +front_matter_var: variable from layout +--- diff --git a/test/source/_methods/3940394-21-9393050-fifif1323-test.md b/test/source/_methods/3940394-21-9393050-fifif1323-test.md new file mode 100644 index 00000000000..848d0204cc4 --- /dev/null +++ b/test/source/_methods/3940394-21-9393050-fifif1323-test.md @@ -0,0 +1,5 @@ +--- +title: "this is a test!" +--- + +wheee diff --git a/test/source/_methods/collection/entries b/test/source/_methods/collection/entries new file mode 100644 index 00000000000..7622ac9ac81 --- /dev/null +++ b/test/source/_methods/collection/entries @@ -0,0 +1,5 @@ +--- +title: "Collection#entries" +--- + +I have no file extension but I should still be a part of the collection. diff --git a/test/source/_methods/extensionless_static_file b/test/source/_methods/extensionless_static_file new file mode 100644 index 00000000000..b050c592890 --- /dev/null +++ b/test/source/_methods/extensionless_static_file @@ -0,0 +1 @@ +I have no front matter. diff --git a/test/source/_methods/trailing-dots...md b/test/source/_methods/trailing-dots...md new file mode 100644 index 00000000000..2ec72a7f4a0 --- /dev/null +++ b/test/source/_methods/trailing-dots...md @@ -0,0 +1,3 @@ +--- +title: Ellipsis Path +--- diff --git a/test/source/_methods/with.dots/.gitignore b/test/source/_methods/with.dots/.gitignore new file mode 100644 index 00000000000..87e42cfcb65 --- /dev/null +++ b/test/source/_methods/with.dots/.gitignore @@ -0,0 +1 @@ +I should be copied diff --git a/test/source/_methods/with.dots/.htaccess b/test/source/_methods/with.dots/.htaccess new file mode 100644 index 00000000000..87e42cfcb65 --- /dev/null +++ b/test/source/_methods/with.dots/.htaccess @@ -0,0 +1 @@ +I should be copied diff --git a/test/source/_plugins/custom_block.rb b/test/source/_plugins/custom_block.rb new file mode 100644 index 00000000000..eee0fbaadaa --- /dev/null +++ b/test/source/_plugins/custom_block.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# For testing excerpt handling of custom tags + +module Jekyll + class DoNothingBlock < Liquid::Block + end + + class DoNothingOther < Liquid::Tag + end +end + +Liquid::Template.register_tag("do_nothing", Jekyll::DoNothingBlock) +Liquid::Template.register_tag("do_nothing_other", Jekyll::DoNothingOther) diff --git a/test/source/_plugins/dummy.rb b/test/source/_plugins/dummy.rb index bfd46e1ce03..25eef88e21b 100644 --- a/test/source/_plugins/dummy.rb +++ b/test/source/_plugins/dummy.rb @@ -1,8 +1,9 @@ +# frozen_string_literal: true + module Jekyll class Dummy < Generator priority :high - def generate(site) - end + def generate(site) end end end diff --git a/test/source/_posts/2008-02-03-wrong-extension.yml b/test/source/_posts/2008-02-03-wrong-extension.yml new file mode 100644 index 00000000000..bb9f7f47789 --- /dev/null +++ b/test/source/_posts/2008-02-03-wrong-extension.yml @@ -0,0 +1,8 @@ +--- +layout: default +title: This file extension is skipped +category: test_post_reader +--- + +`jekyll serve` used to crash if there's a post (document) with a wrong file extension. +This file is used in `./test/test_post_reader.rb` to verify that this doesn't happen anymore. diff --git a/test/source/_posts/2010-01-16-override-data.markdown b/test/source/_posts/2010-01-16-override-data.markdown index 5b1a95c4bda..e5106488d32 100644 --- a/test/source/_posts/2010-01-16-override-data.markdown +++ b/test/source/_posts/2010-01-16-override-data.markdown @@ -2,3 +2,5 @@ date: 2010-01-10 13:07:09 tags: A string --- + +Best **post** ever diff --git a/test/source/_posts/2011-04-12-text-extension.text b/test/source/_posts/2011-04-12-text-extension.text index e69de29bb2d..6b4ef010ad1 100644 --- a/test/source/_posts/2011-04-12-text-extension.text +++ b/test/source/_posts/2011-04-12-text-extension.text @@ -0,0 +1 @@ +Best **post** ever diff --git a/test/source/_posts/2013-01-02-post-excerpt.markdown b/test/source/_posts/2013-01-02-post-excerpt.markdown index 5cac6eb504a..17fc8281d71 100644 --- a/test/source/_posts/2013-01-02-post-excerpt.markdown +++ b/test/source/_posts/2013-01-02-post-excerpt.markdown @@ -11,4 +11,4 @@ Second paragraph Third paragraph -[link]: http://www.jekyllrb.com/ +[link]: https://jekyllrb.com/ diff --git a/test/source/_posts/2013-03-19-not-a-post/dubious.markdown b/test/source/_posts/2013-03-19-not-a-post/dubious.markdown new file mode 100644 index 00000000000..cd2990d7e16 --- /dev/null +++ b/test/source/_posts/2013-03-19-not-a-post/dubious.markdown @@ -0,0 +1,6 @@ +--- +title: What Am I? +--- + +I am not a post. +Am I a document then..? diff --git a/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown b/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown index 49586606adf..930cab1a25d 100644 --- a/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown +++ b/test/source/_posts/2013-07-22-post-excerpt-with-layout.markdown @@ -21,4 +21,4 @@ Second paragraph Third paragraph -[link]: http://www.jekyllrb.com/ +[link]: https://jekyllrb.com/ diff --git a/test/source/_posts/2013-08-01-mkdn-extension.mkdn b/test/source/_posts/2013-08-01-mkdn-extension.mkdn index e69de29bb2d..6b4ef010ad1 100644 --- a/test/source/_posts/2013-08-01-mkdn-extension.mkdn +++ b/test/source/_posts/2013-08-01-mkdn-extension.mkdn @@ -0,0 +1 @@ +Best **post** ever diff --git a/test/source/_posts/2014-11-24-Rmd-extension.Rmd b/test/source/_posts/2014-11-24-Rmd-extension.Rmd index e69de29bb2d..6b4ef010ad1 100644 --- a/test/source/_posts/2014-11-24-Rmd-extension.Rmd +++ b/test/source/_posts/2014-11-24-Rmd-extension.Rmd @@ -0,0 +1 @@ +Best **post** ever diff --git a/test/source/_posts/2015-01-08-post-excerpt-separator.markdown b/test/source/_posts/2015-01-08-post-excerpt-separator.markdown index e8b7ddd9c88..9b94c6dc53a 100644 --- a/test/source/_posts/2015-01-08-post-excerpt-separator.markdown +++ b/test/source/_posts/2015-01-08-post-excerpt-separator.markdown @@ -12,4 +12,4 @@ Second paragraph Third paragraph -[link]: http://www.jekyllrb.com/ +[link]: https://jekyllrb.com/ diff --git a/test/source/_posts/2015-12-27-extra-spaces.markdown b/test/source/_posts/2015-12-27-extra-spaces.markdown new file mode 100644 index 00000000000..d8f785b06f5 --- /dev/null +++ b/test/source/_posts/2015-12-27-extra-spaces.markdown @@ -0,0 +1,5 @@ +--- +extra: spaces +--- + +Best **post** ever diff --git a/test/source/_posts/2016-08-16-indented-link-references.markdown b/test/source/_posts/2016-08-16-indented-link-references.markdown new file mode 100644 index 00000000000..f536616219f --- /dev/null +++ b/test/source/_posts/2016-08-16-indented-link-references.markdown @@ -0,0 +1,16 @@ +--- +--- + +This is the first paragraph. It [has][link_0] [lots][link_1] [of][link_2] +[links][link_3]. + +This is the second paragraph. It has sample code that should not be extracted: + + [fakelink]: www.invalid.com + +And here are the real links: + +[link_0]: www.example.com/0 + [link_1]: www.example.com/1 + [link_2]: www.example.com/2 + [link_3]: www.example.com/3 diff --git a/test/source/_posts/2016-11-26-special-chars-(+).markdown b/test/source/_posts/2016-11-26-special-chars-(+).markdown new file mode 100644 index 00000000000..21cc7714620 --- /dev/null +++ b/test/source/_posts/2016-11-26-special-chars-(+).markdown @@ -0,0 +1,8 @@ +--- +layout: default +title: Special Characters +--- + +url: {{ page.url }} +date: {{ page.date }} +id: {{ page.id }} \ No newline at end of file diff --git a/test/source/_posts/2017-2-5-i-dont-like-zeroes.md b/test/source/_posts/2017-2-5-i-dont-like-zeroes.md new file mode 100644 index 00000000000..95e11f12c00 --- /dev/null +++ b/test/source/_posts/2017-2-5-i-dont-like-zeroes.md @@ -0,0 +1,5 @@ +--- +foo: bar +--- +I have an abbreviated date. Instead of "2017-02-05", I am instead "2017-2-5". +Zeros have always seemed superfluous. diff --git a/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown b/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown new file mode 100644 index 00000000000..a2c9fe56d5a --- /dev/null +++ b/test/source/_posts/2018-01-28-closed-liquid-block-excerpt.markdown @@ -0,0 +1,24 @@ +--- +layout: post +--- + +{% + highlight + ruby +%} +{% assign foo = 'foobar' %} +{% raw +%} +def print_hi(name) + puts "Hi, #{name}" +end +print_hi('Tom') +#=> prints 'Hi, Tom' to STDOUT. +{% + endraw +%} +{% + endhighlight +%} + +So let's talk business. diff --git a/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown b/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown new file mode 100644 index 00000000000..24c2e0eb04d --- /dev/null +++ b/test/source/_posts/2018-01-28-open-liquid-block-excerpt.markdown @@ -0,0 +1,21 @@ +--- +layout: post +--- + +{% + highlight + ruby +%} +{% assign foo = 'foobar' %} +{% raw +%} +def print_hi(name) + puts "Hi, #{name}" +end + +print_hi('Tom') +#=> prints 'Hi, Tom' to STDOUT. +{% endraw %} +{% endhighlight %} + +So let's talk business. diff --git a/test/source/_posts/2018-05-15-closed-liquid-block-excerpt-whitespace-control.md b/test/source/_posts/2018-05-15-closed-liquid-block-excerpt-whitespace-control.md new file mode 100644 index 00000000000..c43559244df --- /dev/null +++ b/test/source/_posts/2018-05-15-closed-liquid-block-excerpt-whitespace-control.md @@ -0,0 +1,9 @@ +--- +title: LIQUID_TAG_REGEX excerpt whitespace control test +layout: post +--- + +{%- for post in site.posts -%} + You are in a maze of twisty little passages, all alike. + There's lots more to say about this, but that's enough for now. +{%- endfor -%} diff --git a/test/source/_posts/2018-05-15-excerpt-whitespace-control-variable.md b/test/source/_posts/2018-05-15-excerpt-whitespace-control-variable.md new file mode 100644 index 00000000000..aad1207a355 --- /dev/null +++ b/test/source/_posts/2018-05-15-excerpt-whitespace-control-variable.md @@ -0,0 +1,7 @@ +--- +title: LIQUID_TAG_REGEX excerpt whitespace control test +layout: post +--- + +{%- assign xyzzy = 'You are in a maze of twisty little passages, all alike.' %} +{{- xyzzy -}} diff --git a/test/source/_posts/2018-05-15-open-liquid-block-excerpt-whitespace-control.md b/test/source/_posts/2018-05-15-open-liquid-block-excerpt-whitespace-control.md new file mode 100644 index 00000000000..4ed799585d3 --- /dev/null +++ b/test/source/_posts/2018-05-15-open-liquid-block-excerpt-whitespace-control.md @@ -0,0 +1,10 @@ +--- +title: LIQUID_TAG_REGEX excerpt whitespace control test +layout: post +--- + +{%- for post in site.posts -%} + You are in a maze of twisty little passages, all alike. + + There's lots more to say about this, but that's enough for now. +{%- endfor -%} diff --git a/test/source/_posts/2018-10-12-trailing-dots...markdown b/test/source/_posts/2018-10-12-trailing-dots...markdown new file mode 100644 index 00000000000..ceaaa3303e1 --- /dev/null +++ b/test/source/_posts/2018-10-12-trailing-dots...markdown @@ -0,0 +1,5 @@ +--- +title: Ellipsis Path +--- + +Lorem ipsum dolor sit amet diff --git a/test/source/_posts/2018-11-15-excerpt-liquid-block.md b/test/source/_posts/2018-11-15-excerpt-liquid-block.md new file mode 100644 index 00000000000..7995d9db6a0 --- /dev/null +++ b/test/source/_posts/2018-11-15-excerpt-liquid-block.md @@ -0,0 +1,29 @@ +--- +title: liquid_block excerpt test with open tags in excerpt +layout: post +--- + +{% assign company = "Yoyodyne" %} +{% do_nothing_other %} +{% do_nothing %} + {% unless false %} + {% for i in (1..10) %} + {% if true %} + {% raw %} + EVIL! PURE AND SIMPLE FROM THE EIGHTH DIMENSION! + {% endraw %} + {% elsif false %} + No matter where you go, there you are. + {% break %} + {% else %} + {% case company %} + {% when "Yoyodyne" %} + Buckaroo Banzai + {% else %} + {% continue %} + + {% endcase %} + {% endif %} + {% endfor %} + {% endunless %} +{% enddo_nothing %} diff --git a/test/source/_roles/named.md b/test/source/_roles/named.md new file mode 100644 index 00000000000..dfb6847614a --- /dev/null +++ b/test/source/_roles/named.md @@ -0,0 +1,5 @@ +--- +name: launcher +--- + +`name` defined in front matter. diff --git a/test/source/_roles/unnamed.md b/test/source/_roles/unnamed.md new file mode 100644 index 00000000000..c35bf6b3a0a --- /dev/null +++ b/test/source/_roles/unnamed.md @@ -0,0 +1,4 @@ +--- +--- + +No `name` in front matter. diff --git a/test/source/_slides/example-slide-4.html b/test/source/_slides/example-slide-4.html index b4bdbe45939..9feabf687e0 100644 --- a/test/source/_slides/example-slide-4.html +++ b/test/source/_slides/example-slide-4.html @@ -5,11 +5,11 @@ Jekyll is a simple, blog-aware, static site generator. It takes a template directory containing raw text files in various formats, runs it through -[Markdown](http://daringfireball.net/projects/markdown/) (or -[Textile](http://redcloth.org/textile)) and -[Liquid](http://wiki.shopify.com/Liquid) +[Markdown](https://daringfireball.net/projects/markdown/) (or +[Textile](https://www.promptworks.com/textile)) and +[Liquid](https://help.shopify.com/themes/liquid/basics) converters, and spits out a complete, ready-to-publish static website suitable for serving with your favorite web server. Jekyll also happens to be the engine -behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll +behind [GitHub Pages](https://pages.github.com/), which means you can use Jekyll to host your project’s page, blog, or website from GitHub’s servers **for free**. diff --git a/test/source/_slides/example-slide-6.html b/test/source/_slides/example-slide-6.html index defbb52d729..26addaf4ea9 100644 --- a/test/source/_slides/example-slide-6.html +++ b/test/source/_slides/example-slide-6.html @@ -7,9 +7,9 @@ directory containing raw text files in various formats, runs it through [Markdown](http://daringfireball.net/projects/markdown/) (or [Textile](http://redcloth.org/textile)) and -[Liquid](http://wiki.shopify.com/Liquid) +[Liquid](https://help.shopify.com/themes/liquid/basics) converters, and spits out a complete, ready-to-publish static website suitable for serving with your favorite web server. Jekyll also happens to be the engine -behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll +behind [GitHub Pages](https://pages.github.com/), which means you can use Jekyll to host your project’s page, blog, or website from GitHub’s servers **for free**. diff --git a/test/source/_slides/example-slide-7.md b/test/source/_slides/example-slide-7.md new file mode 100644 index 00000000000..a17c79fe8c3 --- /dev/null +++ b/test/source/_slides/example-slide-7.md @@ -0,0 +1,6 @@ +--- +am_i_convertible: yes +permalink: /slides/example-slide-7.php +--- + +Am I convertible? {{ page.am_i_convertible }} diff --git a/test/source/_thanksgiving/2015-11-26-thanksgiving.md b/test/source/_thanksgiving/2015-11-26-thanksgiving.md new file mode 100644 index 00000000000..48d2dd58cba --- /dev/null +++ b/test/source/_thanksgiving/2015-11-26-thanksgiving.md @@ -0,0 +1,3 @@ +--- +--- +Happy {{ page.title }} ! diff --git a/test/source/_thanksgiving/black-friday.md b/test/source/_thanksgiving/black-friday.md new file mode 100644 index 00000000000..1d8ea1bbad4 --- /dev/null +++ b/test/source/_thanksgiving/black-friday.md @@ -0,0 +1,3 @@ +--- +--- +{{ page.title }} diff --git a/test/source/_tutorials/dive-in-and-publish-already.md b/test/source/_tutorials/dive-in-and-publish-already.md new file mode 100644 index 00000000000..bb94e0fa7a0 --- /dev/null +++ b/test/source/_tutorials/dive-in-and-publish-already.md @@ -0,0 +1,9 @@ +--- +title: "Dive-In and Publish Already!" +lesson: 3 +approx_time: 30 mins +--- + +Jekyll converts Markdown documents to HTML by default. Don't know what's Markdown? +Read this [documentation](https://daringfireball.net/projects/markdown/) +While you're at it, might as well learn about [Kramdown](https://kramdown.gettalong.org/) diff --git a/test/source/_tutorials/extending-with-plugins.md b/test/source/_tutorials/extending-with-plugins.md new file mode 100644 index 00000000000..03d2ea280c7 --- /dev/null +++ b/test/source/_tutorials/extending-with-plugins.md @@ -0,0 +1,9 @@ +--- +title: "Extending with Plugins" +lesson: 5 +approx_time: 1 min +--- + +A lot can be accomplished by using Jekyll out-of-the-box. But a lot more can be achieved by using plugins that extend Jekyll's functionality. There are numerous plugins supported by the official team and many other third-party plugins provided by the Jekyll Community. + +Check this [documentation page](https://jekyllrb.com/docs/plugins/) dedicated to working with plugins. diff --git a/test/source/_tutorials/getting-started.md b/test/source/_tutorials/getting-started.md new file mode 100644 index 00000000000..cd9bbf85c01 --- /dev/null +++ b/test/source/_tutorials/getting-started.md @@ -0,0 +1,7 @@ +--- +title: "Getting Started" +lesson: 1 +approx_time: 10 mins +--- + +The first thing you need is a working installation of Ruby. Install from [the official website](https://www.ruby-lang.org/en/documentation/installation/). diff --git a/test/source/_tutorials/graduation-day.md b/test/source/_tutorials/graduation-day.md new file mode 100644 index 00000000000..ec1d8c59333 --- /dev/null +++ b/test/source/_tutorials/graduation-day.md @@ -0,0 +1,10 @@ +--- +title: "Graduation Day" +lesson: 6 +approx_time: 10 mins +--- + +Congratulations! You now know enough to start Jekylling! + +Want to report a bug you found? Or give something back to the community? +Head over to the [Jekyll Repo](https://github.com/jekyll/jekyll) at GitHub diff --git a/test/source/_tutorials/lets-roll.md b/test/source/_tutorials/lets-roll.md new file mode 100644 index 00000000000..0cfcfe8aa08 --- /dev/null +++ b/test/source/_tutorials/lets-roll.md @@ -0,0 +1,16 @@ +--- +title: "Let's Roll!" +lesson: 2 +approx_time: 1 min +--- + +Now that you have installed Ruby, Jekyll and Bundler, lets get Jekylling! +Enter the following in your terminal: + + $ jekyll new my blog + +Then preview your new project in your browser right away by entering the following and pointing your browser to `http://localhost:4000` : + + $ bundle exec jekyll serve + +Go ahead. Try it. diff --git a/test/source/_tutorials/tip-of-the-iceberg.md b/test/source/_tutorials/tip-of-the-iceberg.md new file mode 100644 index 00000000000..4dab1cf1e10 --- /dev/null +++ b/test/source/_tutorials/tip-of-the-iceberg.md @@ -0,0 +1,6 @@ +--- +title: "Tip of the Iceberg" +lesson: 4 +--- + +Now that you know some of the basics, learn more about working with [Jekyll](https://jekyllrb.com). diff --git a/test/source/_urls_differ_by_case_invalid/page1.html b/test/source/_urls_differ_by_case_invalid/page1.html new file mode 100644 index 00000000000..a6a79f932db --- /dev/null +++ b/test/source/_urls_differ_by_case_invalid/page1.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /about/ +--- + +About the site diff --git a/test/source/_urls_differ_by_case_invalid/page2.html b/test/source/_urls_differ_by_case_invalid/page2.html new file mode 100644 index 00000000000..21f679f3f97 --- /dev/null +++ b/test/source/_urls_differ_by_case_invalid/page2.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /About/ +--- + +About the site diff --git a/test/source/_urls_differ_by_case_valid/page1.html b/test/source/_urls_differ_by_case_valid/page1.html new file mode 100644 index 00000000000..a6a79f932db --- /dev/null +++ b/test/source/_urls_differ_by_case_valid/page1.html @@ -0,0 +1,6 @@ +--- +title: About +permalink: /about/ +--- + +About the site diff --git a/test/source/_with.dots/mit.txt b/test/source/_with.dots/mit.txt new file mode 100644 index 00000000000..c366b0df4ed --- /dev/null +++ b/test/source/_with.dots/mit.txt @@ -0,0 +1,4 @@ +--- +--- + +I should be output to `/with.dots/mit/index.html`. diff --git a/test/source/_with.dots/permalink.with.slash.tho.md b/test/source/_with.dots/permalink.with.slash.tho.md new file mode 100644 index 00000000000..71b9b2e44a5 --- /dev/null +++ b/test/source/_with.dots/permalink.with.slash.tho.md @@ -0,0 +1,5 @@ +--- +permalink: /with.dots/permalink.with.slash.tho/ +--- + +I'm a file with dots BUT I have a permalink which ends with a slash. diff --git a/test/source/assets/application.coffee b/test/source/assets/application.coffee new file mode 100644 index 00000000000..b9f5e1efa21 --- /dev/null +++ b/test/source/assets/application.coffee @@ -0,0 +1,3 @@ +--- +--- +alert "From your site." diff --git a/test/source/assets/base.js b/test/source/assets/base.js new file mode 100644 index 00000000000..40e8a468987 --- /dev/null +++ b/test/source/assets/base.js @@ -0,0 +1 @@ +alert("From your site."); diff --git a/test/source/assets/test-styles.scss b/test/source/assets/test-styles.scss new file mode 100644 index 00000000000..bf14345a0c6 --- /dev/null +++ b/test/source/assets/test-styles.scss @@ -0,0 +1,4 @@ +--- +--- + +@import "{{ site.skin | default: 'grid' }}"; diff --git a/test/source/category/_posts/2008-9-23-categories.markdown b/test/source/category/_posts/2008-09-23-categories.markdown similarity index 100% rename from test/source/category/_posts/2008-9-23-categories.markdown rename to test/source/category/_posts/2008-09-23-categories.markdown diff --git a/test/source/contacts/foo.md b/test/source/contacts/foo.md new file mode 100644 index 00000000000..4e41bebc11a --- /dev/null +++ b/test/source/contacts/foo.md @@ -0,0 +1,7 @@ +--- +title: Contact Information +--- + +## {{ page.title }} + +In case of emergency, contact Mr. John Doe, 1234, Foo Road, Foo. diff --git a/test/source/contacts/humans.txt b/test/source/contacts/humans.txt new file mode 100644 index 00000000000..84e2982b561 --- /dev/null +++ b/test/source/contacts/humans.txt @@ -0,0 +1,5 @@ +--- +permalink: /contacts/humans/ +--- + +I should be output to `/contacts/humans/index.html`. diff --git a/test/source/deal.with.dots.html b/test/source/deal.with.dots.html index 6c87d806207..fb3d473460f 100644 --- a/test/source/deal.with.dots.html +++ b/test/source/deal.with.dots.html @@ -1,6 +1,5 @@ --- title: Deal with dots -permalink: /deal.with.dots --- Let's test if jekyll deals properly with dots. diff --git a/test/source/dynamic_file.php b/test/source/dynamic_file.php new file mode 100644 index 00000000000..823bb47fab0 --- /dev/null +++ b/test/source/dynamic_file.php @@ -0,0 +1,4 @@ +--- +--- + +I'm a Jekyll file! I should be output as dynamic_file.php, no .html to be found. diff --git a/test/source/index.html b/test/source/index.html index 493fce7cbc0..ec542002ce5 100644 --- a/test/source/index.html +++ b/test/source/index.html @@ -5,6 +5,8 @@ h1. Welcome to my site +{{ layout.front_matter_var }} + h2. Please read our {{ site.posts | size }} Posts