Repository: getnikola/nikola

Issue:
Multiple authors for a post
Currently one can specify a single author of a post using the `author` metadata field.

For post authored by multiple authors, there currently does not seem to be a way to specify that.


Discussion:
Sorry about taking so long to acknowledge this issue, I have been busy.

This is a reasonable request, let's look into it a bit more:

* :+1: Metadata is arbitrary, you can add a "authors" field if you want
* :-1:  It's better if we standardize how that field would look 
* :-1: It's not supported in the default templates. Do you know of any site using multiple authors per post and like how it looks?
* :+1: There is support for multiple authors in docutils if we used document's metadata (no idea how well that works)

So, let's talk about it.
I switched to Hugo, so here is an example of my blog post:

https://lfortran.org/blog/2019/04/why-we-created-lfortran/

You can see multiple people in the authors section, and here is how I did it:

https://gitlab.com/lfortran/web/www.lfortran.org/blob/66157184d69b01c57a576061e1c8b608c85539a5/content/blog/why-we-created-lfortran.md#L5

So perhaps Hugo thinks it's just one author, but I don't mind, as long as it looks good online.
You could do exactly the same thing. Like copy & paste it :-)

Closing then.

On Mon, Aug 5, 2019 at 12:52 PM Ondřej Čertík <notifications@github.com>
wrote:

> I switched to Hugo, so here is an example of my blog post:
>
> https://lfortran.org/blog/2019/04/why-we-created-lfortran/
>
> You can see multiple people in the authors section, and here is how I did
> it:
>
>
> https://gitlab.com/lfortran/web/www.lfortran.org/blob/66157184d69b01c57a576061e1c8b608c85539a5/content/blog/why-we-created-lfortran.md#L5
>
> So perhaps Hugo thinks it's just one author, but I don't mind, as long as
> it looks good online.
>
> —
> You are receiving this because you commented.
> Reply to this email directly, view it on GitHub
> <https://github.com/getnikola/nikola/issues/3252?email_source=notifications&email_token=AAAAMK2XFXXYW5TC2HHJN2LQDBEEJA5CNFSM4HF3DYAKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3SIAVY#issuecomment-518291543>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AAAAMKYXJ55ZBS6TNSQHPGLQDBEEJANCNFSM4HF3DYAA>
> .
>

Perfect!
Hey, sorry to comment on a closed issue, but the current solution does not work for me.
In a shared blog, where there is more than one person writing, and sometimes or often, the entries are co-authored, then, the /authors special page is not useful. The simplest case:

Ann: how to code in fortran
Ben: using jupyter notebook
Ann & Ben: exploring LFrotran together

Then, I expect that in authors/ann and in authors/ben, there are 2 articles in each.
Is this something that I could change from a template?
Metadata is arbitrary you could just have author1 / author2 / author3 and
so on and just fix the post template to support that

El vie., 28 de agosto de 2020 8:41 p. m., fadelkon <notifications@github.com>
escribió:

> Hey, sorry to comment on a closed issue, but the current solution does not
> work for me.
> In a shared blog, where there is more than one person writing, and
> sometimes or often, the entries are co-authored, then, the /authors special
> page is not useful. The simplest case:
>
> Ann: how to code in fortran
> Ben: using jupyter notebook
> Ann & Ben: exploring LFrotran together
>
> Then, I expect that in authors/ann and in authors/ben, there are 2
> articles in each.
> Is this something that I could change from a template?
>
> —
> You are receiving this because you modified the open/close state.
> Reply to this email directly, view it on GitHub
> <https://github.com/getnikola/nikola/issues/3252#issuecomment-683191661>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAAAMK6LT3REOQQQ3DD55M3SDA6ANANCNFSM4HF3DYAA>
> .
>

I understand this, but how can I do it so that I can have "author pages" that for each author, the "shared posts" are credited to each author?

If I used `author2`, then author page will miss the post.

In the other hand, if I populate `author` with `Ann & Ben` and interpret it from my template so that it shows pretty, still, the author pages index will show `Ann`, `Ben` and `Ann & Ben`. I don't want to create "combination authors" like that. I only want 2 authors, `Ann` and `Ben`. In my case, we are more than 2 authors, and the possible combinations are too many.

EDIT:
I've been reading the source code and understand that it's explicitly not supported.
https://github.com/getnikola/nikola/blob/433b3b1e190741f2ef95d74df18f63a803493637/nikola/plugins/task/authors.py#L41


How many pieces should I copy If I wanted to create a modified copy of the authors classifier into, let's say, some multiple_authors one? I imagine it that it would read an hypothetical "authors" field (in plural), or just use "author" and replace the current classifier, via a config option.

EDIT2:

To be clear: with "author pages" or "author index" I am referring to this feature:
```
# If ENABLE_AUTHOR_PAGES is set to True and there is more than one
# author, author pages are generated.
ENABLE_AUTHOR_PAGES = True
```
Good point. Yes, you are right.

Sadly, the authors plugin is fairly convoluted. I don't promise anything
since I am mostly retired from open source, but I will try to take a look.

On Fri, Aug 28, 2020 at 10:07 PM fadelkon <notifications@github.com> wrote:

> I understand this, but how can I do it so that I can have authors index
> page that for each author, the "shared posts" are recognized too?
>
> If I used author2, then author index won't read it.
>
> Similarly, if I populate author: Ann & Ben and interpret it from my
> template, the author index will show Ann, Ben and Ann & Ben. I don't want
> to create "combination authors" like that.
>
> —
> You are receiving this because you modified the open/close state.
> Reply to this email directly, view it on GitHub
> <https://github.com/getnikola/nikola/issues/3252#issuecomment-683209556>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAAAMK65TF2EZ3RYXDUVB2LSDBIFNANCNFSM4HF3DYAA>
> .
>


Resolving patch:
diff --git a/nikola/nikola.py b/nikola/nikola.py
--- a/nikola/nikola.py
+++ b/nikola/nikola.py
@@ -547,6 +547,7 @@ def __init__(self, **config):
             'MATHJAX_CONFIG': '',
             'METADATA_FORMAT': 'nikola',
             'METADATA_MAPPING': {},
+            'MULTIPLE_AUTHORS_PER_POST': False,
             'NEW_POST_DATE_PATH': False,
             'NEW_POST_DATE_PATH_FORMAT': '%Y/%m/%d',
             'OLD_THEME_SUPPORT': True,
@@ -1269,6 +1270,7 @@ def _set_global_context_from_config(self):
         self._GLOBAL_CONTEXT['smartjoin'] = utils.smartjoin
         self._GLOBAL_CONTEXT['colorize_str'] = utils.colorize_str
         self._GLOBAL_CONTEXT['meta_generator_tag'] = self.config.get('META_GENERATOR_TAG')
+        self._GLOBAL_CONTEXT['multiple_authors_per_post'] = self.config.get('MULTIPLE_AUTHORS_PER_POST')
 
         self._GLOBAL_CONTEXT.update(self.config.get('GLOBAL_CONTEXT', {}))
 
diff --git a/nikola/plugins/task/authors.py b/nikola/plugins/task/authors.py
--- a/nikola/plugins/task/authors.py
+++ b/nikola/plugins/task/authors.py
@@ -73,6 +73,7 @@ def set_site(self, site):
         """Set Nikola site."""
         super().set_site(site)
         self.show_list_as_index = site.config['AUTHOR_PAGES_ARE_INDEXES']
+        self.more_than_one_classifications_per_post = site.config.get('MULTIPLE_AUTHORS_PER_POST', False)
         self.template_for_single_list = "authorindex.tmpl" if self.show_list_as_index else "author.tmpl"
         self.translation_manager = utils.ClassificationTranslationManager()
 
@@ -86,7 +87,10 @@ def is_enabled(self, lang=None):
 
     def classify(self, post, lang):
         """Classify the given post for the given language."""
-        return [post.author(lang=lang)]
+        if self.more_than_one_classifications_per_post:
+            return post.authors(lang=lang)
+        else:
+            return [post.author(lang=lang)]
 
     def get_classification_friendly_name(self, classification, lang, only_last_component=False):
         """Extract a friendly name from the classification."""
diff --git a/nikola/post.py b/nikola/post.py
--- a/nikola/post.py
+++ b/nikola/post.py
@@ -547,7 +547,7 @@ def title(self, lang=None):
             lang = nikola.utils.LocaleBorg().current_lang
         return self.meta[lang]['title']
 
-    def author(self, lang=None):
+    def author(self, lang=None) -> str:
         """Return localized author or BLOG_AUTHOR if unspecified.
 
         If lang is not specified, it defaults to the current language from
@@ -562,6 +562,21 @@ def author(self, lang=None):
 
         return author
 
+    def authors(self, lang=None) -> list:
+        """Return localized authors or BLOG_AUTHOR if unspecified.
+
+        If lang is not specified, it defaults to the current language from
+        templates, as set in LocaleBorg.
+        """
+        if lang is None:
+            lang = nikola.utils.LocaleBorg().current_lang
+        if self.meta[lang]['author']:
+            author = [i.strip() for i in self.meta[lang]['author'].split(",")]
+        else:
+            author = [self.config['BLOG_AUTHOR'](lang)]
+
+        return author
+
     def description(self, lang=None):
         """Return localized description."""
         if lang is None:


Test patch: