jekyllt / jasper

Full-featured Jekyll port of Ghost's default theme Casper 👻
https://jekyller.github.io/jasper/
MIT License
581 stars 349 forks source link

How to allow multiple authors #10

Closed gully closed 3 years ago

gully commented 8 years ago

First of all thank you for making this theme and providing it with a permissive license. I am very appreciative.

Question- How can we add multiple authors? It's clear to me how to link a single author: connect the nickname: in config.yml to the category: in the front matter of the mardown post in _posts. The response to Issue #3 explains that it should be possible to add another author. But I can't see how to do it.

Sorry if this is obvious, we tried some hacks and can't seem to come up with an obvious path forward.

biomadeira commented 8 years ago

@gully sorry for the delay replying to you and sorry if I made this sound it would be easily accomplished. In fact, I am pretty sure with serious hacking this would be possible, but as it stands it is not just a question of updating post 'categories' with a new user, because the theme is being built mainly from _config where the main author details are defined.

I have tried editing 'categories' with some 'newauthor' and the gem generates the respective author/newauthor pages but all the rest remains the same... I would guess the best approach to enable proper multiple user support would be to delegate most author information from _config to each post front matter so that each post self contains most info about its author...

I will try a new fork of this theme with proper multiple author support... I will let you know then.

natanio commented 8 years ago

@biomadeira I've just started using Jekyll, and decided to go with this theme. I love Ghost and think the design is really beautiful. So thanks for putting it out there!

@gully I also needed a multiple author solution and messed around for a few hours with no luck. Then I thought of a very simple workaround, that probably isn't the best, but it works if you need it.

In _plugins > jekyll-autgenerator.rb, change GroupSubPageAuthor class to:

class GroupSubPageAuthor < Page
    def initialize(site, base, dir, type, val)
      @site = site
      @base = base
      @dir = dir
      @name = 'index.html'

      self.process(@name)
      self.read_yaml(File.join(base, '_layouts'), "author-#{val}.html")
      self.data["grouptype"] = type
      self.data[type] = val
    end
  end

This is the changed line: self.read_yaml(File.join(base, '_layouts'), "author-#{val}.html")

Next, you just need to make a new layout file with the nickname of your author like author-nickname.html, and add all the yaml details of that author to the front matter. Change site.url etc. references to page.url, page.author, etc, and generate your site. You should now how an author page with the correct details showing!

It's important if you use this to not use categories that are not intended to be authors.

Also, you need to add the author's details to the front matter of each post h/she writes.

Until there's a better solution, I hope this helps!

biomadeira commented 8 years ago

@natanio Great stuff! Thanks!

gully commented 8 years ago

Thank you both for your responses, I really appreciate it! I will try this solution. Thanks again.

gully commented 8 years ago

Great, so I tried the solution from @natanio and got multi-author capability for each post! This feat was just at the edge of my abilities, and I'm glad I stuck it through- I learned much more about how it all works. And it is quite rewarding when it worked. I'll put a few notes here in case anyone else stumbles upon this issue and wants to hack a multi-author solution. Note some redundancies with above.

  1. Modify _plugins/jekyll-autgenerator.rb as instructed above.
  2. In a shell do a grep -R "site.nickname" ., and replace all. For example on a Mac I did a, find . -type f -name '*.html' -exec sed -i '' s/site.nickname/page.nickname/g {} +. Repeat this for bio, author, image. Anything shared with all authors can remain as site, for example baseurl is probably the same for everyone. Basically, hunt down and inspect the instances. They crop up in the xml files too.
  3. In the _layouts/loop.html you have to change the site.image to post.image, along with select other keywords in the footer section. This was a tricky bit because the footer images were not showing up.

It's not clear what the categories section in jekyll-autgenerator.rb will do now that we've messed around with things. I also think the loop.html is looping for each unique N author, but this doesn't matter-- things just get overwritten N times.

All in all this seems to work! Thanks again.

biomadeira commented 8 years ago

Great stuff guys! Thank you ;)

0xdevalias commented 8 years ago

I'll just chime in my solution here in case it helps others. I probably don't need the multiple authors personally, but it felt a bit 'wrong' how it was. I went for the 'author info in data file' approach.

In _data/authors.yml:

devalias:
  nickname: 'devalias'
  name: "Glenn 'devalias' Grant"
  bio: 'TODO: Bio'
  location: 'Australia'
  image: '/assets/images/authors/devalias.png'
  url: 'http://www.devalias.net/'
  short_url: 'devalias.net'
