Git Product home page Git Product logo

jekyll-titles-from-headings's Introduction

Jekyll Titles from Headings

A Jekyll plugin to pull the page title from the first Markdown heading when none is specified.

CI

What it does

If you have a Jekyll page that doesn't have a title specified in the YAML Front Matter, but the first non-whitespace line in the page is a Markdown H1 / H2 / H3, this plugin instructs Jekyll to use that first heading as the page's title.

Why

Because lots of plugins and templates rely on page.title.

If you're using a plugin like Jekyll Optional Front Matter, you'd have to add Front Matter, just to get the title, which you're already specifying in the document.

Additionally, this allows you to store the title semantically, in the document itself so that it's readable, both as Markdown and when rendered, as machine-readable for plugins like Jekyll SEO Tag.

Usage

  1. Add the following to your site's Gemfile:
gem 'jekyll-titles-from-headings'
  1. Add the following to your site's config file:
plugins:
  - jekyll-titles-from-headings

Note: If you are using a Jekyll version less than 3.5.0, use the gems key instead of plugins.

Configuration

Configuration options are optional and placed in _config.yml under the titles_from_headings key. They default to:

titles_from_headings:
  enabled:     true
  strip_title: false
  collections: false

Stripping titles

If your theme renders titles based on page.title, you can remove the title from the content by setting strip_title to prevent rendering it twice.

To limit this behavior to a certain layouts or paths, you can use front matter defaults, e.g.

defaults:
  - scope:
      path: some-path
      layout: some_layout
    values:
      strip_title: true

Processing Collections

If you want to enable this plugin for collection items, set the collections option to true.

Since collection items (including posts) already have a title inferred from their filename, this option changes the behavior of this plugin to override the inferred title. The inferred title is only used as a fallback in case the document doesn't start with a heading.

Disabling

Even if the plugin is enabled (e.g., via the :jekyll_plugins group in your Gemfile) you can disable it by setting the enabled key to false.

jekyll-titles-from-headings's People

Contributors

adamvoss avatar ashmaroli avatar benbalter avatar dato avatar dependabot-preview[bot] avatar dependabot[bot] avatar kenman345 avatar leleabhinav avatar minerobber9000 avatar qwtel avatar robotdana avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

jekyll-titles-from-headings's Issues

Document how to opt a page out

At least until jekyll/minima#128 is available on GitHub Pages, there are times where you really don't want a page to have a designated title, but do want a heading at the start of the page. It is not immediately clear how to accomplish this.

The best solution I have so far is to start with an HTML-comment:

---
---
<!-- -->

# Title

Respect case of heading

Describe the bug

I would expect this plugin to respect the case of characters in the heading when copying it into page.title.

Steps to reproduce the behavior

Write a post containing the following markdown:

## Hello world

This is content.

With a configuration of:

titles_from_headings:
  strip_title: true

Observe that {{ content }} respects the case for the h2 element, but page.title will have a value of Hello World.

Expected behavior

page.title should have a value of Hello world.

Screenshots

image

Note the title of the tab, which uses {{ page.title }}.

post.excerpt includes title even after strip_title is set to true

When generating post.excerpt, even I have strip_title: true, I still get a h1 title.

Way to reproduce:

  1. jekyll new test-site
  2. In _config.yml edit:
theme: minima
show_excerpts: true

plugins:
  - jekyll-titles-from-headings

titles_from_headings:
  enabled:     true
  strip_title: true
  collections: true
  1. Edit the _posts/XXXX-XX-XX-welcome-to-jekyll.markdown - move title to # Title

  2. Generate a website jekyll serve and observe the issue

Incorrect handling of beginning/end balanced hashes in header

Describe the bug

In my README, I use balanced hashes, as it looks nice to me. An example:

# Main Header #
## Sub-Header 1 ##

This is a valid way to specify a header, as GitHub's usual markdown parser will make the balanced-hashes headers into <h1>, <h2>, etc.

However, the title parsing used here fails to strip out the hash at the end, leading to my page title becoming pico8-joycon #, despite this not being what the header shows.

Steps to reproduce the behavior

  1. Go to https://minerobber9000.github.io/pico8-joycon
  2. Observe the page title as shown in the tab name.

Expected behavior

The ending hashes should be stripped from the title before passing it off to seo and the like.

Enabled by default on Github Pages

This plugin caused an issue for me today because it appears to be enabled by default on Github Pages. For use with seo tag plugin I do not set a title on my site's homepage. With this plugin enabled on Github Pages I now have my h2 tag on the page as my homepage's title. I can reproduce the issue locally only if I add - jekyll-titles-from-headings to my gems in _config.yml. So that leads me to believe that the plugin is enabled by default on github pages builds. That 'enabled by default' behavior seems contrary to what I experience with plugins like seo-tag, sitemap, themes. Is that intentional?

@mhellwinkel

Provide configuration to turn off this plugin

I maintain the documentation site for Liquid, and our index page doesn't have a title in its front matter. This plugin is generating a title and placing it on the page even when I explicitly try to use Liquid to stop empty page titles from being rendered.

Please allow a way to disable this plugin. I just spent an hour of my day trying to stop a heading from being rendered on Liquid's index page, and had to resort to setting the title to ' ' to make it go away.

[Feature] Title from non-starting H1

Is your feature request related to a problem? Please describe the problem you're trying to solve.

titles-from-headings ignores H1 titles if they are not at the start of the file.

Describe the solution you'd like

Scan file for H1 title − such titles are likely to be the file title so it seems reasonable to use it even if its not in the first line.

Maybe it could be a new option, so it doesn't change how repositories are handled by default.

Describe alternatives you've considered

Obviously, putting the H1 title on the first line − but in some repositories I need a header navigation so it is not an option.

Additional context

Repository with header navigation such as: https://github.com/MisterTicot/better-dex

remove heading from content

I'm not sure if this is intended behavior, so I wanted to check.

My expectation was that the initial heading that was parsed as the title would then be removed from the content of the post. Otherwise, any theme that displays the post title will display it twice, first as the title, then as the first heading in the content. Obviously, there's no way for the plugin to know anything about the current theme, so maybe make this optional?

Strip Markdown markup from title

Headers in Markdown may include markup:

# My _title_ with footnote[^src]

[^src]: This article is based on previous work by J.E.D.

It would be nice to strip that from the title as it goes to the front-matter, since it will be treated verbatim by browsers and scripts.

Many thanks for considering,

-d

(Moved from benbalter/jekyll-optional-front-matter#6, which was in the wrong plugin.)

Requires double newline after header

I have markdown files that look like:

---
---
# Header
Bla bla ...

This markdown is rendered by GitHub as expected, an extra linebreak after the header is not required. However, the title is only extracted if the header is followed by two newlines.

NoMethodError: undefined method `content'

Just wanted to report what seems to be a bug when there's an .md file in a collection that doesn't have Jekyll front matter? For instance, if bad.md is in a project's root, it ends up in _site as bad.md, unrendered as expected. But if bad.md is instead in _pages, which we've defined as a collection, the build instead errs, per the below.

Sample files at https://gist.github.com/dmalan/0c67667065cfea19a00fc2ec1f83560a. Do just let me know if anything more would be helpful!

this succeeds

$ find .
.
./_config.yml
./_pages
./_pages/good.md
./bad.md
./Gemfile

$bundle install
Fetching gem metadata from https://rubygems.org/...........
Fetching version metadata from https://rubygems.org/..
Fetching dependency metadata from https://rubygems.org/.
Using public_suffix 3.0.0
Using bundler 1.15.4
Using colorator 1.1.0
Using ffi 1.9.18
Using forwardable-extended 2.6.0
Using rb-fsevent 0.10.2
Using kramdown 1.15.0
Using liquid 4.0.0
Using mercenary 0.3.6
Fetching rouge 2.2.1
Installing rouge 2.2.1
Using safe_yaml 1.0.4
Using addressable 2.5.2
Using rb-inotify 0.9.10
Fetching pathutil 0.16.0
Installing pathutil 0.16.0
Using sass-listen 4.0.0
Using listen 3.0.8
Fetching sass 3.5.2
Installing sass 3.5.2
Using jekyll-watch 1.5.0
Using jekyll-sass-converter 1.5.0
Fetching jekyll 3.6.2
Installing jekyll 3.6.2
Fetching jekyll-titles-from-headings 0.5.0
Installing jekyll-titles-from-headings 0.5.0
Bundle complete! 2 Gemfile dependencies, 21 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

$ bundle exec jekyll build -V --trace
  Logging at level: debug
Configuration file: /home/ubuntu/workspace/_config.yml
         Requiring: kramdown
            Source: /home/ubuntu/workspace
       Destination: /home/ubuntu/workspace/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
       EntryFilter: excluded /Gemfile
       EntryFilter: excluded /Gemfile.lock
           Reading: _pages/good.md
         Requiring: kramdown
        Generating: JekyllTitlesFromHeadings::Generator finished in 0.008745871 seconds.
         Rendering: _pages/good.md
  Pre-Render Hooks: _pages/good.md
  Rendering Liquid: _pages/good.md
  Rendering Markup: _pages/good.md
  Rendering Layout: _pages/good.md
                    done in 0.067 seconds.
 Auto-regeneration: disabled. Use --watch to enable.

this fails

$ find .
.
./_config.yml
./_pages
./_pages/bad.md
./_pages/good.md
./Gemfile

$bundle install
Fetching gem metadata from https://rubygems.org/...........
Fetching version metadata from https://rubygems.org/..
Fetching dependency metadata from https://rubygems.org/.
Using public_suffix 3.0.0
Using bundler 1.15.4
Using colorator 1.1.0
Using ffi 1.9.18
Using forwardable-extended 2.6.0
Using rb-fsevent 0.10.2
Using kramdown 1.15.0
Using liquid 4.0.0
Using mercenary 0.3.6
Fetching rouge 2.2.1
Installing rouge 2.2.1
Using safe_yaml 1.0.4
Using addressable 2.5.2
Using rb-inotify 0.9.10
Fetching pathutil 0.16.0
Installing pathutil 0.16.0
Using sass-listen 4.0.0
Using listen 3.0.8
Fetching sass 3.5.2
Installing sass 3.5.2
Using jekyll-watch 1.5.0
Using jekyll-sass-converter 1.5.0
Fetching jekyll 3.6.2
Installing jekyll 3.6.2
Fetching jekyll-titles-from-headings 0.5.0
Installing jekyll-titles-from-headings 0.5.0
Bundle complete! 2 Gemfile dependencies, 21 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

$ bundle exec jekyll build -V --trace
  Logging at level: debug
Configuration file: /home/ubuntu/workspace/_config.yml
         Requiring: kramdown
            Source: /home/ubuntu/workspace
       Destination: /home/ubuntu/workspace/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
       EntryFilter: excluded /Gemfile
       EntryFilter: excluded /Gemfile.lock
           Reading: _pages/good.md
         Requiring: kramdown
bundler: failed to load command: jekyll (/opt/rbenv/versions/2.4.0/bin/jekyll)
NoMethodError: undefined method `content' for #<Jekyll::StaticFile:0x005644948e9048>
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-titles-from-headings-0.5.0/lib/jekyll-titles-from-headings/generator.rb:67:in `title_for'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-titles-from-headings-0.5.0/lib/jekyll-titles-from-headings/generator.rb:44:in `block in generate'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-titles-from-headings-0.5.0/lib/jekyll-titles-from-headings/generator.rb:42:in `each'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-titles-from-headings-0.5.0/lib/jekyll-titles-from-headings/generator.rb:42:in `generate'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/site.rb:176:in `block in generate'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/site.rb:174:in `each'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/site.rb:174:in `generate'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/site.rb:72:in `process'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/command.rb:28:in `process_site'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/commands/build.rb:65:in `build'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/commands/build.rb:36:in `process'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/lib/jekyll/commands/build.rb:18:in `block (2 levels) in init_with_program'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `block in execute'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `each'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mercenary-0.3.6/lib/mercenary/command.rb:220:in `execute'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mercenary-0.3.6/lib/mercenary/program.rb:42:in `go'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/mercenary-0.3.6/lib/mercenary.rb:19:in `program'
  /opt/rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/jekyll-3.6.2/exe/jekyll:15:in `<top (required)>'
  /opt/rbenv/versions/2.4.0/bin/jekyll:22:in `load'
  /opt/rbenv/versions/2.4.0/bin/jekyll:22:in `<top (required)>'

page titles incorrect when using jekyll-asciidoc with :skip-front-matter:

Hi @benbalter, all,

We're currently using Jekyll with Asciidoctor (via jekyll-asciidoc) along with jekyll-titles-from-headings in order to infer page's titles from = headings, rather than explicitly specify them in Jekyll front matter with title:. And we're also using :skip-front-matter: in order to include one file (e.g., baz.adoc) in another (e.g., foo.adoc) without seeing the former's front matter in the latter's HTML output.

A working example is at https://gist.github.com/dmalan/09356831e6cce010f9381e1c360832bb (provided you move default.html to a _layouts directory. It's perhaps worth noting that baz.adoc has published: false in its front matter so that Asciidoctor includes it from foo.adoc while Jekyll doesn't output a partial baz.html file for it. However, when we move foo.adoc and baz.adoc into a collection (e.g., _pages) and change _config.yml from https://gist.github.com/dmalan/09356831e6cce010f9381e1c360832bb#file-_config-yml to https://gist.github.com/dmalan/36113ae977cf5f143f44a23f7d629ee0 in order to support that collection, we're finding that jekyll-titles-from-headings no longer infers a page's title correctly; the page's title instead becomes the page's filename, with the first letter capitalized (i.e., Foo). If, though, we remove :skip-front-matter: from foo.adoc, then jekyll-titles-from-headings starts working again, and foo.adoc ends up with a title of Bar as expected.

Does this sound like an issue with :skip-front-matter: or perhaps with jekyll-titles-from-headings instead? Or is our _config.yml (with the collection) perhaps just misconfigured? 

Thanks very much!

typo in description

Spotted a typo in the description:
"A Jekyll plugin to pull page the title from fist Markdown heading when none is specified"

"pull the page title" rather than "pull page the title"
"first" rather than "fist"

Not working in jekyll 3.8.3

I can't make the library work. Or I do something wrong.

For example, I take a copy of a finished project with a minimal theme https://github.com/jekyll/minima.

In the Gemfile file I add at the end of the line gem 'jekyll-titles-from-headings':

# frozen_string_literal: true

source "https://rubygems.org"
gemspec

gem 'jekyll-titles-from-headings'

I call the command bundle in the terminal. All ok,

In the _config.yml file add the line:

plugins:
 - jekyll-titles-from-headings

titles_from_headings:
  enabled:     true
  strip_title: false
  collections: false

Finished _config.yml:

title: Your awesome title
author: GitHub User
email: [email protected]
description: > # this means to ignore newlines until "twitter_username:"
  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.

# social links
twitter_username: jekyllrb
github_username:  jekyll
rss: rss

show_excerpts: false # set to true to show excerpts on the homepage

# Minima date format
# refer to http://shopify.github.io/liquid/filters/date/ if you want to customize this
minima:
  date_format: "%b %-d, %Y"

# Build settings
theme: minima

plugins:
 - jekyll-feed
 - jekyll-seo-tag
 - jekyll-titles-from-headings

titles_from_headings:
  enabled:     true
  strip_title: false
  collections: false

Change the content of any post ( for example 2016-05-20-welcome-to-jekyll.md) on the following:

---
layout: post
---
# Matrix has you, Neo!

Bla bla

I start the local server jekyll command jekyll serve.

And I should see an article in the list of articles with the title "Matrix has you, Neo!", but the title is "Welcome To Jekyll". What am I doing wrong?

Excerpt metadata ignored when strip_title: true

Describe the bug

When the plugin configuration sets strip_title: true, then an excerpt is always generated from the blog post text and excerpt: [text] is ignored.

Steps to reproduce the behavior

Set up an example blog with jekyll (or anything with collections)
In _config.yml set

titles_from_headings:
  strip_title: false
  collections: true

In a post set meta-data as

---
layout: post
excerpt: 'I am excerpt'
---
# I am Header

this is next content

Run site and look at post listing. The excerpt will be "this is next content"

Expected behavior

I would expect the plugin to always prioritize excerpts explicitly set in metadata.
Expected behavior by cases

Case 1 (current behavior)

  • strip_title: false; excerpt set in post metadata
  • Action: take excerpt from metadata

Case 2 (current behavior)

  • strip_title: false; excerpt not set in post metadata
  • Action: generate excerpt from post with default jekyll behavior

Case 3 (current behavior)

  • strip_title: true; excerpt not set in post metadata
  • Action: Remove title and generate excerpt from remaining content using default behavior

Case 4 (missing behavior)

  • strip_title: true; excerpt set in metadata:
  • Expected Action: take excerpt from metadata

Does not work with Setext-style headers

The following markdown renders an h1 header, but a file starting with it is not given a title by this plugin.

A First Level Header
====================

If you switch to an atx-style header, the plugin works

# A First Level Header

Title not being removed from excerpt for any collection other than posts

Describe the bug

With strip_title: true, post.excerpt has the title removed as expected. For any other type of collection, for example books, book.excerpt will still contain the title.

Steps to reproduce the behavior

Create a Jekyll project with a collection other than post. e.g.:

collections:
  books:
    output: true

Expected behavior

Title should be removed from the collection

Screenshots

N/A

Additional context

N/A

www.fb.com

Describe the bug

A clear and concise description of what the bug is.

Steps to reproduce the behavior

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Skip documents with no `document.content`

In title_for:

def title_for(document)
return document.data["title"] if title?(document)
matches = document.content.match(TITLE_REGEX)
return strip_markup(matches[1] || matches[2]) if matches
document.data["title"] # If we cant match a title, we use the inferred one.
rescue ArgumentError => e
raise e unless e.to_s.start_with?("invalid byte sequence in UTF-8")
end

document.content.match can fail when document.content is nil. This may be colliding with another plugin that doesn't set the document's content.

undefined method `match' for nil:NilClass (NoMethodError)

/cc @benbalter

Follow Jekyll 4.1.1 in not generated excerpts by default

Describe the bug

In Jekyll 4.1.1, excerpts are no longer generated by default (Link). This plugin should not override this behaviour.

Steps to reproduce the behavior

N/A

Expected behavior

This plugins should only strip titles from excerpts if Jekyll has previously generated an except.

Screenshots

N/A

Additional context

N/A

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.