asciidoc_parser/document/
author_line.rs

1use std::slice::Iter;
2
3use crate::{HasSpan, Parser, Span, document::Author};
4
5/// The author line is directly after the document title line in the document
6/// header. When the content on this line is structured correctly, the processor
7/// assigns the content to the built-in author and email attributes.
8#[derive(Clone, Debug, Eq, PartialEq)]
9pub struct AuthorLine<'src> {
10    authors: Vec<Author>,
11    source: Span<'src>,
12}
13
14impl<'src> AuthorLine<'src> {
15    pub(crate) fn parse(source: Span<'src>, parser: &mut Parser) -> Self {
16        let authors: Vec<Author> = source
17            .data()
18            .split("; ")
19            .filter_map(|raw_author| Author::parse(raw_author, parser))
20            .collect();
21
22        for (index, author) in authors.iter().enumerate() {
23            set_nth_attribute(parser, "author", index, author.name());
24            set_nth_attribute(parser, "authorinitials", index, author.initials());
25            set_nth_attribute(parser, "firstname", index, author.firstname());
26
27            if let Some(middlename) = author.middlename() {
28                set_nth_attribute(parser, "middlename", index, middlename);
29            }
30
31            if let Some(lastname) = author.lastname() {
32                set_nth_attribute(parser, "lastname", index, lastname);
33            }
34
35            if let Some(email) = author.email() {
36                set_nth_attribute(parser, "email", index, email);
37            }
38        }
39
40        Self { authors, source }
41    }
42
43    /// Return an iterator over the authors in this author line.
44    pub fn authors(&'src self) -> Iter<'src, Author> {
45        self.authors.iter()
46    }
47}
48
49fn set_nth_attribute<V: AsRef<str>>(parser: &mut Parser, name: &str, index: usize, value: V) {
50    let name = if index == 0 {
51        name.to_string()
52    } else {
53        format!("{name}_{count}", count = index + 1)
54    };
55
56    parser.set_attribute_by_value_from_header(name, value);
57}
58
59impl<'src> HasSpan<'src> for AuthorLine<'src> {
60    fn span(&self) -> Span<'src> {
61        self.source
62    }
63}