casper:
  nickname: 'casper'
  name: "Default Data"
  bio: 'TODO: Bio'
  location: 'Ghostland'
  image: '/assets/images/authors/casper.png'
  url: 'http://www.example.com/'
  short_url: 'example.com'

Then I go through and update all of the old references (scraped through the code manually, but you can probably use the above searches too)

Here's an example of how I did the _layouts/post.html author section:

<section class="author">
    <h4><a href="{{ site.baseurl | chomp_slash }}/author/{{ page.author }}">{{ site.data.authors[page.author].name }}</a></h4>

    {% if site.data.authors[page.author].bio %}
        <p> {{ site.data.authors[page.author].bio }}</p>
    {% else %}
        <p>Read <a href="{{ site.baseurl | chomp_slash }}/author/{{ page.author }}">more posts</a> by this author.</p>
    {% endif %}
    <div class="author-meta">
        {% if site.data.authors[page.author].location %}
            <span class="author-location icon-location">
                {{ site.data.authors[page.author].location }}
            </span>
        {% endif %} 
        {% if site.data.authors[page.author].url and site.data.authors[page.author].short_url %}
            <span class="author-link icon-link"><a href="{{ site.data.authors[page.author].url }}">{{ site.data.authors[page.author].short_url }}</a></span>
        {% endif %}
    </div>
</section>

Some notes on the above

In case anyone wants it, _plugins/chomp_slash.rb

module Jekyll
  module ChompSlashFilter
    def chomp_slash(input)
      input.chomp('/')
    end
  end
end

Liquid::Template.register_filter(Jekyll::ChompSlashFilter)

Just pushed my changes to alias1/devalias.net in case anyone wants to check them out. Could be worth doing a diff across mine/the original and see how hard it would be to merge in (if you want).

drakejin commented 7 years ago

@alias1 Thanks your working. It's great help. Awesome stuff. I will add some few code

mycode

  1. create file ${project}/_data/authors.yml
drakejin:
    nickname: 'drakejin'
    name: "drake jin jin"
    bio: 'blabalblablablablbllbalbablbal '
    location: 'Seoul, Korea'
    image: '/assets/images/authors/drakejin.jpg'
    url: 'http://blog.drakejin.me'
    short_url: 'blog.drakejin.me'
casper:
     nickname: 'casper'
     name: "Default Data"
     bio: 'TODO: Bio'
     location: 'Ghostland'
    image: '/assets/images/authors/casper.png'
     url: 'http://www.example.com/'
     short_url: 'example.com'
  1. modify _config.yml
# Remain property with only "author"
# this author is master of authors

author: "drakejin"
  1. modify _layout/author.html
    <section class="author-profile inner">
       {% if site.data.authors[page.author].image %}
       <figure class="author-image">
            <div class="img" style="background-image: url({{ site.data.authors[page.author].image }})">
                <span class="hidden">{{ site.data.authors[page.author].nickname }}'s Picture</span>
            </div>
        </figure>
       {% endif %}
       <h1 class="author-title">{{ site.data.authors[page.author].nickname }}</h1>
         {% if site.bio %}
            <h2 class="author-bio">{{ site.data.authors[page.author].bio }}</h2>
         {% endif %}
        <div class="author-meta">
             {% if site.data.authors[page.author].location %}
                 <span class="author-location icon-location">{{ site.data.authors[page.author].location }}</span>
            {% endif %}

            {% if site.data.authors[page.author].url %}
               <span class="author-link icon-link"><a href="{{ site.data.authors[page.author].url }}">{{ site.data.authors[page.author].short_url }}</a></span>
            {% endif %}
            <!-- <span class="author-stats"><i class="icon-stats"></i> [[plural ../pagination.total empty='No posts' singular='% post' plural='% posts']]</span> -->
            <span class="author-stats">
               <i class="icon-stats"></i>
                {% if paginator.total_posts == 0 %}
                    No posts
                {% elsif paginator.total_posts == 1 %}
                    1 post
                {% else %}
                    {{ paginator.total_posts }} posts
                {% endif %}
            </span>
        </div>
    </section>
<!-- /author -->
  1. modify _layout/author.xml
{% for post in page.posts %}
    <item>
     <title>{{ post.title }}</title>
     <link>{{ site.baseurl }}{{ post.url }}</link>
     <author>{{ site.data.authors[page.author].nickname }}</author>
     <pubDate>{{ post.date | date_to_xmlschema }}</pubDate>
     <guid>{{ site.baseurl }}{{ post.url }}</guid>
     <description><![CDATA[
        {{ post.content | expand_urls : site.url }}
      ]]></description>
    </item>
 {% endfor %}
  1. modify _layout/post.html

            <!-- Everything inside the #author tags pulls data from the author -->
            <!-- #author-->
        {% for category in page.categories %}
            {% if site.data.authors[category].image %}
            <figure class="author-image">
                <a class="img" href="{{ site.baseurl }}author/{{ site.data.authors[category].nickname }}" style="background-image: url({{ site.data.authors[category].image }})">
                    <span class="hidden">{{ site.data.authors[category].nickname }}'s 사진</span>
                </a>
            </figure>
            {% endif %}
    
            <section class="author">
                <h4><a href="{{ site.baseurl }}author/{{ site.data.authors[category].nickname }}">{{ site.data.authors[category].nickname }}</a></h4>
    
                {% if site.data.authors[category].bio %}
                <p> {{ site.data.authors[category].bio }}</p>
                {% else %}
                <p>Read <a href="{{ site.baseurl }}author/{{ site.data.authors[category].nickname }}">more posts</a> by this author.</p>
                {% endif %}
                <div class="author-meta">
                    {% if site.data.authors[category].location %}
                    <span class="author-location icon-location">
                        {{ site.data.authors[category].location }}
                    </span>
                    {% endif %}
                    {% if site.data.authors[category].url and site.data.authors[category].short_url %}
                    <span class="author-link icon-link"><a href="{{ site.data.authors[category].url }}">{{ site.data.authors[category].short_url }}</a></span>
                    {% endif %}
                </div>
            </section> 
        {% endfor %}
            <!-- /author  -->
  2. modify _include/loop.html

 <!-- This is the post loop - each post will be output using this markup -->
  {% for post in paginator.posts %}
  <article class="post">
      <header class="post-header">
          <h2 class="post-title"><a href="{{ site.baseurl }}{{ post.url | remove: '/' }}">{{ post.title }}</a></h2>
      </header>
      <section class="post-excerpt">
          <p>{{ post.content | strip_html | truncatewords: 26 }} <a class="read-more" href="{{ site.baseurl }}{{ post.url | remove: '/' }}">&raquo;</a></p>
      </section>
      <footer class="post-meta">
     {% for category in post.categories  %}  
          {% if site.data.authors[category].image %}
          <img class="author-thumb" src="{{ site.data.authors[category].image }}" alt="Author image" nopin="nopin" />
          {% endif %}
          <!-- author -->
          <a href='{{ site.baseurl }}author/{{ site.data.authors[category].nickname }}'>{{ site.data.authors[category].nickname }}</a>
          <!-- [[tags prefix=" on "]] -->
      {% endfor %}
          {% if post.tags.size > 0 %}  
              on  
              {% for tag in post.tags %}
                  {% if forloop.index == post.tags.size %}
                     <a href='{{ site.baseurl }}tag/{{ tag }}'>{{ tag | capitalize }}</a>
                  {% else %}
                     <a href='{{ site.baseurl }}tag/{{ tag }}'>{{ tag | capitalize }}</a>,
                  {% endif %}   
              {% endfor %}
          {% endif %}
          <time class="post-date" datetime="{{ post.date | date:'%Y-%m-%d' }}">{{ post.date | date_to_string }}</time>
      </footer>
  </article>
  {% endfor %}

My Question

"categories" to "authors" in post file how to change it..? I want to change the name "categories" to "authors" in _post/makrdown files... Could someone help me?

biomadeira commented 6 years ago

I finally added support for multiple authors (as a default) with a combination of things:

Jekyll supports TAGS and CATEGORIES (https://jekyllrb.com/docs/variables/#site-variables) out of the box. Here, I have used categories as a easy-ish shortcut approach to solve the multiple author problem. Is probably not very elegant though, but good enough for now...

See https://github.com/biomadeira/jasper/commit/ede39352019bc2da8e45e66b5160ba393a54f86f and https://github.com/biomadeira/jasper/commit/285730ccc25dfc5a47333b70276857caeac702d8 for more details on the changes introduced.